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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt53
-rw-r--r--GNUmakefile3
-rw-r--r--SConstruct4
-rwxr-xr-xbuild_files/cmake/cmake_consistency_check.py3
-rw-r--r--build_files/cmake/cmake_consistency_check_config.py11
-rwxr-xr-xbuild_files/cmake/cmake_netbeans_project.py1
-rwxr-xr-xbuild_files/cmake/cmake_qtcreator_project.py1
-rw-r--r--build_files/cmake/cmake_static_check_cppcheck.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/macros.cmake28
-rwxr-xr-xbuild_files/cmake/project_info.py3
-rw-r--r--build_files/cmake/project_source_info.py3
-rw-r--r--doc/build_systems/cmake.txt1
-rw-r--r--doc/build_systems/scons-dev.txt2
-rw-r--r--doc/build_systems/scons.txt1
-rw-r--r--extern/CMakeLists.txt2
-rw-r--r--extern/Eigen2/Eigen/Array39
-rw-r--r--extern/Eigen2/Eigen/Cholesky65
-rw-r--r--extern/Eigen2/Eigen/Core155
-rw-r--r--extern/Eigen2/Eigen/Dense (renamed from extern/Eigen3/Eigen/Dense)3
-rw-r--r--extern/Eigen2/Eigen/Eigen2
-rw-r--r--extern/Eigen2/Eigen/Geometry51
-rw-r--r--extern/Eigen2/Eigen/LU (renamed from extern/Eigen3/Eigen/LU)19
-rw-r--r--extern/Eigen2/Eigen/LeastSquares27
-rw-r--r--extern/Eigen2/Eigen/NewStdVector (renamed from extern/Eigen3/Eigen/src/StlSupport/StdVector.h)127
-rw-r--r--extern/Eigen2/Eigen/QR73
-rw-r--r--extern/Eigen2/Eigen/QtAlignedMalloc29
-rw-r--r--extern/Eigen2/Eigen/SVD (renamed from extern/Eigen3/Eigen/SVD)19
-rw-r--r--extern/Eigen2/Eigen/Sparse132
-rw-r--r--extern/Eigen2/Eigen/StdVector147
-rw-r--r--extern/Eigen2/Eigen/src/Array/BooleanRedux.h (renamed from extern/Eigen3/Eigen/src/Core/BooleanRedux.h)80
-rw-r--r--extern/Eigen2/Eigen/src/Array/CwiseOperators.h453
-rw-r--r--extern/Eigen2/Eigen/src/Array/Functors.h309
-rw-r--r--extern/Eigen2/Eigen/src/Array/Norms.h80
-rw-r--r--extern/Eigen2/Eigen/src/Array/PartialRedux.h347
-rw-r--r--extern/Eigen2/Eigen/src/Array/Random.h (renamed from extern/Eigen3/Eigen/src/Core/Random.h)97
-rw-r--r--extern/Eigen2/Eigen/src/Array/Select.h (renamed from extern/Eigen3/Eigen/src/Core/Select.h)83
-rw-r--r--extern/Eigen2/Eigen/src/Cholesky/CholeskyInstantiations.cpp (renamed from extern/Eigen3/Eigen/src/Eigen2Support/Macros.h)22
-rw-r--r--extern/Eigen2/Eigen/src/Cholesky/LDLT.h198
-rw-r--r--extern/Eigen2/Eigen/src/Cholesky/LLT.h219
-rw-r--r--extern/Eigen2/Eigen/src/Core/Assign.h445
-rw-r--r--extern/Eigen2/Eigen/src/Core/Block.h752
-rw-r--r--extern/Eigen2/Eigen/src/Core/CacheFriendlyProduct.h753
-rw-r--r--extern/Eigen2/Eigen/src/Core/Coeffs.h384
-rw-r--r--extern/Eigen2/Eigen/src/Core/CommaInitializer.h (renamed from extern/Eigen3/Eigen/src/Core/CommaInitializer.h)70
-rw-r--r--extern/Eigen2/Eigen/src/Core/CoreInstantiations.cpp (renamed from extern/Eigen3/Eigen/StdList)34
-rw-r--r--extern/Eigen2/Eigen/src/Core/Cwise.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h)87
-rw-r--r--extern/Eigen2/Eigen/src/Core/CwiseBinaryOp.h304
-rw-r--r--extern/Eigen2/Eigen/src/Core/CwiseNullaryOp.h (renamed from extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h)374
-rw-r--r--extern/Eigen2/Eigen/src/Core/CwiseUnaryOp.h229
-rw-r--r--extern/Eigen2/Eigen/src/Core/DiagonalCoeffs.h124
-rw-r--r--extern/Eigen2/Eigen/src/Core/DiagonalMatrix.h144
-rw-r--r--extern/Eigen2/Eigen/src/Core/DiagonalProduct.h130
-rw-r--r--extern/Eigen2/Eigen/src/Core/Dot.h361
-rw-r--r--extern/Eigen2/Eigen/src/Core/Flagged.h (renamed from extern/Eigen3/Eigen/src/Core/Flagged.h)90
-rw-r--r--extern/Eigen2/Eigen/src/Core/Functors.h378
-rw-r--r--extern/Eigen2/Eigen/src/Core/Fuzzy.h234
-rw-r--r--extern/Eigen2/Eigen/src/Core/GenericPacketMath.h150
-rw-r--r--extern/Eigen2/Eigen/src/Core/IO.h (renamed from extern/Eigen3/Eigen/src/Core/IO.h)128
-rw-r--r--extern/Eigen2/Eigen/src/Core/Map.h111
-rw-r--r--extern/Eigen2/Eigen/src/Core/MapBase.h202
-rw-r--r--extern/Eigen2/Eigen/src/Core/MathFunctions.h295
-rw-r--r--extern/Eigen2/Eigen/src/Core/Matrix.h639
-rw-r--r--extern/Eigen2/Eigen/src/Core/MatrixBase.h632
-rw-r--r--extern/Eigen2/Eigen/src/Core/MatrixStorage.h249
-rw-r--r--extern/Eigen2/Eigen/src/Core/Minor.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/Minor.h)48
-rw-r--r--extern/Eigen2/Eigen/src/Core/NestByValue.h (renamed from extern/Eigen3/Eigen/src/Core/NestByValue.h)45
-rw-r--r--extern/Eigen2/Eigen/src/Core/NumTraits.h142
-rw-r--r--extern/Eigen2/Eigen/src/Core/Part.h377
-rw-r--r--extern/Eigen2/Eigen/src/Core/Product.h769
-rw-r--r--extern/Eigen2/Eigen/src/Core/Redux.h117
-rw-r--r--extern/Eigen2/Eigen/src/Core/SolveTriangular.h297
-rw-r--r--extern/Eigen2/Eigen/src/Core/Sum.h271
-rw-r--r--extern/Eigen2/Eigen/src/Core/Swap.h (renamed from extern/Eigen3/Eigen/src/Core/Swap.h)85
-rw-r--r--extern/Eigen2/Eigen/src/Core/Transpose.h228
-rw-r--r--extern/Eigen2/Eigen/src/Core/Visitor.h (renamed from extern/Eigen3/Eigen/src/Core/Visitor.h)114
-rw-r--r--extern/Eigen2/Eigen/src/Core/arch/AltiVec/PacketMath.h354
-rw-r--r--extern/Eigen2/Eigen/src/Core/arch/SSE/PacketMath.h321
-rw-r--r--extern/Eigen2/Eigen/src/Core/util/Constants.h254
-rw-r--r--extern/Eigen2/Eigen/src/Core/util/DisableMSVCWarnings.h5
-rw-r--r--extern/Eigen2/Eigen/src/Core/util/EnableMSVCWarnings.h4
-rw-r--r--extern/Eigen2/Eigen/src/Core/util/ForwardDeclarations.h125
-rw-r--r--extern/Eigen2/Eigen/src/Core/util/Macros.h273
-rw-r--r--extern/Eigen2/Eigen/src/Core/util/Memory.h387
-rw-r--r--extern/Eigen2/Eigen/src/Core/util/Meta.h183
-rw-r--r--extern/Eigen2/Eigen/src/Core/util/StaticAssert.h (renamed from extern/Eigen3/Eigen/src/Core/util/StaticAssert.h)90
-rw-r--r--extern/Eigen2/Eigen/src/Core/util/XprHelper.h219
-rw-r--r--extern/Eigen2/Eigen/src/Geometry/AlignedBox.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h)35
-rw-r--r--extern/Eigen2/Eigen/src/Geometry/AngleAxis.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AngleAxis.h)10
-rw-r--r--extern/Eigen2/Eigen/src/Geometry/EulerAngles.h (renamed from extern/Eigen3/Eigen/src/Geometry/EulerAngles.h)34
-rw-r--r--extern/Eigen2/Eigen/src/Geometry/Hyperplane.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h)29
-rw-r--r--extern/Eigen2/Eigen/src/Geometry/OrthoMethods.h119
-rw-r--r--extern/Eigen2/Eigen/src/Geometry/ParametrizedLine.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h)18
-rw-r--r--extern/Eigen2/Eigen/src/Geometry/Quaternion.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h)77
-rw-r--r--extern/Eigen2/Eigen/src/Geometry/Rotation2D.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h)10
-rw-r--r--extern/Eigen2/Eigen/src/Geometry/RotationBase.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h)5
-rw-r--r--extern/Eigen2/Eigen/src/Geometry/Scaling.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h)10
-rw-r--r--extern/Eigen2/Eigen/src/Geometry/Transform.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h)67
-rw-r--r--extern/Eigen2/Eigen/src/Geometry/Translation.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h)10
-rw-r--r--extern/Eigen2/Eigen/src/LU/Determinant.h (renamed from extern/Eigen3/Eigen/src/LU/Determinant.h)76
-rw-r--r--extern/Eigen2/Eigen/src/LU/Inverse.h258
-rw-r--r--extern/Eigen2/Eigen/src/LU/LU.h541
-rw-r--r--extern/Eigen2/Eigen/src/LeastSquares/LeastSquares.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h)6
-rw-r--r--extern/Eigen2/Eigen/src/QR/EigenSolver.h722
-rw-r--r--extern/Eigen2/Eigen/src/QR/HessenbergDecomposition.h250
-rw-r--r--extern/Eigen2/Eigen/src/QR/QR.h334
-rw-r--r--extern/Eigen2/Eigen/src/QR/QrInstantiations.cpp (renamed from extern/Eigen3/Eigen/StdVector)31
-rw-r--r--extern/Eigen2/Eigen/src/QR/SelfAdjointEigenSolver.h402
-rw-r--r--extern/Eigen2/Eigen/src/QR/Tridiagonalization.h431
-rw-r--r--extern/Eigen2/Eigen/src/SVD/SVD.h (renamed from extern/Eigen3/Eigen/src/Eigen2Support/SVD.h)49
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/AmbiVector.h (renamed from extern/Eigen3/Eigen/src/Sparse/AmbiVector.h)136
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/CholmodSupport.h236
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/CompressedStorage.h (renamed from extern/Eigen3/Eigen/src/Sparse/CompressedStorage.h)65
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/CoreIterators.h (renamed from extern/Eigen3/Eigen/src/Sparse/CoreIterators.h)25
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/DynamicSparseMatrix.h (renamed from extern/Eigen3/Eigen/src/Sparse/DynamicSparseMatrix.h)235
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/MappedSparseMatrix.h (renamed from extern/Eigen3/Eigen/src/Sparse/MappedSparseMatrix.h)118
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/RandomSetter.h330
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseAssign.h (renamed from extern/Eigen3/Eigen/src/Sparse/SparseAssign.h)0
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseBlock.h (renamed from extern/Eigen3/Eigen/src/Sparse/SparseBlock.h)359
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseCwise.h178
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseCwiseBinaryOp.h453
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseCwiseUnaryOp.h186
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseDiagonalProduct.h159
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseDot.h (renamed from extern/Eigen3/Eigen/src/Sparse/SparseDot.h)36
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseFlagged.h102
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseFuzzy.h (renamed from extern/Eigen3/Eigen/src/Sparse/SparseFuzzy.h)10
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseLDLT.h346
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseLLT.h205
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseLU.h148
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseMatrix.h452
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseMatrixBase.h (renamed from extern/Eigen3/Eigen/src/Sparse/SparseMatrixBase.h)428
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseProduct.h415
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseRedux.h (renamed from extern/Eigen3/Eigen/StdDeque)38
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseTranspose.h90
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseUtil.h148
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SparseVector.h (renamed from extern/Eigen3/Eigen/src/Sparse/SparseVector.h)263
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/SuperLUSupport.h565
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/TaucsSupport.h210
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/TriangularSolver.h178
-rw-r--r--extern/Eigen2/Eigen/src/Sparse/UmfPackSupport.h289
-rwxr-xr-xextern/Eigen2/eigen-update.sh (renamed from extern/Eigen3/eigen-update.sh)14
-rw-r--r--extern/Eigen3/Eigen/Array11
-rw-r--r--extern/Eigen3/Eigen/Cholesky33
-rw-r--r--extern/Eigen3/Eigen/Core360
-rw-r--r--extern/Eigen3/Eigen/Eigen2
-rw-r--r--extern/Eigen3/Eigen/Eigen2Support82
-rw-r--r--extern/Eigen3/Eigen/Eigenvalues44
-rw-r--r--extern/Eigen3/Eigen/Geometry67
-rw-r--r--extern/Eigen3/Eigen/Householder27
-rw-r--r--extern/Eigen3/Eigen/Jacobi30
-rw-r--r--extern/Eigen3/Eigen/LeastSquares36
-rw-r--r--extern/Eigen3/Eigen/QR45
-rw-r--r--extern/Eigen3/Eigen/QtAlignedMalloc34
-rw-r--r--extern/Eigen3/Eigen/Sparse69
-rw-r--r--extern/Eigen3/Eigen/src/Cholesky/LDLT.h484
-rw-r--r--extern/Eigen3/Eigen/src/Cholesky/LLT.h386
-rw-r--r--extern/Eigen3/Eigen/src/Core/Array.h322
-rw-r--r--extern/Eigen3/Eigen/src/Core/ArrayBase.h239
-rw-r--r--extern/Eigen3/Eigen/src/Core/ArrayWrapper.h239
-rw-r--r--extern/Eigen3/Eigen/src/Core/Assign.h593
-rw-r--r--extern/Eigen3/Eigen/src/Core/BandMatrix.h346
-rw-r--r--extern/Eigen3/Eigen/src/Core/Block.h349
-rw-r--r--extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h240
-rw-r--r--extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h137
-rw-r--r--extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h148
-rw-r--r--extern/Eigen3/Eigen/src/Core/DenseBase.h543
-rw-r--r--extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h765
-rw-r--r--extern/Eigen3/Eigen/src/Core/DenseStorage.h304
-rw-r--r--extern/Eigen3/Eigen/src/Core/Diagonal.h227
-rw-r--r--extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h306
-rw-r--r--extern/Eigen3/Eigen/src/Core/DiagonalProduct.h135
-rw-r--r--extern/Eigen3/Eigen/src/Core/Dot.h272
-rw-r--r--extern/Eigen3/Eigen/src/Core/EigenBase.h172
-rw-r--r--extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h157
-rw-r--r--extern/Eigen3/Eigen/src/Core/Functors.h942
-rw-r--r--extern/Eigen3/Eigen/src/Core/Fuzzy.h161
-rw-r--r--extern/Eigen3/Eigen/src/Core/GenericPacketMath.h339
-rw-r--r--extern/Eigen3/Eigen/src/Core/GlobalFunctions.h95
-rw-r--r--extern/Eigen3/Eigen/src/Core/Map.h205
-rw-r--r--extern/Eigen3/Eigen/src/Core/MapBase.h255
-rw-r--r--extern/Eigen3/Eigen/src/Core/MathFunctions.h843
-rw-r--r--extern/Eigen3/Eigen/src/Core/Matrix.h439
-rw-r--r--extern/Eigen3/Eigen/src/Core/MatrixBase.h520
-rw-r--r--extern/Eigen3/Eigen/src/Core/NoAlias.h136
-rw-r--r--extern/Eigen3/Eigen/src/Core/NumTraits.h160
-rw-r--r--extern/Eigen3/Eigen/src/Core/PermutationMatrix.h696
-rw-r--r--extern/Eigen3/Eigen/src/Core/PlainObjectBase.h737
-rw-r--r--extern/Eigen3/Eigen/src/Core/Product.h625
-rw-r--r--extern/Eigen3/Eigen/src/Core/ProductBase.h288
-rw-r--r--extern/Eigen3/Eigen/src/Core/Redux.h404
-rw-r--r--extern/Eigen3/Eigen/src/Core/Replicate.h179
-rw-r--r--extern/Eigen3/Eigen/src/Core/ReturnByValue.h99
-rw-r--r--extern/Eigen3/Eigen/src/Core/Reverse.h230
-rw-r--r--extern/Eigen3/Eigen/src/Core/SelfAdjointView.h325
-rw-r--r--extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h195
-rw-r--r--extern/Eigen3/Eigen/src/Core/SolveTriangular.h263
-rw-r--r--extern/Eigen3/Eigen/src/Core/StableNorm.h190
-rw-r--r--extern/Eigen3/Eigen/src/Core/Stride.h119
-rw-r--r--extern/Eigen3/Eigen/src/Core/Transpose.h425
-rw-r--r--extern/Eigen3/Eigen/src/Core/Transpositions.h447
-rw-r--r--extern/Eigen3/Eigen/src/Core/TriangularMatrix.h838
-rw-r--r--extern/Eigen3/Eigen/src/Core/VectorBlock.h296
-rw-r--r--extern/Eigen3/Eigen/src/Core/VectorwiseOp.h557
-rw-r--r--extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h228
-rw-r--r--extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h509
-rw-r--r--extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h64
-rw-r--r--extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h270
-rw-r--r--extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h420
-rw-r--r--extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h447
-rw-r--r--extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h395
-rw-r--r--extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h634
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h452
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h1285
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h439
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h225
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h559
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/Parallelizer.h154
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h427
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h278
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h136
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h104
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h403
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h325
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h319
-rw-r--r--extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h150
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/BlasUtil.h271
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/Constants.h439
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h42
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h307
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/Macros.h418
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/Memory.h911
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/Meta.h229
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/ReenableStupidWarnings.h14
-rw-r--r--extern/Eigen3/Eigen/src/Core/util/XprHelper.h460
-rw-r--r--extern/Eigen3/Eigen/src/Eigen2Support/Block.h137
-rw-r--r--extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h309
-rw-r--r--extern/Eigen3/Eigen/src/Eigen2Support/Geometry/All.h115
-rw-r--r--extern/Eigen3/Eigen/src/Eigen2Support/LU.h133
-rw-r--r--extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h82
-rw-r--r--extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h68
-rw-r--r--extern/Eigen3/Eigen/src/Eigen2Support/Memory.h58
-rw-r--r--extern/Eigen3/Eigen/src/Eigen2Support/Meta.h86
-rw-r--r--extern/Eigen3/Eigen/src/Eigen2Support/QR.h79
-rw-r--r--extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h53
-rw-r--r--extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h105
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h332
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h448
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h588
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/EigenvaluesCommon.h31
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h239
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h384
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h170
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h474
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h520
-rw-r--r--extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h568
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/AlignedBox.h352
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/AngleAxis.h241
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Homogeneous.h318
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Hyperplane.h280
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h229
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h168
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Quaternion.h751
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Rotation2D.h165
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/RotationBase.h217
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Scaling.h182
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Transform.h1396
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Translation.h215
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/Umeyama.h183
-rw-r--r--extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h126
-rw-r--r--extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h79
-rw-r--r--extern/Eigen3/Eigen/src/Householder/Householder.h133
-rw-r--r--extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h429
-rw-r--r--extern/Eigen3/Eigen/src/Jacobi/Jacobi.h430
-rw-r--r--extern/Eigen3/Eigen/src/LU/FullPivLU.h754
-rw-r--r--extern/Eigen3/Eigen/src/LU/Inverse.h407
-rw-r--r--extern/Eigen3/Eigen/src/LU/PartialPivLU.h509
-rw-r--r--extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h340
-rw-r--r--extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h532
-rw-r--r--extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h546
-rw-r--r--extern/Eigen3/Eigen/src/QR/HouseholderQR.h355
-rw-r--r--extern/Eigen3/Eigen/src/SVD/JacobiSVD.h716
-rw-r--r--extern/Eigen3/Eigen/src/SVD/UpperBidiagonalization.h159
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/SparseCwiseBinaryOp.h375
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/SparseCwiseUnaryOp.h146
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/SparseDenseProduct.h231
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/SparseDiagonalProduct.h195
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/SparseMatrix.h651
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/SparseProduct.h141
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/SparseRedux.h56
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/SparseSelfAdjointView.h454
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/SparseSparseProduct.h401
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/SparseTranspose.h68
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/SparseTriangularView.h100
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/SparseUtil.h130
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/SparseView.h109
-rw-r--r--extern/Eigen3/Eigen/src/Sparse/TriangularSolver.h339
-rw-r--r--extern/Eigen3/Eigen/src/StlSupport/StdDeque.h149
-rw-r--r--extern/Eigen3/Eigen/src/StlSupport/StdList.h129
-rw-r--r--extern/Eigen3/Eigen/src/StlSupport/details.h99
-rw-r--r--extern/Eigen3/Eigen/src/misc/Image.h95
-rw-r--r--extern/Eigen3/Eigen/src/misc/Kernel.h92
-rw-r--r--extern/Eigen3/Eigen/src/misc/Solve.h87
-rw-r--r--extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h143
-rw-r--r--extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h202
-rw-r--r--extern/Eigen3/Eigen/src/plugins/BlockMethods.h595
-rw-r--r--extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h61
-rw-r--r--extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h187
-rw-r--r--extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h120
-rw-r--r--extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h82
-rw-r--r--extern/SConscript1
-rw-r--r--extern/bullet2/src/LinearMath/btScalar.h2
-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/glew/CMakeLists.txt1
-rw-r--r--extern/lzma/CMakeLists.txt1
-rw-r--r--extern/lzo/CMakeLists.txt1
-rw-r--r--extern/recastnavigation/recast-capi.cpp1
-rw-r--r--extern/recastnavigation/recast-capi.h1
-rw-r--r--intern/audaspace/CMakeLists.txt1
-rw-r--r--intern/ffmpeg/ffmpeg_compat.h3
-rw-r--r--intern/ghost/GHOST_ISystem.h2
-rw-r--r--intern/ghost/intern/GHOST_System.cpp9
-rw-r--r--intern/ghost/intern/GHOST_System.h4
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm4
-rw-r--r--intern/itasc/Armature.cpp1
-rw-r--r--intern/itasc/Armature.hpp1
-rw-r--r--intern/itasc/CMakeLists.txt315
-rw-r--r--intern/itasc/Cache.cpp1
-rw-r--r--intern/itasc/Cache.hpp1
-rw-r--r--intern/itasc/ConstraintSet.cpp7
-rw-r--r--intern/itasc/ConstraintSet.hpp1
-rw-r--r--intern/itasc/ControlledObject.cpp3
-rw-r--r--intern/itasc/ControlledObject.hpp1
-rw-r--r--intern/itasc/CopyPose.cpp3
-rw-r--r--intern/itasc/CopyPose.hpp1
-rw-r--r--intern/itasc/Distance.cpp1
-rw-r--r--intern/itasc/Distance.hpp1
-rw-r--r--intern/itasc/FixedObject.cpp1
-rw-r--r--intern/itasc/FixedObject.hpp1
-rw-r--r--intern/itasc/MovingFrame.cpp1
-rw-r--r--intern/itasc/MovingFrame.hpp1
-rw-r--r--intern/itasc/Object.hpp1
-rw-r--r--intern/itasc/SConscript9
-rw-r--r--intern/itasc/Scene.cpp19
-rw-r--r--intern/itasc/Scene.hpp1
-rw-r--r--intern/itasc/Solver.hpp1
-rw-r--r--intern/itasc/UncontrolledObject.cpp1
-rw-r--r--intern/itasc/UncontrolledObject.hpp1
-rw-r--r--intern/itasc/WDLSSolver.cpp7
-rw-r--r--intern/itasc/WDLSSolver.hpp1
-rw-r--r--intern/itasc/WSDLSSolver.cpp9
-rw-r--r--intern/itasc/WSDLSSolver.hpp1
-rw-r--r--intern/itasc/WorldObject.cpp1
-rw-r--r--intern/itasc/WorldObject.hpp1
-rw-r--r--intern/itasc/eigen_types.cpp1
-rw-r--r--intern/itasc/eigen_types.hpp1
-rw-r--r--intern/itasc/kdl/frameacc.inl1
-rw-r--r--intern/itasc/kdl/framevel.inl1
-rw-r--r--intern/itasc/kdl/inertia.cpp2
-rw-r--r--intern/itasc/kdl/inertia.hpp2
-rw-r--r--intern/itasc/kdl/utilities/svd_eigen_HH.hpp2
-rw-r--r--intern/memutil/MEM_CacheLimiter.h38
-rw-r--r--intern/memutil/MEM_CacheLimiterC-Api.h6
-rw-r--r--intern/memutil/intern/MEM_CacheLimiterC-Api.cpp10
-rw-r--r--intern/moto/CMakeLists.txt10
-rw-r--r--intern/opennl/CMakeLists.txt3
-rw-r--r--intern/opennl/SConscript2
-rw-r--r--intern/opennl/extern/ONL_opennl.h2
-rw-r--r--intern/opennl/intern/opennl.c1
-rw-r--r--intern/opennl/superlu/colamd.c2586
-rw-r--r--intern/opennl/superlu/colamd.h70
-rw-r--r--intern/opennl/superlu/get_perm_c.c3
-rw-r--r--intern/smoke/CMakeLists.txt1
-rwxr-xr-xpo/check_po.py1
-rwxr-xr-xpo/clean_po.py1
-rwxr-xr-xpo/merge_po.py1
-rwxr-xr-xpo/update_mo.py1
-rw-r--r--po/update_msg.py1
-rwxr-xr-xpo/update_po.py1
-rwxr-xr-xpo/update_pot.py1
-rwxr-xr-xrelease/bin/blender-softwaregl22
-rw-r--r--release/datafiles/LICENSE-bfont.ttf.txt1
-rw-r--r--release/plugins/Makefile3
-rw-r--r--release/plugins/bmake2
-rw-r--r--release/plugins/sequence/Makefile32
-rw-r--r--release/plugins/sequence/blur.c1
-rw-r--r--release/plugins/sequence/scatter.c1
-rw-r--r--release/plugins/texture/Makefile3
-rw-r--r--release/plugins/texture/clouds2.c1
-rw-r--r--release/plugins/texture/tiles.c1
-rw-r--r--release/scripts/modules/bpy_types.py29
-rw-r--r--release/scripts/presets/keyconfig/maya.py4
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_smart_project.py4
-rw-r--r--release/scripts/startup/bl_operators/vertexpaint_dirt.py2
-rw-r--r--release/scripts/startup/bl_operators/wm.py34
-rw-r--r--release/scripts/startup/bl_ui/__init__.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py16
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py4
-rw-r--r--release/scripts/startup/bl_ui/space_info.py2
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py8
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py13
-rw-r--r--release/text/readme.html2
-rw-r--r--release/windows/installer/00.sconsblender.nsi1
-rw-r--r--source/blender/CMakeLists.txt1
-rw-r--r--source/blender/SConscript1
-rw-r--r--source/blender/blenfont/intern/blf_lang.c1
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h177
-rw-r--r--source/blender/blenkernel/BKE_blender.h1
-rw-r--r--source/blender/blenkernel/BKE_bmesh.h1
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h56
-rw-r--r--source/blender/blenkernel/BKE_customdata.h54
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h6
-rw-r--r--source/blender/blenkernel/BKE_image.h4
-rw-r--r--source/blender/blenkernel/BKE_key.h2
-rw-r--r--source/blender/blenkernel/BKE_library.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h62
-rw-r--r--source/blender/blenkernel/BKE_modifier.h7
-rw-r--r--source/blender/blenkernel/BKE_multires.h8
-rw-r--r--source/blender/blenkernel/BKE_paint.h2
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h2
-rw-r--r--source/blender/blenkernel/BKE_subsurf.h8
-rw-r--r--source/blender/blenkernel/BKE_tessmesh.h71
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h8
-rw-r--r--source/blender/blenkernel/CMakeLists.txt13
-rw-r--r--source/blender/blenkernel/SConscript1
-rw-r--r--source/blender/blenkernel/intern/BME_Customdata.c6
-rw-r--r--source/blender/blenkernel/intern/BME_conversions.c17
-rw-r--r--source/blender/blenkernel/intern/BME_eulers.c108
-rw-r--r--source/blender/blenkernel/intern/BME_mesh.c42
-rw-r--r--source/blender/blenkernel/intern/BME_structure.c69
-rw-r--r--source/blender/blenkernel/intern/BME_tools.c114
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c1673
-rw-r--r--source/blender/blenkernel/intern/action.c11
-rw-r--r--source/blender/blenkernel/intern/anim.c29
-rw-r--r--source/blender/blenkernel/intern/armature.c8
-rw-r--r--source/blender/blenkernel/intern/blender.c21
-rw-r--r--source/blender/blenkernel/intern/brush.c12
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c96
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c873
-rw-r--r--source/blender/blenkernel/intern/cloth.c11
-rw-r--r--source/blender/blenkernel/intern/collision.c1
-rw-r--r--source/blender/blenkernel/intern/constraint.c8
-rw-r--r--source/blender/blenkernel/intern/curve.c11
-rw-r--r--source/blender/blenkernel/intern/customdata.c583
-rw-r--r--source/blender/blenkernel/intern/deform.c9
-rw-r--r--source/blender/blenkernel/intern/displist.c6
-rw-r--r--source/blender/blenkernel/intern/editderivedbmesh.c1639
-rw-r--r--source/blender/blenkernel/intern/effect.c2
-rw-r--r--source/blender/blenkernel/intern/fcurve.c54
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c4
-rw-r--r--source/blender/blenkernel/intern/image.c130
-rw-r--r--source/blender/blenkernel/intern/key.c71
-rw-r--r--source/blender/blenkernel/intern/lattice.c8
-rw-r--r--source/blender/blenkernel/intern/library.c36
-rw-r--r--source/blender/blenkernel/intern/material.c20
-rw-r--r--source/blender/blenkernel/intern/mball.c9
-rw-r--r--source/blender/blenkernel/intern/mesh.c1067
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c119
-rw-r--r--source/blender/blenkernel/intern/modifiers_bmesh.c220
-rw-r--r--source/blender/blenkernel/intern/multires.c393
-rw-r--r--source/blender/blenkernel/intern/node.c9
-rw-r--r--source/blender/blenkernel/intern/object.c67
-rw-r--r--source/blender/blenkernel/intern/particle.c55
-rw-r--r--source/blender/blenkernel/intern/particle_system.c30
-rw-r--r--source/blender/blenkernel/intern/seqcache.c170
-rw-r--r--source/blender/blenkernel/intern/sequencer.c10
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c12
-rw-r--r--source/blender/blenkernel/intern/smoke.c16
-rw-r--r--source/blender/blenkernel/intern/speaker.c8
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c1083
-rw-r--r--source/blender/blenkernel/intern/texture.c22
-rw-r--r--source/blender/blenkernel/intern/world.c8
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c34
-rw-r--r--source/blender/blenlib/BLI_array.h162
-rw-r--r--source/blender/blenlib/BLI_bpath.h8
-rw-r--r--source/blender/blenlib/BLI_cellalloc.h57
-rw-r--r--source/blender/blenlib/BLI_edgehash.h106
-rw-r--r--source/blender/blenlib/BLI_editVert.h3
-rw-r--r--source/blender/blenlib/BLI_math_color.h6
-rw-r--r--source/blender/blenlib/BLI_math_geom.h5
-rw-r--r--source/blender/blenlib/BLI_math_vector.h5
-rw-r--r--source/blender/blenlib/BLI_mempool.h120
-rw-r--r--source/blender/blenlib/BLI_scanfill.h2
-rwxr-xr-xsource/blender/blenlib/BLI_smallhash.h73
-rwxr-xr-xsource/blender/blenlib/BLI_sparsemap.h73
-rw-r--r--source/blender/blenlib/BLI_threads.h1
-rw-r--r--source/blender/blenlib/BLI_utildefines.h2
-rw-r--r--source/blender/blenlib/CMakeLists.txt6
-rw-r--r--source/blender/blenlib/SConscript2
-rw-r--r--source/blender/blenlib/intern/BLI_cellalloc.c203
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c6
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c130
-rw-r--r--source/blender/blenlib/intern/bpath.c57
-rw-r--r--source/blender/blenlib/intern/edgehash.c126
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c4
-rw-r--r--source/blender/blenlib/intern/math_geom.c69
-rw-r--r--source/blender/blenlib/intern/math_vector.c14
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c35
-rw-r--r--source/blender/blenlib/intern/path_util.c3
-rw-r--r--source/blender/blenlib/intern/pbvh.c2
-rw-r--r--source/blender/blenlib/intern/scanfill.c137
-rw-r--r--source/blender/blenlib/intern/smallhash.c280
-rw-r--r--source/blender/blenlib/intern/string_utf8.c2
-rw-r--r--source/blender/blenlib/intern/threads.c5
-rw-r--r--source/blender/blenloader/SConscript2
-rw-r--r--source/blender/blenloader/intern/readfile.c104
-rw-r--r--source/blender/blenloader/intern/writefile.c3
-rw-r--r--source/blender/blenpluginapi/SConscript2
-rw-r--r--source/blender/bmesh/CMakeLists.txt137
-rw-r--r--source/blender/bmesh/SConscript40
-rw-r--r--source/blender/bmesh/bmesh.h327
-rw-r--r--source/blender/bmesh/bmesh_class.h166
-rw-r--r--source/blender/bmesh/bmesh_error.h43
-rw-r--r--source/blender/bmesh/bmesh_filters.h4
-rw-r--r--source/blender/bmesh/bmesh_iterators.h82
-rw-r--r--source/blender/bmesh/bmesh_marking.h54
-rw-r--r--source/blender/bmesh/bmesh_operator_api.h499
-rw-r--r--source/blender/bmesh/bmesh_operators.h95
-rw-r--r--source/blender/bmesh/bmesh_queries.h89
-rw-r--r--source/blender/bmesh/bmesh_walkers.h94
-rw-r--r--source/blender/bmesh/editmesh_tools.c (renamed from source/blender/editors/mesh/editmesh_tools.c)6699
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c674
-rw-r--r--source/blender/bmesh/intern/bmesh_eulers.c1208
-rw-r--r--source/blender/bmesh/intern/bmesh_filters.c5
-rw-r--r--source/blender/bmesh/intern/bmesh_inline.c44
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c950
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c464
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c729
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c412
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c729
-rw-r--r--source/blender/bmesh/intern/bmesh_newcore.c1805
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c1108
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c1383
-rw-r--r--source/blender/bmesh/intern/bmesh_operators_private.h79
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c968
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h98
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c540
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.c1029
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h103
-rw-r--r--source/blender/bmesh/intern/bmesh_to_editmesh.c318
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.c263
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_impl.c883
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_private.h87
-rw-r--r--source/blender/bmesh/intern/editmesh_to_bmesh.c476
-rw-r--r--source/blender/bmesh/intern/in-progress/BME_conversions.c478
-rw-r--r--source/blender/bmesh/operators/bevel.c825
-rw-r--r--source/blender/bmesh/operators/bmesh_dupeops.c618
-rw-r--r--source/blender/bmesh/operators/connectops.c398
-rw-r--r--source/blender/bmesh/operators/createops.c1257
-rw-r--r--source/blender/bmesh/operators/dissolveops.c374
-rw-r--r--source/blender/bmesh/operators/edgesplitop.c447
-rw-r--r--source/blender/bmesh/operators/extrudeops.c577
-rw-r--r--source/blender/bmesh/operators/join_triangles.c358
-rw-r--r--source/blender/bmesh/operators/mesh_conv.c873
-rw-r--r--source/blender/bmesh/operators/mirror.c127
-rw-r--r--source/blender/bmesh/operators/primitiveops.c687
-rw-r--r--source/blender/bmesh/operators/removedoubles.c561
-rw-r--r--source/blender/bmesh/operators/subdivideop.c1183
-rw-r--r--source/blender/bmesh/operators/subdivideop.h41
-rw-r--r--source/blender/bmesh/operators/triangulateop.c194
-rw-r--r--source/blender/bmesh/operators/utils.c1292
-rw-r--r--source/blender/bmesh/tools/BME_bevel.c918
-rw-r--r--source/blender/bmesh/tools/BME_dupe_ops.c318
-rw-r--r--source/blender/bmesh/tools/BME_duplicate.c307
-rw-r--r--source/blender/bmesh/tools/BME_extrude.c216
-rw-r--r--source/blender/bmesh/tools/BME_weld.c333
-rw-r--r--source/blender/editors/animation/SConscript2
-rw-r--r--source/blender/editors/animation/keyingsets.c8
-rw-r--r--source/blender/editors/armature/SConscript1
-rw-r--r--source/blender/editors/armature/editarmature.c9
-rw-r--r--source/blender/editors/armature/meshlaplacian.c14
-rw-r--r--source/blender/editors/armature/reeb.c13
-rw-r--r--source/blender/editors/curve/SConscript2
-rw-r--r--source/blender/editors/curve/editcurve.c11
-rw-r--r--source/blender/editors/curve/editfont.c4
-rw-r--r--source/blender/editors/datafiles/SConscript2
-rw-r--r--source/blender/editors/gpencil/SConscript2
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c1
-rw-r--r--source/blender/editors/include/ED_mesh.h251
-rw-r--r--source/blender/editors/include/ED_object.h7
-rwxr-xr-xsource/blender/editors/include/ED_toolmode.h80
-rw-r--r--source/blender/editors/include/ED_util.h8
-rw-r--r--source/blender/editors/include/ED_uvedit.h25
-rw-r--r--source/blender/editors/include/ED_view3d.h20
-rw-r--r--source/blender/editors/interface/SConscript2
-rw-r--r--source/blender/editors/interface/interface_handlers.c42
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt22
-rw-r--r--source/blender/editors/mesh/SConscript1
-rw-r--r--source/blender/editors/mesh/bmesh_select.c2678
-rw-r--r--source/blender/editors/mesh/bmesh_selecthistory.c126
-rw-r--r--source/blender/editors/mesh/bmesh_tools.c4845
-rw-r--r--source/blender/editors/mesh/bmeshutils.c875
-rw-r--r--source/blender/editors/mesh/editbmesh_add.c647
-rw-r--r--source/blender/editors/mesh/editbmesh_bvh.c781
-rw-r--r--source/blender/editors/mesh/editbmesh_bvh.h38
-rw-r--r--source/blender/editors/mesh/editface.c656
-rw-r--r--source/blender/editors/mesh/editmesh.c2056
-rw-r--r--source/blender/editors/mesh/editmesh_add.c1790
-rw-r--r--source/blender/editors/mesh/editmesh_lib.c2855
-rw-r--r--source/blender/editors/mesh/editmesh_loop.c738
-rw-r--r--source/blender/editors/mesh/editmesh_mods.c4496
-rwxr-xr-xsource/blender/editors/mesh/knifetool.c1989
-rw-r--r--source/blender/editors/mesh/loopcut.c375
-rw-r--r--source/blender/editors/mesh/mesh_data.c286
-rw-r--r--source/blender/editors/mesh/mesh_intern.h121
-rw-r--r--source/blender/editors/mesh/mesh_ops.c46
-rw-r--r--source/blender/editors/mesh/meshtools.c225
-rw-r--r--source/blender/editors/metaball/mball_edit.c4
-rw-r--r--source/blender/editors/object/CMakeLists.txt1
-rw-r--r--source/blender/editors/object/SConscript2
-rw-r--r--source/blender/editors/object/object_add.c34
-rw-r--r--source/blender/editors/object/object_bake.c46
-rw-r--r--source/blender/editors/object/object_edit.c17
-rw-r--r--source/blender/editors/object/object_hook.c55
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_lattice.c4
-rw-r--r--source/blender/editors/object/object_modifier.c107
-rw-r--r--source/blender/editors/object/object_ops.c3
-rw-r--r--source/blender/editors/object/object_relations.c24
-rw-r--r--source/blender/editors/object/object_shapekey.c6
-rw-r--r--source/blender/editors/object/object_transform.c57
-rw-r--r--source/blender/editors/object/object_vgroup.c181
-rw-r--r--source/blender/editors/physics/SConscript2
-rw-r--r--source/blender/editors/physics/particle_edit.c23
-rw-r--r--source/blender/editors/physics/particle_object.c4
-rw-r--r--source/blender/editors/render/CMakeLists.txt1
-rw-r--r--source/blender/editors/render/SConscript2
-rw-r--r--source/blender/editors/render/render_internal.c64
-rw-r--r--source/blender/editors/render/render_shading.c18
-rw-r--r--source/blender/editors/screen/CMakeLists.txt1
-rw-r--r--source/blender/editors/screen/SConscript2
-rw-r--r--source/blender/editors/screen/screen_ops.c16
-rw-r--r--source/blender/editors/sculpt_paint/SConscript2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c42
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c8
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c373
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c36
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c4
-rw-r--r--source/blender/editors/space_action/action_edit.c2
-rw-r--r--source/blender/editors/space_api/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_api/SConscript2
-rw-r--r--source/blender/editors/space_api/spacetypes.c2
-rw-r--r--source/blender/editors/space_buttons/SConscript2
-rw-r--r--source/blender/editors/space_image/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_image/SConscript2
-rw-r--r--source/blender/editors/space_image/space_image.c20
-rw-r--r--source/blender/editors/space_info/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_info/SConscript2
-rw-r--r--source/blender/editors/space_info/info_stats.c27
-rw-r--r--source/blender/editors/space_node/SConscript2
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c14
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c4
-rw-r--r--source/blender/editors/space_text/text_ops.c2
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_view3d/SConscript2
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c75
-rw-r--r--source/blender/editors/space_view3d/drawobject.c657
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c1
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c157
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c45
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c22
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c183
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c114
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c4
-rw-r--r--source/blender/editors/transform/CMakeLists.txt1
-rw-r--r--source/blender/editors/transform/SConscript2
-rw-r--r--source/blender/editors/transform/transform.c989
-rw-r--r--source/blender/editors/transform/transform.h28
-rw-r--r--source/blender/editors/transform/transform_conversions.c556
-rw-r--r--source/blender/editors/transform/transform_generics.c26
-rw-r--r--source/blender/editors/transform/transform_manipulator.c88
-rw-r--r--source/blender/editors/transform/transform_orientations.c111
-rw-r--r--source/blender/editors/transform/transform_snap.c76
-rw-r--r--source/blender/editors/util/CMakeLists.txt2
-rw-r--r--source/blender/editors/util/SConscript2
-rw-r--r--source/blender/editors/util/crazyspace.c78
-rw-r--r--source/blender/editors/util/ed_util.c12
-rw-r--r--source/blender/editors/util/editmode_undo.c22
-rw-r--r--source/blender/editors/uvedit/CMakeLists.txt1
-rw-r--r--source/blender/editors/uvedit/SConscript2
-rw-r--r--source/blender/editors/uvedit/uvedit_buttons.c77
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c478
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h14
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c2188
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c4
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.h2
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c698
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c28
-rw-r--r--source/blender/ikplugin/CMakeLists.txt6
-rw-r--r--source/blender/ikplugin/SConscript5
-rw-r--r--source/blender/imbuf/CMakeLists.txt13
-rw-r--r--source/blender/imbuf/IMB_imbuf.h13
-rw-r--r--source/blender/imbuf/IMB_moviecache.h56
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c58
-rw-r--r--source/blender/imbuf/intern/indexer.c2
-rw-r--r--source/blender/imbuf/intern/module.c1
-rw-r--r--source/blender/imbuf/intern/moviecache.c382
-rw-r--r--source/blender/makesdna/DNA_ID.h8
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h28
-rw-r--r--source/blender/makesdna/DNA_key_types.h7
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h31
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h41
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h10
-rw-r--r--source/blender/makesdna/DNA_object_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h2
-rw-r--r--source/blender/makesdna/DNA_vec_types.h4
-rw-r--r--source/blender/makesdna/intern/SConscript2
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c1
-rw-r--r--source/blender/makesrna/RNA_access.h2
-rw-r--r--source/blender/makesrna/SConscript2
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt1
-rw-r--r--source/blender/makesrna/intern/SConscript2
-rw-r--r--source/blender/makesrna/intern/rna_ID.c8
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c2
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c839
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c17
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c25
-rw-r--r--source/blender/makesrna/intern/rna_object.c9
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_scene.c10
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c1
-rw-r--r--source/blender/modifiers/CMakeLists.txt4
-rw-r--r--source/blender/modifiers/MOD_modifiertypes.h1
-rw-r--r--source/blender/modifiers/SConscript2
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c8
-rw-r--r--source/blender/modifiers/intern/MOD_array.c692
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c9
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c4
-rw-r--r--source/blender/modifiers/intern/MOD_boolean_util.c38
-rw-r--r--source/blender/modifiers/intern/MOD_build.c131
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c2
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c6
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c4
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c22
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c5
-rw-r--r--source/blender/modifiers/intern/MOD_edgesplit.c1269
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c40
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim_util.c10
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c4
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c4
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c16
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c10
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c373
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c6
-rw-r--r--source/blender/modifiers/intern/MOD_ngoninterp.c330
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c16
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c6
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c16
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c4
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c2
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c2
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c2
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c348
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c4
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c4
-rw-r--r--source/blender/modifiers/intern/MOD_util.c13
-rw-r--r--source/blender/modifiers/intern/MOD_util.h4
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c6
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c4
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c6
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c4
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c4
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c8
-rw-r--r--source/blender/python/mathutils/mathutils.c2
-rw-r--r--source/blender/python/mathutils/mathutils.h2
-rw-r--r--source/blender/python/mathutils/mathutils_Color.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Color.h2
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.h2
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.h2
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.h2
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.h2
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c2
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.h2
-rw-r--r--source/blender/render/SConscript2
-rw-r--r--source/blender/render/intern/source/convertblender.c63
-rw-r--r--source/blender/render/intern/source/strand.c4
-rw-r--r--source/blender/windowmanager/SConscript2
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c1
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c5
-rw-r--r--source/blenderplayer/CMakeLists.txt4
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c19
-rw-r--r--source/creator/CMakeLists.txt2
-rw-r--r--source/creator/creator.c39
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.cpp29
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp10
-rw-r--r--source/gameengine/Converter/BL_SkinDeformer.cpp4
-rw-r--r--source/gameengine/Converter/CMakeLists.txt2
-rw-r--r--source/gameengine/Converter/SConscript2
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp36
-rw-r--r--source/gameengine/Ketsji/BL_Action.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_Dome.cpp8
-rw-r--r--source/gameengine/Ketsji/KX_Dome.h1
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp16
-rw-r--r--source/gameengine/VideoTexture/BlendType.h1
-rw-r--r--source/gameengine/VideoTexture/Common.h1
-rw-r--r--source/gameengine/VideoTexture/Exception.cpp7
-rw-r--r--source/gameengine/VideoTexture/Exception.h1
-rw-r--r--source/gameengine/VideoTexture/FilterBase.cpp9
-rw-r--r--source/gameengine/VideoTexture/FilterBase.h1
-rw-r--r--source/gameengine/VideoTexture/FilterBlueScreen.cpp7
-rw-r--r--source/gameengine/VideoTexture/FilterBlueScreen.h1
-rw-r--r--source/gameengine/VideoTexture/FilterColor.cpp7
-rw-r--r--source/gameengine/VideoTexture/FilterColor.h1
-rw-r--r--source/gameengine/VideoTexture/FilterNormal.cpp7
-rw-r--r--source/gameengine/VideoTexture/FilterNormal.h1
-rw-r--r--source/gameengine/VideoTexture/FilterSource.cpp8
-rw-r--r--source/gameengine/VideoTexture/FilterSource.h1
-rw-r--r--source/gameengine/VideoTexture/ImageBase.cpp8
-rw-r--r--source/gameengine/VideoTexture/ImageBase.h1
-rw-r--r--source/gameengine/VideoTexture/ImageBuff.cpp8
-rw-r--r--source/gameengine/VideoTexture/ImageBuff.h1
-rw-r--r--source/gameengine/VideoTexture/ImageMix.cpp9
-rw-r--r--source/gameengine/VideoTexture/ImageMix.h1
-rw-r--r--source/gameengine/VideoTexture/ImageRender.cpp8
-rw-r--r--source/gameengine/VideoTexture/ImageRender.h1
-rw-r--r--source/gameengine/VideoTexture/ImageViewport.cpp8
-rw-r--r--source/gameengine/VideoTexture/ImageViewport.h1
-rw-r--r--source/gameengine/VideoTexture/PyTypeList.cpp7
-rw-r--r--source/gameengine/VideoTexture/PyTypeList.h1
-rw-r--r--source/gameengine/VideoTexture/Texture.cpp8
-rw-r--r--source/gameengine/VideoTexture/Texture.h1
-rw-r--r--source/gameengine/VideoTexture/VideoBase.cpp8
-rw-r--r--source/gameengine/VideoTexture/VideoBase.h1
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.cpp9
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.h1
-rw-r--r--source/gameengine/VideoTexture/blendVideoTex.cpp8
-rw-r--r--source/tests/check_deprecated.py2
842 files changed, 85407 insertions, 83735 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7631b24f7cd..328db89b028 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -61,13 +61,6 @@ set(CMAKE_BUILD_TYPE_INIT "Release")
# quiet output for Makefiles, 'make -s' helps too
# set_property(GLOBAL PROPERTY RULE_MESSAGES OFF)
-# global compile definitions since add_definitions() adds for all.
-set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUG _DEBUG)
-set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE NDEBUG)
-set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL NDEBUG)
-set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO DEBUG _DEBUG)
-
-
#-----------------------------------------------------------------------------
# Set policy
@@ -129,7 +122,7 @@ option(WITH_BUILDINFO "Include extra build details (only disable for develop
option(WITH_IK_ITASC "Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)" ON)
option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke and audio effects)" OFF)
option(WITH_BULLET "Enable Bullet (Physics Engine)" ON)
-option(WITH_GAMEENGINE "Enable Game Engine" ON)
+option(WITH_GAMEENGINE "Enable Game Engine" OFF) # DISABLE FOR BMESH UNTIL NAVMESH IS WORKING
option(WITH_PLAYER "Build Player" OFF)
# GHOST Windowing Library Options
@@ -155,7 +148,7 @@ else()
endif()
if(UNIX AND NOT APPLE)
- option(WITH_X11_XINPUT "Enable X11 Xinput (tablet support and unicode input)" ON)
+ option(WITH_X11_XINPUT "Enable X11 Xinput (tablet support)" ON)
option(WITH_BUILTIN_GLEW "Use GLEW OpenGL wrapper library bundled with blender" ON)
else()
# not an option for other OS's
@@ -510,8 +503,8 @@ if(UNIX AND NOT APPLE)
set(PLATFORM_LINKFLAGS "-pthread")
- # lfs on glibc, all compilers should use
- add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE")
# GNU Compiler
if(CMAKE_COMPILER_IS_GNUCC)
@@ -619,21 +612,21 @@ elseif(WIN32)
set(CMAKE_C_FLAGS "/nologo /J /W0 /Gd /wd4018 /wd4244 /wd4305 /wd4800 /wd4065 /wd4267 /we4013 /EHsc" CACHE STRING "MSVC MT C++ flags " FORCE)
if(CMAKE_CL_64)
- set(CMAKE_CXX_FLAGS_DEBUG "/Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)
+ set(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)
else()
- set(CMAKE_CXX_FLAGS_DEBUG "/Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /ZI /J" CACHE STRING "MSVC MT flags " FORCE)
+ set(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /ZI /J" CACHE STRING "MSVC MT flags " FORCE)
endif()
- set(CMAKE_CXX_FLAGS_RELEASE "/O2 /Ob2 /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
- set(CMAKE_CXX_FLAGS_MINSIZEREL "/O1 /Ob1 /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
- set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/O2 /Ob1 /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)
+ set(CMAKE_CXX_FLAGS_RELEASE "/O2 /Ob2 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
+ set(CMAKE_CXX_FLAGS_MINSIZEREL "/O1 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/O2 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)
if(CMAKE_CL_64)
- set(CMAKE_C_FLAGS_DEBUG "/Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)
+ set(CMAKE_C_FLAGS_DEBUG "/D_DEBUG /Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)
else()
- set(CMAKE_C_FLAGS_DEBUG "/Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /ZI /J" CACHE STRING "MSVC MT flags " FORCE)
+ set(CMAKE_C_FLAGS_DEBUG "/D_DEBUG /Od /Gm /EHsc /RTC1 /MTd /W3 /nologo /ZI /J" CACHE STRING "MSVC MT flags " FORCE)
endif()
- set(CMAKE_C_FLAGS_RELEASE "/O2 /Ob2 /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
- set(CMAKE_C_FLAGS_MINSIZEREL "/O1 /Ob1 /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
- set(CMAKE_C_FLAGS_RELWITHDEBINFO "/O2 /Ob1 /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)
+ set(CMAKE_C_FLAGS_RELEASE "/O2 /Ob2 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
+ set(CMAKE_C_FLAGS_MINSIZEREL "/O1 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
+ set(CMAKE_C_FLAGS_RELWITHDEBINFO "/O2 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)
if(WITH_INTERNATIONAL)
set(GETTEXT ${LIBDIR}/gettext)
@@ -791,6 +784,9 @@ elseif(WIN32)
add_definitions(-DFREE_WINDOWS)
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
+
if(WITH_INTERNATIONAL)
set(GETTEXT ${LIBDIR}/gcc/gettext)
set(GETTEXT_INCLUDE_DIRS ${GETTEXT}/include)
@@ -1221,6 +1217,21 @@ endif()
#-----------------------------------------------------------------------------
# Extra compile flags
+if((NOT WIN32) AND (NOT MSVC))
+ # used for internal debug checks
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
+
+ # assert() checks for this.
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
+ set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -DNDEBUG")
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DNDEBUG")
+
+ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
+ set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -DNDEBUG")
+ set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DNDEBUG")
+endif()
+
if(CMAKE_COMPILER_IS_GNUCC)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ALL -Wall)
diff --git a/GNUmakefile b/GNUmakefile
index b06344ca238..c68c8684687 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -1,5 +1,6 @@
# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*-
-# vim: tabstop=4
+# vim: tabstop=8
+# $Id$
#
# ##### BEGIN GPL LICENSE BLOCK #####
#
diff --git a/SConstruct b/SConstruct
index 93787cdddce..aeaef581145 100644
--- a/SConstruct
+++ b/SConstruct
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-#
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
@@ -30,8 +30,6 @@
# Then read all SConscripts and build
#
# TODO: fix /FORCE:MULTIPLE on windows to get proper debug builds.
-# TODO: directory copy functions are far too complicated, see:
-# http://wiki.blender.org/index.php/User:Ideasman42/SConsNotSimpleInstallingFiles
import platform as pltfrm
diff --git a/build_files/cmake/cmake_consistency_check.py b/build_files/cmake/cmake_consistency_check.py
index b1fc88bfe26..880cb582f1e 100755
--- a/build_files/cmake/cmake_consistency_check.py
+++ b/build_files/cmake/cmake_consistency_check.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
@@ -74,7 +75,7 @@ def is_c_header(filename):
def is_c(filename):
ext = splitext(filename)[1]
- return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"))
+ return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc"))
def is_c_any(filename):
diff --git a/build_files/cmake/cmake_consistency_check_config.py b/build_files/cmake/cmake_consistency_check_config.py
index 86f51273ff5..7a80e34ff7f 100644
--- a/build_files/cmake/cmake_consistency_check_config.py
+++ b/build_files/cmake/cmake_consistency_check_config.py
@@ -44,7 +44,16 @@ IGNORE = (
"extern/eltopo/common/meshes/ObjLoader.hpp",
"extern/eltopo/common/meshes/TriangleIndex.hpp",
"extern/eltopo/common/meshes/meshloader.h",
- "extern/eltopo/eltopo3d/broadphase_blenderbvh.h"
+ "extern/eltopo/eltopo3d/broadphase_blenderbvh.h",
+
+ # for bmesh branch only
+ "source/blender/bmesh/editmesh_tools.c",
+ "source/blender/bmesh/intern/in-progress/BME_conversions.c",
+ "source/blender/bmesh/tools/BME_bevel.c",
+ "source/blender/bmesh/tools/BME_dupe_ops.c",
+ "source/blender/bmesh/tools/BME_duplicate.c",
+ "source/blender/bmesh/tools/BME_extrude.c",
+ "source/blender/bmesh/tools/BME_weld.c",
"extern/recastnavigation/Recast/Include/RecastLog.h",
"extern/recastnavigation/Recast/Include/RecastTimer.h",
"intern/audaspace/SRC/AUD_SRCResampleFactory.h",
diff --git a/build_files/cmake/cmake_netbeans_project.py b/build_files/cmake/cmake_netbeans_project.py
index 769b4adb37b..02dfec06c0b 100755
--- a/build_files/cmake/cmake_netbeans_project.py
+++ b/build_files/cmake/cmake_netbeans_project.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/build_files/cmake/cmake_qtcreator_project.py b/build_files/cmake/cmake_qtcreator_project.py
index fc5c00ec2ec..2a2774c9944 100755
--- a/build_files/cmake/cmake_qtcreator_project.py
+++ b/build_files/cmake/cmake_qtcreator_project.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/build_files/cmake/cmake_static_check_cppcheck.py b/build_files/cmake/cmake_static_check_cppcheck.py
index 8720cb83054..1c8d619a513 100644
--- a/build_files/cmake/cmake_static_check_cppcheck.py
+++ b/build_files/cmake/cmake_static_check_cppcheck.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/build_files/cmake/cmake_static_check_sparse.py b/build_files/cmake/cmake_static_check_sparse.py
index bd7629e4229..aa2d56e5509 100644
--- a/build_files/cmake/cmake_static_check_sparse.py
+++ b/build_files/cmake/cmake_static_check_sparse.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/build_files/cmake/cmake_static_check_splint.py b/build_files/cmake/cmake_static_check_splint.py
index edfefa3d068..08d83337426 100644
--- a/build_files/cmake/cmake_static_check_splint.py
+++ b/build_files/cmake/cmake_static_check_splint.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index bf90ef85eb0..d8db6883f18 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -16,7 +16,7 @@ macro(file_suffix
unset(_file_name_EXT)
endmacro()
-# useful for adding debug suffix to library lists:
+# usefil for adding debug suffix to library lists:
# /somepath/foo.lib --> /somepath/foo_d.lib
macro(file_list_suffix
fp_list_new fp_list fn_suffix
@@ -412,32 +412,6 @@ macro(remove_strict_flags)
endmacro()
-# note, we can only append flags on a single file so we need to negate the options.
-# at the moment we cant shut up ffmpeg deprecations, so use this, but will
-# probably add more removals here.
-macro(remove_strict_flags_file
- filenames)
-
- foreach(_SOURCE ${ARGV})
-
- if(CMAKE_COMPILER_IS_GNUCC)
- set_source_files_properties(${_SOURCE}
- PROPERTIES
- COMPILE_FLAGS "-Wno-deprecated-declarations"
- )
- endif()
-
- if(MSVC)
- # TODO
- endif()
-
- endforeach()
-
- unset(_SOURCE)
-
-endmacro()
-
-
macro(ADD_CHECK_C_COMPILER_FLAG
_CFLAGS
_CACHE_VAR
diff --git a/build_files/cmake/project_info.py b/build_files/cmake/project_info.py
index 8e813d39b64..db12884469b 100755
--- a/build_files/cmake/project_info.py
+++ b/build_files/cmake/project_info.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
@@ -104,7 +105,7 @@ def is_glsl(filename):
def is_c(filename):
ext = splitext(filename)[1]
- return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"))
+ return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc"))
def is_c_any(filename):
diff --git a/build_files/cmake/project_source_info.py b/build_files/cmake/project_source_info.py
index 5d646eea2c1..c636d778aaa 100644
--- a/build_files/cmake/project_source_info.py
+++ b/build_files/cmake/project_source_info.py
@@ -1,3 +1,4 @@
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
@@ -40,7 +41,7 @@ def is_c_header(filename):
def is_c(filename):
ext = os.path.splitext(filename)[1]
- return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"))
+ return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc"))
def is_c_any(filename):
diff --git a/doc/build_systems/cmake.txt b/doc/build_systems/cmake.txt
index b7a6bd9871e..d0e8a088ca7 100644
--- a/doc/build_systems/cmake.txt
+++ b/doc/build_systems/cmake.txt
@@ -1,3 +1,4 @@
+$Id$
Blender CMake build system
============================
diff --git a/doc/build_systems/scons-dev.txt b/doc/build_systems/scons-dev.txt
index b7cac8109d4..4cc4e6c6ec2 100644
--- a/doc/build_systems/scons-dev.txt
+++ b/doc/build_systems/scons-dev.txt
@@ -1,3 +1,5 @@
+$Id$
+
Internals of Blenders SCons scripts
===================================
diff --git a/doc/build_systems/scons.txt b/doc/build_systems/scons.txt
index d6ead8d32ae..9d018bcc790 100644
--- a/doc/build_systems/scons.txt
+++ b/doc/build_systems/scons.txt
@@ -1,3 +1,4 @@
+$Id$
Blenders SCons build scripts
============================
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 321ebc11985..c8429c0e77b 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -26,8 +26,6 @@
# Otherwise we get warnings here that we cant fix in external projects
remove_strict_flags()
-add_subdirectory(colamd)
-
if(WITH_BULLET)
add_subdirectory(bullet2)
endif()
diff --git a/extern/Eigen2/Eigen/Array b/extern/Eigen2/Eigen/Array
new file mode 100644
index 00000000000..c847f9521fe
--- /dev/null
+++ b/extern/Eigen2/Eigen/Array
@@ -0,0 +1,39 @@
+#ifndef EIGEN_ARRAY_MODULE_H
+#define EIGEN_ARRAY_MODULE_H
+
+#include "Core"
+
+#include "src/Core/util/DisableMSVCWarnings.h"
+
+namespace Eigen {
+
+/** \defgroup Array_Module Array module
+ * This module provides several handy features to manipulate matrices as simple array of values.
+ * In addition to listed classes, it defines various methods of the Cwise interface
+ * (accessible from MatrixBase::cwise()), including:
+ * - matrix-scalar sum,
+ * - coeff-wise comparison operators,
+ * - sin, cos, sqrt, pow, exp, log, square, cube, inverse (reciprocal).
+ *
+ * This module also provides various MatrixBase methods, including:
+ * - \ref MatrixBase::all() "all", \ref MatrixBase::any() "any",
+ * - \ref MatrixBase::Random() "random matrix initialization"
+ *
+ * \code
+ * #include <Eigen/Array>
+ * \endcode
+ */
+
+#include "src/Array/CwiseOperators.h"
+#include "src/Array/Functors.h"
+#include "src/Array/BooleanRedux.h"
+#include "src/Array/Select.h"
+#include "src/Array/PartialRedux.h"
+#include "src/Array/Random.h"
+#include "src/Array/Norms.h"
+
+} // namespace Eigen
+
+#include "src/Core/util/EnableMSVCWarnings.h"
+
+#endif // EIGEN_ARRAY_MODULE_H
diff --git a/extern/Eigen2/Eigen/Cholesky b/extern/Eigen2/Eigen/Cholesky
new file mode 100644
index 00000000000..f1806f726c7
--- /dev/null
+++ b/extern/Eigen2/Eigen/Cholesky
@@ -0,0 +1,65 @@
+#ifndef EIGEN_CHOLESKY_MODULE_H
+#define EIGEN_CHOLESKY_MODULE_H
+
+#include "Core"
+
+#include "src/Core/util/DisableMSVCWarnings.h"
+
+// Note that EIGEN_HIDE_HEAVY_CODE has to be defined per module
+#if (defined EIGEN_EXTERN_INSTANTIATIONS) && (EIGEN_EXTERN_INSTANTIATIONS>=2)
+ #ifndef EIGEN_HIDE_HEAVY_CODE
+ #define EIGEN_HIDE_HEAVY_CODE
+ #endif
+#elif defined EIGEN_HIDE_HEAVY_CODE
+ #undef EIGEN_HIDE_HEAVY_CODE
+#endif
+
+namespace Eigen {
+
+/** \defgroup Cholesky_Module Cholesky module
+ *
+ * \nonstableyet
+ *
+ * This module provides two variants of the Cholesky decomposition for selfadjoint (hermitian) matrices.
+ * Those decompositions are accessible via the following MatrixBase methods:
+ * - MatrixBase::llt(),
+ * - MatrixBase::ldlt()
+ *
+ * \code
+ * #include <Eigen/Cholesky>
+ * \endcode
+ */
+
+#include "src/Array/CwiseOperators.h"
+#include "src/Array/Functors.h"
+#include "src/Cholesky/LLT.h"
+#include "src/Cholesky/LDLT.h"
+
+} // namespace Eigen
+
+#define EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(MATRIXTYPE,PREFIX) \
+ PREFIX template class LLT<MATRIXTYPE>; \
+ PREFIX template class LDLT<MATRIXTYPE>
+
+#define EIGEN_CHOLESKY_MODULE_INSTANTIATE(PREFIX) \
+ EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(Matrix2f,PREFIX); \
+ EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(Matrix2d,PREFIX); \
+ EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(Matrix3f,PREFIX); \
+ EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(Matrix3d,PREFIX); \
+ EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(Matrix4f,PREFIX); \
+ EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(Matrix4d,PREFIX); \
+ EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(MatrixXf,PREFIX); \
+ EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(MatrixXd,PREFIX); \
+ EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(MatrixXcf,PREFIX); \
+ EIGEN_CHOLESKY_MODULE_INSTANTIATE_TYPE(MatrixXcd,PREFIX)
+
+#ifdef EIGEN_EXTERN_INSTANTIATIONS
+
+namespace Eigen {
+ EIGEN_CHOLESKY_MODULE_INSTANTIATE(extern);
+} // namespace Eigen
+#endif
+
+#include "src/Core/util/EnableMSVCWarnings.h"
+
+#endif // EIGEN_CHOLESKY_MODULE_H
diff --git a/extern/Eigen2/Eigen/Core b/extern/Eigen2/Eigen/Core
new file mode 100644
index 00000000000..060c60f1306
--- /dev/null
+++ b/extern/Eigen2/Eigen/Core
@@ -0,0 +1,155 @@
+#ifndef EIGEN_CORE_H
+#define EIGEN_CORE_H
+
+// first thing Eigen does: prevent MSVC from committing suicide
+#include "src/Core/util/DisableMSVCWarnings.h"
+
+#ifdef _MSC_VER
+ #include <malloc.h> // for _aligned_malloc -- need it regardless of whether vectorization is enabled
+ #if (_MSC_VER >= 1500) // 2008 or later
+ // Remember that usage of defined() in a #define is undefined by the standard.
+ // a user reported that in 64-bit mode, MSVC doesn't care to define _M_IX86_FP.
+ #if (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || defined(_M_X64)
+ #define EIGEN_SSE2_ON_MSVC_2008_OR_LATER
+ #endif
+ #endif
+#endif
+
+#ifdef __GNUC__
+ #define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__>=x && __GNUC_MINOR__>=y) || __GNUC__>x)
+#else
+ #define EIGEN_GNUC_AT_LEAST(x,y) 0
+#endif
+
+// Remember that usage of defined() in a #define is undefined by the standard
+#if (defined __SSE2__) && ( (!defined __GNUC__) || EIGEN_GNUC_AT_LEAST(4,2) )
+ #define EIGEN_SSE2_BUT_NOT_OLD_GCC
+#endif
+
+#ifndef EIGEN_DONT_VECTORIZE
+ #if defined (EIGEN_SSE2_BUT_NOT_OLD_GCC) || defined(EIGEN_SSE2_ON_MSVC_2008_OR_LATER)
+ #define EIGEN_VECTORIZE
+ #define EIGEN_VECTORIZE_SSE
+ #include <emmintrin.h>
+ #include <xmmintrin.h>
+ #ifdef __SSE3__
+ #include <pmmintrin.h>
+ #endif
+ #ifdef __SSSE3__
+ #include <tmmintrin.h>
+ #endif
+ #elif defined __ALTIVEC__
+ #define EIGEN_VECTORIZE
+ #define EIGEN_VECTORIZE_ALTIVEC
+ #include <altivec.h>
+ // We need to #undef all these ugly tokens defined in <altivec.h>
+ // => use __vector instead of vector
+ #undef bool
+ #undef vector
+ #undef pixel
+ #endif
+#endif
+
+#include <cstdlib>
+#include <cmath>
+#include <complex>
+#include <cassert>
+#include <functional>
+#include <iostream>
+#include <cstring>
+#include <string>
+#include <limits>
+#include <cstddef>
+
+#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(EIGEN_NO_EXCEPTIONS)
+ #define EIGEN_EXCEPTIONS
+#endif
+
+#ifdef EIGEN_EXCEPTIONS
+ #include <new>
+#endif
+
+// this needs to be done after all possible windows C header includes and before any Eigen source includes
+// (system C++ includes are supposed to be able to deal with this already):
+// windows.h defines min and max macros which would make Eigen fail to compile.
+#if defined(min) || defined(max)
+#error The preprocessor symbols 'min' or 'max' are defined. If you are compiling on Windows, do #define NOMINMAX to prevent windows.h from defining these symbols.
+#endif
+
+namespace Eigen {
+
+/** \defgroup Core_Module Core module
+ * This is the main module of Eigen providing dense matrix and vector support
+ * (both fixed and dynamic size) with all the features corresponding to a BLAS library
+ * and much more...
+ *
+ * \code
+ * #include <Eigen/Core>
+ * \endcode
+ */
+
+#include "src/Core/util/Macros.h"
+#include "src/Core/util/Constants.h"
+#include "src/Core/util/ForwardDeclarations.h"
+#include "src/Core/util/Meta.h"
+#include "src/Core/util/XprHelper.h"
+#include "src/Core/util/StaticAssert.h"
+#include "src/Core/util/Memory.h"
+
+#include "src/Core/NumTraits.h"
+#include "src/Core/MathFunctions.h"
+#include "src/Core/GenericPacketMath.h"
+
+#if defined EIGEN_VECTORIZE_SSE
+ #include "src/Core/arch/SSE/PacketMath.h"
+#elif defined EIGEN_VECTORIZE_ALTIVEC
+ #include "src/Core/arch/AltiVec/PacketMath.h"
+#endif
+
+#ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
+#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 16
+#endif
+
+#include "src/Core/Functors.h"
+#include "src/Core/MatrixBase.h"
+#include "src/Core/Coeffs.h"
+
+#ifndef EIGEN_PARSED_BY_DOXYGEN // work around Doxygen bug triggered by Assign.h r814874
+ // at least confirmed with Doxygen 1.5.5 and 1.5.6
+ #include "src/Core/Assign.h"
+#endif
+
+#include "src/Core/MatrixStorage.h"
+#include "src/Core/NestByValue.h"
+#include "src/Core/Flagged.h"
+#include "src/Core/Matrix.h"
+#include "src/Core/Cwise.h"
+#include "src/Core/CwiseBinaryOp.h"
+#include "src/Core/CwiseUnaryOp.h"
+#include "src/Core/CwiseNullaryOp.h"
+#include "src/Core/Dot.h"
+#include "src/Core/Product.h"
+#include "src/Core/DiagonalProduct.h"
+#include "src/Core/SolveTriangular.h"
+#include "src/Core/MapBase.h"
+#include "src/Core/Map.h"
+#include "src/Core/Block.h"
+#include "src/Core/Minor.h"
+#include "src/Core/Transpose.h"
+#include "src/Core/DiagonalMatrix.h"
+#include "src/Core/DiagonalCoeffs.h"
+#include "src/Core/Sum.h"
+#include "src/Core/Redux.h"
+#include "src/Core/Visitor.h"
+#include "src/Core/Fuzzy.h"
+#include "src/Core/IO.h"
+#include "src/Core/Swap.h"
+#include "src/Core/CommaInitializer.h"
+#include "src/Core/Part.h"
+#include "src/Core/CacheFriendlyProduct.h"
+
+} // namespace Eigen
+
+#include "src/Core/util/EnableMSVCWarnings.h"
+
+#endif // EIGEN_CORE_H
diff --git a/extern/Eigen3/Eigen/Dense b/extern/Eigen2/Eigen/Dense
index 5768910bd88..9655edcd7aa 100644
--- a/extern/Eigen3/Eigen/Dense
+++ b/extern/Eigen2/Eigen/Dense
@@ -1,7 +1,8 @@
#include "Core"
+#include "Array"
#include "LU"
#include "Cholesky"
#include "QR"
#include "SVD"
#include "Geometry"
-#include "Eigenvalues"
+#include "LeastSquares"
diff --git a/extern/Eigen2/Eigen/Eigen b/extern/Eigen2/Eigen/Eigen
new file mode 100644
index 00000000000..654c8dc6380
--- /dev/null
+++ b/extern/Eigen2/Eigen/Eigen
@@ -0,0 +1,2 @@
+#include "Dense"
+#include "Sparse"
diff --git a/extern/Eigen2/Eigen/Geometry b/extern/Eigen2/Eigen/Geometry
new file mode 100644
index 00000000000..617b25eb6f5
--- /dev/null
+++ b/extern/Eigen2/Eigen/Geometry
@@ -0,0 +1,51 @@
+#ifndef EIGEN_GEOMETRY_MODULE_H
+#define EIGEN_GEOMETRY_MODULE_H
+
+#include "Core"
+
+#include "src/Core/util/DisableMSVCWarnings.h"
+
+#include "Array"
+#include <limits>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+namespace Eigen {
+
+/** \defgroup Geometry_Module Geometry module
+ *
+ * \nonstableyet
+ *
+ * This module provides support for:
+ * - fixed-size homogeneous transformations
+ * - translation, scaling, 2D and 3D rotations
+ * - quaternions
+ * - \ref MatrixBase::cross() "cross product"
+ * - \ref MatrixBase::unitOrthogonal() "orthognal vector generation"
+ * - some linear components: parametrized-lines and hyperplanes
+ *
+ * \code
+ * #include <Eigen/Geometry>
+ * \endcode
+ */
+
+#include "src/Geometry/OrthoMethods.h"
+#include "src/Geometry/RotationBase.h"
+#include "src/Geometry/Rotation2D.h"
+#include "src/Geometry/Quaternion.h"
+#include "src/Geometry/AngleAxis.h"
+#include "src/Geometry/EulerAngles.h"
+#include "src/Geometry/Transform.h"
+#include "src/Geometry/Translation.h"
+#include "src/Geometry/Scaling.h"
+#include "src/Geometry/Hyperplane.h"
+#include "src/Geometry/ParametrizedLine.h"
+#include "src/Geometry/AlignedBox.h"
+
+} // namespace Eigen
+
+#include "src/Core/util/EnableMSVCWarnings.h"
+
+#endif // EIGEN_GEOMETRY_MODULE_H
diff --git a/extern/Eigen3/Eigen/LU b/extern/Eigen2/Eigen/LU
index 226f88ca38a..0ce69456598 100644
--- a/extern/Eigen3/Eigen/LU
+++ b/extern/Eigen2/Eigen/LU
@@ -3,7 +3,7 @@
#include "Core"
-#include "src/Core/util/DisableStupidWarnings.h"
+#include "src/Core/util/DisableMSVCWarnings.h"
namespace Eigen {
@@ -18,25 +18,12 @@ namespace Eigen {
* \endcode
*/
-#include "src/misc/Solve.h"
-#include "src/misc/Kernel.h"
-#include "src/misc/Image.h"
-#include "src/LU/FullPivLU.h"
-#include "src/LU/PartialPivLU.h"
+#include "src/LU/LU.h"
#include "src/LU/Determinant.h"
#include "src/LU/Inverse.h"
-#if defined EIGEN_VECTORIZE_SSE
- #include "src/LU/arch/Inverse_SSE.h"
-#endif
-
-#ifdef EIGEN2_SUPPORT
- #include "src/Eigen2Support/LU.h"
-#endif
-
} // namespace Eigen
-#include "src/Core/util/ReenableStupidWarnings.h"
+#include "src/Core/util/EnableMSVCWarnings.h"
#endif // EIGEN_LU_MODULE_H
-/* vim: set filetype=cpp et sw=2 ts=2 ai: */
diff --git a/extern/Eigen2/Eigen/LeastSquares b/extern/Eigen2/Eigen/LeastSquares
new file mode 100644
index 00000000000..573a13cb42f
--- /dev/null
+++ b/extern/Eigen2/Eigen/LeastSquares
@@ -0,0 +1,27 @@
+#ifndef EIGEN_REGRESSION_MODULE_H
+#define EIGEN_REGRESSION_MODULE_H
+
+#include "Core"
+
+#include "src/Core/util/DisableMSVCWarnings.h"
+
+#include "QR"
+#include "Geometry"
+
+namespace Eigen {
+
+/** \defgroup LeastSquares_Module LeastSquares module
+ * This module provides linear regression and related features.
+ *
+ * \code
+ * #include <Eigen/LeastSquares>
+ * \endcode
+ */
+
+#include "src/LeastSquares/LeastSquares.h"
+
+} // namespace Eigen
+
+#include "src/Core/util/EnableMSVCWarnings.h"
+
+#endif // EIGEN_REGRESSION_MODULE_H
diff --git a/extern/Eigen3/Eigen/src/StlSupport/StdVector.h b/extern/Eigen2/Eigen/NewStdVector
index 27d6ab539f9..f37de5ff673 100644
--- a/extern/Eigen3/Eigen/src/StlSupport/StdVector.h
+++ b/extern/Eigen2/Eigen/NewStdVector
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2009 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.com>
//
// Eigen is free software; you can redistribute it and/or
@@ -23,40 +23,68 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-#ifndef EIGEN_STDVECTOR_H
-#define EIGEN_STDVECTOR_H
-
-#include "Eigen/src/StlSupport/details.h"
-
-/**
- * This section contains a convenience MACRO which allows an easy specialization of
- * std::vector such that for data types with alignment issues the correct allocator
- * is used automatically.
- */
-#define EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(...) \
-namespace std \
-{ \
- template<> \
- class vector<__VA_ARGS__, std::allocator<__VA_ARGS__> > \
- : public vector<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > \
- { \
- typedef vector<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > vector_base; \
- public: \
- typedef __VA_ARGS__ value_type; \
- typedef vector_base::allocator_type allocator_type; \
- typedef vector_base::size_type size_type; \
- typedef vector_base::iterator iterator; \
- explicit vector(const allocator_type& a = allocator_type()) : vector_base(a) {} \
- template<typename InputIterator> \
- vector(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) : vector_base(first, last, a) {} \
- vector(const vector& c) : vector_base(c) {} \
- explicit vector(size_type num, const value_type& val = value_type()) : vector_base(num, val) {} \
- vector(iterator start, iterator end) : vector_base(start, end) {} \
- vector& operator=(const vector& x) { \
- vector_base::operator=(x); \
- return *this; \
- } \
- }; \
+#ifndef EIGEN_STDVECTOR_MODULE_H
+#define EIGEN_STDVECTOR_MODULE_H
+
+#include "Core"
+#include <vector>
+
+namespace Eigen {
+
+// This one is needed to prevent reimplementing the whole std::vector.
+template <class T>
+class aligned_allocator_indirection : public aligned_allocator<T>
+{
+public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T value_type;
+
+ template<class U>
+ struct rebind
+ {
+ typedef aligned_allocator_indirection<U> other;
+ };
+
+ aligned_allocator_indirection() throw() {}
+ aligned_allocator_indirection(const aligned_allocator_indirection& ) throw() : aligned_allocator<T>() {}
+ aligned_allocator_indirection(const aligned_allocator<T>& ) throw() {}
+ template<class U>
+ aligned_allocator_indirection(const aligned_allocator_indirection<U>& ) throw() {}
+ template<class U>
+ aligned_allocator_indirection(const aligned_allocator<U>& ) throw() {}
+ ~aligned_allocator_indirection() throw() {}
+};
+
+#ifdef _MSC_VER
+
+ // sometimes, MSVC detects, at compile time, that the argument x
+ // in std::vector::resize(size_t s,T x) won't be aligned and generate an error
+ // even if this function is never called. Whence this little wrapper.
+ #define EIGEN_WORKAROUND_MSVC_STD_VECTOR(T) Eigen::ei_workaround_msvc_std_vector<T>
+ template<typename T> struct ei_workaround_msvc_std_vector : public T
+ {
+ inline ei_workaround_msvc_std_vector() : T() {}
+ inline ei_workaround_msvc_std_vector(const T& other) : T(other) {}
+ inline operator T& () { return *static_cast<T*>(this); }
+ inline operator const T& () const { return *static_cast<const T*>(this); }
+ template<typename OtherT>
+ inline T& operator=(const OtherT& other)
+ { T::operator=(other); return *this; }
+ inline ei_workaround_msvc_std_vector& operator=(const ei_workaround_msvc_std_vector& other)
+ { T::operator=(other); return *this; }
+ };
+
+#else
+
+ #define EIGEN_WORKAROUND_MSVC_STD_VECTOR(T) T
+
+#endif
+
}
namespace std {
@@ -80,13 +108,13 @@ namespace std {
return *this; \
}
- template<typename T>
- class vector<T,EIGEN_ALIGNED_ALLOCATOR<T> >
- : public vector<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T),
- Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T)> >
+template<typename T>
+class vector<T,Eigen::aligned_allocator<T> >
+ : public vector<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T),
+ Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T)> >
{
- typedef vector<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T),
- Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T)> > vector_base;
+ typedef vector<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T),
+ Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STD_VECTOR(T)> > vector_base;
EIGEN_STD_VECTOR_SPECIALIZATION_BODY
void resize(size_type new_size)
@@ -108,13 +136,6 @@ namespace std {
{ return vector_base::insert(position,x); }
void insert(const_iterator position, size_type new_size, const value_type& x)
{ vector_base::insert(position, new_size, x); }
-#elif defined(_GLIBCXX_VECTOR) && (!(EIGEN_GNUC_AT_LEAST(4,1)))
- /* Note that before gcc-4.1 we already have: std::vector::resize(size_type,const T&).
- * However, this specialization is still needed to make the above EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION trick to work. */
- void resize(size_type new_size, const value_type& x)
- {
- vector_base::resize(new_size,x);
- }
#elif defined(_GLIBCXX_VECTOR) && EIGEN_GNUC_AT_LEAST(4,2)
// workaround GCC std::vector implementation
void resize(size_type new_size, const value_type& x)
@@ -124,6 +145,10 @@ namespace std {
else
vector_base::insert(vector_base::end(), new_size - vector_base::size(), x);
}
+#elif defined(_GLIBCXX_VECTOR) && (!EIGEN_GNUC_AT_LEAST(4,1))
+ // Note that before gcc-4.1 we already have: std::vector::resize(size_type,const T&),
+ // no no need to workaround !
+ using vector_base::resize;
#else
// either GCC 4.1 or non-GCC
// default implementation which should always work.
@@ -135,7 +160,9 @@ namespace std {
vector_base::insert(vector_base::end(), new_size - vector_base::size(), x);
}
#endif
- };
+
+};
+
}
-#endif // EIGEN_STDVECTOR_H
+#endif // EIGEN_STDVECTOR_MODULE_H
diff --git a/extern/Eigen2/Eigen/QR b/extern/Eigen2/Eigen/QR
new file mode 100644
index 00000000000..97907d1e50f
--- /dev/null
+++ b/extern/Eigen2/Eigen/QR
@@ -0,0 +1,73 @@
+#ifndef EIGEN_QR_MODULE_H
+#define EIGEN_QR_MODULE_H
+
+#include "Core"
+
+#include "src/Core/util/DisableMSVCWarnings.h"
+
+#include "Cholesky"
+
+// Note that EIGEN_HIDE_HEAVY_CODE has to be defined per module
+#if (defined EIGEN_EXTERN_INSTANTIATIONS) && (EIGEN_EXTERN_INSTANTIATIONS>=2)
+ #ifndef EIGEN_HIDE_HEAVY_CODE
+ #define EIGEN_HIDE_HEAVY_CODE
+ #endif
+#elif defined EIGEN_HIDE_HEAVY_CODE
+ #undef EIGEN_HIDE_HEAVY_CODE
+#endif
+
+namespace Eigen {
+
+/** \defgroup QR_Module QR module
+ *
+ * \nonstableyet
+ *
+ * This module mainly provides QR decomposition and an eigen value solver.
+ * This module also provides some MatrixBase methods, including:
+ * - MatrixBase::qr(),
+ * - MatrixBase::eigenvalues(),
+ * - MatrixBase::operatorNorm()
+ *
+ * \code
+ * #include <Eigen/QR>
+ * \endcode
+ */
+
+#include "src/QR/QR.h"
+#include "src/QR/Tridiagonalization.h"
+#include "src/QR/EigenSolver.h"
+#include "src/QR/SelfAdjointEigenSolver.h"
+#include "src/QR/HessenbergDecomposition.h"
+
+// declare all classes for a given matrix type
+#define EIGEN_QR_MODULE_INSTANTIATE_TYPE(MATRIXTYPE,PREFIX) \
+ PREFIX template class QR<MATRIXTYPE>; \
+ PREFIX template class Tridiagonalization<MATRIXTYPE>; \
+ PREFIX template class HessenbergDecomposition<MATRIXTYPE>; \
+ PREFIX template class SelfAdjointEigenSolver<MATRIXTYPE>
+
+// removed because it does not support complex yet
+// PREFIX template class EigenSolver<MATRIXTYPE>
+
+// declare all class for all types
+#define EIGEN_QR_MODULE_INSTANTIATE(PREFIX) \
+ EIGEN_QR_MODULE_INSTANTIATE_TYPE(Matrix2f,PREFIX); \
+ EIGEN_QR_MODULE_INSTANTIATE_TYPE(Matrix2d,PREFIX); \
+ EIGEN_QR_MODULE_INSTANTIATE_TYPE(Matrix3f,PREFIX); \
+ EIGEN_QR_MODULE_INSTANTIATE_TYPE(Matrix3d,PREFIX); \
+ EIGEN_QR_MODULE_INSTANTIATE_TYPE(Matrix4f,PREFIX); \
+ EIGEN_QR_MODULE_INSTANTIATE_TYPE(Matrix4d,PREFIX); \
+ EIGEN_QR_MODULE_INSTANTIATE_TYPE(MatrixXf,PREFIX); \
+ EIGEN_QR_MODULE_INSTANTIATE_TYPE(MatrixXd,PREFIX); \
+ EIGEN_QR_MODULE_INSTANTIATE_TYPE(MatrixXcf,PREFIX); \
+ EIGEN_QR_MODULE_INSTANTIATE_TYPE(MatrixXcd,PREFIX)
+
+#ifdef EIGEN_EXTERN_INSTANTIATIONS
+ EIGEN_QR_MODULE_INSTANTIATE(extern);
+#endif // EIGEN_EXTERN_INSTANTIATIONS
+
+} // namespace Eigen
+
+#include "src/Core/util/EnableMSVCWarnings.h"
+
+#endif // EIGEN_QR_MODULE_H
diff --git a/extern/Eigen2/Eigen/QtAlignedMalloc b/extern/Eigen2/Eigen/QtAlignedMalloc
new file mode 100644
index 00000000000..fde227328fa
--- /dev/null
+++ b/extern/Eigen2/Eigen/QtAlignedMalloc
@@ -0,0 +1,29 @@
+
+#ifndef EIGEN_QTMALLOC_MODULE_H
+#define EIGEN_QTMALLOC_MODULE_H
+
+#include "Core"
+
+#if (!EIGEN_MALLOC_ALREADY_ALIGNED)
+
+inline void *qMalloc(size_t size)
+{
+ return Eigen::ei_aligned_malloc(size);
+}
+
+inline void qFree(void *ptr)
+{
+ Eigen::ei_aligned_free(ptr);
+}
+
+inline void *qRealloc(void *ptr, size_t size)
+{
+ void* newPtr = Eigen::ei_aligned_malloc(size);
+ memcpy(newPtr, ptr, size);
+ Eigen::ei_aligned_free(ptr);
+ return newPtr;
+}
+
+#endif
+
+#endif // EIGEN_QTMALLOC_MODULE_H
diff --git a/extern/Eigen3/Eigen/SVD b/extern/Eigen2/Eigen/SVD
index d24471fd724..eef05564bde 100644
--- a/extern/Eigen3/Eigen/SVD
+++ b/extern/Eigen2/Eigen/SVD
@@ -1,17 +1,15 @@
#ifndef EIGEN_SVD_MODULE_H
#define EIGEN_SVD_MODULE_H
-#include "QR"
-#include "Householder"
-#include "Jacobi"
+#include "Core"
-#include "src/Core/util/DisableStupidWarnings.h"
+#include "src/Core/util/DisableMSVCWarnings.h"
namespace Eigen {
/** \defgroup SVD_Module SVD module
*
- *
+ * \nonstableyet
*
* This module provides SVD decomposition for (currently) real matrices.
* This decomposition is accessible via the following MatrixBase method:
@@ -22,17 +20,10 @@ namespace Eigen {
* \endcode
*/
-#include "src/misc/Solve.h"
-#include "src/SVD/JacobiSVD.h"
-#include "src/SVD/UpperBidiagonalization.h"
-
-#ifdef EIGEN2_SUPPORT
-#include "src/Eigen2Support/SVD.h"
-#endif
+#include "src/SVD/SVD.h"
} // namespace Eigen
-#include "src/Core/util/ReenableStupidWarnings.h"
+#include "src/Core/util/EnableMSVCWarnings.h"
#endif // EIGEN_SVD_MODULE_H
-/* vim: set filetype=cpp et sw=2 ts=2 ai: */
diff --git a/extern/Eigen2/Eigen/Sparse b/extern/Eigen2/Eigen/Sparse
new file mode 100644
index 00000000000..536c284549b
--- /dev/null
+++ b/extern/Eigen2/Eigen/Sparse
@@ -0,0 +1,132 @@
+#ifndef EIGEN_SPARSE_MODULE_H
+#define EIGEN_SPARSE_MODULE_H
+
+#include "Core"
+
+#include "src/Core/util/DisableMSVCWarnings.h"
+
+#include <vector>
+#include <map>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+
+#ifdef EIGEN_GOOGLEHASH_SUPPORT
+ #include <google/dense_hash_map>
+#endif
+
+#ifdef EIGEN_CHOLMOD_SUPPORT
+ extern "C" {
+ #include "cholmod.h"
+ }
+#endif
+
+#ifdef EIGEN_TAUCS_SUPPORT
+ // taucs.h declares a lot of mess
+ #define isnan
+ #define finite
+ #define isinf
+ extern "C" {
+ #include "taucs.h"
+ }
+ #undef isnan
+ #undef finite
+ #undef isinf
+
+ #ifdef min
+ #undef min
+ #endif
+ #ifdef max
+ #undef max
+ #endif
+ #ifdef complex
+ #undef complex
+ #endif
+#endif
+
+#ifdef EIGEN_SUPERLU_SUPPORT
+ typedef int int_t;
+ #include "superlu/slu_Cnames.h"
+ #include "superlu/supermatrix.h"
+ #include "superlu/slu_util.h"
+
+ namespace SuperLU_S {
+ #include "superlu/slu_sdefs.h"
+ }
+ namespace SuperLU_D {
+ #include "superlu/slu_ddefs.h"
+ }
+ namespace SuperLU_C {
+ #include "superlu/slu_cdefs.h"
+ }
+ namespace SuperLU_Z {
+ #include "superlu/slu_zdefs.h"
+ }
+ namespace Eigen { struct SluMatrix; }
+#endif
+
+#ifdef EIGEN_UMFPACK_SUPPORT
+ #include "umfpack.h"
+#endif
+
+namespace Eigen {
+
+/** \defgroup Sparse_Module Sparse module
+ *
+ * \nonstableyet
+ *
+ * See the \ref TutorialSparse "Sparse tutorial"
+ *
+ * \code
+ * #include <Eigen/QR>
+ * \endcode
+ */
+
+#include "src/Sparse/SparseUtil.h"
+#include "src/Sparse/SparseMatrixBase.h"
+#include "src/Sparse/CompressedStorage.h"
+#include "src/Sparse/AmbiVector.h"
+#include "src/Sparse/RandomSetter.h"
+#include "src/Sparse/SparseBlock.h"
+#include "src/Sparse/SparseMatrix.h"
+#include "src/Sparse/DynamicSparseMatrix.h"
+#include "src/Sparse/MappedSparseMatrix.h"
+#include "src/Sparse/SparseVector.h"
+#include "src/Sparse/CoreIterators.h"
+#include "src/Sparse/SparseTranspose.h"
+#include "src/Sparse/SparseCwise.h"
+#include "src/Sparse/SparseCwiseUnaryOp.h"
+#include "src/Sparse/SparseCwiseBinaryOp.h"
+#include "src/Sparse/SparseDot.h"
+#include "src/Sparse/SparseAssign.h"
+#include "src/Sparse/SparseRedux.h"
+#include "src/Sparse/SparseFuzzy.h"
+#include "src/Sparse/SparseFlagged.h"
+#include "src/Sparse/SparseProduct.h"
+#include "src/Sparse/SparseDiagonalProduct.h"
+#include "src/Sparse/TriangularSolver.h"
+#include "src/Sparse/SparseLLT.h"
+#include "src/Sparse/SparseLDLT.h"
+#include "src/Sparse/SparseLU.h"
+
+#ifdef EIGEN_CHOLMOD_SUPPORT
+# include "src/Sparse/CholmodSupport.h"
+#endif
+
+#ifdef EIGEN_TAUCS_SUPPORT
+# include "src/Sparse/TaucsSupport.h"
+#endif
+
+#ifdef EIGEN_SUPERLU_SUPPORT
+# include "src/Sparse/SuperLUSupport.h"
+#endif
+
+#ifdef EIGEN_UMFPACK_SUPPORT
+# include "src/Sparse/UmfPackSupport.h"
+#endif
+
+} // namespace Eigen
+
+#include "src/Core/util/EnableMSVCWarnings.h"
+
+#endif // EIGEN_SPARSE_MODULE_H
diff --git a/extern/Eigen2/Eigen/StdVector b/extern/Eigen2/Eigen/StdVector
new file mode 100644
index 00000000000..c0744d6a0f3
--- /dev/null
+++ b/extern/Eigen2/Eigen/StdVector
@@ -0,0 +1,147 @@
+#ifdef EIGEN_USE_NEW_STDVECTOR
+#include "NewStdVector"
+#else
+
+#ifndef EIGEN_STDVECTOR_MODULE_H
+#define EIGEN_STDVECTOR_MODULE_H
+
+#if defined(_GLIBCXX_VECTOR) || defined(_VECTOR_)
+#error you must include <Eigen/StdVector> before <vector>. Also note that <Eigen/Sparse> includes <vector>, so it must be included after <Eigen/StdVector> too.
+#endif
+
+#ifndef EIGEN_GNUC_AT_LEAST
+#ifdef __GNUC__
+ #define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__>=x && __GNUC_MINOR__>=y) || __GNUC__>x)
+#else
+ #define EIGEN_GNUC_AT_LEAST(x,y) 0
+#endif
+#endif
+
+#define vector std_vector
+#include <vector>
+#undef vector
+
+namespace Eigen {
+
+template<typename T> class aligned_allocator;
+
+// meta programming to determine if a class has a given member
+struct ei_does_not_have_aligned_operator_new_marker_sizeof {int a[1];};
+struct ei_has_aligned_operator_new_marker_sizeof {int a[2];};
+
+template<typename ClassType>
+struct ei_has_aligned_operator_new {
+ template<typename T>
+ static ei_has_aligned_operator_new_marker_sizeof
+ test(T const *, typename T::ei_operator_new_marker_type const * = 0);
+ static ei_does_not_have_aligned_operator_new_marker_sizeof
+ test(...);
+
+ // note that the following indirection is needed for gcc-3.3
+ enum {ret = sizeof(test(static_cast<ClassType*>(0)))
+ == sizeof(ei_has_aligned_operator_new_marker_sizeof) };
+};
+
+#ifdef _MSC_VER
+
+ // sometimes, MSVC detects, at compile time, that the argument x
+ // in std::vector::resize(size_t s,T x) won't be aligned and generate an error
+ // even if this function is never called. Whence this little wrapper.
+ #define _EIGEN_WORKAROUND_MSVC_STD_VECTOR(T) Eigen::ei_workaround_msvc_std_vector<T>
+ template<typename T> struct ei_workaround_msvc_std_vector : public T
+ {
+ inline ei_workaround_msvc_std_vector() : T() {}
+ inline ei_workaround_msvc_std_vector(const T& other) : T(other) {}
+ inline operator T& () { return *static_cast<T*>(this); }
+ inline operator const T& () const { return *static_cast<const T*>(this); }
+ template<typename OtherT>
+ inline T& operator=(const OtherT& other)
+ { T::operator=(other); return *this; }
+ inline ei_workaround_msvc_std_vector& operator=(const ei_workaround_msvc_std_vector& other)
+ { T::operator=(other); return *this; }
+ };
+
+#else
+
+ #define _EIGEN_WORKAROUND_MSVC_STD_VECTOR(T) T
+
+#endif
+
+}
+
+namespace std {
+
+#define EIGEN_STD_VECTOR_SPECIALIZATION_BODY \
+ public: \
+ typedef T value_type; \
+ typedef typename vector_base::allocator_type allocator_type; \
+ typedef typename vector_base::size_type size_type; \
+ typedef typename vector_base::iterator iterator; \
+ explicit vector(const allocator_type& __a = allocator_type()) : vector_base(__a) {} \
+ vector(const vector& c) : vector_base(c) {} \
+ vector(size_type num, const value_type& val = value_type()) : vector_base(num, val) {} \
+ vector(iterator start, iterator end) : vector_base(start, end) {} \
+ vector& operator=(const vector& __x) { \
+ vector_base::operator=(__x); \
+ return *this; \
+ }
+
+template<typename T,
+ typename AllocT = std::allocator<T>,
+ bool HasAlignedNew = Eigen::ei_has_aligned_operator_new<T>::ret>
+class vector : public std::std_vector<T,AllocT>
+{
+ typedef std_vector<T, AllocT> vector_base;
+ EIGEN_STD_VECTOR_SPECIALIZATION_BODY
+};
+
+template<typename T,typename DummyAlloc>
+class vector<T,DummyAlloc,true>
+ : public std::std_vector<_EIGEN_WORKAROUND_MSVC_STD_VECTOR(T),
+ Eigen::aligned_allocator<_EIGEN_WORKAROUND_MSVC_STD_VECTOR(T)> >
+{
+ typedef std_vector<_EIGEN_WORKAROUND_MSVC_STD_VECTOR(T),
+ Eigen::aligned_allocator<_EIGEN_WORKAROUND_MSVC_STD_VECTOR(T)> > vector_base;
+ EIGEN_STD_VECTOR_SPECIALIZATION_BODY
+
+ void resize(size_type __new_size)
+ { resize(__new_size, T()); }
+
+ #if defined(_VECTOR_)
+ // workaround MSVC std::vector implementation
+ void resize(size_type __new_size, const value_type& __x)
+ {
+ if (vector_base::size() < __new_size)
+ vector_base::_Insert_n(vector_base::end(), __new_size - vector_base::size(), __x);
+ else if (__new_size < vector_base::size())
+ vector_base::erase(vector_base::begin() + __new_size, vector_base::end());
+ }
+ #elif defined(_GLIBCXX_VECTOR) && EIGEN_GNUC_AT_LEAST(4,2)
+ // workaround GCC std::vector implementation
+ void resize(size_type __new_size, const value_type& __x)
+ {
+ if (__new_size < vector_base::size())
+ vector_base::_M_erase_at_end(this->_M_impl._M_start + __new_size);
+ else
+ vector_base::insert(vector_base::end(), __new_size - vector_base::size(), __x);
+ }
+ #elif defined(_GLIBCXX_VECTOR) && EIGEN_GNUC_AT_LEAST(4,1)
+ void resize(size_type __new_size, const value_type& __x)
+ {
+ if (__new_size < vector_base::size())
+ vector_base::erase(vector_base::begin() + __new_size, vector_base::end());
+ else
+ vector_base::insert(vector_base::end(), __new_size - vector_base::size(), __x);
+ }
+ #else
+ // Before gcc-4.1 we already have: std::vector::resize(size_type,const T&),
+ // so no need for a workaround !
+ using vector_base::resize;
+ #endif
+};
+
+}
+
+#endif // EIGEN_STDVECTOR_MODULE_H
+
+#endif // EIGEN_USE_NEW_STDVECTOR \ No newline at end of file
diff --git a/extern/Eigen3/Eigen/src/Core/BooleanRedux.h b/extern/Eigen2/Eigen/src/Array/BooleanRedux.h
index 5c3444a57c9..4e8218327eb 100644
--- a/extern/Eigen3/Eigen/src/Core/BooleanRedux.h
+++ b/extern/Eigen2/Eigen/src/Array/BooleanRedux.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -25,10 +25,8 @@
#ifndef EIGEN_ALLANDANY_H
#define EIGEN_ALLANDANY_H
-namespace internal {
-
template<typename Derived, int UnrollCount>
-struct all_unroller
+struct ei_all_unroller
{
enum {
col = (UnrollCount-1) / Derived::RowsAtCompileTime,
@@ -37,24 +35,24 @@ struct all_unroller
inline static bool run(const Derived &mat)
{
- return all_unroller<Derived, UnrollCount-1>::run(mat) && mat.coeff(row, col);
+ return ei_all_unroller<Derived, UnrollCount-1>::run(mat) && mat.coeff(row, col);
}
};
template<typename Derived>
-struct all_unroller<Derived, 1>
+struct ei_all_unroller<Derived, 1>
{
inline static bool run(const Derived &mat) { return mat.coeff(0, 0); }
};
template<typename Derived>
-struct all_unroller<Derived, Dynamic>
+struct ei_all_unroller<Derived, Dynamic>
{
inline static bool run(const Derived &) { return false; }
};
template<typename Derived, int UnrollCount>
-struct any_unroller
+struct ei_any_unroller
{
enum {
col = (UnrollCount-1) / Derived::RowsAtCompileTime,
@@ -63,87 +61,85 @@ struct any_unroller
inline static bool run(const Derived &mat)
{
- return any_unroller<Derived, UnrollCount-1>::run(mat) || mat.coeff(row, col);
+ return ei_any_unroller<Derived, UnrollCount-1>::run(mat) || mat.coeff(row, col);
}
};
template<typename Derived>
-struct any_unroller<Derived, 1>
+struct ei_any_unroller<Derived, 1>
{
inline static bool run(const Derived &mat) { return mat.coeff(0, 0); }
};
template<typename Derived>
-struct any_unroller<Derived, Dynamic>
+struct ei_any_unroller<Derived, Dynamic>
{
inline static bool run(const Derived &) { return false; }
};
-} // end namespace internal
-
-/** \returns true if all coefficients are true
+/** \array_module
+ *
+ * \returns true if all coefficients are true
+ *
+ * \addexample CwiseAll \label How to check whether a point is inside a box (using operator< and all())
*
* Example: \include MatrixBase_all.cpp
* Output: \verbinclude MatrixBase_all.out
*
- * \sa any(), Cwise::operator<()
+ * \sa MatrixBase::any(), Cwise::operator<()
*/
template<typename Derived>
-inline bool DenseBase<Derived>::all() const
+inline bool MatrixBase<Derived>::all() const
{
- enum {
- unroll = SizeAtCompileTime != Dynamic
- && CoeffReadCost != Dynamic
- && NumTraits<Scalar>::AddCost != Dynamic
- && SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
- };
+ const bool unroll = SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost)
+ <= EIGEN_UNROLLING_LIMIT;
if(unroll)
- return internal::all_unroller<Derived,
+ return ei_all_unroller<Derived,
unroll ? int(SizeAtCompileTime) : Dynamic
>::run(derived());
else
{
- for(Index j = 0; j < cols(); ++j)
- for(Index i = 0; i < rows(); ++i)
+ for(int j = 0; j < cols(); ++j)
+ for(int i = 0; i < rows(); ++i)
if (!coeff(i, j)) return false;
return true;
}
}
-/** \returns true if at least one coefficient is true
+/** \array_module
+ *
+ * \returns true if at least one coefficient is true
*
- * \sa all()
+ * \sa MatrixBase::all()
*/
template<typename Derived>
-inline bool DenseBase<Derived>::any() const
+inline bool MatrixBase<Derived>::any() const
{
- enum {
- unroll = SizeAtCompileTime != Dynamic
- && CoeffReadCost != Dynamic
- && NumTraits<Scalar>::AddCost != Dynamic
- && SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
- };
+ const bool unroll = SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost)
+ <= EIGEN_UNROLLING_LIMIT;
if(unroll)
- return internal::any_unroller<Derived,
+ return ei_any_unroller<Derived,
unroll ? int(SizeAtCompileTime) : Dynamic
>::run(derived());
else
{
- for(Index j = 0; j < cols(); ++j)
- for(Index i = 0; i < rows(); ++i)
+ for(int j = 0; j < cols(); ++j)
+ for(int i = 0; i < rows(); ++i)
if (coeff(i, j)) return true;
return false;
}
}
-/** \returns the number of coefficients which evaluate to true
+/** \array_module
+ *
+ * \returns the number of coefficients which evaluate to true
*
- * \sa all(), any()
+ * \sa MatrixBase::all(), MatrixBase::any()
*/
template<typename Derived>
-inline typename DenseBase<Derived>::Index DenseBase<Derived>::count() const
+inline int MatrixBase<Derived>::count() const
{
- return derived().template cast<bool>().template cast<Index>().sum();
+ return this->cast<bool>().cast<int>().sum();
}
#endif // EIGEN_ALLANDANY_H
diff --git a/extern/Eigen2/Eigen/src/Array/CwiseOperators.h b/extern/Eigen2/Eigen/src/Array/CwiseOperators.h
new file mode 100644
index 00000000000..4b6346daa51
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Array/CwiseOperators.h
@@ -0,0 +1,453 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_ARRAY_CWISE_OPERATORS_H
+#define EIGEN_ARRAY_CWISE_OPERATORS_H
+
+// -- unary operators --
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise square root of *this.
+ *
+ * Example: \include Cwise_sqrt.cpp
+ * Output: \verbinclude Cwise_sqrt.out
+ *
+ * \sa pow(), square()
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_sqrt_op)
+Cwise<ExpressionType>::sqrt() const
+{
+ return _expression();
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise exponential of *this.
+ *
+ * Example: \include Cwise_exp.cpp
+ * Output: \verbinclude Cwise_exp.out
+ *
+ * \sa pow(), log(), sin(), cos()
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_exp_op)
+Cwise<ExpressionType>::exp() const
+{
+ return _expression();
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise logarithm of *this.
+ *
+ * Example: \include Cwise_log.cpp
+ * Output: \verbinclude Cwise_log.out
+ *
+ * \sa exp()
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_log_op)
+Cwise<ExpressionType>::log() const
+{
+ return _expression();
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise cosine of *this.
+ *
+ * Example: \include Cwise_cos.cpp
+ * Output: \verbinclude Cwise_cos.out
+ *
+ * \sa sin(), exp()
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_cos_op)
+Cwise<ExpressionType>::cos() const
+{
+ return _expression();
+}
+
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise sine of *this.
+ *
+ * Example: \include Cwise_sin.cpp
+ * Output: \verbinclude Cwise_sin.out
+ *
+ * \sa cos(), exp()
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_sin_op)
+Cwise<ExpressionType>::sin() const
+{
+ return _expression();
+}
+
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise power of *this to the given exponent.
+ *
+ * Example: \include Cwise_pow.cpp
+ * Output: \verbinclude Cwise_pow.out
+ *
+ * \sa exp(), log()
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_pow_op)
+Cwise<ExpressionType>::pow(const Scalar& exponent) const
+{
+ return EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_pow_op)(_expression(), ei_scalar_pow_op<Scalar>(exponent));
+}
+
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise inverse of *this.
+ *
+ * Example: \include Cwise_inverse.cpp
+ * Output: \verbinclude Cwise_inverse.out
+ *
+ * \sa operator/(), operator*()
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_inverse_op)
+Cwise<ExpressionType>::inverse() const
+{
+ return _expression();
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise square of *this.
+ *
+ * Example: \include Cwise_square.cpp
+ * Output: \verbinclude Cwise_square.out
+ *
+ * \sa operator/(), operator*(), abs2()
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_square_op)
+Cwise<ExpressionType>::square() const
+{
+ return _expression();
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise cube of *this.
+ *
+ * Example: \include Cwise_cube.cpp
+ * Output: \verbinclude Cwise_cube.out
+ *
+ * \sa square(), pow()
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_cube_op)
+Cwise<ExpressionType>::cube() const
+{
+ return _expression();
+}
+
+
+// -- binary operators --
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise \< operator of *this and \a other
+ *
+ * Example: \include Cwise_less.cpp
+ * Output: \verbinclude Cwise_less.out
+ *
+ * \sa MatrixBase::all(), MatrixBase::any(), operator>(), operator<=()
+ */
+template<typename ExpressionType>
+template<typename OtherDerived>
+inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)
+Cwise<ExpressionType>::operator<(const MatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)(_expression(), other.derived());
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise \<= operator of *this and \a other
+ *
+ * Example: \include Cwise_less_equal.cpp
+ * Output: \verbinclude Cwise_less_equal.out
+ *
+ * \sa MatrixBase::all(), MatrixBase::any(), operator>=(), operator<()
+ */
+template<typename ExpressionType>
+template<typename OtherDerived>
+inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less_equal)
+Cwise<ExpressionType>::operator<=(const MatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_CWISE_BINOP_RETURN_TYPE(std::less_equal)(_expression(), other.derived());
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise \> operator of *this and \a other
+ *
+ * Example: \include Cwise_greater.cpp
+ * Output: \verbinclude Cwise_greater.out
+ *
+ * \sa MatrixBase::all(), MatrixBase::any(), operator>=(), operator<()
+ */
+template<typename ExpressionType>
+template<typename OtherDerived>
+inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater)
+Cwise<ExpressionType>::operator>(const MatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater)(_expression(), other.derived());
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise \>= operator of *this and \a other
+ *
+ * Example: \include Cwise_greater_equal.cpp
+ * Output: \verbinclude Cwise_greater_equal.out
+ *
+ * \sa MatrixBase::all(), MatrixBase::any(), operator>(), operator<=()
+ */
+template<typename ExpressionType>
+template<typename OtherDerived>
+inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater_equal)
+Cwise<ExpressionType>::operator>=(const MatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater_equal)(_expression(), other.derived());
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise == operator of *this and \a other
+ *
+ * \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 MatrixBase::isApprox() and
+ * MatrixBase::isMuchSmallerThan().
+ *
+ * Example: \include Cwise_equal_equal.cpp
+ * Output: \verbinclude Cwise_equal_equal.out
+ *
+ * \sa MatrixBase::all(), MatrixBase::any(), MatrixBase::isApprox(), MatrixBase::isMuchSmallerThan()
+ */
+template<typename ExpressionType>
+template<typename OtherDerived>
+inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::equal_to)
+Cwise<ExpressionType>::operator==(const MatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_CWISE_BINOP_RETURN_TYPE(std::equal_to)(_expression(), other.derived());
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise != operator of *this and \a other
+ *
+ * \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 MatrixBase::isApprox() and
+ * MatrixBase::isMuchSmallerThan().
+ *
+ * Example: \include Cwise_not_equal.cpp
+ * Output: \verbinclude Cwise_not_equal.out
+ *
+ * \sa MatrixBase::all(), MatrixBase::any(), MatrixBase::isApprox(), MatrixBase::isMuchSmallerThan()
+ */
+template<typename ExpressionType>
+template<typename OtherDerived>
+inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::not_equal_to)
+Cwise<ExpressionType>::operator!=(const MatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_CWISE_BINOP_RETURN_TYPE(std::not_equal_to)(_expression(), other.derived());
+}
+
+// comparisons to scalar value
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise \< operator of *this and a scalar \a s
+ *
+ * \sa operator<(const MatrixBase<OtherDerived> &) const
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less)
+Cwise<ExpressionType>::operator<(Scalar s) const
+{
+ return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less)(_expression(),
+ typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise \<= operator of *this and a scalar \a s
+ *
+ * \sa operator<=(const MatrixBase<OtherDerived> &) const
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less_equal)
+Cwise<ExpressionType>::operator<=(Scalar s) const
+{
+ return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less_equal)(_expression(),
+ typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise \> operator of *this and a scalar \a s
+ *
+ * \sa operator>(const MatrixBase<OtherDerived> &) const
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater)
+Cwise<ExpressionType>::operator>(Scalar s) const
+{
+ return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater)(_expression(),
+ typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise \>= operator of *this and a scalar \a s
+ *
+ * \sa operator>=(const MatrixBase<OtherDerived> &) const
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater_equal)
+Cwise<ExpressionType>::operator>=(Scalar s) const
+{
+ return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater_equal)(_expression(),
+ typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise == operator of *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 MatrixBase::isApprox() and
+ * MatrixBase::isMuchSmallerThan().
+ *
+ * \sa operator==(const MatrixBase<OtherDerived> &) const
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::equal_to)
+Cwise<ExpressionType>::operator==(Scalar s) const
+{
+ return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::equal_to)(_expression(),
+ typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
+}
+
+/** \array_module
+ *
+ * \returns an expression of the coefficient-wise != operator of *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 MatrixBase::isApprox() and
+ * MatrixBase::isMuchSmallerThan().
+ *
+ * \sa operator!=(const MatrixBase<OtherDerived> &) const
+ */
+template<typename ExpressionType>
+inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)
+Cwise<ExpressionType>::operator!=(Scalar s) const
+{
+ return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)(_expression(),
+ typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
+}
+
+// scalar addition
+
+/** \array_module
+ *
+ * \returns an expression of \c *this with each coeff incremented by the constant \a scalar
+ *
+ * Example: \include Cwise_plus.cpp
+ * Output: \verbinclude Cwise_plus.out
+ *
+ * \sa operator+=(), operator-()
+ */
+template<typename ExpressionType>
+inline const typename Cwise<ExpressionType>::ScalarAddReturnType
+Cwise<ExpressionType>::operator+(const Scalar& scalar) const
+{
+ return typename Cwise<ExpressionType>::ScalarAddReturnType(m_matrix, ei_scalar_add_op<Scalar>(scalar));
+}
+
+/** \array_module
+ *
+ * Adds the given \a scalar to each coeff of this expression.
+ *
+ * Example: \include Cwise_plus_equal.cpp
+ * Output: \verbinclude Cwise_plus_equal.out
+ *
+ * \sa operator+(), operator-=()
+ */
+template<typename ExpressionType>
+inline ExpressionType& Cwise<ExpressionType>::operator+=(const Scalar& scalar)
+{
+ return m_matrix.const_cast_derived() = *this + scalar;
+}
+
+/** \array_module
+ *
+ * \returns an expression of \c *this with each coeff decremented by the constant \a scalar
+ *
+ * Example: \include Cwise_minus.cpp
+ * Output: \verbinclude Cwise_minus.out
+ *
+ * \sa operator+(), operator-=()
+ */
+template<typename ExpressionType>
+inline const typename Cwise<ExpressionType>::ScalarAddReturnType
+Cwise<ExpressionType>::operator-(const Scalar& scalar) const
+{
+ return *this + (-scalar);
+}
+
+/** \array_module
+ *
+ * Substracts the given \a scalar from each coeff of this expression.
+ *
+ * Example: \include Cwise_minus_equal.cpp
+ * Output: \verbinclude Cwise_minus_equal.out
+ *
+ * \sa operator+=(), operator-()
+ */
+
+template<typename ExpressionType>
+inline ExpressionType& Cwise<ExpressionType>::operator-=(const Scalar& scalar)
+{
+ return m_matrix.const_cast_derived() = *this - scalar;
+}
+
+#endif // EIGEN_ARRAY_CWISE_OPERATORS_H
diff --git a/extern/Eigen2/Eigen/src/Array/Functors.h b/extern/Eigen2/Eigen/src/Array/Functors.h
new file mode 100644
index 00000000000..c2c325a788e
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Array/Functors.h
@@ -0,0 +1,309 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_ARRAY_FUNCTORS_H
+#define EIGEN_ARRAY_FUNCTORS_H
+
+/** \internal
+ * \array_module
+ *
+ * \brief Template functor to add a scalar to a fixed other one
+ *
+ * \sa class CwiseUnaryOp, Array::operator+
+ */
+/* If you wonder why doing the ei_pset1() in packetOp() is an optimization check ei_scalar_multiple_op */
+template<typename Scalar>
+struct ei_scalar_add_op {
+ typedef typename ei_packet_traits<Scalar>::type PacketScalar;
+ // FIXME default copy constructors seems bugged with std::complex<>
+ inline ei_scalar_add_op(const ei_scalar_add_op& other) : m_other(other.m_other) { }
+ inline ei_scalar_add_op(const Scalar& other) : m_other(other) { }
+ inline Scalar operator() (const Scalar& a) const { return a + m_other; }
+ inline const PacketScalar packetOp(const PacketScalar& a) const
+ { return ei_padd(a, ei_pset1(m_other)); }
+ const Scalar m_other;
+private:
+ ei_scalar_add_op& operator=(const ei_scalar_add_op&);
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_add_op<Scalar> >
+{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = ei_packet_traits<Scalar>::size>1 }; };
+
+/** \internal
+ *
+ * \array_module
+ *
+ * \brief Template functor to compute the square root of a scalar
+ *
+ * \sa class CwiseUnaryOp, Cwise::sqrt()
+ */
+template<typename Scalar> struct ei_scalar_sqrt_op EIGEN_EMPTY_STRUCT {
+ inline const Scalar operator() (const Scalar& a) const { return ei_sqrt(a); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_sqrt_op<Scalar> >
+{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
+
+/** \internal
+ *
+ * \array_module
+ *
+ * \brief Template functor to compute the exponential of a scalar
+ *
+ * \sa class CwiseUnaryOp, Cwise::exp()
+ */
+template<typename Scalar> struct ei_scalar_exp_op EIGEN_EMPTY_STRUCT {
+ inline const Scalar operator() (const Scalar& a) const { return ei_exp(a); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_exp_op<Scalar> >
+{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
+
+/** \internal
+ *
+ * \array_module
+ *
+ * \brief Template functor to compute the logarithm of a scalar
+ *
+ * \sa class CwiseUnaryOp, Cwise::log()
+ */
+template<typename Scalar> struct ei_scalar_log_op EIGEN_EMPTY_STRUCT {
+ inline const Scalar operator() (const Scalar& a) const { return ei_log(a); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_log_op<Scalar> >
+{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
+
+/** \internal
+ *
+ * \array_module
+ *
+ * \brief Template functor to compute the cosine of a scalar
+ *
+ * \sa class CwiseUnaryOp, Cwise::cos()
+ */
+template<typename Scalar> struct ei_scalar_cos_op EIGEN_EMPTY_STRUCT {
+ inline const Scalar operator() (const Scalar& a) const { return ei_cos(a); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_cos_op<Scalar> >
+{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
+
+/** \internal
+ *
+ * \array_module
+ *
+ * \brief Template functor to compute the sine of a scalar
+ *
+ * \sa class CwiseUnaryOp, Cwise::sin()
+ */
+template<typename Scalar> struct ei_scalar_sin_op EIGEN_EMPTY_STRUCT {
+ inline const Scalar operator() (const Scalar& a) const { return ei_sin(a); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_sin_op<Scalar> >
+{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
+
+/** \internal
+ *
+ * \array_module
+ *
+ * \brief Template functor to raise a scalar to a power
+ *
+ * \sa class CwiseUnaryOp, Cwise::pow
+ */
+template<typename Scalar>
+struct ei_scalar_pow_op {
+ // FIXME default copy constructors seems bugged with std::complex<>
+ inline ei_scalar_pow_op(const ei_scalar_pow_op& other) : m_exponent(other.m_exponent) { }
+ inline ei_scalar_pow_op(const Scalar& exponent) : m_exponent(exponent) {}
+ inline Scalar operator() (const Scalar& a) const { return ei_pow(a, m_exponent); }
+ const Scalar m_exponent;
+private:
+ ei_scalar_pow_op& operator=(const ei_scalar_pow_op&);
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_pow_op<Scalar> >
+{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
+
+/** \internal
+ *
+ * \array_module
+ *
+ * \brief Template functor to compute the inverse of a scalar
+ *
+ * \sa class CwiseUnaryOp, Cwise::inverse()
+ */
+template<typename Scalar>
+struct ei_scalar_inverse_op {
+ inline Scalar operator() (const Scalar& a) const { return Scalar(1)/a; }
+ template<typename PacketScalar>
+ inline const PacketScalar packetOp(const PacketScalar& a) const
+ { return ei_pdiv(ei_pset1(Scalar(1)),a); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_inverse_op<Scalar> >
+{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = int(ei_packet_traits<Scalar>::size)>1 }; };
+
+/** \internal
+ *
+ * \array_module
+ *
+ * \brief Template functor to compute the square of a scalar
+ *
+ * \sa class CwiseUnaryOp, Cwise::square()
+ */
+template<typename Scalar>
+struct ei_scalar_square_op {
+ inline Scalar operator() (const Scalar& a) const { return a*a; }
+ template<typename PacketScalar>
+ inline const PacketScalar packetOp(const PacketScalar& a) const
+ { return ei_pmul(a,a); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_square_op<Scalar> >
+{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = int(ei_packet_traits<Scalar>::size)>1 }; };
+
+/** \internal
+ *
+ * \array_module
+ *
+ * \brief Template functor to compute the cube of a scalar
+ *
+ * \sa class CwiseUnaryOp, Cwise::cube()
+ */
+template<typename Scalar>
+struct ei_scalar_cube_op {
+ inline Scalar operator() (const Scalar& a) const { return a*a*a; }
+ template<typename PacketScalar>
+ inline const PacketScalar packetOp(const PacketScalar& a) const
+ { return ei_pmul(a,ei_pmul(a,a)); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_cube_op<Scalar> >
+{ enum { Cost = 2*NumTraits<Scalar>::MulCost, PacketAccess = int(ei_packet_traits<Scalar>::size)>1 }; };
+
+// default ei_functor_traits for STL functors:
+
+template<typename T>
+struct ei_functor_traits<std::multiplies<T> >
+{ enum { Cost = NumTraits<T>::MulCost, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::divides<T> >
+{ enum { Cost = NumTraits<T>::MulCost, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::plus<T> >
+{ enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::minus<T> >
+{ enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::negate<T> >
+{ enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::logical_or<T> >
+{ enum { Cost = 1, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::logical_and<T> >
+{ enum { Cost = 1, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::logical_not<T> >
+{ enum { Cost = 1, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::greater<T> >
+{ enum { Cost = 1, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::less<T> >
+{ enum { Cost = 1, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::greater_equal<T> >
+{ enum { Cost = 1, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::less_equal<T> >
+{ enum { Cost = 1, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::equal_to<T> >
+{ enum { Cost = 1, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::not_equal_to<T> >
+{ enum { Cost = 1, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::binder2nd<T> >
+{ enum { Cost = ei_functor_traits<T>::Cost, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::binder1st<T> >
+{ enum { Cost = ei_functor_traits<T>::Cost, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::unary_negate<T> >
+{ enum { Cost = 1 + ei_functor_traits<T>::Cost, PacketAccess = false }; };
+
+template<typename T>
+struct ei_functor_traits<std::binary_negate<T> >
+{ enum { Cost = 1 + ei_functor_traits<T>::Cost, PacketAccess = false }; };
+
+#ifdef EIGEN_STDEXT_SUPPORT
+
+template<typename T0,typename T1>
+struct ei_functor_traits<std::project1st<T0,T1> >
+{ enum { Cost = 0, PacketAccess = false }; };
+
+template<typename T0,typename T1>
+struct ei_functor_traits<std::project2nd<T0,T1> >
+{ enum { Cost = 0, PacketAccess = false }; };
+
+template<typename T0,typename T1>
+struct ei_functor_traits<std::select2nd<std::pair<T0,T1> > >
+{ enum { Cost = 0, PacketAccess = false }; };
+
+template<typename T0,typename T1>
+struct ei_functor_traits<std::select1st<std::pair<T0,T1> > >
+{ enum { Cost = 0, PacketAccess = false }; };
+
+template<typename T0,typename T1>
+struct ei_functor_traits<std::unary_compose<T0,T1> >
+{ enum { Cost = ei_functor_traits<T0>::Cost + ei_functor_traits<T1>::Cost, PacketAccess = false }; };
+
+template<typename T0,typename T1,typename T2>
+struct ei_functor_traits<std::binary_compose<T0,T1,T2> >
+{ enum { Cost = ei_functor_traits<T0>::Cost + ei_functor_traits<T1>::Cost + ei_functor_traits<T2>::Cost, PacketAccess = false }; };
+
+#endif // EIGEN_STDEXT_SUPPORT
+
+#endif // EIGEN_ARRAY_FUNCTORS_H
diff --git a/extern/Eigen2/Eigen/src/Array/Norms.h b/extern/Eigen2/Eigen/src/Array/Norms.h
new file mode 100644
index 00000000000..6b92e6a099d
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Array/Norms.h
@@ -0,0 +1,80 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_ARRAY_NORMS_H
+#define EIGEN_ARRAY_NORMS_H
+
+template<typename Derived, int p>
+struct ei_lpNorm_selector
+{
+ typedef typename NumTraits<typename ei_traits<Derived>::Scalar>::Real RealScalar;
+ inline static RealScalar run(const MatrixBase<Derived>& m)
+ {
+ return ei_pow(m.cwise().abs().cwise().pow(p).sum(), RealScalar(1)/p);
+ }
+};
+
+template<typename Derived>
+struct ei_lpNorm_selector<Derived, 1>
+{
+ inline static typename NumTraits<typename ei_traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
+ {
+ return m.cwise().abs().sum();
+ }
+};
+
+template<typename Derived>
+struct ei_lpNorm_selector<Derived, 2>
+{
+ inline static typename NumTraits<typename ei_traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
+ {
+ return m.norm();
+ }
+};
+
+template<typename Derived>
+struct ei_lpNorm_selector<Derived, Infinity>
+{
+ inline static typename NumTraits<typename ei_traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
+ {
+ return m.cwise().abs().maxCoeff();
+ }
+};
+
+/** \array_module
+ *
+ * \returns the \f$ \ell^p \f$ norm of *this, that is, returns the p-th root of the sum of the p-th powers of the absolute values
+ * of the coefficients of *this. If \a p is the special value \a Eigen::Infinity, this function returns the \f$ \ell^p\infty \f$
+ * norm, that is the maximum of the absolute values of the coefficients of *this.
+ *
+ * \sa norm()
+ */
+template<typename Derived>
+template<int p>
+inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::lpNorm() const
+{
+ return ei_lpNorm_selector<Derived, p>::run(*this);
+}
+
+#endif // EIGEN_ARRAY_NORMS_H
diff --git a/extern/Eigen2/Eigen/src/Array/PartialRedux.h b/extern/Eigen2/Eigen/src/Array/PartialRedux.h
new file mode 100644
index 00000000000..3a052ca8a3d
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Array/PartialRedux.h
@@ -0,0 +1,347 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_PARTIAL_REDUX_H
+#define EIGEN_PARTIAL_REDUX_H
+
+/** \array_module \ingroup Array
+ *
+ * \class PartialReduxExpr
+ *
+ * \brief Generic expression of a partially reduxed matrix
+ *
+ * \param MatrixType the type of the matrix we are applying the redux operation
+ * \param MemberOp type of the member functor
+ * \param Direction indicates the direction of the redux (Vertical or Horizontal)
+ *
+ * This class represents an expression of a partial redux operator of a matrix.
+ * It is the return type of PartialRedux functions,
+ * and most of the time this is the only way it is used.
+ *
+ * \sa class PartialRedux
+ */
+
+template< typename MatrixType, typename MemberOp, int Direction>
+class PartialReduxExpr;
+
+template<typename MatrixType, typename MemberOp, int Direction>
+struct ei_traits<PartialReduxExpr<MatrixType, MemberOp, Direction> >
+{
+ typedef typename MemberOp::result_type Scalar;
+ typedef typename MatrixType::Scalar InputScalar;
+ typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
+ typedef typename ei_cleantype<MatrixTypeNested>::type _MatrixTypeNested;
+ enum {
+ RowsAtCompileTime = Direction==Vertical ? 1 : MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::ColsAtCompileTime,
+ MaxRowsAtCompileTime = Direction==Vertical ? 1 : MatrixType::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::MaxColsAtCompileTime,
+ Flags = (unsigned int)_MatrixTypeNested::Flags & HereditaryBits,
+ TraversalSize = Direction==Vertical ? RowsAtCompileTime : ColsAtCompileTime
+ };
+ #if EIGEN_GNUC_AT_LEAST(3,4)
+ typedef typename MemberOp::template Cost<InputScalar,int(TraversalSize)> CostOpType;
+ #else
+ typedef typename MemberOp::template Cost<InputScalar,TraversalSize> CostOpType;
+ #endif
+ enum {
+ CoeffReadCost = TraversalSize * ei_traits<_MatrixTypeNested>::CoeffReadCost + int(CostOpType::value)
+ };
+};
+
+template< typename MatrixType, typename MemberOp, int Direction>
+class PartialReduxExpr : ei_no_assignment_operator,
+ public MatrixBase<PartialReduxExpr<MatrixType, MemberOp, Direction> >
+{
+ public:
+
+ EIGEN_GENERIC_PUBLIC_INTERFACE(PartialReduxExpr)
+ typedef typename ei_traits<PartialReduxExpr>::MatrixTypeNested MatrixTypeNested;
+ typedef typename ei_traits<PartialReduxExpr>::_MatrixTypeNested _MatrixTypeNested;
+
+ PartialReduxExpr(const MatrixType& mat, const MemberOp& func = MemberOp())
+ : m_matrix(mat), m_functor(func) {}
+
+ int rows() const { return (Direction==Vertical ? 1 : m_matrix.rows()); }
+ int cols() const { return (Direction==Horizontal ? 1 : m_matrix.cols()); }
+
+ const Scalar coeff(int i, int j) const
+ {
+ if (Direction==Vertical)
+ return m_functor(m_matrix.col(j));
+ else
+ return m_functor(m_matrix.row(i));
+ }
+
+ protected:
+ const MatrixTypeNested m_matrix;
+ const MemberOp m_functor;
+};
+
+#define EIGEN_MEMBER_FUNCTOR(MEMBER,COST) \
+ template <typename ResultType> \
+ struct ei_member_##MEMBER EIGEN_EMPTY_STRUCT { \
+ typedef ResultType result_type; \
+ template<typename Scalar, int Size> struct Cost \
+ { enum { value = COST }; }; \
+ template<typename Derived> \
+ inline ResultType operator()(const MatrixBase<Derived>& mat) const \
+ { return mat.MEMBER(); } \
+ }
+
+EIGEN_MEMBER_FUNCTOR(squaredNorm, Size * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
+EIGEN_MEMBER_FUNCTOR(norm, (Size+5) * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
+EIGEN_MEMBER_FUNCTOR(sum, (Size-1)*NumTraits<Scalar>::AddCost);
+EIGEN_MEMBER_FUNCTOR(minCoeff, (Size-1)*NumTraits<Scalar>::AddCost);
+EIGEN_MEMBER_FUNCTOR(maxCoeff, (Size-1)*NumTraits<Scalar>::AddCost);
+EIGEN_MEMBER_FUNCTOR(all, (Size-1)*NumTraits<Scalar>::AddCost);
+EIGEN_MEMBER_FUNCTOR(any, (Size-1)*NumTraits<Scalar>::AddCost);
+EIGEN_MEMBER_FUNCTOR(count, (Size-1)*NumTraits<Scalar>::AddCost);
+
+/** \internal */
+template <typename BinaryOp, typename Scalar>
+struct ei_member_redux {
+ typedef typename ei_result_of<
+ BinaryOp(Scalar)
+ >::type result_type;
+ template<typename _Scalar, int Size> struct Cost
+ { enum { value = (Size-1) * ei_functor_traits<BinaryOp>::Cost }; };
+ ei_member_redux(const BinaryOp func) : m_functor(func) {}
+ template<typename Derived>
+ inline result_type operator()(const MatrixBase<Derived>& mat) const
+ { return mat.redux(m_functor); }
+ const BinaryOp m_functor;
+private:
+ ei_member_redux& operator=(const ei_member_redux&);
+};
+
+/** \array_module \ingroup Array
+ *
+ * \class PartialRedux
+ *
+ * \brief Pseudo expression providing partial reduction operations
+ *
+ * \param ExpressionType the type of the object on which to do partial reductions
+ * \param Direction indicates the direction of the redux (Vertical or Horizontal)
+ *
+ * This class represents a pseudo expression with partial reduction features.
+ * It is the return type of MatrixBase::colwise() and MatrixBase::rowwise()
+ * and most of the time this is the only way it is used.
+ *
+ * Example: \include MatrixBase_colwise.cpp
+ * Output: \verbinclude MatrixBase_colwise.out
+ *
+ * \sa MatrixBase::colwise(), MatrixBase::rowwise(), class PartialReduxExpr
+ */
+template<typename ExpressionType, int Direction> class PartialRedux
+{
+ public:
+
+ typedef typename ei_traits<ExpressionType>::Scalar Scalar;
+ typedef typename ei_meta_if<ei_must_nest_by_value<ExpressionType>::ret,
+ ExpressionType, const ExpressionType&>::ret ExpressionTypeNested;
+
+ template<template<typename _Scalar> class Functor> struct ReturnType
+ {
+ typedef PartialReduxExpr<ExpressionType,
+ Functor<typename ei_traits<ExpressionType>::Scalar>,
+ Direction
+ > Type;
+ };
+
+ template<typename BinaryOp> struct ReduxReturnType
+ {
+ typedef PartialReduxExpr<ExpressionType,
+ ei_member_redux<BinaryOp,typename ei_traits<ExpressionType>::Scalar>,
+ Direction
+ > Type;
+ };
+
+ typedef typename ExpressionType::PlainMatrixType CrossReturnType;
+
+ inline PartialRedux(const ExpressionType& matrix) : m_matrix(matrix) {}
+
+ /** \internal */
+ inline const ExpressionType& _expression() const { return m_matrix; }
+
+ template<typename BinaryOp>
+ const typename ReduxReturnType<BinaryOp>::Type
+ redux(const BinaryOp& func = BinaryOp()) const;
+
+ /** \returns a row (or column) vector expression of the smallest coefficient
+ * of each column (or row) of the referenced expression.
+ *
+ * Example: \include PartialRedux_minCoeff.cpp
+ * Output: \verbinclude PartialRedux_minCoeff.out
+ *
+ * \sa MatrixBase::minCoeff() */
+ const typename ReturnType<ei_member_minCoeff>::Type minCoeff() const
+ { return _expression(); }
+
+ /** \returns a row (or column) vector expression of the largest coefficient
+ * of each column (or row) of the referenced expression.
+ *
+ * Example: \include PartialRedux_maxCoeff.cpp
+ * Output: \verbinclude PartialRedux_maxCoeff.out
+ *
+ * \sa MatrixBase::maxCoeff() */
+ const typename ReturnType<ei_member_maxCoeff>::Type maxCoeff() const
+ { return _expression(); }
+
+ /** \returns a row (or column) vector expression of the squared norm
+ * of each column (or row) of the referenced expression.
+ *
+ * Example: \include PartialRedux_squaredNorm.cpp
+ * Output: \verbinclude PartialRedux_squaredNorm.out
+ *
+ * \sa MatrixBase::squaredNorm() */
+ const typename ReturnType<ei_member_squaredNorm>::Type squaredNorm() const
+ { return _expression(); }
+
+ /** \returns a row (or column) vector expression of the norm
+ * of each column (or row) of the referenced expression.
+ *
+ * Example: \include PartialRedux_norm.cpp
+ * Output: \verbinclude PartialRedux_norm.out
+ *
+ * \sa MatrixBase::norm() */
+ const typename ReturnType<ei_member_norm>::Type norm() const
+ { return _expression(); }
+
+ /** \returns a row (or column) vector expression of the sum
+ * of each column (or row) of the referenced expression.
+ *
+ * Example: \include PartialRedux_sum.cpp
+ * Output: \verbinclude PartialRedux_sum.out
+ *
+ * \sa MatrixBase::sum() */
+ const typename ReturnType<ei_member_sum>::Type sum() const
+ { return _expression(); }
+
+ /** \returns a row (or column) vector expression representing
+ * whether \b all coefficients of each respective column (or row) are \c true.
+ *
+ * \sa MatrixBase::all() */
+ const typename ReturnType<ei_member_all>::Type all() const
+ { return _expression(); }
+
+ /** \returns a row (or column) vector expression representing
+ * whether \b at \b least one coefficient of each respective column (or row) is \c true.
+ *
+ * \sa MatrixBase::any() */
+ const typename ReturnType<ei_member_any>::Type any() const
+ { return _expression(); }
+
+ /** \returns a row (or column) vector expression representing
+ * the number of \c true coefficients of each respective column (or row).
+ *
+ * Example: \include PartialRedux_count.cpp
+ * Output: \verbinclude PartialRedux_count.out
+ *
+ * \sa MatrixBase::count() */
+ const PartialReduxExpr<ExpressionType, ei_member_count<int>, Direction> count() const
+ { return _expression(); }
+
+ /** \returns a 3x3 matrix expression of the cross product
+ * of each column or row of the referenced expression with the \a other vector.
+ *
+ * \geometry_module
+ *
+ * \sa MatrixBase::cross() */
+ template<typename OtherDerived>
+ const CrossReturnType cross(const MatrixBase<OtherDerived>& other) const
+ {
+ EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(CrossReturnType,3,3)
+ EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,3)
+ EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
+ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
+
+ if(Direction==Vertical)
+ return (CrossReturnType()
+ << _expression().col(0).cross(other),
+ _expression().col(1).cross(other),
+ _expression().col(2).cross(other)).finished();
+ else
+ return (CrossReturnType()
+ << _expression().row(0).cross(other),
+ _expression().row(1).cross(other),
+ _expression().row(2).cross(other)).finished();
+ }
+
+ protected:
+ ExpressionTypeNested m_matrix;
+
+ private:
+ PartialRedux& operator=(const PartialRedux&);
+};
+
+/** \array_module
+ *
+ * \returns a PartialRedux wrapper of *this providing additional partial reduction operations
+ *
+ * Example: \include MatrixBase_colwise.cpp
+ * Output: \verbinclude MatrixBase_colwise.out
+ *
+ * \sa rowwise(), class PartialRedux
+ */
+template<typename Derived>
+inline const PartialRedux<Derived,Vertical>
+MatrixBase<Derived>::colwise() const
+{
+ return derived();
+}
+
+/** \array_module
+ *
+ * \returns a PartialRedux wrapper of *this providing additional partial reduction operations
+ *
+ * Example: \include MatrixBase_rowwise.cpp
+ * Output: \verbinclude MatrixBase_rowwise.out
+ *
+ * \sa colwise(), class PartialRedux
+ */
+template<typename Derived>
+inline const PartialRedux<Derived,Horizontal>
+MatrixBase<Derived>::rowwise() const
+{
+ return derived();
+}
+
+/** \returns a row or column vector expression of \c *this reduxed by \a func
+ *
+ * The template parameter \a BinaryOp is the type of the functor
+ * of the custom redux operator. Note that func must be an associative operator.
+ *
+ * \sa class PartialRedux, MatrixBase::colwise(), MatrixBase::rowwise()
+ */
+template<typename ExpressionType, int Direction>
+template<typename BinaryOp>
+const typename PartialRedux<ExpressionType,Direction>::template ReduxReturnType<BinaryOp>::Type
+PartialRedux<ExpressionType,Direction>::redux(const BinaryOp& func) const
+{
+ return typename ReduxReturnType<BinaryOp>::Type(_expression(), func);
+}
+
+#endif // EIGEN_PARTIAL_REDUX_H
diff --git a/extern/Eigen3/Eigen/src/Core/Random.h b/extern/Eigen2/Eigen/src/Array/Random.h
index b7d90103a5b..9185fe4a7d3 100644
--- a/extern/Eigen3/Eigen/src/Core/Random.h
+++ b/extern/Eigen2/Eigen/src/Array/Random.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -25,46 +25,42 @@
#ifndef EIGEN_RANDOM_H
#define EIGEN_RANDOM_H
-namespace internal {
-
-template<typename Scalar> struct scalar_random_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_random_op)
- template<typename Index>
- inline const Scalar operator() (Index, Index = 0) const { return random<Scalar>(); }
+template<typename Scalar> struct ei_scalar_random_op EIGEN_EMPTY_STRUCT {
+ inline ei_scalar_random_op(void) {}
+ inline const Scalar operator() (int, int) const { return ei_random<Scalar>(); }
};
-
template<typename Scalar>
-struct functor_traits<scalar_random_op<Scalar> >
+struct ei_functor_traits<ei_scalar_random_op<Scalar> >
{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false, IsRepeatable = false }; };
-} // end namespace internal
-
-/** \returns a random matrix expression
+/** \array_module
+ *
+ * \returns a random matrix (not an expression, the matrix is immediately evaluated).
*
* The parameters \a rows and \a cols are the number of rows and of columns of
* the returned matrix. Must be compatible with this MatrixBase type.
*
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types,
- * it is redundant to pass \a rows and \a cols as arguments, so Random() should be used
+ * it is redundant to pass \a rows and \a cols as arguments, so ei_random() should be used
* instead.
*
+ * \addexample RandomExample \label How to create a matrix with random coefficients
+ *
* Example: \include MatrixBase_random_int_int.cpp
* Output: \verbinclude MatrixBase_random_int_int.out
*
- * This expression has the "evaluate before nesting" flag so that it will be evaluated into
- * a temporary matrix whenever it is nested in a larger expression. This prevents unexpected
- * behavior with expressions involving random matrices.
- *
- * \sa MatrixBase::setRandom(), MatrixBase::Random(Index), MatrixBase::Random()
+ * \sa MatrixBase::setRandom(), MatrixBase::Random(int), MatrixBase::Random()
*/
template<typename Derived>
-inline const CwiseNullaryOp<internal::scalar_random_op<typename internal::traits<Derived>::Scalar>, Derived>
-DenseBase<Derived>::Random(Index rows, Index cols)
+inline const CwiseNullaryOp<ei_scalar_random_op<typename ei_traits<Derived>::Scalar>, Derived>
+MatrixBase<Derived>::Random(int rows, int cols)
{
- return NullaryExpr(rows, cols, internal::scalar_random_op<Scalar>());
+ return NullaryExpr(rows, cols, ei_scalar_random_op<Scalar>());
}
-/** \returns a random vector expression
+/** \array_module
+ *
+ * \returns a random vector (not an expression, the vector is immediately evaluated).
*
* The parameter \a size is the size of the returned vector.
* Must be compatible with this MatrixBase type.
@@ -72,26 +68,25 @@ DenseBase<Derived>::Random(Index rows, Index cols)
* \only_for_vectors
*
* This variant is meant to be used for dynamic-size vector types. For fixed-size types,
- * it is redundant to pass \a size as argument, so Random() should be used
+ * it is redundant to pass \a size as argument, so ei_random() should be used
* instead.
*
* Example: \include MatrixBase_random_int.cpp
* Output: \verbinclude MatrixBase_random_int.out
*
- * This expression has the "evaluate before nesting" flag so that it will be evaluated into
- * a temporary vector whenever it is nested in a larger expression. This prevents unexpected
- * behavior with expressions involving random matrices.
- *
- * \sa MatrixBase::setRandom(), MatrixBase::Random(Index,Index), MatrixBase::Random()
+ * \sa MatrixBase::setRandom(), MatrixBase::Random(int,int), MatrixBase::Random()
*/
template<typename Derived>
-inline const CwiseNullaryOp<internal::scalar_random_op<typename internal::traits<Derived>::Scalar>, Derived>
-DenseBase<Derived>::Random(Index size)
+inline const CwiseNullaryOp<ei_scalar_random_op<typename ei_traits<Derived>::Scalar>, Derived>
+MatrixBase<Derived>::Random(int size)
{
- return NullaryExpr(size, internal::scalar_random_op<Scalar>());
+ return NullaryExpr(size, ei_scalar_random_op<Scalar>());
}
-/** \returns a fixed-size random matrix or vector expression
+/** \array_module
+ *
+ * \returns a fixed-size random matrix or vector
+ * (not an expression, the matrix is immediately evaluated).
*
* This variant is only for fixed-size MatrixBase types. For dynamic-size types, you
* need to use the variants taking size arguments.
@@ -99,28 +94,26 @@ DenseBase<Derived>::Random(Index size)
* Example: \include MatrixBase_random.cpp
* Output: \verbinclude MatrixBase_random.out
*
- * This expression has the "evaluate before nesting" flag so that it will be evaluated into
- * a temporary matrix whenever it is nested in a larger expression. This prevents unexpected
- * behavior with expressions involving random matrices.
- *
- * \sa MatrixBase::setRandom(), MatrixBase::Random(Index,Index), MatrixBase::Random(Index)
+ * \sa MatrixBase::setRandom(), MatrixBase::Random(int,int), MatrixBase::Random(int)
*/
template<typename Derived>
-inline const CwiseNullaryOp<internal::scalar_random_op<typename internal::traits<Derived>::Scalar>, Derived>
-DenseBase<Derived>::Random()
+inline const CwiseNullaryOp<ei_scalar_random_op<typename ei_traits<Derived>::Scalar>, Derived>
+MatrixBase<Derived>::Random()
{
- return NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, internal::scalar_random_op<Scalar>());
+ return NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, ei_scalar_random_op<Scalar>());
}
-/** Sets all coefficients in this expression to random values.
+/** \array_module
+ *
+ * Sets all coefficients in this expression to random values.
*
* Example: \include MatrixBase_setRandom.cpp
* Output: \verbinclude MatrixBase_setRandom.out
*
- * \sa class CwiseNullaryOp, setRandom(Index), setRandom(Index,Index)
+ * \sa class CwiseNullaryOp, setRandom(int), setRandom(int,int)
*/
template<typename Derived>
-inline Derived& DenseBase<Derived>::setRandom()
+inline Derived& MatrixBase<Derived>::setRandom()
{
return *this = Random(rows(), cols());
}
@@ -132,11 +125,11 @@ inline Derived& DenseBase<Derived>::setRandom()
* Example: \include Matrix_setRandom_int.cpp
* Output: \verbinclude Matrix_setRandom_int.out
*
- * \sa MatrixBase::setRandom(), setRandom(Index,Index), class CwiseNullaryOp, MatrixBase::Random()
+ * \sa MatrixBase::setRandom(), setRandom(int,int), class CwiseNullaryOp, MatrixBase::Random()
*/
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setRandom(Index size)
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
+Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setRandom(int size)
{
resize(size);
return setRandom();
@@ -150,11 +143,11 @@ PlainObjectBase<Derived>::setRandom(Index size)
* Example: \include Matrix_setRandom_int_int.cpp
* Output: \verbinclude Matrix_setRandom_int_int.out
*
- * \sa MatrixBase::setRandom(), setRandom(Index), class CwiseNullaryOp, MatrixBase::Random()
+ * \sa MatrixBase::setRandom(), setRandom(int), class CwiseNullaryOp, MatrixBase::Random()
*/
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setRandom(Index rows, Index cols)
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
+Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setRandom(int rows, int cols)
{
resize(rows, cols);
return setRandom();
diff --git a/extern/Eigen3/Eigen/src/Core/Select.h b/extern/Eigen2/Eigen/src/Array/Select.h
index d0cd66a261a..9dc3fb1b27a 100644
--- a/extern/Eigen3/Eigen/src/Core/Select.h
+++ b/extern/Eigen2/Eigen/src/Array/Select.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -25,8 +25,9 @@
#ifndef EIGEN_SELECT_H
#define EIGEN_SELECT_H
-/** \class Select
- * \ingroup Core_Module
+/** \array_module \ingroup Array
+ *
+ * \class Select
*
* \brief Expression of a coefficient wise version of the C++ ternary operator ?:
*
@@ -35,19 +36,15 @@
* \param ElseMatrixType the type of the \em else expression
*
* This class represents an expression of a coefficient wise version of the C++ ternary operator ?:.
- * It is the return type of DenseBase::select() and most of the time this is the only way it is used.
+ * It is the return type of MatrixBase::select() and most of the time this is the only way it is used.
*
- * \sa DenseBase::select(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const
+ * \sa MatrixBase::select(const MatrixBase<ThenDerived>&, const MatrixBase<ElseDerived>&) const
*/
-namespace internal {
template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
-struct traits<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
- : traits<ThenMatrixType>
+struct ei_traits<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
{
- typedef typename traits<ThenMatrixType>::Scalar Scalar;
- typedef Dense StorageKind;
- typedef typename traits<ThenMatrixType>::XprKind XprKind;
+ typedef typename ei_traits<ThenMatrixType>::Scalar Scalar;
typedef typename ConditionMatrixType::Nested ConditionMatrixNested;
typedef typename ThenMatrixType::Nested ThenMatrixNested;
typedef typename ElseMatrixType::Nested ElseMatrixNested;
@@ -57,43 +54,41 @@ struct traits<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
MaxRowsAtCompileTime = ConditionMatrixType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = ConditionMatrixType::MaxColsAtCompileTime,
Flags = (unsigned int)ThenMatrixType::Flags & ElseMatrixType::Flags & HereditaryBits,
- CoeffReadCost = traits<typename remove_all<ConditionMatrixNested>::type>::CoeffReadCost
- + EIGEN_SIZE_MAX(traits<typename remove_all<ThenMatrixNested>::type>::CoeffReadCost,
- traits<typename remove_all<ElseMatrixNested>::type>::CoeffReadCost)
+ CoeffReadCost = ei_traits<typename ei_cleantype<ConditionMatrixNested>::type>::CoeffReadCost
+ + EIGEN_ENUM_MAX(ei_traits<typename ei_cleantype<ThenMatrixNested>::type>::CoeffReadCost,
+ ei_traits<typename ei_cleantype<ElseMatrixNested>::type>::CoeffReadCost)
};
};
-}
template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
-class Select : internal::no_assignment_operator,
- public internal::dense_xpr_base< Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >::type
+class Select : ei_no_assignment_operator,
+ public MatrixBase<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
{
public:
- typedef typename internal::dense_xpr_base<Select>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Select)
+ EIGEN_GENERIC_PUBLIC_INTERFACE(Select)
Select(const ConditionMatrixType& conditionMatrix,
const ThenMatrixType& thenMatrix,
const ElseMatrixType& elseMatrix)
: m_condition(conditionMatrix), m_then(thenMatrix), m_else(elseMatrix)
{
- eigen_assert(m_condition.rows() == m_then.rows() && m_condition.rows() == m_else.rows());
- eigen_assert(m_condition.cols() == m_then.cols() && m_condition.cols() == m_else.cols());
+ ei_assert(m_condition.rows() == m_then.rows() && m_condition.rows() == m_else.rows());
+ ei_assert(m_condition.cols() == m_then.cols() && m_condition.cols() == m_else.cols());
}
- Index rows() const { return m_condition.rows(); }
- Index cols() const { return m_condition.cols(); }
+ int rows() const { return m_condition.rows(); }
+ int cols() const { return m_condition.cols(); }
- const Scalar coeff(Index i, Index j) const
+ const Scalar coeff(int i, int j) const
{
if (m_condition.coeff(i,j))
return m_then.coeff(i,j);
else
return m_else.coeff(i,j);
}
-
- const Scalar coeff(Index i) const
+
+ const Scalar coeff(int i) const
{
if (m_condition.coeff(i))
return m_then.coeff(i);
@@ -108,7 +103,9 @@ class Select : internal::no_assignment_operator,
};
-/** \returns a matrix where each coefficient (i,j) is equal to \a thenMatrix(i,j)
+/** \array_module
+ *
+ * \returns a matrix where each coefficient (i,j) is equal to \a thenMatrix(i,j)
* if \c *this(i,j), and \a elseMatrix(i,j) otherwise.
*
* Example: \include MatrixBase_select.cpp
@@ -119,39 +116,43 @@ class Select : internal::no_assignment_operator,
template<typename Derived>
template<typename ThenDerived,typename ElseDerived>
inline const Select<Derived,ThenDerived,ElseDerived>
-DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix,
- const DenseBase<ElseDerived>& elseMatrix) const
+MatrixBase<Derived>::select(const MatrixBase<ThenDerived>& thenMatrix,
+ const MatrixBase<ElseDerived>& elseMatrix) const
{
return Select<Derived,ThenDerived,ElseDerived>(derived(), thenMatrix.derived(), elseMatrix.derived());
}
-/** Version of DenseBase::select(const DenseBase&, const DenseBase&) with
+/** \array_module
+ *
+ * Version of MatrixBase::select(const MatrixBase&, const MatrixBase&) with
* the \em else expression being a scalar value.
*
- * \sa DenseBase::select(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const, class Select
+ * \sa MatrixBase::select(const MatrixBase<ThenDerived>&, const MatrixBase<ElseDerived>&) const, class Select
*/
template<typename Derived>
template<typename ThenDerived>
-inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType>
-DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix,
+inline const Select<Derived,ThenDerived, NestByValue<typename ThenDerived::ConstantReturnType> >
+MatrixBase<Derived>::select(const MatrixBase<ThenDerived>& thenMatrix,
typename ThenDerived::Scalar elseScalar) const
{
- return Select<Derived,ThenDerived,typename ThenDerived::ConstantReturnType>(
+ return Select<Derived,ThenDerived,NestByValue<typename ThenDerived::ConstantReturnType> >(
derived(), thenMatrix.derived(), ThenDerived::Constant(rows(),cols(),elseScalar));
}
-/** Version of DenseBase::select(const DenseBase&, const DenseBase&) with
+/** \array_module
+ *
+ * Version of MatrixBase::select(const MatrixBase&, const MatrixBase&) with
* the \em then expression being a scalar value.
*
- * \sa DenseBase::select(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const, class Select
+ * \sa MatrixBase::select(const MatrixBase<ThenDerived>&, const MatrixBase<ElseDerived>&) const, class Select
*/
template<typename Derived>
template<typename ElseDerived>
-inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived >
-DenseBase<Derived>::select(typename ElseDerived::Scalar thenScalar,
- const DenseBase<ElseDerived>& elseMatrix) const
+inline const Select<Derived, NestByValue<typename ElseDerived::ConstantReturnType>, ElseDerived >
+MatrixBase<Derived>::select(typename ElseDerived::Scalar thenScalar,
+ const MatrixBase<ElseDerived>& elseMatrix) const
{
- return Select<Derived,typename ElseDerived::ConstantReturnType,ElseDerived>(
+ return Select<Derived,NestByValue<typename ElseDerived::ConstantReturnType>,ElseDerived>(
derived(), ElseDerived::Constant(rows(),cols(),thenScalar), elseMatrix.derived());
}
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Macros.h b/extern/Eigen2/Eigen/src/Cholesky/CholeskyInstantiations.cpp
index 77e85a41e3d..e7f40a2ce9c 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Macros.h
+++ b/extern/Eigen2/Eigen/src/Cholesky/CholeskyInstantiations.cpp
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -22,14 +22,14 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-#ifndef EIGEN2_MACROS_H
-#define EIGEN2_MACROS_H
+#ifndef EIGEN_EXTERN_INSTANTIATIONS
+#define EIGEN_EXTERN_INSTANTIATIONS
+#endif
+#include "../../Core"
+#undef EIGEN_EXTERN_INSTANTIATIONS
-#define ei_assert eigen_assert
-#define ei_internal_assert eigen_internal_assert
+#include "../../Cholesky"
-#define EIGEN_ALIGN_128 EIGEN_ALIGN16
-
-#define EIGEN_ARCH_WANTS_ALIGNMENT EIGEN_ALIGN_STATICALLY
-
-#endif // EIGEN2_MACROS_H
+namespace Eigen {
+ EIGEN_CHOLESKY_MODULE_INSTANTIATE();
+}
diff --git a/extern/Eigen2/Eigen/src/Cholesky/LDLT.h b/extern/Eigen2/Eigen/src/Cholesky/LDLT.h
new file mode 100644
index 00000000000..205b78a6ded
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Cholesky/LDLT.h
@@ -0,0 +1,198 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_LDLT_H
+#define EIGEN_LDLT_H
+
+/** \ingroup cholesky_Module
+ *
+ * \class LDLT
+ *
+ * \brief Robust Cholesky decomposition of a matrix and associated features
+ *
+ * \param MatrixType the type of the matrix of which we are computing the LDL^T Cholesky decomposition
+ *
+ * This class performs a Cholesky decomposition without square root of a symmetric, positive definite
+ * matrix A such that A = L D L^* = U^* D U, where L is lower triangular with a unit diagonal
+ * and D is a diagonal matrix.
+ *
+ * Compared to a standard Cholesky decomposition, avoiding the square roots allows for faster and more
+ * stable computation.
+ *
+ * Note that during the decomposition, only the upper triangular part of A is considered. Therefore,
+ * the strict lower part does not have to store correct values.
+ *
+ * \sa MatrixBase::ldlt(), class LLT
+ */
+template<typename MatrixType> class LDLT
+{
+ public:
+
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+ typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
+
+ LDLT(const MatrixType& matrix)
+ : m_matrix(matrix.rows(), matrix.cols())
+ {
+ compute(matrix);
+ }
+
+ /** \returns the lower triangular matrix L */
+ inline Part<MatrixType, UnitLowerTriangular> matrixL(void) const { return m_matrix; }
+
+ /** \returns the coefficients of the diagonal matrix D */
+ inline DiagonalCoeffs<MatrixType> vectorD(void) const { return m_matrix.diagonal(); }
+
+ /** \returns true if the matrix is positive definite */
+ inline bool isPositiveDefinite(void) const { return m_isPositiveDefinite; }
+
+ template<typename RhsDerived, typename ResultType>
+ bool solve(const MatrixBase<RhsDerived> &b, ResultType *result) const;
+
+ template<typename Derived>
+ bool solveInPlace(MatrixBase<Derived> &bAndX) const;
+
+ void compute(const MatrixType& matrix);
+
+ protected:
+ /** \internal
+ * Used to compute and store the cholesky decomposition A = L D L^* = U^* D U.
+ * The strict upper part is used during the decomposition, the strict lower
+ * part correspond to the coefficients of L (its diagonal is equal to 1 and
+ * is not stored), and the diagonal entries correspond to D.
+ */
+ MatrixType m_matrix;
+
+ bool m_isPositiveDefinite;
+};
+
+/** Compute / recompute the LLT decomposition A = L D L^* = U^* D U of \a matrix
+ */
+template<typename MatrixType>
+void LDLT<MatrixType>::compute(const MatrixType& a)
+{
+ assert(a.rows()==a.cols());
+ const int size = a.rows();
+ m_matrix.resize(size, size);
+ m_isPositiveDefinite = true;
+ const RealScalar eps = ei_sqrt(precision<Scalar>());
+
+ if (size<=1)
+ {
+ m_matrix = a;
+ return;
+ }
+
+ // Let's preallocate a temporay vector to evaluate the matrix-vector product into it.
+ // Unlike the standard LLT decomposition, here we cannot evaluate it to the destination
+ // matrix because it a sub-row which is not compatible suitable for efficient packet evaluation.
+ // (at least if we assume the matrix is col-major)
+ Matrix<Scalar,MatrixType::RowsAtCompileTime,1> _temporary(size);
+
+ // Note that, in this algorithm the rows of the strict upper part of m_matrix is used to store
+ // column vector, thus the strange .conjugate() and .transpose()...
+
+ m_matrix.row(0) = a.row(0).conjugate();
+ m_matrix.col(0).end(size-1) = m_matrix.row(0).end(size-1) / m_matrix.coeff(0,0);
+ for (int j = 1; j < size; ++j)
+ {
+ RealScalar tmp = ei_real(a.coeff(j,j) - (m_matrix.row(j).start(j) * m_matrix.col(j).start(j).conjugate()).coeff(0,0));
+ m_matrix.coeffRef(j,j) = tmp;
+
+ if (tmp < eps)
+ {
+ m_isPositiveDefinite = false;
+ return;
+ }
+
+ int endSize = size-j-1;
+ if (endSize>0)
+ {
+ _temporary.end(endSize) = ( m_matrix.block(j+1,0, endSize, j)
+ * m_matrix.col(j).start(j).conjugate() ).lazy();
+
+ m_matrix.row(j).end(endSize) = a.row(j).end(endSize).conjugate()
+ - _temporary.end(endSize).transpose();
+
+ m_matrix.col(j).end(endSize) = m_matrix.row(j).end(endSize) / tmp;
+ }
+ }
+}
+
+/** Computes the solution x of \f$ A x = b \f$ using the current decomposition of A.
+ * The result is stored in \a result
+ *
+ * \returns true in case of success, false otherwise.
+ *
+ * In other words, it computes \f$ b = A^{-1} b \f$ with
+ * \f$ {L^{*}}^{-1} D^{-1} L^{-1} b \f$ from right to left.
+ *
+ * \sa LDLT::solveInPlace(), MatrixBase::ldlt()
+ */
+template<typename MatrixType>
+template<typename RhsDerived, typename ResultType>
+bool LDLT<MatrixType>
+::solve(const MatrixBase<RhsDerived> &b, ResultType *result) const
+{
+ const int size = m_matrix.rows();
+ ei_assert(size==b.rows() && "LLT::solve(): invalid number of rows of the right hand side matrix b");
+ *result = b;
+ return solveInPlace(*result);
+}
+
+/** This is the \em in-place version of solve().
+ *
+ * \param bAndX represents both the right-hand side matrix b and result x.
+ *
+ * This version avoids a copy when the right hand side matrix b is not
+ * needed anymore.
+ *
+ * \sa LDLT::solve(), MatrixBase::ldlt()
+ */
+template<typename MatrixType>
+template<typename Derived>
+bool LDLT<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
+{
+ const int size = m_matrix.rows();
+ ei_assert(size==bAndX.rows());
+ if (!m_isPositiveDefinite)
+ return false;
+ matrixL().solveTriangularInPlace(bAndX);
+ bAndX = (m_matrix.cwise().inverse().template part<Diagonal>() * bAndX).lazy();
+ m_matrix.adjoint().template part<UnitUpperTriangular>().solveTriangularInPlace(bAndX);
+ return true;
+}
+
+/** \cholesky_module
+ * \returns the Cholesky decomposition without square root of \c *this
+ */
+template<typename Derived>
+inline const LDLT<typename MatrixBase<Derived>::PlainMatrixType>
+MatrixBase<Derived>::ldlt() const
+{
+ return derived();
+}
+
+#endif // EIGEN_LDLT_H
diff --git a/extern/Eigen2/Eigen/src/Cholesky/LLT.h b/extern/Eigen2/Eigen/src/Cholesky/LLT.h
new file mode 100644
index 00000000000..42c959f83a2
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Cholesky/LLT.h
@@ -0,0 +1,219 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_LLT_H
+#define EIGEN_LLT_H
+
+/** \ingroup cholesky_Module
+ *
+ * \class LLT
+ *
+ * \brief Standard Cholesky decomposition (LL^T) of a matrix and associated features
+ *
+ * \param MatrixType the type of the matrix of which we are computing the LL^T Cholesky decomposition
+ *
+ * This class performs a LL^T Cholesky decomposition of a symmetric, positive definite
+ * matrix A such that A = LL^* = U^*U, where L is lower triangular.
+ *
+ * While the Cholesky decomposition is particularly useful to solve selfadjoint problems like D^*D x = b,
+ * for that purpose, we recommend the Cholesky decomposition without square root which is more stable
+ * and even faster. Nevertheless, this standard Cholesky decomposition remains useful in many other
+ * situations like generalised eigen problems with hermitian matrices.
+ *
+ * Remember that Cholesky decompositions are not rank-revealing. This LLT decomposition is only stable on positive definite matrices,
+ * use LDLT instead for the semidefinite case. Also, do not use a Cholesky decomposition to determine whether a system of equations
+ * has a solution.
+ *
+ * \sa MatrixBase::llt(), class LDLT
+ */
+ /* HEY THIS DOX IS DISABLED BECAUSE THERE's A BUG EITHER HERE OR IN LDLT ABOUT THAT (OR BOTH)
+ * Note that during the decomposition, only the upper triangular part of A is considered. Therefore,
+ * the strict lower part does not have to store correct values.
+ */
+template<typename MatrixType> class LLT
+{
+ private:
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+ typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
+
+ enum {
+ PacketSize = ei_packet_traits<Scalar>::size,
+ AlignmentMask = int(PacketSize)-1
+ };
+
+ public:
+
+ /**
+ * \brief Default Constructor.
+ *
+ * The default constructor is useful in cases in which the user intends to
+ * perform decompositions via LLT::compute(const MatrixType&).
+ */
+ LLT() : m_matrix(), m_isInitialized(false) {}
+
+ LLT(const MatrixType& matrix)
+ : m_matrix(matrix.rows(), matrix.cols()),
+ m_isInitialized(false)
+ {
+ compute(matrix);
+ }
+
+ /** \returns the lower triangular matrix L */
+ inline Part<MatrixType, LowerTriangular> matrixL(void) const
+ {
+ ei_assert(m_isInitialized && "LLT is not initialized.");
+ return m_matrix;
+ }
+
+ /** \deprecated */
+ inline bool isPositiveDefinite(void) const { return m_isInitialized && m_isPositiveDefinite; }
+
+ template<typename RhsDerived, typename ResultType>
+ bool solve(const MatrixBase<RhsDerived> &b, ResultType *result) const;
+
+ template<typename Derived>
+ bool solveInPlace(MatrixBase<Derived> &bAndX) const;
+
+ void compute(const MatrixType& matrix);
+
+ protected:
+ /** \internal
+ * Used to compute and store L
+ * The strict upper part is not used and even not initialized.
+ */
+ MatrixType m_matrix;
+ bool m_isInitialized;
+ bool m_isPositiveDefinite;
+};
+
+/** Computes / recomputes the Cholesky decomposition A = LL^* = U^*U of \a matrix
+ */
+template<typename MatrixType>
+void LLT<MatrixType>::compute(const MatrixType& a)
+{
+ assert(a.rows()==a.cols());
+ m_isPositiveDefinite = true;
+ const int size = a.rows();
+ m_matrix.resize(size, size);
+ // 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. This cutoff is suggested
+ // in "Analysis of the Cholesky Decomposition of a Semi-definite Matrix" by
+ // Nicholas J. Higham. Also see "Accuracy and Stability of Numerical
+ // Algorithms" page 217, also by Higham.
+ const RealScalar cutoff = machine_epsilon<Scalar>() * size * a.diagonal().cwise().abs().maxCoeff();
+ RealScalar x;
+ x = ei_real(a.coeff(0,0));
+ m_matrix.coeffRef(0,0) = ei_sqrt(x);
+ if(size==1)
+ {
+ m_isInitialized = true;
+ return;
+ }
+ m_matrix.col(0).end(size-1) = a.row(0).end(size-1).adjoint() / ei_real(m_matrix.coeff(0,0));
+ for (int j = 1; j < size; ++j)
+ {
+ x = ei_real(a.coeff(j,j)) - m_matrix.row(j).start(j).squaredNorm();
+ if (x < cutoff)
+ {
+ m_isPositiveDefinite = false;
+ continue;
+ }
+
+ m_matrix.coeffRef(j,j) = x = ei_sqrt(x);
+
+ int endSize = size-j-1;
+ if (endSize>0) {
+ // Note that when all matrix columns have good alignment, then the following
+ // product is guaranteed to be optimal with respect to alignment.
+ m_matrix.col(j).end(endSize) =
+ (m_matrix.block(j+1, 0, endSize, j) * m_matrix.row(j).start(j).adjoint()).lazy();
+
+ // FIXME could use a.col instead of a.row
+ m_matrix.col(j).end(endSize) = (a.row(j).end(endSize).adjoint()
+ - m_matrix.col(j).end(endSize) ) / x;
+ }
+ }
+
+ m_isInitialized = true;
+}
+
+/** Computes the solution x of \f$ A x = b \f$ using the current decomposition of A.
+ * The result is stored in \a result
+ *
+ * \returns true always! If you need to check for existence of solutions, use another decomposition like LU, QR, or SVD.
+ *
+ * In other words, it computes \f$ b = A^{-1} b \f$ with
+ * \f$ {L^{*}}^{-1} L^{-1} b \f$ from right to left.
+ *
+ * Example: \include LLT_solve.cpp
+ * Output: \verbinclude LLT_solve.out
+ *
+ * \sa LLT::solveInPlace(), MatrixBase::llt()
+ */
+template<typename MatrixType>
+template<typename RhsDerived, typename ResultType>
+bool LLT<MatrixType>::solve(const MatrixBase<RhsDerived> &b, ResultType *result) const
+{
+ ei_assert(m_isInitialized && "LLT is not initialized.");
+ const int size = m_matrix.rows();
+ ei_assert(size==b.rows() && "LLT::solve(): invalid number of rows of the right hand side matrix b");
+ return solveInPlace((*result) = b);
+}
+
+/** This is the \em in-place version of solve().
+ *
+ * \param bAndX represents both the right-hand side matrix b and result x.
+ *
+ * \returns true always! If you need to check for existence of solutions, use another decomposition like LU, QR, or SVD.
+ *
+ * This version avoids a copy when the right hand side matrix b is not
+ * needed anymore.
+ *
+ * \sa LLT::solve(), MatrixBase::llt()
+ */
+template<typename MatrixType>
+template<typename Derived>
+bool LLT<MatrixType>::solveInPlace(MatrixBase<Derived> &bAndX) const
+{
+ ei_assert(m_isInitialized && "LLT is not initialized.");
+ const int size = m_matrix.rows();
+ ei_assert(size==bAndX.rows());
+ matrixL().solveTriangularInPlace(bAndX);
+ m_matrix.adjoint().template part<UpperTriangular>().solveTriangularInPlace(bAndX);
+ return true;
+}
+
+/** \cholesky_module
+ * \returns the LLT decomposition of \c *this
+ */
+template<typename Derived>
+inline const LLT<typename MatrixBase<Derived>::PlainMatrixType>
+MatrixBase<Derived>::llt() const
+{
+ return LLT<PlainMatrixType>(derived());
+}
+
+#endif // EIGEN_LLT_H
diff --git a/extern/Eigen2/Eigen/src/Core/Assign.h b/extern/Eigen2/Eigen/src/Core/Assign.h
new file mode 100644
index 00000000000..57205075596
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/Assign.h
@@ -0,0 +1,445 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2007 Michael Olbrich <michael.olbrich@gmx.net>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_ASSIGN_H
+#define EIGEN_ASSIGN_H
+
+/***************************************************************************
+* Part 1 : the logic deciding a strategy for vectorization and unrolling
+***************************************************************************/
+
+template <typename Derived, typename OtherDerived>
+struct ei_assign_traits
+{
+public:
+ enum {
+ DstIsAligned = Derived::Flags & AlignedBit,
+ SrcIsAligned = OtherDerived::Flags & AlignedBit,
+ SrcAlignment = DstIsAligned && SrcIsAligned ? Aligned : Unaligned
+ };
+
+private:
+ enum {
+ InnerSize = int(Derived::Flags)&RowMajorBit
+ ? Derived::ColsAtCompileTime
+ : Derived::RowsAtCompileTime,
+ InnerMaxSize = int(Derived::Flags)&RowMajorBit
+ ? Derived::MaxColsAtCompileTime
+ : Derived::MaxRowsAtCompileTime,
+ PacketSize = ei_packet_traits<typename Derived::Scalar>::size
+ };
+
+ enum {
+ MightVectorize = (int(Derived::Flags) & int(OtherDerived::Flags) & ActualPacketAccessBit)
+ && ((int(Derived::Flags)&RowMajorBit)==(int(OtherDerived::Flags)&RowMajorBit)),
+ MayInnerVectorize = MightVectorize && int(InnerSize)!=Dynamic && int(InnerSize)%int(PacketSize)==0
+ && int(DstIsAligned) && int(SrcIsAligned),
+ MayLinearVectorize = MightVectorize && (int(Derived::Flags) & int(OtherDerived::Flags) & LinearAccessBit),
+ MaySliceVectorize = MightVectorize && int(InnerMaxSize)>=3*PacketSize /* slice vectorization can be slow, so we only
+ want it if the slices are big, which is indicated by InnerMaxSize rather than InnerSize, think of the case
+ of a dynamic block in a fixed-size matrix */
+ };
+
+public:
+ enum {
+ Vectorization = int(MayInnerVectorize) ? int(InnerVectorization)
+ : int(MayLinearVectorize) ? int(LinearVectorization)
+ : int(MaySliceVectorize) ? int(SliceVectorization)
+ : int(NoVectorization)
+ };
+
+private:
+ enum {
+ UnrollingLimit = EIGEN_UNROLLING_LIMIT * (int(Vectorization) == int(NoVectorization) ? 1 : int(PacketSize)),
+ MayUnrollCompletely = int(Derived::SizeAtCompileTime) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit),
+ MayUnrollInner = int(InnerSize * OtherDerived::CoeffReadCost) <= int(UnrollingLimit)
+ };
+
+public:
+ enum {
+ Unrolling = (int(Vectorization) == int(InnerVectorization) || int(Vectorization) == int(NoVectorization))
+ ? (
+ int(MayUnrollCompletely) ? int(CompleteUnrolling)
+ : int(MayUnrollInner) ? int(InnerUnrolling)
+ : int(NoUnrolling)
+ )
+ : int(Vectorization) == int(LinearVectorization)
+ ? ( int(MayUnrollCompletely) && int(DstIsAligned) ? int(CompleteUnrolling) : int(NoUnrolling) )
+ : int(NoUnrolling)
+ };
+};
+
+/***************************************************************************
+* Part 2 : meta-unrollers
+***************************************************************************/
+
+/***********************
+*** No vectorization ***
+***********************/
+
+template<typename Derived1, typename Derived2, int Index, int Stop>
+struct ei_assign_novec_CompleteUnrolling
+{
+ enum {
+ row = int(Derived1::Flags)&RowMajorBit
+ ? Index / int(Derived1::ColsAtCompileTime)
+ : Index % Derived1::RowsAtCompileTime,
+ col = int(Derived1::Flags)&RowMajorBit
+ ? Index % int(Derived1::ColsAtCompileTime)
+ : Index / Derived1::RowsAtCompileTime
+ };
+
+ EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
+ {
+ dst.copyCoeff(row, col, src);
+ ei_assign_novec_CompleteUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src);
+ }
+};
+
+template<typename Derived1, typename Derived2, int Stop>
+struct ei_assign_novec_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
+{
+ EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &) {}
+};
+
+template<typename Derived1, typename Derived2, int Index, int Stop>
+struct ei_assign_novec_InnerUnrolling
+{
+ EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src, int row_or_col)
+ {
+ const bool rowMajor = int(Derived1::Flags)&RowMajorBit;
+ const int row = rowMajor ? row_or_col : Index;
+ const int col = rowMajor ? Index : row_or_col;
+ dst.copyCoeff(row, col, src);
+ ei_assign_novec_InnerUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src, row_or_col);
+ }
+};
+
+template<typename Derived1, typename Derived2, int Stop>
+struct ei_assign_novec_InnerUnrolling<Derived1, Derived2, Stop, Stop>
+{
+ EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &, int) {}
+};
+
+/**************************
+*** Inner vectorization ***
+**************************/
+
+template<typename Derived1, typename Derived2, int Index, int Stop>
+struct ei_assign_innervec_CompleteUnrolling
+{
+ enum {
+ row = int(Derived1::Flags)&RowMajorBit
+ ? Index / int(Derived1::ColsAtCompileTime)
+ : Index % Derived1::RowsAtCompileTime,
+ col = int(Derived1::Flags)&RowMajorBit
+ ? Index % int(Derived1::ColsAtCompileTime)
+ : Index / Derived1::RowsAtCompileTime,
+ SrcAlignment = ei_assign_traits<Derived1,Derived2>::SrcAlignment
+ };
+
+ EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
+ {
+ dst.template copyPacket<Derived2, Aligned, SrcAlignment>(row, col, src);
+ ei_assign_innervec_CompleteUnrolling<Derived1, Derived2,
+ Index+ei_packet_traits<typename Derived1::Scalar>::size, Stop>::run(dst, src);
+ }
+};
+
+template<typename Derived1, typename Derived2, int Stop>
+struct ei_assign_innervec_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
+{
+ EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &) {}
+};
+
+template<typename Derived1, typename Derived2, int Index, int Stop>
+struct ei_assign_innervec_InnerUnrolling
+{
+ EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src, int row_or_col)
+ {
+ const int row = int(Derived1::Flags)&RowMajorBit ? row_or_col : Index;
+ const int col = int(Derived1::Flags)&RowMajorBit ? Index : row_or_col;
+ dst.template copyPacket<Derived2, Aligned, Aligned>(row, col, src);
+ ei_assign_innervec_InnerUnrolling<Derived1, Derived2,
+ Index+ei_packet_traits<typename Derived1::Scalar>::size, Stop>::run(dst, src, row_or_col);
+ }
+};
+
+template<typename Derived1, typename Derived2, int Stop>
+struct ei_assign_innervec_InnerUnrolling<Derived1, Derived2, Stop, Stop>
+{
+ EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &, int) {}
+};
+
+/***************************************************************************
+* Part 3 : implementation of all cases
+***************************************************************************/
+
+template<typename Derived1, typename Derived2,
+ int Vectorization = ei_assign_traits<Derived1, Derived2>::Vectorization,
+ int Unrolling = ei_assign_traits<Derived1, Derived2>::Unrolling>
+struct ei_assign_impl;
+
+/***********************
+*** No vectorization ***
+***********************/
+
+template<typename Derived1, typename Derived2>
+struct ei_assign_impl<Derived1, Derived2, NoVectorization, NoUnrolling>
+{
+ inline static void run(Derived1 &dst, const Derived2 &src)
+ {
+ const int innerSize = dst.innerSize();
+ const int outerSize = dst.outerSize();
+ for(int j = 0; j < outerSize; ++j)
+ for(int i = 0; i < innerSize; ++i)
+ {
+ if(int(Derived1::Flags)&RowMajorBit)
+ dst.copyCoeff(j, i, src);
+ else
+ dst.copyCoeff(i, j, src);
+ }
+ }
+};
+
+template<typename Derived1, typename Derived2>
+struct ei_assign_impl<Derived1, Derived2, NoVectorization, CompleteUnrolling>
+{
+ EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
+ {
+ ei_assign_novec_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
+ ::run(dst, src);
+ }
+};
+
+template<typename Derived1, typename Derived2>
+struct ei_assign_impl<Derived1, Derived2, NoVectorization, InnerUnrolling>
+{
+ EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
+ {
+ const bool rowMajor = int(Derived1::Flags)&RowMajorBit;
+ const int innerSize = rowMajor ? Derived1::ColsAtCompileTime : Derived1::RowsAtCompileTime;
+ const int outerSize = dst.outerSize();
+ for(int j = 0; j < outerSize; ++j)
+ ei_assign_novec_InnerUnrolling<Derived1, Derived2, 0, innerSize>
+ ::run(dst, src, j);
+ }
+};
+
+/**************************
+*** Inner vectorization ***
+**************************/
+
+template<typename Derived1, typename Derived2>
+struct ei_assign_impl<Derived1, Derived2, InnerVectorization, NoUnrolling>
+{
+ inline static void run(Derived1 &dst, const Derived2 &src)
+ {
+ const int innerSize = dst.innerSize();
+ const int outerSize = dst.outerSize();
+ const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
+ for(int j = 0; j < outerSize; ++j)
+ for(int i = 0; i < innerSize; i+=packetSize)
+ {
+ if(int(Derived1::Flags)&RowMajorBit)
+ dst.template copyPacket<Derived2, Aligned, Aligned>(j, i, src);
+ else
+ dst.template copyPacket<Derived2, Aligned, Aligned>(i, j, src);
+ }
+ }
+};
+
+template<typename Derived1, typename Derived2>
+struct ei_assign_impl<Derived1, Derived2, InnerVectorization, CompleteUnrolling>
+{
+ EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
+ {
+ ei_assign_innervec_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
+ ::run(dst, src);
+ }
+};
+
+template<typename Derived1, typename Derived2>
+struct ei_assign_impl<Derived1, Derived2, InnerVectorization, InnerUnrolling>
+{
+ EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
+ {
+ const bool rowMajor = int(Derived1::Flags)&RowMajorBit;
+ const int innerSize = rowMajor ? Derived1::ColsAtCompileTime : Derived1::RowsAtCompileTime;
+ const int outerSize = dst.outerSize();
+ for(int j = 0; j < outerSize; ++j)
+ ei_assign_innervec_InnerUnrolling<Derived1, Derived2, 0, innerSize>
+ ::run(dst, src, j);
+ }
+};
+
+/***************************
+*** Linear vectorization ***
+***************************/
+
+template<typename Derived1, typename Derived2>
+struct ei_assign_impl<Derived1, Derived2, LinearVectorization, NoUnrolling>
+{
+ inline static void run(Derived1 &dst, const Derived2 &src)
+ {
+ const int size = dst.size();
+ const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
+ const int alignedStart = ei_assign_traits<Derived1,Derived2>::DstIsAligned ? 0
+ : ei_alignmentOffset(&dst.coeffRef(0), size);
+ const int alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize;
+
+ for(int index = 0; index < alignedStart; ++index)
+ dst.copyCoeff(index, src);
+
+ for(int index = alignedStart; index < alignedEnd; index += packetSize)
+ {
+ dst.template copyPacket<Derived2, Aligned, ei_assign_traits<Derived1,Derived2>::SrcAlignment>(index, src);
+ }
+
+ for(int index = alignedEnd; index < size; ++index)
+ dst.copyCoeff(index, src);
+ }
+};
+
+template<typename Derived1, typename Derived2>
+struct ei_assign_impl<Derived1, Derived2, LinearVectorization, CompleteUnrolling>
+{
+ EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
+ {
+ const int size = Derived1::SizeAtCompileTime;
+ const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
+ const int alignedSize = (size/packetSize)*packetSize;
+
+ ei_assign_innervec_CompleteUnrolling<Derived1, Derived2, 0, alignedSize>::run(dst, src);
+ ei_assign_novec_CompleteUnrolling<Derived1, Derived2, alignedSize, size>::run(dst, src);
+ }
+};
+
+/**************************
+*** Slice vectorization ***
+***************************/
+
+template<typename Derived1, typename Derived2>
+struct ei_assign_impl<Derived1, Derived2, SliceVectorization, NoUnrolling>
+{
+ inline static void run(Derived1 &dst, const Derived2 &src)
+ {
+ const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
+ const int packetAlignedMask = packetSize - 1;
+ const int innerSize = dst.innerSize();
+ const int outerSize = dst.outerSize();
+ const int alignedStep = (packetSize - dst.stride() % packetSize) & packetAlignedMask;
+ int alignedStart = ei_assign_traits<Derived1,Derived2>::DstIsAligned ? 0
+ : ei_alignmentOffset(&dst.coeffRef(0,0), innerSize);
+
+ for(int i = 0; i < outerSize; ++i)
+ {
+ const int alignedEnd = alignedStart + ((innerSize-alignedStart) & ~packetAlignedMask);
+
+ // do the non-vectorizable part of the assignment
+ for (int index = 0; index<alignedStart ; ++index)
+ {
+ if(Derived1::Flags&RowMajorBit)
+ dst.copyCoeff(i, index, src);
+ else
+ dst.copyCoeff(index, i, src);
+ }
+
+ // do the vectorizable part of the assignment
+ for (int index = alignedStart; index<alignedEnd; index+=packetSize)
+ {
+ if(Derived1::Flags&RowMajorBit)
+ dst.template copyPacket<Derived2, Aligned, Unaligned>(i, index, src);
+ else
+ dst.template copyPacket<Derived2, Aligned, Unaligned>(index, i, src);
+ }
+
+ // do the non-vectorizable part of the assignment
+ for (int index = alignedEnd; index<innerSize ; ++index)
+ {
+ if(Derived1::Flags&RowMajorBit)
+ dst.copyCoeff(i, index, src);
+ else
+ dst.copyCoeff(index, i, src);
+ }
+
+ alignedStart = std::min<int>((alignedStart+alignedStep)%packetSize, innerSize);
+ }
+ }
+};
+
+/***************************************************************************
+* Part 4 : implementation of MatrixBase methods
+***************************************************************************/
+
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
+ ::lazyAssign(const MatrixBase<OtherDerived>& other)
+{
+ EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived)
+ EIGEN_STATIC_ASSERT((ei_is_same_type<typename Derived::Scalar, typename OtherDerived::Scalar>::ret),
+ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
+ ei_assert(rows() == other.rows() && cols() == other.cols());
+ ei_assign_impl<Derived, OtherDerived>::run(derived(),other.derived());
+ return derived();
+}
+
+template<typename Derived, typename OtherDerived,
+ bool EvalBeforeAssigning = (int(OtherDerived::Flags) & EvalBeforeAssigningBit) != 0,
+ bool NeedToTranspose = Derived::IsVectorAtCompileTime
+ && OtherDerived::IsVectorAtCompileTime
+ && int(Derived::RowsAtCompileTime) == int(OtherDerived::ColsAtCompileTime)
+ && int(Derived::ColsAtCompileTime) == int(OtherDerived::RowsAtCompileTime)
+ && int(Derived::SizeAtCompileTime) != 1>
+struct ei_assign_selector;
+
+template<typename Derived, typename OtherDerived>
+struct ei_assign_selector<Derived,OtherDerived,false,false> {
+ EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); }
+};
+template<typename Derived, typename OtherDerived>
+struct ei_assign_selector<Derived,OtherDerived,true,false> {
+ EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); }
+};
+template<typename Derived, typename OtherDerived>
+struct ei_assign_selector<Derived,OtherDerived,false,true> {
+ EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); }
+};
+template<typename Derived, typename OtherDerived>
+struct ei_assign_selector<Derived,OtherDerived,true,true> {
+ EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); }
+};
+
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
+ ::operator=(const MatrixBase<OtherDerived>& other)
+{
+ return ei_assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
+}
+
+#endif // EIGEN_ASSIGN_H
diff --git a/extern/Eigen2/Eigen/src/Core/Block.h b/extern/Eigen2/Eigen/src/Core/Block.h
new file mode 100644
index 00000000000..7f422aa5c07
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/Block.h
@@ -0,0 +1,752 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_BLOCK_H
+#define EIGEN_BLOCK_H
+
+/** \class Block
+ *
+ * \brief Expression of a fixed-size or dynamic-size block
+ *
+ * \param MatrixType the type of the object in which we are taking a block
+ * \param BlockRows the number of rows of the block we are taking at compile time (optional)
+ * \param BlockCols the number of columns of the block we are taking at compile time (optional)
+ * \param _PacketAccess allows to enforce aligned loads and stores if set to ForceAligned.
+ * The default is AsRequested. This parameter is internaly used by Eigen
+ * in expressions such as \code mat.block() += other; \endcode and most of
+ * the time this is the only way it is used.
+ * \param _DirectAccessStatus \internal used for partial specialization
+ *
+ * This class represents an expression of either a fixed-size or dynamic-size block. It is the return
+ * type of MatrixBase::block(int,int,int,int) and MatrixBase::block<int,int>(int,int) and
+ * most of the time this is the only way it is used.
+ *
+ * However, if you want to directly maniputate block expressions,
+ * for instance if you want to write a function returning such an expression, you
+ * will need to use this class.
+ *
+ * Here is an example illustrating the dynamic case:
+ * \include class_Block.cpp
+ * Output: \verbinclude class_Block.out
+ *
+ * \note Even though this expression has dynamic size, in the case where \a MatrixType
+ * has fixed size, this expression inherits a fixed maximal size which means that evaluating
+ * it does not cause a dynamic memory allocation.
+ *
+ * Here is an example illustrating the fixed-size case:
+ * \include class_FixedBlock.cpp
+ * Output: \verbinclude class_FixedBlock.out
+ *
+ * \sa MatrixBase::block(int,int,int,int), MatrixBase::block(int,int), class VectorBlock
+ */
+
+template<typename MatrixType, int BlockRows, int BlockCols, int _PacketAccess, int _DirectAccessStatus>
+struct ei_traits<Block<MatrixType, BlockRows, BlockCols, _PacketAccess, _DirectAccessStatus> >
+{
+ typedef typename ei_traits<MatrixType>::Scalar Scalar;
+ typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
+ typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
+ enum{
+ RowsAtCompileTime = ei_traits<MatrixType>::RowsAtCompileTime == 1 ? 1 : BlockRows,
+ ColsAtCompileTime = ei_traits<MatrixType>::ColsAtCompileTime == 1 ? 1 : BlockCols,
+ MaxRowsAtCompileTime = RowsAtCompileTime == 1 ? 1
+ : (BlockRows==Dynamic ? int(ei_traits<MatrixType>::MaxRowsAtCompileTime) : BlockRows),
+ MaxColsAtCompileTime = ColsAtCompileTime == 1 ? 1
+ : (BlockCols==Dynamic ? int(ei_traits<MatrixType>::MaxColsAtCompileTime) : BlockCols),
+ RowMajor = int(ei_traits<MatrixType>::Flags)&RowMajorBit,
+ InnerSize = RowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
+ InnerMaxSize = RowMajor ? int(MaxColsAtCompileTime) : int(MaxRowsAtCompileTime),
+ MaskPacketAccessBit = (InnerMaxSize == Dynamic || (InnerSize >= ei_packet_traits<Scalar>::size))
+ ? PacketAccessBit : 0,
+ FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
+ Flags = (ei_traits<MatrixType>::Flags & (HereditaryBits | MaskPacketAccessBit | DirectAccessBit)) | FlagsLinearAccessBit,
+ CoeffReadCost = ei_traits<MatrixType>::CoeffReadCost,
+ PacketAccess = _PacketAccess
+ };
+ typedef typename ei_meta_if<int(PacketAccess)==ForceAligned,
+ Block<MatrixType, BlockRows, BlockCols, _PacketAccess, _DirectAccessStatus>&,
+ Block<MatrixType, BlockRows, BlockCols, ForceAligned, _DirectAccessStatus> >::ret AlignedDerivedType;
+};
+
+template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess, int _DirectAccessStatus> class Block
+ : public MatrixBase<Block<MatrixType, BlockRows, BlockCols, PacketAccess, _DirectAccessStatus> >
+{
+ public:
+
+ EIGEN_GENERIC_PUBLIC_INTERFACE(Block)
+
+ class InnerIterator;
+
+ /** Column or Row constructor
+ */
+ inline Block(const MatrixType& matrix, int i)
+ : m_matrix(matrix),
+ // It is a row if and only if BlockRows==1 and BlockCols==MatrixType::ColsAtCompileTime,
+ // and it is a column if and only if BlockRows==MatrixType::RowsAtCompileTime and BlockCols==1,
+ // all other cases are invalid.
+ // The case a 1x1 matrix seems ambiguous, but the result is the same anyway.
+ m_startRow( (BlockRows==1) && (BlockCols==MatrixType::ColsAtCompileTime) ? i : 0),
+ m_startCol( (BlockRows==MatrixType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
+ m_blockRows(matrix.rows()), // if it is a row, then m_blockRows has a fixed-size of 1, so no pb to try to overwrite it
+ m_blockCols(matrix.cols()) // same for m_blockCols
+ {
+ ei_assert( (i>=0) && (
+ ((BlockRows==1) && (BlockCols==MatrixType::ColsAtCompileTime) && i<matrix.rows())
+ ||((BlockRows==MatrixType::RowsAtCompileTime) && (BlockCols==1) && i<matrix.cols())));
+ }
+
+ /** Fixed-size constructor
+ */
+ inline Block(const MatrixType& matrix, int startRow, int startCol)
+ : m_matrix(matrix), m_startRow(startRow), m_startCol(startCol),
+ m_blockRows(matrix.rows()), m_blockCols(matrix.cols())
+ {
+ EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
+ ei_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= matrix.rows()
+ && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= matrix.cols());
+ }
+
+ /** Dynamic-size constructor
+ */
+ inline Block(const MatrixType& matrix,
+ int startRow, int startCol,
+ int blockRows, int blockCols)
+ : m_matrix(matrix), m_startRow(startRow), m_startCol(startCol),
+ m_blockRows(blockRows), m_blockCols(blockCols)
+ {
+ ei_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
+ && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
+ ei_assert(startRow >= 0 && blockRows >= 1 && startRow + blockRows <= matrix.rows()
+ && startCol >= 0 && blockCols >= 1 && startCol + blockCols <= matrix.cols());
+ }
+
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
+
+ inline int rows() const { return m_blockRows.value(); }
+ inline int cols() const { return m_blockCols.value(); }
+
+ inline Scalar& coeffRef(int row, int col)
+ {
+ return m_matrix.const_cast_derived()
+ .coeffRef(row + m_startRow.value(), col + m_startCol.value());
+ }
+
+ inline const Scalar coeff(int row, int col) const
+ {
+ return m_matrix.coeff(row + m_startRow.value(), col + m_startCol.value());
+ }
+
+ inline Scalar& coeffRef(int index)
+ {
+ return m_matrix.const_cast_derived()
+ .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
+ m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
+ }
+
+ inline const Scalar coeff(int index) const
+ {
+ return m_matrix
+ .coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
+ m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
+ }
+
+ template<int LoadMode>
+ inline PacketScalar packet(int row, int col) const
+ {
+ return m_matrix.template packet<Unaligned>
+ (row + m_startRow.value(), col + m_startCol.value());
+ }
+
+ template<int LoadMode>
+ inline void writePacket(int row, int col, const PacketScalar& x)
+ {
+ m_matrix.const_cast_derived().template writePacket<Unaligned>
+ (row + m_startRow.value(), col + m_startCol.value(), x);
+ }
+
+ template<int LoadMode>
+ inline PacketScalar packet(int index) const
+ {
+ return m_matrix.template packet<Unaligned>
+ (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
+ m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
+ }
+
+ template<int LoadMode>
+ inline void writePacket(int index, const PacketScalar& x)
+ {
+ m_matrix.const_cast_derived().template writePacket<Unaligned>
+ (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
+ m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), x);
+ }
+
+ protected:
+
+ const typename MatrixType::Nested m_matrix;
+ const ei_int_if_dynamic<MatrixType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow;
+ const ei_int_if_dynamic<MatrixType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol;
+ const ei_int_if_dynamic<RowsAtCompileTime> m_blockRows;
+ const ei_int_if_dynamic<ColsAtCompileTime> m_blockCols;
+};
+
+/** \internal */
+template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess>
+class Block<MatrixType,BlockRows,BlockCols,PacketAccess,HasDirectAccess>
+ : public MapBase<Block<MatrixType, BlockRows, BlockCols,PacketAccess,HasDirectAccess> >
+{
+ public:
+
+ _EIGEN_GENERIC_PUBLIC_INTERFACE(Block, MapBase<Block>)
+
+ class InnerIterator;
+ typedef typename ei_traits<Block>::AlignedDerivedType AlignedDerivedType;
+ friend class Block<MatrixType,BlockRows,BlockCols,PacketAccess==AsRequested?ForceAligned:AsRequested,HasDirectAccess>;
+
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
+
+ AlignedDerivedType _convertToForceAligned()
+ {
+ return Block<MatrixType,BlockRows,BlockCols,ForceAligned,HasDirectAccess>
+ (m_matrix, Base::m_data, Base::m_rows.value(), Base::m_cols.value());
+ }
+
+ /** Column or Row constructor
+ */
+ inline Block(const MatrixType& matrix, int i)
+ : Base(&matrix.const_cast_derived().coeffRef(
+ (BlockRows==1) && (BlockCols==MatrixType::ColsAtCompileTime) ? i : 0,
+ (BlockRows==MatrixType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
+ BlockRows==1 ? 1 : matrix.rows(),
+ BlockCols==1 ? 1 : matrix.cols()),
+ m_matrix(matrix)
+ {
+ ei_assert( (i>=0) && (
+ ((BlockRows==1) && (BlockCols==MatrixType::ColsAtCompileTime) && i<matrix.rows())
+ ||((BlockRows==MatrixType::RowsAtCompileTime) && (BlockCols==1) && i<matrix.cols())));
+ }
+
+ /** Fixed-size constructor
+ */
+ inline Block(const MatrixType& matrix, int startRow, int startCol)
+ : Base(&matrix.const_cast_derived().coeffRef(startRow,startCol)), m_matrix(matrix)
+ {
+ ei_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= matrix.rows()
+ && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= matrix.cols());
+ }
+
+ /** Dynamic-size constructor
+ */
+ inline Block(const MatrixType& matrix,
+ int startRow, int startCol,
+ int blockRows, int blockCols)
+ : Base(&matrix.const_cast_derived().coeffRef(startRow,startCol), blockRows, blockCols),
+ m_matrix(matrix)
+ {
+ ei_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
+ && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
+ ei_assert(startRow >= 0 && blockRows >= 1 && startRow + blockRows <= matrix.rows()
+ && startCol >= 0 && blockCols >= 1 && startCol + blockCols <= matrix.cols());
+ }
+
+ inline int stride(void) const { return m_matrix.stride(); }
+
+ protected:
+
+ /** \internal used by allowAligned() */
+ inline Block(const MatrixType& matrix, const Scalar* data, int blockRows, int blockCols)
+ : Base(data, blockRows, blockCols), m_matrix(matrix)
+ {}
+
+ const typename MatrixType::Nested m_matrix;
+};
+
+/** \returns a dynamic-size expression of a block in *this.
+ *
+ * \param startRow the first row in the block
+ * \param startCol the first column in the block
+ * \param blockRows the number of rows in the block
+ * \param blockCols the number of columns in the block
+ *
+ * \addexample BlockIntIntIntInt \label How to reference a sub-matrix (dynamic-size)
+ *
+ * Example: \include MatrixBase_block_int_int_int_int.cpp
+ * Output: \verbinclude MatrixBase_block_int_int_int_int.out
+ *
+ * \note Even though the returned expression has dynamic size, in the case
+ * when it is applied to a fixed-size matrix, it inherits a fixed maximal size,
+ * which means that evaluating it does not cause a dynamic memory allocation.
+ *
+ * \sa class Block, block(int,int)
+ */
+template<typename Derived>
+inline typename BlockReturnType<Derived>::Type MatrixBase<Derived>
+ ::block(int startRow, int startCol, int blockRows, int blockCols)
+{
+ return typename BlockReturnType<Derived>::Type(derived(), startRow, startCol, blockRows, blockCols);
+}
+
+/** This is the const version of block(int,int,int,int). */
+template<typename Derived>
+inline const typename BlockReturnType<Derived>::Type MatrixBase<Derived>
+ ::block(int startRow, int startCol, int blockRows, int blockCols) const
+{
+ return typename BlockReturnType<Derived>::Type(derived(), startRow, startCol, blockRows, blockCols);
+}
+
+/** \returns a dynamic-size expression of a segment (i.e. a vector block) in *this.
+ *
+ * \only_for_vectors
+ *
+ * \addexample SegmentIntInt \label How to reference a sub-vector (dynamic size)
+ *
+ * \param start the first coefficient in the segment
+ * \param size the number of coefficients in the segment
+ *
+ * Example: \include MatrixBase_segment_int_int.cpp
+ * Output: \verbinclude MatrixBase_segment_int_int.out
+ *
+ * \note Even though the returned expression has dynamic size, in the case
+ * when it is applied to a fixed-size vector, it inherits a fixed maximal size,
+ * which means that evaluating it does not cause a dynamic memory allocation.
+ *
+ * \sa class Block, segment(int)
+ */
+template<typename Derived>
+inline typename BlockReturnType<Derived>::SubVectorType MatrixBase<Derived>
+ ::segment(int start, int size)
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return typename BlockReturnType<Derived>::SubVectorType(derived(), RowsAtCompileTime == 1 ? 0 : start,
+ ColsAtCompileTime == 1 ? 0 : start,
+ RowsAtCompileTime == 1 ? 1 : size,
+ ColsAtCompileTime == 1 ? 1 : size);
+}
+
+/** This is the const version of segment(int,int).*/
+template<typename Derived>
+inline const typename BlockReturnType<Derived>::SubVectorType
+MatrixBase<Derived>::segment(int start, int size) const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return typename BlockReturnType<Derived>::SubVectorType(derived(), RowsAtCompileTime == 1 ? 0 : start,
+ ColsAtCompileTime == 1 ? 0 : start,
+ RowsAtCompileTime == 1 ? 1 : size,
+ ColsAtCompileTime == 1 ? 1 : size);
+}
+
+/** \returns a dynamic-size expression of the first coefficients of *this.
+ *
+ * \only_for_vectors
+ *
+ * \param size the number of coefficients in the block
+ *
+ * \addexample BlockInt \label How to reference a sub-vector (fixed-size)
+ *
+ * Example: \include MatrixBase_start_int.cpp
+ * Output: \verbinclude MatrixBase_start_int.out
+ *
+ * \note Even though the returned expression has dynamic size, in the case
+ * when it is applied to a fixed-size vector, it inherits a fixed maximal size,
+ * which means that evaluating it does not cause a dynamic memory allocation.
+ *
+ * \sa class Block, block(int,int)
+ */
+template<typename Derived>
+inline typename BlockReturnType<Derived,Dynamic>::SubVectorType
+MatrixBase<Derived>::start(int size)
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return Block<Derived,
+ RowsAtCompileTime == 1 ? 1 : Dynamic,
+ ColsAtCompileTime == 1 ? 1 : Dynamic>
+ (derived(), 0, 0,
+ RowsAtCompileTime == 1 ? 1 : size,
+ ColsAtCompileTime == 1 ? 1 : size);
+}
+
+/** This is the const version of start(int).*/
+template<typename Derived>
+inline const typename BlockReturnType<Derived,Dynamic>::SubVectorType
+MatrixBase<Derived>::start(int size) const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return Block<Derived,
+ RowsAtCompileTime == 1 ? 1 : Dynamic,
+ ColsAtCompileTime == 1 ? 1 : Dynamic>
+ (derived(), 0, 0,
+ RowsAtCompileTime == 1 ? 1 : size,
+ ColsAtCompileTime == 1 ? 1 : size);
+}
+
+/** \returns a dynamic-size expression of the last coefficients of *this.
+ *
+ * \only_for_vectors
+ *
+ * \param size the number of coefficients in the block
+ *
+ * \addexample BlockEnd \label How to reference the end of a vector (fixed-size)
+ *
+ * Example: \include MatrixBase_end_int.cpp
+ * Output: \verbinclude MatrixBase_end_int.out
+ *
+ * \note Even though the returned expression has dynamic size, in the case
+ * when it is applied to a fixed-size vector, it inherits a fixed maximal size,
+ * which means that evaluating it does not cause a dynamic memory allocation.
+ *
+ * \sa class Block, block(int,int)
+ */
+template<typename Derived>
+inline typename BlockReturnType<Derived,Dynamic>::SubVectorType
+MatrixBase<Derived>::end(int size)
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return Block<Derived,
+ RowsAtCompileTime == 1 ? 1 : Dynamic,
+ ColsAtCompileTime == 1 ? 1 : Dynamic>
+ (derived(),
+ RowsAtCompileTime == 1 ? 0 : rows() - size,
+ ColsAtCompileTime == 1 ? 0 : cols() - size,
+ RowsAtCompileTime == 1 ? 1 : size,
+ ColsAtCompileTime == 1 ? 1 : size);
+}
+
+/** This is the const version of end(int).*/
+template<typename Derived>
+inline const typename BlockReturnType<Derived,Dynamic>::SubVectorType
+MatrixBase<Derived>::end(int size) const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return Block<Derived,
+ RowsAtCompileTime == 1 ? 1 : Dynamic,
+ ColsAtCompileTime == 1 ? 1 : Dynamic>
+ (derived(),
+ RowsAtCompileTime == 1 ? 0 : rows() - size,
+ ColsAtCompileTime == 1 ? 0 : cols() - size,
+ RowsAtCompileTime == 1 ? 1 : size,
+ ColsAtCompileTime == 1 ? 1 : size);
+}
+
+/** \returns a fixed-size expression of a segment (i.e. a vector block) in \c *this
+ *
+ * \only_for_vectors
+ *
+ * The template parameter \a Size is the number of coefficients in the block
+ *
+ * \param start the index of the first element of the sub-vector
+ *
+ * Example: \include MatrixBase_template_int_segment.cpp
+ * Output: \verbinclude MatrixBase_template_int_segment.out
+ *
+ * \sa class Block
+ */
+template<typename Derived>
+template<int Size>
+inline typename BlockReturnType<Derived,Size>::SubVectorType
+MatrixBase<Derived>::segment(int start)
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return Block<Derived, (RowsAtCompileTime == 1 ? 1 : Size),
+ (ColsAtCompileTime == 1 ? 1 : Size)>
+ (derived(), RowsAtCompileTime == 1 ? 0 : start,
+ ColsAtCompileTime == 1 ? 0 : start);
+}
+
+/** This is the const version of segment<int>(int).*/
+template<typename Derived>
+template<int Size>
+inline const typename BlockReturnType<Derived,Size>::SubVectorType
+MatrixBase<Derived>::segment(int start) const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return Block<Derived, (RowsAtCompileTime == 1 ? 1 : Size),
+ (ColsAtCompileTime == 1 ? 1 : Size)>
+ (derived(), RowsAtCompileTime == 1 ? 0 : start,
+ ColsAtCompileTime == 1 ? 0 : start);
+}
+
+/** \returns a fixed-size expression of the first coefficients of *this.
+ *
+ * \only_for_vectors
+ *
+ * The template parameter \a Size is the number of coefficients in the block
+ *
+ * \addexample BlockStart \label How to reference the start of a vector (fixed-size)
+ *
+ * Example: \include MatrixBase_template_int_start.cpp
+ * Output: \verbinclude MatrixBase_template_int_start.out
+ *
+ * \sa class Block
+ */
+template<typename Derived>
+template<int Size>
+inline typename BlockReturnType<Derived,Size>::SubVectorType
+MatrixBase<Derived>::start()
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return Block<Derived, (RowsAtCompileTime == 1 ? 1 : Size),
+ (ColsAtCompileTime == 1 ? 1 : Size)>(derived(), 0, 0);
+}
+
+/** This is the const version of start<int>().*/
+template<typename Derived>
+template<int Size>
+inline const typename BlockReturnType<Derived,Size>::SubVectorType
+MatrixBase<Derived>::start() const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return Block<Derived, (RowsAtCompileTime == 1 ? 1 : Size),
+ (ColsAtCompileTime == 1 ? 1 : Size)>(derived(), 0, 0);
+}
+
+/** \returns a fixed-size expression of the last coefficients of *this.
+ *
+ * \only_for_vectors
+ *
+ * The template parameter \a Size is the number of coefficients in the block
+ *
+ * Example: \include MatrixBase_template_int_end.cpp
+ * Output: \verbinclude MatrixBase_template_int_end.out
+ *
+ * \sa class Block
+ */
+template<typename Derived>
+template<int Size>
+inline typename BlockReturnType<Derived,Size>::SubVectorType
+MatrixBase<Derived>::end()
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return Block<Derived, RowsAtCompileTime == 1 ? 1 : Size,
+ ColsAtCompileTime == 1 ? 1 : Size>
+ (derived(),
+ RowsAtCompileTime == 1 ? 0 : rows() - Size,
+ ColsAtCompileTime == 1 ? 0 : cols() - Size);
+}
+
+/** This is the const version of end<int>.*/
+template<typename Derived>
+template<int Size>
+inline const typename BlockReturnType<Derived,Size>::SubVectorType
+MatrixBase<Derived>::end() const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return Block<Derived, RowsAtCompileTime == 1 ? 1 : Size,
+ ColsAtCompileTime == 1 ? 1 : Size>
+ (derived(),
+ RowsAtCompileTime == 1 ? 0 : rows() - Size,
+ ColsAtCompileTime == 1 ? 0 : cols() - Size);
+}
+
+/** \returns a dynamic-size expression of a corner of *this.
+ *
+ * \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight,
+ * \a Eigen::BottomLeft, \a Eigen::BottomRight.
+ * \param cRows the number of rows in the corner
+ * \param cCols the number of columns in the corner
+ *
+ * \addexample BlockCornerDynamicSize \label How to reference a sub-corner of a matrix
+ *
+ * Example: \include MatrixBase_corner_enum_int_int.cpp
+ * Output: \verbinclude MatrixBase_corner_enum_int_int.out
+ *
+ * \note Even though the returned expression has dynamic size, in the case
+ * when it is applied to a fixed-size matrix, it inherits a fixed maximal size,
+ * which means that evaluating it does not cause a dynamic memory allocation.
+ *
+ * \sa class Block, block(int,int,int,int)
+ */
+template<typename Derived>
+inline typename BlockReturnType<Derived>::Type MatrixBase<Derived>
+ ::corner(CornerType type, int cRows, int cCols)
+{
+ switch(type)
+ {
+ default:
+ ei_assert(false && "Bad corner type.");
+ case TopLeft:
+ return typename BlockReturnType<Derived>::Type(derived(), 0, 0, cRows, cCols);
+ case TopRight:
+ return typename BlockReturnType<Derived>::Type(derived(), 0, cols() - cCols, cRows, cCols);
+ case BottomLeft:
+ return typename BlockReturnType<Derived>::Type(derived(), rows() - cRows, 0, cRows, cCols);
+ case BottomRight:
+ return typename BlockReturnType<Derived>::Type(derived(), rows() - cRows, cols() - cCols, cRows, cCols);
+ }
+}
+
+/** This is the const version of corner(CornerType, int, int).*/
+template<typename Derived>
+inline const typename BlockReturnType<Derived>::Type
+MatrixBase<Derived>::corner(CornerType type, int cRows, int cCols) const
+{
+ switch(type)
+ {
+ default:
+ ei_assert(false && "Bad corner type.");
+ case TopLeft:
+ return typename BlockReturnType<Derived>::Type(derived(), 0, 0, cRows, cCols);
+ case TopRight:
+ return typename BlockReturnType<Derived>::Type(derived(), 0, cols() - cCols, cRows, cCols);
+ case BottomLeft:
+ return typename BlockReturnType<Derived>::Type(derived(), rows() - cRows, 0, cRows, cCols);
+ case BottomRight:
+ return typename BlockReturnType<Derived>::Type(derived(), rows() - cRows, cols() - cCols, cRows, cCols);
+ }
+}
+
+/** \returns a fixed-size expression of a corner of *this.
+ *
+ * \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight,
+ * \a Eigen::BottomLeft, \a Eigen::BottomRight.
+ *
+ * The template parameters CRows and CCols arethe number of rows and columns in the corner.
+ *
+ * Example: \include MatrixBase_template_int_int_corner_enum.cpp
+ * Output: \verbinclude MatrixBase_template_int_int_corner_enum.out
+ *
+ * \sa class Block, block(int,int,int,int)
+ */
+template<typename Derived>
+template<int CRows, int CCols>
+inline typename BlockReturnType<Derived, CRows, CCols>::Type
+MatrixBase<Derived>::corner(CornerType type)
+{
+ switch(type)
+ {
+ default:
+ ei_assert(false && "Bad corner type.");
+ case TopLeft:
+ return Block<Derived, CRows, CCols>(derived(), 0, 0);
+ case TopRight:
+ return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols);
+ case BottomLeft:
+ return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0);
+ case BottomRight:
+ return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols);
+ }
+}
+
+/** This is the const version of corner<int, int>(CornerType).*/
+template<typename Derived>
+template<int CRows, int CCols>
+inline const typename BlockReturnType<Derived, CRows, CCols>::Type
+MatrixBase<Derived>::corner(CornerType type) const
+{
+ switch(type)
+ {
+ default:
+ ei_assert(false && "Bad corner type.");
+ case TopLeft:
+ return Block<Derived, CRows, CCols>(derived(), 0, 0);
+ case TopRight:
+ return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols);
+ case BottomLeft:
+ return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0);
+ case BottomRight:
+ return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols);
+ }
+}
+
+/** \returns a fixed-size expression of a block in *this.
+ *
+ * The template parameters \a BlockRows and \a BlockCols are the number of
+ * rows and columns in the block.
+ *
+ * \param startRow the first row in the block
+ * \param startCol the first column in the block
+ *
+ * \addexample BlockSubMatrixFixedSize \label How to reference a sub-matrix (fixed-size)
+ *
+ * Example: \include MatrixBase_block_int_int.cpp
+ * Output: \verbinclude MatrixBase_block_int_int.out
+ *
+ * \note since block is a templated member, the keyword template has to be used
+ * if the matrix type is also a template parameter: \code m.template block<3,3>(1,1); \endcode
+ *
+ * \sa class Block, block(int,int,int,int)
+ */
+template<typename Derived>
+template<int BlockRows, int BlockCols>
+inline typename BlockReturnType<Derived, BlockRows, BlockCols>::Type
+MatrixBase<Derived>::block(int startRow, int startCol)
+{
+ return Block<Derived, BlockRows, BlockCols>(derived(), startRow, startCol);
+}
+
+/** This is the const version of block<>(int, int). */
+template<typename Derived>
+template<int BlockRows, int BlockCols>
+inline const typename BlockReturnType<Derived, BlockRows, BlockCols>::Type
+MatrixBase<Derived>::block(int startRow, int startCol) const
+{
+ return Block<Derived, BlockRows, BlockCols>(derived(), startRow, startCol);
+}
+
+/** \returns an expression of the \a i-th column of *this. Note that the numbering starts at 0.
+ *
+ * \addexample BlockColumn \label How to reference a single column of a matrix
+ *
+ * Example: \include MatrixBase_col.cpp
+ * Output: \verbinclude MatrixBase_col.out
+ *
+ * \sa row(), class Block */
+template<typename Derived>
+inline typename MatrixBase<Derived>::ColXpr
+MatrixBase<Derived>::col(int i)
+{
+ return ColXpr(derived(), i);
+}
+
+/** This is the const version of col(). */
+template<typename Derived>
+inline const typename MatrixBase<Derived>::ColXpr
+MatrixBase<Derived>::col(int i) const
+{
+ return ColXpr(derived(), i);
+}
+
+/** \returns an expression of the \a i-th row of *this. Note that the numbering starts at 0.
+ *
+ * \addexample BlockRow \label How to reference a single row of a matrix
+ *
+ * Example: \include MatrixBase_row.cpp
+ * Output: \verbinclude MatrixBase_row.out
+ *
+ * \sa col(), class Block */
+template<typename Derived>
+inline typename MatrixBase<Derived>::RowXpr
+MatrixBase<Derived>::row(int i)
+{
+ return RowXpr(derived(), i);
+}
+
+/** This is the const version of row(). */
+template<typename Derived>
+inline const typename MatrixBase<Derived>::RowXpr
+MatrixBase<Derived>::row(int i) const
+{
+ return RowXpr(derived(), i);
+}
+
+#endif // EIGEN_BLOCK_H
diff --git a/extern/Eigen2/Eigen/src/Core/CacheFriendlyProduct.h b/extern/Eigen2/Eigen/src/Core/CacheFriendlyProduct.h
new file mode 100644
index 00000000000..b1362b0a80c
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/CacheFriendlyProduct.h
@@ -0,0 +1,753 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_CACHE_FRIENDLY_PRODUCT_H
+#define EIGEN_CACHE_FRIENDLY_PRODUCT_H
+
+template <int L2MemorySize,typename Scalar>
+struct ei_L2_block_traits {
+ enum {width = 8 * ei_meta_sqrt<L2MemorySize/(64*sizeof(Scalar))>::ret };
+};
+
+#ifndef EIGEN_EXTERN_INSTANTIATIONS
+
+template<typename Scalar>
+static void ei_cache_friendly_product(
+ int _rows, int _cols, int depth,
+ bool _lhsRowMajor, const Scalar* _lhs, int _lhsStride,
+ bool _rhsRowMajor, const Scalar* _rhs, int _rhsStride,
+ bool resRowMajor, Scalar* res, int resStride)
+{
+ const Scalar* EIGEN_RESTRICT lhs;
+ const Scalar* EIGEN_RESTRICT rhs;
+ int lhsStride, rhsStride, rows, cols;
+ bool lhsRowMajor;
+
+ if (resRowMajor)
+ {
+ lhs = _rhs;
+ rhs = _lhs;
+ lhsStride = _rhsStride;
+ rhsStride = _lhsStride;
+ cols = _rows;
+ rows = _cols;
+ lhsRowMajor = !_rhsRowMajor;
+ ei_assert(_lhsRowMajor);
+ }
+ else
+ {
+ lhs = _lhs;
+ rhs = _rhs;
+ lhsStride = _lhsStride;
+ rhsStride = _rhsStride;
+ rows = _rows;
+ cols = _cols;
+ lhsRowMajor = _lhsRowMajor;
+ ei_assert(!_rhsRowMajor);
+ }
+
+ typedef typename ei_packet_traits<Scalar>::type PacketType;
+
+ enum {
+ PacketSize = sizeof(PacketType)/sizeof(Scalar),
+ #if (defined __i386__)
+ // i386 architecture provides only 8 xmm registers,
+ // so let's reduce the max number of rows processed at once.
+ MaxBlockRows = 4,
+ MaxBlockRows_ClampingMask = 0xFFFFFC,
+ #else
+ MaxBlockRows = 8,
+ MaxBlockRows_ClampingMask = 0xFFFFF8,
+ #endif
+ // maximal size of the blocks fitted in L2 cache
+ MaxL2BlockSize = ei_L2_block_traits<EIGEN_TUNE_FOR_CPU_CACHE_SIZE,Scalar>::width
+ };
+
+ const bool resIsAligned = (PacketSize==1) || (((resStride%PacketSize) == 0) && (size_t(res)%16==0));
+
+ const int remainingSize = depth % PacketSize;
+ const int size = depth - remainingSize; // third dimension of the product clamped to packet boundaries
+ const int l2BlockRows = MaxL2BlockSize > rows ? rows : MaxL2BlockSize;
+ const int l2BlockCols = MaxL2BlockSize > cols ? cols : MaxL2BlockSize;
+ const int l2BlockSize = MaxL2BlockSize > size ? size : MaxL2BlockSize;
+ const int l2BlockSizeAligned = (1 + std::max(l2BlockSize,l2BlockCols)/PacketSize)*PacketSize;
+ const bool needRhsCopy = (PacketSize>1) && ((rhsStride%PacketSize!=0) || (size_t(rhs)%16!=0));
+ Scalar* EIGEN_RESTRICT block = 0;
+ const int allocBlockSize = l2BlockRows*size;
+ block = ei_aligned_stack_new(Scalar, allocBlockSize);
+ Scalar* EIGEN_RESTRICT rhsCopy
+ = ei_aligned_stack_new(Scalar, l2BlockSizeAligned*l2BlockSizeAligned);
+
+ // loops on each L2 cache friendly blocks of the result
+ for(int l2i=0; l2i<rows; l2i+=l2BlockRows)
+ {
+ const int l2blockRowEnd = std::min(l2i+l2BlockRows, rows);
+ const int l2blockRowEndBW = l2blockRowEnd & MaxBlockRows_ClampingMask; // end of the rows aligned to bw
+ const int l2blockRemainingRows = l2blockRowEnd - l2blockRowEndBW; // number of remaining rows
+ //const int l2blockRowEndBWPlusOne = l2blockRowEndBW + (l2blockRemainingRows?0:MaxBlockRows);
+
+ // build a cache friendly blocky matrix
+ int count = 0;
+
+ // copy l2blocksize rows of m_lhs to blocks of ps x bw
+ for(int l2k=0; l2k<size; l2k+=l2BlockSize)
+ {
+ const int l2blockSizeEnd = std::min(l2k+l2BlockSize, size);
+
+ for (int i = l2i; i<l2blockRowEndBW/*PlusOne*/; i+=MaxBlockRows)
+ {
+ // TODO merge the "if l2blockRemainingRows" using something like:
+ // const int blockRows = std::min(i+MaxBlockRows, rows) - i;
+
+ for (int k=l2k; k<l2blockSizeEnd; k+=PacketSize)
+ {
+ // TODO write these loops using meta unrolling
+ // negligible for large matrices but useful for small ones
+ if (lhsRowMajor)
+ {
+ for (int w=0; w<MaxBlockRows; ++w)
+ for (int s=0; s<PacketSize; ++s)
+ block[count++] = lhs[(i+w)*lhsStride + (k+s)];
+ }
+ else
+ {
+ for (int w=0; w<MaxBlockRows; ++w)
+ for (int s=0; s<PacketSize; ++s)
+ block[count++] = lhs[(i+w) + (k+s)*lhsStride];
+ }
+ }
+ }
+ if (l2blockRemainingRows>0)
+ {
+ for (int k=l2k; k<l2blockSizeEnd; k+=PacketSize)
+ {
+ if (lhsRowMajor)
+ {
+ for (int w=0; w<l2blockRemainingRows; ++w)
+ for (int s=0; s<PacketSize; ++s)
+ block[count++] = lhs[(l2blockRowEndBW+w)*lhsStride + (k+s)];
+ }
+ else
+ {
+ for (int w=0; w<l2blockRemainingRows; ++w)
+ for (int s=0; s<PacketSize; ++s)
+ block[count++] = lhs[(l2blockRowEndBW+w) + (k+s)*lhsStride];
+ }
+ }
+ }
+ }
+
+ for(int l2j=0; l2j<cols; l2j+=l2BlockCols)
+ {
+ int l2blockColEnd = std::min(l2j+l2BlockCols, cols);
+
+ for(int l2k=0; l2k<size; l2k+=l2BlockSize)
+ {
+ // acumulate bw rows of lhs time a single column of rhs to a bw x 1 block of res
+ int l2blockSizeEnd = std::min(l2k+l2BlockSize, size);
+
+ // if not aligned, copy the rhs block
+ if (needRhsCopy)
+ for(int l1j=l2j; l1j<l2blockColEnd; l1j+=1)
+ {
+ ei_internal_assert(l2BlockSizeAligned*(l1j-l2j)+(l2blockSizeEnd-l2k) < l2BlockSizeAligned*l2BlockSizeAligned);
+ memcpy(rhsCopy+l2BlockSizeAligned*(l1j-l2j),&(rhs[l1j*rhsStride+l2k]),(l2blockSizeEnd-l2k)*sizeof(Scalar));
+ }
+
+ // for each bw x 1 result's block
+ for(int l1i=l2i; l1i<l2blockRowEndBW; l1i+=MaxBlockRows)
+ {
+ int offsetblock = l2k * (l2blockRowEnd-l2i) + (l1i-l2i)*(l2blockSizeEnd-l2k) - l2k*MaxBlockRows;
+ const Scalar* EIGEN_RESTRICT localB = &block[offsetblock];
+
+ for(int l1j=l2j; l1j<l2blockColEnd; l1j+=1)
+ {
+ const Scalar* EIGEN_RESTRICT rhsColumn;
+ if (needRhsCopy)
+ rhsColumn = &(rhsCopy[l2BlockSizeAligned*(l1j-l2j)-l2k]);
+ else
+ rhsColumn = &(rhs[l1j*rhsStride]);
+
+ PacketType dst[MaxBlockRows];
+ dst[3] = dst[2] = dst[1] = dst[0] = ei_pset1(Scalar(0.));
+ if (MaxBlockRows==8)
+ dst[7] = dst[6] = dst[5] = dst[4] = dst[0];
+
+ PacketType tmp;
+
+ for(int k=l2k; k<l2blockSizeEnd; k+=PacketSize)
+ {
+ tmp = ei_ploadu(&rhsColumn[k]);
+ PacketType A0, A1, A2, A3, A4, A5;
+ A0 = ei_pload(localB + k*MaxBlockRows);
+ A1 = ei_pload(localB + k*MaxBlockRows+1*PacketSize);
+ A2 = ei_pload(localB + k*MaxBlockRows+2*PacketSize);
+ A3 = ei_pload(localB + k*MaxBlockRows+3*PacketSize);
+ if (MaxBlockRows==8) A4 = ei_pload(localB + k*MaxBlockRows+4*PacketSize);
+ if (MaxBlockRows==8) A5 = ei_pload(localB + k*MaxBlockRows+5*PacketSize);
+ dst[0] = ei_pmadd(tmp, A0, dst[0]);
+ if (MaxBlockRows==8) A0 = ei_pload(localB + k*MaxBlockRows+6*PacketSize);
+ dst[1] = ei_pmadd(tmp, A1, dst[1]);
+ if (MaxBlockRows==8) A1 = ei_pload(localB + k*MaxBlockRows+7*PacketSize);
+ dst[2] = ei_pmadd(tmp, A2, dst[2]);
+ dst[3] = ei_pmadd(tmp, A3, dst[3]);
+ if (MaxBlockRows==8)
+ {
+ dst[4] = ei_pmadd(tmp, A4, dst[4]);
+ dst[5] = ei_pmadd(tmp, A5, dst[5]);
+ dst[6] = ei_pmadd(tmp, A0, dst[6]);
+ dst[7] = ei_pmadd(tmp, A1, dst[7]);
+ }
+ }
+
+ Scalar* EIGEN_RESTRICT localRes = &(res[l1i + l1j*resStride]);
+
+ if (PacketSize>1 && resIsAligned)
+ {
+ // the result is aligned: let's do packet reduction
+ ei_pstore(&(localRes[0]), ei_padd(ei_pload(&(localRes[0])), ei_preduxp(&dst[0])));
+ if (PacketSize==2)
+ ei_pstore(&(localRes[2]), ei_padd(ei_pload(&(localRes[2])), ei_preduxp(&(dst[2]))));
+ if (MaxBlockRows==8)
+ {
+ ei_pstore(&(localRes[4]), ei_padd(ei_pload(&(localRes[4])), ei_preduxp(&(dst[4]))));
+ if (PacketSize==2)
+ ei_pstore(&(localRes[6]), ei_padd(ei_pload(&(localRes[6])), ei_preduxp(&(dst[6]))));
+ }
+ }
+ else
+ {
+ // not aligned => per coeff packet reduction
+ localRes[0] += ei_predux(dst[0]);
+ localRes[1] += ei_predux(dst[1]);
+ localRes[2] += ei_predux(dst[2]);
+ localRes[3] += ei_predux(dst[3]);
+ if (MaxBlockRows==8)
+ {
+ localRes[4] += ei_predux(dst[4]);
+ localRes[5] += ei_predux(dst[5]);
+ localRes[6] += ei_predux(dst[6]);
+ localRes[7] += ei_predux(dst[7]);
+ }
+ }
+ }
+ }
+ if (l2blockRemainingRows>0)
+ {
+ int offsetblock = l2k * (l2blockRowEnd-l2i) + (l2blockRowEndBW-l2i)*(l2blockSizeEnd-l2k) - l2k*l2blockRemainingRows;
+ const Scalar* localB = &block[offsetblock];
+
+ for(int l1j=l2j; l1j<l2blockColEnd; l1j+=1)
+ {
+ const Scalar* EIGEN_RESTRICT rhsColumn;
+ if (needRhsCopy)
+ rhsColumn = &(rhsCopy[l2BlockSizeAligned*(l1j-l2j)-l2k]);
+ else
+ rhsColumn = &(rhs[l1j*rhsStride]);
+
+ PacketType dst[MaxBlockRows];
+ dst[3] = dst[2] = dst[1] = dst[0] = ei_pset1(Scalar(0.));
+ if (MaxBlockRows==8)
+ dst[7] = dst[6] = dst[5] = dst[4] = dst[0];
+
+ // let's declare a few other temporary registers
+ PacketType tmp;
+
+ for(int k=l2k; k<l2blockSizeEnd; k+=PacketSize)
+ {
+ tmp = ei_pload(&rhsColumn[k]);
+
+ dst[0] = ei_pmadd(tmp, ei_pload(&(localB[k*l2blockRemainingRows ])), dst[0]);
+ if (l2blockRemainingRows>=2) dst[1] = ei_pmadd(tmp, ei_pload(&(localB[k*l2blockRemainingRows+ PacketSize])), dst[1]);
+ if (l2blockRemainingRows>=3) dst[2] = ei_pmadd(tmp, ei_pload(&(localB[k*l2blockRemainingRows+2*PacketSize])), dst[2]);
+ if (l2blockRemainingRows>=4) dst[3] = ei_pmadd(tmp, ei_pload(&(localB[k*l2blockRemainingRows+3*PacketSize])), dst[3]);
+ if (MaxBlockRows==8)
+ {
+ if (l2blockRemainingRows>=5) dst[4] = ei_pmadd(tmp, ei_pload(&(localB[k*l2blockRemainingRows+4*PacketSize])), dst[4]);
+ if (l2blockRemainingRows>=6) dst[5] = ei_pmadd(tmp, ei_pload(&(localB[k*l2blockRemainingRows+5*PacketSize])), dst[5]);
+ if (l2blockRemainingRows>=7) dst[6] = ei_pmadd(tmp, ei_pload(&(localB[k*l2blockRemainingRows+6*PacketSize])), dst[6]);
+ if (l2blockRemainingRows>=8) dst[7] = ei_pmadd(tmp, ei_pload(&(localB[k*l2blockRemainingRows+7*PacketSize])), dst[7]);
+ }
+ }
+
+ Scalar* EIGEN_RESTRICT localRes = &(res[l2blockRowEndBW + l1j*resStride]);
+
+ // process the remaining rows once at a time
+ localRes[0] += ei_predux(dst[0]);
+ if (l2blockRemainingRows>=2) localRes[1] += ei_predux(dst[1]);
+ if (l2blockRemainingRows>=3) localRes[2] += ei_predux(dst[2]);
+ if (l2blockRemainingRows>=4) localRes[3] += ei_predux(dst[3]);
+ if (MaxBlockRows==8)
+ {
+ if (l2blockRemainingRows>=5) localRes[4] += ei_predux(dst[4]);
+ if (l2blockRemainingRows>=6) localRes[5] += ei_predux(dst[5]);
+ if (l2blockRemainingRows>=7) localRes[6] += ei_predux(dst[6]);
+ if (l2blockRemainingRows>=8) localRes[7] += ei_predux(dst[7]);
+ }
+
+ }
+ }
+ }
+ }
+ }
+ if (PacketSize>1 && remainingSize)
+ {
+ if (lhsRowMajor)
+ {
+ for (int j=0; j<cols; ++j)
+ for (int i=0; i<rows; ++i)
+ {
+ Scalar tmp = lhs[i*lhsStride+size] * rhs[j*rhsStride+size];
+ // FIXME this loop get vectorized by the compiler !
+ for (int k=1; k<remainingSize; ++k)
+ tmp += lhs[i*lhsStride+size+k] * rhs[j*rhsStride+size+k];
+ res[i+j*resStride] += tmp;
+ }
+ }
+ else
+ {
+ for (int j=0; j<cols; ++j)
+ for (int i=0; i<rows; ++i)
+ {
+ Scalar tmp = lhs[i+size*lhsStride] * rhs[j*rhsStride+size];
+ for (int k=1; k<remainingSize; ++k)
+ tmp += lhs[i+(size+k)*lhsStride] * rhs[j*rhsStride+size+k];
+ res[i+j*resStride] += tmp;
+ }
+ }
+ }
+
+ ei_aligned_stack_delete(Scalar, block, allocBlockSize);
+ ei_aligned_stack_delete(Scalar, rhsCopy, l2BlockSizeAligned*l2BlockSizeAligned);
+}
+
+#endif // EIGEN_EXTERN_INSTANTIATIONS
+
+/* Optimized col-major matrix * vector product:
+ * This algorithm processes 4 columns at onces that allows to both reduce
+ * the number of load/stores of the result by a factor 4 and to reduce
+ * the instruction dependency. Moreover, we know that all bands have the
+ * same alignment pattern.
+ * TODO: since rhs gets evaluated only once, no need to evaluate it
+ */
+template<typename Scalar, typename RhsType>
+static EIGEN_DONT_INLINE void ei_cache_friendly_product_colmajor_times_vector(
+ int size,
+ const Scalar* lhs, int lhsStride,
+ const RhsType& rhs,
+ Scalar* res)
+{
+ #ifdef _EIGEN_ACCUMULATE_PACKETS
+ #error _EIGEN_ACCUMULATE_PACKETS has already been defined
+ #endif
+ #define _EIGEN_ACCUMULATE_PACKETS(A0,A13,A2) \
+ ei_pstore(&res[j], \
+ ei_padd(ei_pload(&res[j]), \
+ ei_padd( \
+ ei_padd(ei_pmul(ptmp0,EIGEN_CAT(ei_ploa , A0)(&lhs0[j])), \
+ ei_pmul(ptmp1,EIGEN_CAT(ei_ploa , A13)(&lhs1[j]))), \
+ ei_padd(ei_pmul(ptmp2,EIGEN_CAT(ei_ploa , A2)(&lhs2[j])), \
+ ei_pmul(ptmp3,EIGEN_CAT(ei_ploa , A13)(&lhs3[j]))) )))
+
+ typedef typename ei_packet_traits<Scalar>::type Packet;
+ const int PacketSize = sizeof(Packet)/sizeof(Scalar);
+
+ enum { AllAligned = 0, EvenAligned, FirstAligned, NoneAligned };
+ const int columnsAtOnce = 4;
+ const int peels = 2;
+ const int PacketAlignedMask = PacketSize-1;
+ const int PeelAlignedMask = PacketSize*peels-1;
+
+ // How many coeffs of the result do we have to skip to be aligned.
+ // Here we assume data are at least aligned on the base scalar type that is mandatory anyway.
+ const int alignedStart = ei_alignmentOffset(res,size);
+ const int alignedSize = PacketSize>1 ? alignedStart + ((size-alignedStart) & ~PacketAlignedMask) : 0;
+ const int peeledSize = peels>1 ? alignedStart + ((alignedSize-alignedStart) & ~PeelAlignedMask) : alignedStart;
+
+ const int alignmentStep = PacketSize>1 ? (PacketSize - lhsStride % PacketSize) & PacketAlignedMask : 0;
+ int alignmentPattern = alignmentStep==0 ? AllAligned
+ : alignmentStep==(PacketSize/2) ? EvenAligned
+ : FirstAligned;
+
+ // we cannot assume the first element is aligned because of sub-matrices
+ const int lhsAlignmentOffset = ei_alignmentOffset(lhs,size);
+
+ // find how many columns do we have to skip to be aligned with the result (if possible)
+ int skipColumns = 0;
+ if (PacketSize>1)
+ {
+ ei_internal_assert(size_t(lhs+lhsAlignmentOffset)%sizeof(Packet)==0 || size<PacketSize);
+
+ while (skipColumns<PacketSize &&
+ alignedStart != ((lhsAlignmentOffset + alignmentStep*skipColumns)%PacketSize))
+ ++skipColumns;
+ if (skipColumns==PacketSize)
+ {
+ // nothing can be aligned, no need to skip any column
+ alignmentPattern = NoneAligned;
+ skipColumns = 0;
+ }
+ else
+ {
+ skipColumns = std::min(skipColumns,rhs.size());
+ // note that the skiped columns are processed later.
+ }
+
+ ei_internal_assert((alignmentPattern==NoneAligned) || (size_t(lhs+alignedStart+lhsStride*skipColumns)%sizeof(Packet))==0);
+ }
+
+ int offset1 = (FirstAligned && alignmentStep==1?3:1);
+ int offset3 = (FirstAligned && alignmentStep==1?1:3);
+
+ int columnBound = ((rhs.size()-skipColumns)/columnsAtOnce)*columnsAtOnce + skipColumns;
+ for (int i=skipColumns; i<columnBound; i+=columnsAtOnce)
+ {
+ Packet ptmp0 = ei_pset1(rhs[i]), ptmp1 = ei_pset1(rhs[i+offset1]),
+ ptmp2 = ei_pset1(rhs[i+2]), ptmp3 = ei_pset1(rhs[i+offset3]);
+
+ // this helps a lot generating better binary code
+ const Scalar *lhs0 = lhs + i*lhsStride, *lhs1 = lhs + (i+offset1)*lhsStride,
+ *lhs2 = lhs + (i+2)*lhsStride, *lhs3 = lhs + (i+offset3)*lhsStride;
+
+ if (PacketSize>1)
+ {
+ /* explicit vectorization */
+ // process initial unaligned coeffs
+ for (int j=0; j<alignedStart; ++j)
+ res[j] += ei_pfirst(ptmp0)*lhs0[j] + ei_pfirst(ptmp1)*lhs1[j] + ei_pfirst(ptmp2)*lhs2[j] + ei_pfirst(ptmp3)*lhs3[j];
+
+ if (alignedSize>alignedStart)
+ {
+ switch(alignmentPattern)
+ {
+ case AllAligned:
+ for (int j = alignedStart; j<alignedSize; j+=PacketSize)
+ _EIGEN_ACCUMULATE_PACKETS(d,d,d);
+ break;
+ case EvenAligned:
+ for (int j = alignedStart; j<alignedSize; j+=PacketSize)
+ _EIGEN_ACCUMULATE_PACKETS(d,du,d);
+ break;
+ case FirstAligned:
+ if(peels>1)
+ {
+ Packet A00, A01, A02, A03, A10, A11, A12, A13;
+
+ A01 = ei_pload(&lhs1[alignedStart-1]);
+ A02 = ei_pload(&lhs2[alignedStart-2]);
+ A03 = ei_pload(&lhs3[alignedStart-3]);
+
+ for (int j = alignedStart; j<peeledSize; j+=peels*PacketSize)
+ {
+ A11 = ei_pload(&lhs1[j-1+PacketSize]); ei_palign<1>(A01,A11);
+ A12 = ei_pload(&lhs2[j-2+PacketSize]); ei_palign<2>(A02,A12);
+ A13 = ei_pload(&lhs3[j-3+PacketSize]); ei_palign<3>(A03,A13);
+
+ A00 = ei_pload (&lhs0[j]);
+ A10 = ei_pload (&lhs0[j+PacketSize]);
+ A00 = ei_pmadd(ptmp0, A00, ei_pload(&res[j]));
+ A10 = ei_pmadd(ptmp0, A10, ei_pload(&res[j+PacketSize]));
+
+ A00 = ei_pmadd(ptmp1, A01, A00);
+ A01 = ei_pload(&lhs1[j-1+2*PacketSize]); ei_palign<1>(A11,A01);
+ A00 = ei_pmadd(ptmp2, A02, A00);
+ A02 = ei_pload(&lhs2[j-2+2*PacketSize]); ei_palign<2>(A12,A02);
+ A00 = ei_pmadd(ptmp3, A03, A00);
+ ei_pstore(&res[j],A00);
+ A03 = ei_pload(&lhs3[j-3+2*PacketSize]); ei_palign<3>(A13,A03);
+ A10 = ei_pmadd(ptmp1, A11, A10);
+ A10 = ei_pmadd(ptmp2, A12, A10);
+ A10 = ei_pmadd(ptmp3, A13, A10);
+ ei_pstore(&res[j+PacketSize],A10);
+ }
+ }
+ for (int j = peeledSize; j<alignedSize; j+=PacketSize)
+ _EIGEN_ACCUMULATE_PACKETS(d,du,du);
+ break;
+ default:
+ for (int j = alignedStart; j<alignedSize; j+=PacketSize)
+ _EIGEN_ACCUMULATE_PACKETS(du,du,du);
+ break;
+ }
+ }
+ } // end explicit vectorization
+
+ /* process remaining coeffs (or all if there is no explicit vectorization) */
+ for (int j=alignedSize; j<size; ++j)
+ res[j] += ei_pfirst(ptmp0)*lhs0[j] + ei_pfirst(ptmp1)*lhs1[j] + ei_pfirst(ptmp2)*lhs2[j] + ei_pfirst(ptmp3)*lhs3[j];
+ }
+
+ // process remaining first and last columns (at most columnsAtOnce-1)
+ int end = rhs.size();
+ int start = columnBound;
+ do
+ {
+ for (int i=start; i<end; ++i)
+ {
+ Packet ptmp0 = ei_pset1(rhs[i]);
+ const Scalar* lhs0 = lhs + i*lhsStride;
+
+ if (PacketSize>1)
+ {
+ /* explicit vectorization */
+ // process first unaligned result's coeffs
+ for (int j=0; j<alignedStart; ++j)
+ res[j] += ei_pfirst(ptmp0) * lhs0[j];
+
+ // process aligned result's coeffs
+ if ((size_t(lhs0+alignedStart)%sizeof(Packet))==0)
+ for (int j = alignedStart;j<alignedSize;j+=PacketSize)
+ ei_pstore(&res[j], ei_pmadd(ptmp0,ei_pload(&lhs0[j]),ei_pload(&res[j])));
+ else
+ for (int j = alignedStart;j<alignedSize;j+=PacketSize)
+ ei_pstore(&res[j], ei_pmadd(ptmp0,ei_ploadu(&lhs0[j]),ei_pload(&res[j])));
+ }
+
+ // process remaining scalars (or all if no explicit vectorization)
+ for (int j=alignedSize; j<size; ++j)
+ res[j] += ei_pfirst(ptmp0) * lhs0[j];
+ }
+ if (skipColumns)
+ {
+ start = 0;
+ end = skipColumns;
+ skipColumns = 0;
+ }
+ else
+ break;
+ } while(PacketSize>1);
+ #undef _EIGEN_ACCUMULATE_PACKETS
+}
+
+// TODO add peeling to mask unaligned load/stores
+template<typename Scalar, typename ResType>
+static EIGEN_DONT_INLINE void ei_cache_friendly_product_rowmajor_times_vector(
+ const Scalar* lhs, int lhsStride,
+ const Scalar* rhs, int rhsSize,
+ ResType& res)
+{
+ #ifdef _EIGEN_ACCUMULATE_PACKETS
+ #error _EIGEN_ACCUMULATE_PACKETS has already been defined
+ #endif
+
+ #define _EIGEN_ACCUMULATE_PACKETS(A0,A13,A2) {\
+ Packet b = ei_pload(&rhs[j]); \
+ ptmp0 = ei_pmadd(b, EIGEN_CAT(ei_ploa,A0) (&lhs0[j]), ptmp0); \
+ ptmp1 = ei_pmadd(b, EIGEN_CAT(ei_ploa,A13)(&lhs1[j]), ptmp1); \
+ ptmp2 = ei_pmadd(b, EIGEN_CAT(ei_ploa,A2) (&lhs2[j]), ptmp2); \
+ ptmp3 = ei_pmadd(b, EIGEN_CAT(ei_ploa,A13)(&lhs3[j]), ptmp3); }
+
+ typedef typename ei_packet_traits<Scalar>::type Packet;
+ const int PacketSize = sizeof(Packet)/sizeof(Scalar);
+
+ enum { AllAligned=0, EvenAligned=1, FirstAligned=2, NoneAligned=3 };
+ const int rowsAtOnce = 4;
+ const int peels = 2;
+ const int PacketAlignedMask = PacketSize-1;
+ const int PeelAlignedMask = PacketSize*peels-1;
+ const int size = rhsSize;
+
+ // How many coeffs of the result do we have to skip to be aligned.
+ // Here we assume data are at least aligned on the base scalar type that is mandatory anyway.
+ const int alignedStart = ei_alignmentOffset(rhs, size);
+ const int alignedSize = PacketSize>1 ? alignedStart + ((size-alignedStart) & ~PacketAlignedMask) : 0;
+ const int peeledSize = peels>1 ? alignedStart + ((alignedSize-alignedStart) & ~PeelAlignedMask) : alignedStart;
+
+ const int alignmentStep = PacketSize>1 ? (PacketSize - lhsStride % PacketSize) & PacketAlignedMask : 0;
+ int alignmentPattern = alignmentStep==0 ? AllAligned
+ : alignmentStep==(PacketSize/2) ? EvenAligned
+ : FirstAligned;
+
+ // we cannot assume the first element is aligned because of sub-matrices
+ const int lhsAlignmentOffset = ei_alignmentOffset(lhs,size);
+
+ // find how many rows do we have to skip to be aligned with rhs (if possible)
+ int skipRows = 0;
+ if (PacketSize>1)
+ {
+ ei_internal_assert(size_t(lhs+lhsAlignmentOffset)%sizeof(Packet)==0 || size<PacketSize);
+
+ while (skipRows<PacketSize &&
+ alignedStart != ((lhsAlignmentOffset + alignmentStep*skipRows)%PacketSize))
+ ++skipRows;
+ if (skipRows==PacketSize)
+ {
+ // nothing can be aligned, no need to skip any column
+ alignmentPattern = NoneAligned;
+ skipRows = 0;
+ }
+ else
+ {
+ skipRows = std::min(skipRows,res.size());
+ // note that the skiped columns are processed later.
+ }
+ ei_internal_assert((alignmentPattern==NoneAligned) || PacketSize==1
+ || (size_t(lhs+alignedStart+lhsStride*skipRows)%sizeof(Packet))==0);
+ }
+
+ int offset1 = (FirstAligned && alignmentStep==1?3:1);
+ int offset3 = (FirstAligned && alignmentStep==1?1:3);
+
+ int rowBound = ((res.size()-skipRows)/rowsAtOnce)*rowsAtOnce + skipRows;
+ for (int i=skipRows; i<rowBound; i+=rowsAtOnce)
+ {
+ Scalar tmp0 = Scalar(0), tmp1 = Scalar(0), tmp2 = Scalar(0), tmp3 = Scalar(0);
+
+ // this helps the compiler generating good binary code
+ const Scalar *lhs0 = lhs + i*lhsStride, *lhs1 = lhs + (i+offset1)*lhsStride,
+ *lhs2 = lhs + (i+2)*lhsStride, *lhs3 = lhs + (i+offset3)*lhsStride;
+
+ if (PacketSize>1)
+ {
+ /* explicit vectorization */
+ Packet ptmp0 = ei_pset1(Scalar(0)), ptmp1 = ei_pset1(Scalar(0)), ptmp2 = ei_pset1(Scalar(0)), ptmp3 = ei_pset1(Scalar(0));
+
+ // process initial unaligned coeffs
+ // FIXME this loop get vectorized by the compiler !
+ for (int j=0; j<alignedStart; ++j)
+ {
+ Scalar b = rhs[j];
+ tmp0 += b*lhs0[j]; tmp1 += b*lhs1[j]; tmp2 += b*lhs2[j]; tmp3 += b*lhs3[j];
+ }
+
+ if (alignedSize>alignedStart)
+ {
+ switch(alignmentPattern)
+ {
+ case AllAligned:
+ for (int j = alignedStart; j<alignedSize; j+=PacketSize)
+ _EIGEN_ACCUMULATE_PACKETS(d,d,d);
+ break;
+ case EvenAligned:
+ for (int j = alignedStart; j<alignedSize; j+=PacketSize)
+ _EIGEN_ACCUMULATE_PACKETS(d,du,d);
+ break;
+ case FirstAligned:
+ if (peels>1)
+ {
+ /* Here we proccess 4 rows with with two peeled iterations to hide
+ * tghe overhead of unaligned loads. Moreover unaligned loads are handled
+ * using special shift/move operations between the two aligned packets
+ * overlaping the desired unaligned packet. This is *much* more efficient
+ * than basic unaligned loads.
+ */
+ Packet A01, A02, A03, b, A11, A12, A13;
+ A01 = ei_pload(&lhs1[alignedStart-1]);
+ A02 = ei_pload(&lhs2[alignedStart-2]);
+ A03 = ei_pload(&lhs3[alignedStart-3]);
+
+ for (int j = alignedStart; j<peeledSize; j+=peels*PacketSize)
+ {
+ b = ei_pload(&rhs[j]);
+ A11 = ei_pload(&lhs1[j-1+PacketSize]); ei_palign<1>(A01,A11);
+ A12 = ei_pload(&lhs2[j-2+PacketSize]); ei_palign<2>(A02,A12);
+ A13 = ei_pload(&lhs3[j-3+PacketSize]); ei_palign<3>(A03,A13);
+
+ ptmp0 = ei_pmadd(b, ei_pload (&lhs0[j]), ptmp0);
+ ptmp1 = ei_pmadd(b, A01, ptmp1);
+ A01 = ei_pload(&lhs1[j-1+2*PacketSize]); ei_palign<1>(A11,A01);
+ ptmp2 = ei_pmadd(b, A02, ptmp2);
+ A02 = ei_pload(&lhs2[j-2+2*PacketSize]); ei_palign<2>(A12,A02);
+ ptmp3 = ei_pmadd(b, A03, ptmp3);
+ A03 = ei_pload(&lhs3[j-3+2*PacketSize]); ei_palign<3>(A13,A03);
+
+ b = ei_pload(&rhs[j+PacketSize]);
+ ptmp0 = ei_pmadd(b, ei_pload (&lhs0[j+PacketSize]), ptmp0);
+ ptmp1 = ei_pmadd(b, A11, ptmp1);
+ ptmp2 = ei_pmadd(b, A12, ptmp2);
+ ptmp3 = ei_pmadd(b, A13, ptmp3);
+ }
+ }
+ for (int j = peeledSize; j<alignedSize; j+=PacketSize)
+ _EIGEN_ACCUMULATE_PACKETS(d,du,du);
+ break;
+ default:
+ for (int j = alignedStart; j<alignedSize; j+=PacketSize)
+ _EIGEN_ACCUMULATE_PACKETS(du,du,du);
+ break;
+ }
+ tmp0 += ei_predux(ptmp0);
+ tmp1 += ei_predux(ptmp1);
+ tmp2 += ei_predux(ptmp2);
+ tmp3 += ei_predux(ptmp3);
+ }
+ } // end explicit vectorization
+
+ // process remaining coeffs (or all if no explicit vectorization)
+ // FIXME this loop get vectorized by the compiler !
+ for (int j=alignedSize; j<size; ++j)
+ {
+ Scalar b = rhs[j];
+ tmp0 += b*lhs0[j]; tmp1 += b*lhs1[j]; tmp2 += b*lhs2[j]; tmp3 += b*lhs3[j];
+ }
+ res[i] += tmp0; res[i+offset1] += tmp1; res[i+2] += tmp2; res[i+offset3] += tmp3;
+ }
+
+ // process remaining first and last rows (at most columnsAtOnce-1)
+ int end = res.size();
+ int start = rowBound;
+ do
+ {
+ for (int i=start; i<end; ++i)
+ {
+ Scalar tmp0 = Scalar(0);
+ Packet ptmp0 = ei_pset1(tmp0);
+ const Scalar* lhs0 = lhs + i*lhsStride;
+ // process first unaligned result's coeffs
+ // FIXME this loop get vectorized by the compiler !
+ for (int j=0; j<alignedStart; ++j)
+ tmp0 += rhs[j] * lhs0[j];
+
+ if (alignedSize>alignedStart)
+ {
+ // process aligned rhs coeffs
+ if ((size_t(lhs0+alignedStart)%sizeof(Packet))==0)
+ for (int j = alignedStart;j<alignedSize;j+=PacketSize)
+ ptmp0 = ei_pmadd(ei_pload(&rhs[j]), ei_pload(&lhs0[j]), ptmp0);
+ else
+ for (int j = alignedStart;j<alignedSize;j+=PacketSize)
+ ptmp0 = ei_pmadd(ei_pload(&rhs[j]), ei_ploadu(&lhs0[j]), ptmp0);
+ tmp0 += ei_predux(ptmp0);
+ }
+
+ // process remaining scalars
+ // FIXME this loop get vectorized by the compiler !
+ for (int j=alignedSize; j<size; ++j)
+ tmp0 += rhs[j] * lhs0[j];
+ res[i] += tmp0;
+ }
+ if (skipRows)
+ {
+ start = 0;
+ end = skipRows;
+ skipRows = 0;
+ }
+ else
+ break;
+ } while(PacketSize>1);
+
+ #undef _EIGEN_ACCUMULATE_PACKETS
+}
+
+#endif // EIGEN_CACHE_FRIENDLY_PRODUCT_H
diff --git a/extern/Eigen2/Eigen/src/Core/Coeffs.h b/extern/Eigen2/Eigen/src/Core/Coeffs.h
new file mode 100644
index 00000000000..23a84228b24
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/Coeffs.h
@@ -0,0 +1,384 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_COEFFS_H
+#define EIGEN_COEFFS_H
+
+/** Short version: don't use this function, use
+ * \link operator()(int,int) const \endlink instead.
+ *
+ * Long version: this function is similar to
+ * \link operator()(int,int) const \endlink, but without the assertion.
+ * Use this for limiting the performance cost of debugging code when doing
+ * repeated coefficient access. Only use this when it is guaranteed that the
+ * parameters \a row and \a col are in range.
+ *
+ * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this
+ * function equivalent to \link operator()(int,int) const \endlink.
+ *
+ * \sa operator()(int,int) const, coeffRef(int,int), coeff(int) const
+ */
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
+ ::coeff(int row, int col) const
+{
+ ei_internal_assert(row >= 0 && row < rows()
+ && col >= 0 && col < cols());
+ return derived().coeff(row, col);
+}
+
+/** \returns the coefficient at given the given row and column.
+ *
+ * \sa operator()(int,int), operator[](int) const
+ */
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
+ ::operator()(int row, int col) const
+{
+ ei_assert(row >= 0 && row < rows()
+ && col >= 0 && col < cols());
+ return derived().coeff(row, col);
+}
+
+/** Short version: don't use this function, use
+ * \link operator()(int,int) \endlink instead.
+ *
+ * Long version: this function is similar to
+ * \link operator()(int,int) \endlink, but without the assertion.
+ * Use this for limiting the performance cost of debugging code when doing
+ * repeated coefficient access. Only use this when it is guaranteed that the
+ * parameters \a row and \a col are in range.
+ *
+ * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this
+ * function equivalent to \link operator()(int,int) \endlink.
+ *
+ * \sa operator()(int,int), coeff(int, int) const, coeffRef(int)
+ */
+template<typename Derived>
+EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
+ ::coeffRef(int row, int col)
+{
+ ei_internal_assert(row >= 0 && row < rows()
+ && col >= 0 && col < cols());
+ return derived().coeffRef(row, col);
+}
+
+/** \returns a reference to the coefficient at given the given row and column.
+ *
+ * \sa operator()(int,int) const, operator[](int)
+ */
+template<typename Derived>
+EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
+ ::operator()(int row, int col)
+{
+ ei_assert(row >= 0 && row < rows()
+ && col >= 0 && col < cols());
+ return derived().coeffRef(row, col);
+}
+
+/** Short version: don't use this function, use
+ * \link operator[](int) const \endlink instead.
+ *
+ * Long version: this function is similar to
+ * \link operator[](int) const \endlink, but without the assertion.
+ * Use this for limiting the performance cost of debugging code when doing
+ * repeated coefficient access. Only use this when it is guaranteed that the
+ * parameter \a index is in range.
+ *
+ * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this
+ * function equivalent to \link operator[](int) const \endlink.
+ *
+ * \sa operator[](int) const, coeffRef(int), coeff(int,int) const
+ */
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
+ ::coeff(int index) const
+{
+ ei_internal_assert(index >= 0 && index < size());
+ return derived().coeff(index);
+}
+
+/** \returns the coefficient at given index.
+ *
+ * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit.
+ *
+ * \sa operator[](int), operator()(int,int) const, x() const, y() const,
+ * z() const, w() const
+ */
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
+ ::operator[](int index) const
+{
+ ei_assert(index >= 0 && index < size());
+ return derived().coeff(index);
+}
+
+/** \returns the coefficient at given index.
+ *
+ * This is synonymous to operator[](int) const.
+ *
+ * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit.
+ *
+ * \sa operator[](int), operator()(int,int) const, x() const, y() const,
+ * z() const, w() const
+ */
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
+ ::operator()(int index) const
+{
+ ei_assert(index >= 0 && index < size());
+ return derived().coeff(index);
+}
+
+/** Short version: don't use this function, use
+ * \link operator[](int) \endlink instead.
+ *
+ * Long version: this function is similar to
+ * \link operator[](int) \endlink, but without the assertion.
+ * Use this for limiting the performance cost of debugging code when doing
+ * repeated coefficient access. Only use this when it is guaranteed that the
+ * parameters \a row and \a col are in range.
+ *
+ * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this
+ * function equivalent to \link operator[](int) \endlink.
+ *
+ * \sa operator[](int), coeff(int) const, coeffRef(int,int)
+ */
+template<typename Derived>
+EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
+ ::coeffRef(int index)
+{
+ ei_internal_assert(index >= 0 && index < size());
+ return derived().coeffRef(index);
+}
+
+/** \returns a reference to the coefficient at given index.
+ *
+ * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit.
+ *
+ * \sa operator[](int) const, operator()(int,int), x(), y(), z(), w()
+ */
+template<typename Derived>
+EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
+ ::operator[](int index)
+{
+ ei_assert(index >= 0 && index < size());
+ return derived().coeffRef(index);
+}
+
+/** \returns a reference to the coefficient at given index.
+ *
+ * This is synonymous to operator[](int).
+ *
+ * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit.
+ *
+ * \sa operator[](int) const, operator()(int,int), x(), y(), z(), w()
+ */
+template<typename Derived>
+EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
+ ::operator()(int index)
+{
+ ei_assert(index >= 0 && index < size());
+ return derived().coeffRef(index);
+}
+
+/** equivalent to operator[](0). */
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
+ ::x() const { return (*this)[0]; }
+
+/** equivalent to operator[](1). */
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
+ ::y() const { return (*this)[1]; }
+
+/** equivalent to operator[](2). */
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
+ ::z() const { return (*this)[2]; }
+
+/** equivalent to operator[](3). */
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename ei_traits<Derived>::Scalar MatrixBase<Derived>
+ ::w() const { return (*this)[3]; }
+
+/** equivalent to operator[](0). */
+template<typename Derived>
+EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
+ ::x() { return (*this)[0]; }
+
+/** equivalent to operator[](1). */
+template<typename Derived>
+EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
+ ::y() { return (*this)[1]; }
+
+/** equivalent to operator[](2). */
+template<typename Derived>
+EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
+ ::z() { return (*this)[2]; }
+
+/** equivalent to operator[](3). */
+template<typename Derived>
+EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar& MatrixBase<Derived>
+ ::w() { return (*this)[3]; }
+
+/** \returns the packet of coefficients starting at the given row and column. It is your responsibility
+ * to ensure that a packet really starts there. This method is only available on expressions having the
+ * PacketAccessBit.
+ *
+ * The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select
+ * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
+ * starting at an address which is a multiple of the packet size.
+ */
+template<typename Derived>
+template<int LoadMode>
+EIGEN_STRONG_INLINE typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type
+MatrixBase<Derived>::packet(int row, int col) const
+{
+ ei_internal_assert(row >= 0 && row < rows()
+ && col >= 0 && col < cols());
+ return derived().template packet<LoadMode>(row,col);
+}
+
+/** Stores the given packet of coefficients, at the given row and column of this expression. It is your responsibility
+ * to ensure that a packet really starts there. This method is only available on expressions having the
+ * PacketAccessBit.
+ *
+ * The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select
+ * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
+ * starting at an address which is a multiple of the packet size.
+ */
+template<typename Derived>
+template<int StoreMode>
+EIGEN_STRONG_INLINE void MatrixBase<Derived>::writePacket
+(int row, int col, const typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type& x)
+{
+ ei_internal_assert(row >= 0 && row < rows()
+ && col >= 0 && col < cols());
+ derived().template writePacket<StoreMode>(row,col,x);
+}
+
+/** \returns the packet of coefficients starting at the given index. It is your responsibility
+ * to ensure that a packet really starts there. This method is only available on expressions having the
+ * PacketAccessBit and the LinearAccessBit.
+ *
+ * The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select
+ * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
+ * starting at an address which is a multiple of the packet size.
+ */
+template<typename Derived>
+template<int LoadMode>
+EIGEN_STRONG_INLINE typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type
+MatrixBase<Derived>::packet(int index) const
+{
+ ei_internal_assert(index >= 0 && index < size());
+ return derived().template packet<LoadMode>(index);
+}
+
+/** Stores the given packet of coefficients, at the given index in this expression. It is your responsibility
+ * to ensure that a packet really starts there. This method is only available on expressions having the
+ * PacketAccessBit and the LinearAccessBit.
+ *
+ * The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select
+ * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
+ * starting at an address which is a multiple of the packet size.
+ */
+template<typename Derived>
+template<int StoreMode>
+EIGEN_STRONG_INLINE void MatrixBase<Derived>::writePacket
+(int index, const typename ei_packet_traits<typename ei_traits<Derived>::Scalar>::type& x)
+{
+ ei_internal_assert(index >= 0 && index < size());
+ derived().template writePacket<StoreMode>(index,x);
+}
+
+#ifndef EIGEN_PARSED_BY_DOXYGEN
+
+/** \internal Copies the coefficient at position (row,col) of other into *this.
+ *
+ * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code
+ * with usual assignments.
+ *
+ * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox.
+ */
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE void MatrixBase<Derived>::copyCoeff(int row, int col, const MatrixBase<OtherDerived>& other)
+{
+ ei_internal_assert(row >= 0 && row < rows()
+ && col >= 0 && col < cols());
+ derived().coeffRef(row, col) = other.derived().coeff(row, col);
+}
+
+/** \internal Copies the coefficient at the given index of other into *this.
+ *
+ * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code
+ * with usual assignments.
+ *
+ * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox.
+ */
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE void MatrixBase<Derived>::copyCoeff(int index, const MatrixBase<OtherDerived>& other)
+{
+ ei_internal_assert(index >= 0 && index < size());
+ derived().coeffRef(index) = other.derived().coeff(index);
+}
+
+/** \internal Copies the packet at position (row,col) of other into *this.
+ *
+ * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code
+ * with usual assignments.
+ *
+ * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox.
+ */
+template<typename Derived>
+template<typename OtherDerived, int StoreMode, int LoadMode>
+EIGEN_STRONG_INLINE void MatrixBase<Derived>::copyPacket(int row, int col, const MatrixBase<OtherDerived>& other)
+{
+ ei_internal_assert(row >= 0 && row < rows()
+ && col >= 0 && col < cols());
+ derived().template writePacket<StoreMode>(row, col,
+ other.derived().template packet<LoadMode>(row, col));
+}
+
+/** \internal Copies the packet at the given index of other into *this.
+ *
+ * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code
+ * with usual assignments.
+ *
+ * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox.
+ */
+template<typename Derived>
+template<typename OtherDerived, int StoreMode, int LoadMode>
+EIGEN_STRONG_INLINE void MatrixBase<Derived>::copyPacket(int index, const MatrixBase<OtherDerived>& other)
+{
+ ei_internal_assert(index >= 0 && index < size());
+ derived().template writePacket<StoreMode>(index,
+ other.derived().template packet<LoadMode>(index));
+}
+
+#endif
+
+#endif // EIGEN_COEFFS_H
diff --git a/extern/Eigen3/Eigen/src/Core/CommaInitializer.h b/extern/Eigen2/Eigen/src/Core/CommaInitializer.h
index 92422bf2fa0..f66cbd6d5e1 100644
--- a/extern/Eigen3/Eigen/src/Core/CommaInitializer.h
+++ b/extern/Eigen2/Eigen/src/Core/CommaInitializer.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
@@ -27,7 +27,6 @@
#define EIGEN_COMMAINITIALIZER_H
/** \class CommaInitializer
- * \ingroup Core_Module
*
* \brief Helper class used by the comma initializer operator
*
@@ -37,72 +36,70 @@
*
* \sa \ref MatrixBaseCommaInitRef "MatrixBase::operator<<", CommaInitializer::finished()
*/
-template<typename XprType>
+template<typename MatrixType>
struct CommaInitializer
{
- typedef typename XprType::Scalar Scalar;
- typedef typename XprType::Index Index;
-
- inline CommaInitializer(XprType& xpr, const Scalar& s)
- : m_xpr(xpr), m_row(0), m_col(1), m_currentBlockRows(1)
+ typedef typename ei_traits<MatrixType>::Scalar Scalar;
+ inline CommaInitializer(MatrixType& mat, const Scalar& s)
+ : m_matrix(mat), m_row(0), m_col(1), m_currentBlockRows(1)
{
- m_xpr.coeffRef(0,0) = s;
+ m_matrix.coeffRef(0,0) = s;
}
template<typename OtherDerived>
- inline CommaInitializer(XprType& xpr, const DenseBase<OtherDerived>& other)
- : m_xpr(xpr), m_row(0), m_col(other.cols()), m_currentBlockRows(other.rows())
+ inline CommaInitializer(MatrixType& mat, const MatrixBase<OtherDerived>& other)
+ : m_matrix(mat), m_row(0), m_col(other.cols()), m_currentBlockRows(other.rows())
{
- m_xpr.block(0, 0, other.rows(), other.cols()) = other;
+ m_matrix.block(0, 0, other.rows(), other.cols()) = other;
}
/* inserts a scalar value in the target matrix */
CommaInitializer& operator,(const Scalar& s)
{
- if (m_col==m_xpr.cols())
+ if (m_col==m_matrix.cols())
{
m_row+=m_currentBlockRows;
m_col = 0;
m_currentBlockRows = 1;
- eigen_assert(m_row<m_xpr.rows()
+ ei_assert(m_row<m_matrix.rows()
&& "Too many rows passed to comma initializer (operator<<)");
}
- eigen_assert(m_col<m_xpr.cols()
+ ei_assert(m_col<m_matrix.cols()
&& "Too many coefficients passed to comma initializer (operator<<)");
- eigen_assert(m_currentBlockRows==1);
- m_xpr.coeffRef(m_row, m_col++) = s;
+ ei_assert(m_currentBlockRows==1);
+ m_matrix.coeffRef(m_row, m_col++) = s;
return *this;
}
/* inserts a matrix expression in the target matrix */
template<typename OtherDerived>
- CommaInitializer& operator,(const DenseBase<OtherDerived>& other)
+ CommaInitializer& operator,(const MatrixBase<OtherDerived>& other)
{
- if (m_col==m_xpr.cols())
+ if (m_col==m_matrix.cols())
{
m_row+=m_currentBlockRows;
m_col = 0;
m_currentBlockRows = other.rows();
- eigen_assert(m_row+m_currentBlockRows<=m_xpr.rows()
+ ei_assert(m_row+m_currentBlockRows<=m_matrix.rows()
&& "Too many rows passed to comma initializer (operator<<)");
}
- eigen_assert(m_col<m_xpr.cols()
+ ei_assert(m_col<m_matrix.cols()
&& "Too many coefficients passed to comma initializer (operator<<)");
- eigen_assert(m_currentBlockRows==other.rows());
+ ei_assert(m_currentBlockRows==other.rows());
if (OtherDerived::SizeAtCompileTime != Dynamic)
- m_xpr.template block<OtherDerived::RowsAtCompileTime != Dynamic ? OtherDerived::RowsAtCompileTime : 1,
+ m_matrix.template block<OtherDerived::RowsAtCompileTime != Dynamic ? OtherDerived::RowsAtCompileTime : 1,
OtherDerived::ColsAtCompileTime != Dynamic ? OtherDerived::ColsAtCompileTime : 1>
(m_row, m_col) = other;
else
- m_xpr.block(m_row, m_col, other.rows(), other.cols()) = other;
+ m_matrix.block(m_row, m_col, other.rows(), other.cols()) = other;
m_col += other.cols();
return *this;
}
inline ~CommaInitializer()
{
- eigen_assert((m_row+m_currentBlockRows) == m_xpr.rows()
- && m_col == m_xpr.cols()
+ ei_assert((m_row+m_currentBlockRows) == m_matrix.rows()
+ && m_col == m_matrix.cols()
&& "Too few coefficients passed to comma initializer (operator<<)");
}
@@ -113,12 +110,15 @@ struct CommaInitializer
* quaternion.fromRotationMatrix((Matrix3f() << axis0, axis1, axis2).finished());
* \endcode
*/
- inline XprType& finished() { return m_xpr; }
+ inline MatrixType& finished() { return m_matrix; }
+
+ MatrixType& m_matrix; // target matrix
+ int m_row; // current row id
+ int m_col; // current col id
+ int m_currentBlockRows; // current block height
- XprType& m_xpr; // target expression
- Index m_row; // current row id
- Index m_col; // current col id
- Index m_currentBlockRows; // current block height
+private:
+ CommaInitializer& operator=(const CommaInitializer&);
};
/** \anchor MatrixBaseCommaInitRef
@@ -127,13 +127,15 @@ struct CommaInitializer
* The coefficients must be provided in a row major order and exactly match
* the size of the matrix. Otherwise an assertion is raised.
*
+ * \addexample CommaInit \label How to easily set all the coefficients of a matrix
+ *
* Example: \include MatrixBase_set.cpp
* Output: \verbinclude MatrixBase_set.out
*
* \sa CommaInitializer::finished(), class CommaInitializer
*/
template<typename Derived>
-inline CommaInitializer<Derived> DenseBase<Derived>::operator<< (const Scalar& s)
+inline CommaInitializer<Derived> MatrixBase<Derived>::operator<< (const Scalar& s)
{
return CommaInitializer<Derived>(*static_cast<Derived*>(this), s);
}
@@ -142,7 +144,7 @@ inline CommaInitializer<Derived> DenseBase<Derived>::operator<< (const Scalar& s
template<typename Derived>
template<typename OtherDerived>
inline CommaInitializer<Derived>
-DenseBase<Derived>::operator<<(const DenseBase<OtherDerived>& other)
+MatrixBase<Derived>::operator<<(const MatrixBase<OtherDerived>& other)
{
return CommaInitializer<Derived>(*static_cast<Derived *>(this), other);
}
diff --git a/extern/Eigen3/Eigen/StdList b/extern/Eigen2/Eigen/src/Core/CoreInstantiations.cpp
index d914ded4f93..56a9448917a 100644
--- a/extern/Eigen3/Eigen/StdList
+++ b/extern/Eigen2/Eigen/src/Core/CoreInstantiations.cpp
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -22,20 +22,26 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-#ifndef EIGEN_STDLIST_MODULE_H
-#define EIGEN_STDLIST_MODULE_H
-
-#include "Core"
-#include <list>
-
-#if (defined(_MSC_VER) && defined(_WIN64)) /* MSVC auto aligns in 64 bit builds */
+#ifdef EIGEN_EXTERN_INSTANTIATIONS
+#undef EIGEN_EXTERN_INSTANTIATIONS
+#endif
-#define EIGEN_DEFINE_STL_LIST_SPECIALIZATION(...)
+#include "../../Core"
-#else
+namespace Eigen
+{
-#include "src/StlSupport/StdList.h"
+#define EIGEN_INSTANTIATE_PRODUCT(TYPE) \
+template static void ei_cache_friendly_product<TYPE>( \
+ int _rows, int _cols, int depth, \
+ bool _lhsRowMajor, const TYPE* _lhs, int _lhsStride, \
+ bool _rhsRowMajor, const TYPE* _rhs, int _rhsStride, \
+ bool resRowMajor, TYPE* res, int resStride)
-#endif
+EIGEN_INSTANTIATE_PRODUCT(float);
+EIGEN_INSTANTIATE_PRODUCT(double);
+EIGEN_INSTANTIATE_PRODUCT(int);
+EIGEN_INSTANTIATE_PRODUCT(std::complex<float>);
+EIGEN_INSTANTIATE_PRODUCT(std::complex<double>);
-#endif // EIGEN_STDLIST_MODULE_H
+}
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h b/extern/Eigen2/Eigen/src/Core/Cwise.h
index 2dc83b6a7dd..4dc9d514b04 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h
+++ b/extern/Eigen2/Eigen/src/Core/Cwise.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
@@ -29,18 +29,30 @@
/** \internal
* convenient macro to defined the return type of a cwise binary operation */
#define EIGEN_CWISE_BINOP_RETURN_TYPE(OP) \
- CwiseBinaryOp<OP<typename internal::traits<ExpressionType>::Scalar>, ExpressionType, OtherDerived>
+ CwiseBinaryOp<OP<typename ei_traits<ExpressionType>::Scalar>, ExpressionType, OtherDerived>
+
+#define EIGEN_CWISE_PRODUCT_RETURN_TYPE \
+ CwiseBinaryOp< \
+ ei_scalar_product_op< \
+ typename ei_scalar_product_traits< \
+ typename ei_traits<ExpressionType>::Scalar, \
+ typename ei_traits<OtherDerived>::Scalar \
+ >::ReturnType \
+ >, \
+ ExpressionType, \
+ OtherDerived \
+ >
/** \internal
* convenient macro to defined the return type of a cwise unary operation */
#define EIGEN_CWISE_UNOP_RETURN_TYPE(OP) \
- CwiseUnaryOp<OP<typename internal::traits<ExpressionType>::Scalar>, ExpressionType>
+ CwiseUnaryOp<OP<typename ei_traits<ExpressionType>::Scalar>, ExpressionType>
/** \internal
* convenient macro to defined the return type of a cwise comparison to a scalar */
#define EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(OP) \
- CwiseBinaryOp<OP<typename internal::traits<ExpressionType>::Scalar>, ExpressionType, \
- typename ExpressionType::ConstantReturnType >
+ CwiseBinaryOp<OP<typename ei_traits<ExpressionType>::Scalar>, ExpressionType, \
+ NestByValue<typename ExpressionType::ConstantReturnType> >
/** \class Cwise
*
@@ -52,22 +64,21 @@
* It is the return type of MatrixBase::cwise()
* and most of the time this is the only way it is used.
*
+ * Note that some methods are defined in the \ref Array module.
+ *
* Example: \include MatrixBase_cwise_const.cpp
* Output: \verbinclude MatrixBase_cwise_const.out
*
- * 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_CWISE_PLUGIN.
- *
* \sa MatrixBase::cwise() const, MatrixBase::cwise()
*/
template<typename ExpressionType> class Cwise
{
public:
- typedef typename internal::traits<ExpressionType>::Scalar Scalar;
- typedef typename internal::conditional<internal::must_nest_by_value<ExpressionType>::ret,
- ExpressionType, const ExpressionType&>::type ExpressionTypeNested;
- typedef CwiseUnaryOp<internal::scalar_add_op<Scalar>, ExpressionType> ScalarAddReturnType;
+ typedef typename ei_traits<ExpressionType>::Scalar Scalar;
+ typedef typename ei_meta_if<ei_must_nest_by_value<ExpressionType>::ret,
+ ExpressionType, const ExpressionType&>::ret ExpressionTypeNested;
+ typedef CwiseUnaryOp<ei_scalar_add_op<Scalar>, ExpressionType> ScalarAddReturnType;
inline Cwise(const ExpressionType& matrix) : m_matrix(matrix) {}
@@ -75,36 +86,32 @@ template<typename ExpressionType> class Cwise
inline const ExpressionType& _expression() const { return m_matrix; }
template<typename OtherDerived>
- const EIGEN_CWISE_PRODUCT_RETURN_TYPE(ExpressionType,OtherDerived)
+ const EIGEN_CWISE_PRODUCT_RETURN_TYPE
operator*(const MatrixBase<OtherDerived> &other) const;
template<typename OtherDerived>
- const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)
+ const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
operator/(const MatrixBase<OtherDerived> &other) const;
- /** \deprecated ArrayBase::min() */
template<typename OtherDerived>
- const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_min_op)
- (min)(const MatrixBase<OtherDerived> &other) const
- { return EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_min_op)(_expression(), other.derived()); }
+ const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)
+ min(const MatrixBase<OtherDerived> &other) const;
- /** \deprecated ArrayBase::max() */
template<typename OtherDerived>
- const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_max_op)
- (max)(const MatrixBase<OtherDerived> &other) const
- { return EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_max_op)(_expression(), other.derived()); }
-
- const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs_op) abs() const;
- const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs2_op) abs2() const;
- const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_square_op) square() const;
- const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_cube_op) cube() const;
- const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_inverse_op) inverse() const;
- const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_sqrt_op) sqrt() const;
- const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_exp_op) exp() const;
- const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_log_op) log() const;
- const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_cos_op) cos() const;
- const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_sin_op) sin() const;
- const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_pow_op) pow(const Scalar& exponent) const;
+ const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)
+ max(const MatrixBase<OtherDerived> &other) const;
+
+ const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs_op) abs() const;
+ const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs2_op) abs2() const;
+ const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_square_op) square() const;
+ const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_cube_op) cube() const;
+ const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_inverse_op) inverse() const;
+ const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_sqrt_op) sqrt() const;
+ const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_exp_op) exp() const;
+ const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_log_op) log() const;
+ const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_cos_op) cos() const;
+ const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_sin_op) sin() const;
+ const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_pow_op) pow(const Scalar& exponent) const;
const ScalarAddReturnType
operator+(const Scalar& scalar) const;
@@ -171,8 +178,10 @@ template<typename ExpressionType> class Cwise
protected:
ExpressionTypeNested m_matrix;
-};
+ private:
+ Cwise& operator=(const Cwise&);
+};
/** \returns a Cwise wrapper of *this providing additional coefficient-wise operations
*
@@ -182,7 +191,8 @@ template<typename ExpressionType> class Cwise
* \sa class Cwise, cwise()
*/
template<typename Derived>
-inline const Cwise<Derived> MatrixBase<Derived>::cwise() const
+inline const Cwise<Derived>
+MatrixBase<Derived>::cwise() const
{
return derived();
}
@@ -195,7 +205,8 @@ inline const Cwise<Derived> MatrixBase<Derived>::cwise() const
* \sa class Cwise, cwise() const
*/
template<typename Derived>
-inline Cwise<Derived> MatrixBase<Derived>::cwise()
+inline Cwise<Derived>
+MatrixBase<Derived>::cwise()
{
return derived();
}
diff --git a/extern/Eigen2/Eigen/src/Core/CwiseBinaryOp.h b/extern/Eigen2/Eigen/src/Core/CwiseBinaryOp.h
new file mode 100644
index 00000000000..c4223e2204e
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/CwiseBinaryOp.h
@@ -0,0 +1,304 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_CWISE_BINARY_OP_H
+#define EIGEN_CWISE_BINARY_OP_H
+
+/** \class CwiseBinaryOp
+ *
+ * \brief Generic expression of a coefficient-wise operator between two matrices or vectors
+ *
+ * \param BinaryOp template functor implementing the operator
+ * \param Lhs the type of the left-hand side
+ * \param Rhs the type of the right-hand side
+ *
+ * This class represents an expression of a generic binary operator of two matrices or vectors.
+ * It is the return type of the operator+, operator-, and the Cwise methods, and most
+ * of the time this is the only way it is used.
+ *
+ * However, if you want to write a function returning such an expression, you
+ * will need to use this class.
+ *
+ * \sa MatrixBase::binaryExpr(const MatrixBase<OtherDerived> &,const CustomBinaryOp &) const, class CwiseUnaryOp, class CwiseNullaryOp
+ */
+template<typename BinaryOp, typename Lhs, typename Rhs>
+struct ei_traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
+{
+ // even though we require Lhs and Rhs to have the same scalar type (see CwiseBinaryOp constructor),
+ // we still want to handle the case when the result type is different.
+ typedef typename ei_result_of<
+ BinaryOp(
+ typename Lhs::Scalar,
+ typename Rhs::Scalar
+ )
+ >::type Scalar;
+ typedef typename Lhs::Nested LhsNested;
+ typedef typename Rhs::Nested RhsNested;
+ typedef typename ei_unref<LhsNested>::type _LhsNested;
+ typedef typename ei_unref<RhsNested>::type _RhsNested;
+ enum {
+ LhsCoeffReadCost = _LhsNested::CoeffReadCost,
+ RhsCoeffReadCost = _RhsNested::CoeffReadCost,
+ LhsFlags = _LhsNested::Flags,
+ RhsFlags = _RhsNested::Flags,
+ RowsAtCompileTime = Lhs::RowsAtCompileTime,
+ ColsAtCompileTime = Lhs::ColsAtCompileTime,
+ MaxRowsAtCompileTime = Lhs::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = Lhs::MaxColsAtCompileTime,
+ Flags = (int(LhsFlags) | int(RhsFlags)) & (
+ HereditaryBits
+ | (int(LhsFlags) & int(RhsFlags) & (LinearAccessBit | AlignedBit))
+ | (ei_functor_traits<BinaryOp>::PacketAccess && ((int(LhsFlags) & RowMajorBit)==(int(RhsFlags) & RowMajorBit))
+ ? (int(LhsFlags) & int(RhsFlags) & PacketAccessBit) : 0)),
+ CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + ei_functor_traits<BinaryOp>::Cost
+ };
+};
+
+template<typename BinaryOp, typename Lhs, typename Rhs>
+class CwiseBinaryOp : ei_no_assignment_operator,
+ public MatrixBase<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
+{
+ public:
+
+ EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseBinaryOp)
+ typedef typename ei_traits<CwiseBinaryOp>::LhsNested LhsNested;
+ typedef typename ei_traits<CwiseBinaryOp>::RhsNested RhsNested;
+
+ EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
+ : m_lhs(lhs), m_rhs(rhs), m_functor(func)
+ {
+ // we require Lhs and Rhs to have the same scalar type. Currently there is no example of a binary functor
+ // that would take two operands of different types. If there were such an example, then this check should be
+ // moved to the BinaryOp functors, on a per-case basis. This would however require a change in the BinaryOp functors, as
+ // currently they take only one typename Scalar template parameter.
+ // It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
+ // So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
+ // add together a float matrix and a double matrix.
+ EIGEN_STATIC_ASSERT((ei_functor_allows_mixing_real_and_complex<BinaryOp>::ret
+ ? int(ei_is_same_type<typename Lhs::RealScalar, typename Rhs::RealScalar>::ret)
+ : int(ei_is_same_type<typename Lhs::Scalar, typename Rhs::Scalar>::ret)),
+ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
+ // require the sizes to match
+ EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs)
+ ei_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
+ }
+
+ EIGEN_STRONG_INLINE int rows() const { return m_lhs.rows(); }
+ EIGEN_STRONG_INLINE int cols() const { return m_lhs.cols(); }
+
+ EIGEN_STRONG_INLINE const Scalar coeff(int row, int col) const
+ {
+ return m_functor(m_lhs.coeff(row, col), m_rhs.coeff(row, col));
+ }
+
+ template<int LoadMode>
+ EIGEN_STRONG_INLINE PacketScalar packet(int row, int col) const
+ {
+ return m_functor.packetOp(m_lhs.template packet<LoadMode>(row, col), m_rhs.template packet<LoadMode>(row, col));
+ }
+
+ EIGEN_STRONG_INLINE const Scalar coeff(int index) const
+ {
+ return m_functor(m_lhs.coeff(index), m_rhs.coeff(index));
+ }
+
+ template<int LoadMode>
+ EIGEN_STRONG_INLINE PacketScalar packet(int index) const
+ {
+ return m_functor.packetOp(m_lhs.template packet<LoadMode>(index), m_rhs.template packet<LoadMode>(index));
+ }
+
+ protected:
+ const LhsNested m_lhs;
+ const RhsNested m_rhs;
+ const BinaryOp m_functor;
+};
+
+/**\returns an expression of the difference of \c *this and \a other
+ *
+ * \note If you want to substract a given scalar from all coefficients, see Cwise::operator-().
+ *
+ * \sa class CwiseBinaryOp, MatrixBase::operator-=(), Cwise::operator-()
+ */
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const CwiseBinaryOp<ei_scalar_difference_op<typename ei_traits<Derived>::Scalar>,
+ Derived, OtherDerived>
+MatrixBase<Derived>::operator-(const MatrixBase<OtherDerived> &other) const
+{
+ return CwiseBinaryOp<ei_scalar_difference_op<Scalar>,
+ Derived, OtherDerived>(derived(), other.derived());
+}
+
+/** replaces \c *this by \c *this - \a other.
+ *
+ * \returns a reference to \c *this
+ */
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE Derived &
+MatrixBase<Derived>::operator-=(const MatrixBase<OtherDerived> &other)
+{
+ return *this = *this - other;
+}
+
+/** \relates MatrixBase
+ *
+ * \returns an expression of the sum of \c *this and \a other
+ *
+ * \note If you want to add a given scalar to all coefficients, see Cwise::operator+().
+ *
+ * \sa class CwiseBinaryOp, MatrixBase::operator+=(), Cwise::operator+()
+ */
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const CwiseBinaryOp<ei_scalar_sum_op<typename ei_traits<Derived>::Scalar>, Derived, OtherDerived>
+MatrixBase<Derived>::operator+(const MatrixBase<OtherDerived> &other) const
+{
+ return CwiseBinaryOp<ei_scalar_sum_op<Scalar>, Derived, OtherDerived>(derived(), other.derived());
+}
+
+/** replaces \c *this by \c *this + \a other.
+ *
+ * \returns a reference to \c *this
+ */
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE Derived &
+MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other)
+{
+ return *this = *this + other;
+}
+
+/** \returns an expression of the Schur product (coefficient wise product) of *this and \a other
+ *
+ * Example: \include Cwise_product.cpp
+ * Output: \verbinclude Cwise_product.out
+ *
+ * \sa class CwiseBinaryOp, operator/(), square()
+ */
+template<typename ExpressionType>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const EIGEN_CWISE_PRODUCT_RETURN_TYPE
+Cwise<ExpressionType>::operator*(const MatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_CWISE_PRODUCT_RETURN_TYPE(_expression(), other.derived());
+}
+
+/** \returns an expression of the coefficient-wise quotient of *this and \a other
+ *
+ * Example: \include Cwise_quotient.cpp
+ * Output: \verbinclude Cwise_quotient.out
+ *
+ * \sa class CwiseBinaryOp, operator*(), inverse()
+ */
+template<typename ExpressionType>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
+Cwise<ExpressionType>::operator/(const MatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)(_expression(), other.derived());
+}
+
+/** Replaces this expression by its coefficient-wise product with \a other.
+ *
+ * Example: \include Cwise_times_equal.cpp
+ * Output: \verbinclude Cwise_times_equal.out
+ *
+ * \sa operator*(), operator/=()
+ */
+template<typename ExpressionType>
+template<typename OtherDerived>
+inline ExpressionType& Cwise<ExpressionType>::operator*=(const MatrixBase<OtherDerived> &other)
+{
+ return m_matrix.const_cast_derived() = *this * other;
+}
+
+/** Replaces this expression by its coefficient-wise quotient by \a other.
+ *
+ * Example: \include Cwise_slash_equal.cpp
+ * Output: \verbinclude Cwise_slash_equal.out
+ *
+ * \sa operator/(), operator*=()
+ */
+template<typename ExpressionType>
+template<typename OtherDerived>
+inline ExpressionType& Cwise<ExpressionType>::operator/=(const MatrixBase<OtherDerived> &other)
+{
+ return m_matrix.const_cast_derived() = *this / other;
+}
+
+/** \returns an expression of the coefficient-wise min of *this and \a other
+ *
+ * Example: \include Cwise_min.cpp
+ * Output: \verbinclude Cwise_min.out
+ *
+ * \sa class CwiseBinaryOp
+ */
+template<typename ExpressionType>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)
+Cwise<ExpressionType>::min(const MatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)(_expression(), other.derived());
+}
+
+/** \returns an expression of the coefficient-wise max of *this and \a other
+ *
+ * Example: \include Cwise_max.cpp
+ * Output: \verbinclude Cwise_max.out
+ *
+ * \sa class CwiseBinaryOp
+ */
+template<typename ExpressionType>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)
+Cwise<ExpressionType>::max(const MatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)(_expression(), other.derived());
+}
+
+/** \returns an expression of a custom coefficient-wise operator \a func of *this and \a other
+ *
+ * The template parameter \a CustomBinaryOp is the type of the functor
+ * of the custom operator (see class CwiseBinaryOp for an example)
+ *
+ * \addexample CustomCwiseBinaryFunctors \label How to use custom coeff wise binary functors
+ *
+ * Here is an example illustrating the use of custom functors:
+ * \include class_CwiseBinaryOp.cpp
+ * Output: \verbinclude class_CwiseBinaryOp.out
+ *
+ * \sa class CwiseBinaryOp, MatrixBase::operator+, MatrixBase::operator-, Cwise::operator*, Cwise::operator/
+ */
+template<typename Derived>
+template<typename CustomBinaryOp, typename OtherDerived>
+EIGEN_STRONG_INLINE const CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>
+MatrixBase<Derived>::binaryExpr(const MatrixBase<OtherDerived> &other, const CustomBinaryOp& func) const
+{
+ return CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>(derived(), other.derived(), func);
+}
+
+#endif // EIGEN_CWISE_BINARY_OP_H
diff --git a/extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h b/extern/Eigen2/Eigen/src/Core/CwiseNullaryOp.h
index c616e7ae13d..4ee5b58afec 100644
--- a/extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h
+++ b/extern/Eigen2/Eigen/src/Core/CwiseNullaryOp.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -26,84 +26,81 @@
#define EIGEN_CWISE_NULLARY_OP_H
/** \class CwiseNullaryOp
- * \ingroup Core_Module
*
* \brief Generic expression of a matrix where all coefficients are defined by a functor
*
* \param NullaryOp template functor implementing the operator
- * \param PlainObjectType the underlying plain matrix/array type
*
* This class represents an expression of a generic nullary operator.
- * It is the return type of the Ones(), Zero(), Constant(), Identity() and Random() methods,
+ * It is the return type of the Ones(), Zero(), Constant(), Identity() and Random() functions,
* and most of the time this is the only way it is used.
*
* However, if you want to write a function returning such an expression, you
* will need to use this class.
*
- * \sa class CwiseUnaryOp, class CwiseBinaryOp, DenseBase::NullaryExpr()
+ * \sa class CwiseUnaryOp, class CwiseBinaryOp, MatrixBase::NullaryExpr()
*/
-
-namespace internal {
-template<typename NullaryOp, typename PlainObjectType>
-struct traits<CwiseNullaryOp<NullaryOp, PlainObjectType> > : traits<PlainObjectType>
+template<typename NullaryOp, typename MatrixType>
+struct ei_traits<CwiseNullaryOp<NullaryOp, MatrixType> > : ei_traits<MatrixType>
{
enum {
- Flags = (traits<PlainObjectType>::Flags
+ Flags = (ei_traits<MatrixType>::Flags
& ( HereditaryBits
- | (functor_has_linear_access<NullaryOp>::ret ? LinearAccessBit : 0)
- | (functor_traits<NullaryOp>::PacketAccess ? PacketAccessBit : 0)))
- | (functor_traits<NullaryOp>::IsRepeatable ? 0 : EvalBeforeNestingBit),
- CoeffReadCost = functor_traits<NullaryOp>::Cost
+ | (ei_functor_has_linear_access<NullaryOp>::ret ? LinearAccessBit : 0)
+ | (ei_functor_traits<NullaryOp>::PacketAccess ? PacketAccessBit : 0)))
+ | (ei_functor_traits<NullaryOp>::IsRepeatable ? 0 : EvalBeforeNestingBit),
+ CoeffReadCost = ei_functor_traits<NullaryOp>::Cost
};
};
-}
-template<typename NullaryOp, typename PlainObjectType>
-class CwiseNullaryOp : internal::no_assignment_operator,
- public internal::dense_xpr_base< CwiseNullaryOp<NullaryOp, PlainObjectType> >::type
+template<typename NullaryOp, typename MatrixType>
+class CwiseNullaryOp : ei_no_assignment_operator,
+ public MatrixBase<CwiseNullaryOp<NullaryOp, MatrixType> >
{
public:
- typedef typename internal::dense_xpr_base<CwiseNullaryOp>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(CwiseNullaryOp)
+ EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseNullaryOp)
- CwiseNullaryOp(Index rows, Index cols, const NullaryOp& func = NullaryOp())
+ CwiseNullaryOp(int rows, int cols, const NullaryOp& func = NullaryOp())
: m_rows(rows), m_cols(cols), m_functor(func)
{
- eigen_assert(rows >= 0
- && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
- && cols >= 0
- && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
+ ei_assert(rows > 0
+ && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
+ && cols > 0
+ && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
}
- EIGEN_STRONG_INLINE Index rows() const { return m_rows.value(); }
- EIGEN_STRONG_INLINE Index cols() const { return m_cols.value(); }
+ EIGEN_STRONG_INLINE int rows() const { return m_rows.value(); }
+ EIGEN_STRONG_INLINE int cols() const { return m_cols.value(); }
- EIGEN_STRONG_INLINE const Scalar coeff(Index rows, Index cols) const
+ EIGEN_STRONG_INLINE const Scalar coeff(int rows, int cols) const
{
return m_functor(rows, cols);
}
template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
+ EIGEN_STRONG_INLINE PacketScalar packet(int, int) const
{
- return m_functor.packetOp(row, col);
+ return m_functor.packetOp();
}
- EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
+ EIGEN_STRONG_INLINE const Scalar coeff(int index) const
{
- return m_functor(index);
+ if(RowsAtCompileTime == 1)
+ return m_functor(0, index);
+ else
+ return m_functor(index, 0);
}
template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet(Index index) const
+ EIGEN_STRONG_INLINE PacketScalar packet(int) const
{
- return m_functor.packetOp(index);
+ return m_functor.packetOp();
}
protected:
- const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_rows;
- const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_cols;
+ const ei_int_if_dynamic<RowsAtCompileTime> m_rows;
+ const ei_int_if_dynamic<ColsAtCompileTime> m_cols;
const NullaryOp m_functor;
};
@@ -124,7 +121,7 @@ class CwiseNullaryOp : internal::no_assignment_operator,
template<typename Derived>
template<typename CustomNullaryOp>
EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, Derived>
-DenseBase<Derived>::NullaryExpr(Index rows, Index cols, const CustomNullaryOp& func)
+MatrixBase<Derived>::NullaryExpr(int rows, int cols, const CustomNullaryOp& func)
{
return CwiseNullaryOp<CustomNullaryOp, Derived>(rows, cols, func);
}
@@ -147,16 +144,17 @@ DenseBase<Derived>::NullaryExpr(Index rows, Index cols, const CustomNullaryOp& f
template<typename Derived>
template<typename CustomNullaryOp>
EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, Derived>
-DenseBase<Derived>::NullaryExpr(Index size, const CustomNullaryOp& func)
+MatrixBase<Derived>::NullaryExpr(int size, const CustomNullaryOp& func)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ ei_assert(IsVectorAtCompileTime);
if(RowsAtCompileTime == 1) return CwiseNullaryOp<CustomNullaryOp, Derived>(1, size, func);
else return CwiseNullaryOp<CustomNullaryOp, Derived>(size, 1, func);
}
/** \returns an expression of a matrix defined by a custom functor \a func
*
- * This variant is only for fixed-size DenseBase types. For dynamic-size types, you
+ * This variant is only for fixed-size MatrixBase types. For dynamic-size types, you
* need to use the variants taking size arguments.
*
* The template parameter \a CustomNullaryOp is the type of the functor.
@@ -166,7 +164,7 @@ DenseBase<Derived>::NullaryExpr(Index size, const CustomNullaryOp& func)
template<typename Derived>
template<typename CustomNullaryOp>
EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, Derived>
-DenseBase<Derived>::NullaryExpr(const CustomNullaryOp& func)
+MatrixBase<Derived>::NullaryExpr(const CustomNullaryOp& func)
{
return CwiseNullaryOp<CustomNullaryOp, Derived>(RowsAtCompileTime, ColsAtCompileTime, func);
}
@@ -174,7 +172,7 @@ DenseBase<Derived>::NullaryExpr(const CustomNullaryOp& func)
/** \returns an expression of a constant matrix of value \a value
*
* The parameters \a rows and \a cols are the number of rows and of columns of
- * the returned matrix. Must be compatible with this DenseBase type.
+ * the returned matrix. Must be compatible with this MatrixBase type.
*
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types,
* it is redundant to pass \a rows and \a cols as arguments, so Zero() should be used
@@ -185,16 +183,16 @@ DenseBase<Derived>::NullaryExpr(const CustomNullaryOp& func)
* \sa class CwiseNullaryOp
*/
template<typename Derived>
-EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
-DenseBase<Derived>::Constant(Index rows, Index cols, const Scalar& value)
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
+MatrixBase<Derived>::Constant(int rows, int cols, const Scalar& value)
{
- return DenseBase<Derived>::NullaryExpr(rows, cols, internal::scalar_constant_op<Scalar>(value));
+ return NullaryExpr(rows, cols, ei_scalar_constant_op<Scalar>(value));
}
/** \returns an expression of a constant matrix of value \a value
*
* The parameter \a size is the size of the returned vector.
- * Must be compatible with this DenseBase type.
+ * Must be compatible with this MatrixBase type.
*
* \only_for_vectors
*
@@ -207,15 +205,15 @@ DenseBase<Derived>::Constant(Index rows, Index cols, const Scalar& value)
* \sa class CwiseNullaryOp
*/
template<typename Derived>
-EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
-DenseBase<Derived>::Constant(Index size, const Scalar& value)
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
+MatrixBase<Derived>::Constant(int size, const Scalar& value)
{
- return DenseBase<Derived>::NullaryExpr(size, internal::scalar_constant_op<Scalar>(value));
+ return NullaryExpr(size, ei_scalar_constant_op<Scalar>(value));
}
/** \returns an expression of a constant matrix of value \a value
*
- * This variant is only for fixed-size DenseBase types. For dynamic-size types, you
+ * This variant is only for fixed-size MatrixBase types. For dynamic-size types, you
* need to use the variants taking size arguments.
*
* The template parameter \a CustomNullaryOp is the type of the functor.
@@ -223,90 +221,21 @@ DenseBase<Derived>::Constant(Index size, const Scalar& value)
* \sa class CwiseNullaryOp
*/
template<typename Derived>
-EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
-DenseBase<Derived>::Constant(const Scalar& value)
-{
- EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
- return DenseBase<Derived>::NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, internal::scalar_constant_op<Scalar>(value));
-}
-
-/**
- * \brief Sets a linearly space vector.
- *
- * The function generates 'size' equally spaced values in the closed interval [low,high].
- * This particular version of LinSpaced() uses sequential access, i.e. vector access is
- * assumed to be a(0), a(1), ..., a(size). This assumption allows for better vectorization
- * and yields faster code than the random access version.
- *
- * \only_for_vectors
- *
- * Example: \include DenseBase_LinSpaced_seq.cpp
- * Output: \verbinclude DenseBase_LinSpaced_seq.out
- *
- * \sa setLinSpaced(Index,const Scalar&,const Scalar&), LinSpaced(Index,Scalar,Scalar), CwiseNullaryOp
- */
-template<typename Derived>
-EIGEN_STRONG_INLINE const typename DenseBase<Derived>::SequentialLinSpacedReturnType
-DenseBase<Derived>::LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar,false>(low,high,size));
-}
-
-/**
- * \copydoc DenseBase::LinSpaced(Sequential_t, Index, const Scalar&, const Scalar&)
- * Special version for fixed size types which does not require the size parameter.
- */
-template<typename Derived>
-EIGEN_STRONG_INLINE const typename DenseBase<Derived>::SequentialLinSpacedReturnType
-DenseBase<Derived>::LinSpaced(Sequential_t, const Scalar& low, const Scalar& high)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
- return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar,false>(low,high,Derived::SizeAtCompileTime));
-}
-
-/**
- * \brief Sets a linearly space vector.
- *
- * The function generates 'size' equally spaced values in the closed interval [low,high].
- *
- * \only_for_vectors
- *
- * Example: \include DenseBase_LinSpaced.cpp
- * Output: \verbinclude DenseBase_LinSpaced.out
- *
- * \sa setLinSpaced(Index,const Scalar&,const Scalar&), LinSpaced(Sequential_t,Index,const Scalar&,const Scalar&,Index), CwiseNullaryOp
- */
-template<typename Derived>
-EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
-DenseBase<Derived>::LinSpaced(Index size, const Scalar& low, const Scalar& high)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar,true>(low,high,size));
-}
-
-/**
- * \copydoc DenseBase::LinSpaced(Index, const Scalar&, const Scalar&)
- * Special version for fixed size types which does not require the size parameter.
- */
-template<typename Derived>
-EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
-DenseBase<Derived>::LinSpaced(const Scalar& low, const Scalar& high)
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
+MatrixBase<Derived>::Constant(const Scalar& value)
{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
- return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar,true>(low,high,Derived::SizeAtCompileTime));
+ return NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, ei_scalar_constant_op<Scalar>(value));
}
/** \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */
template<typename Derived>
-bool DenseBase<Derived>::isApproxToConstant
+bool MatrixBase<Derived>::isApproxToConstant
(const Scalar& value, RealScalar prec) const
{
- for(Index j = 0; j < cols(); ++j)
- for(Index i = 0; i < rows(); ++i)
- if(!internal::isApprox(this->coeff(i, j), value, prec))
+ for(int j = 0; j < cols(); ++j)
+ for(int i = 0; i < rows(); ++i)
+ if(!ei_isApprox(coeff(i, j), value, prec))
return false;
return true;
}
@@ -315,7 +244,7 @@ bool DenseBase<Derived>::isApproxToConstant
*
* \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */
template<typename Derived>
-bool DenseBase<Derived>::isConstant
+bool MatrixBase<Derived>::isConstant
(const Scalar& value, RealScalar prec) const
{
return isApproxToConstant(value, prec);
@@ -326,17 +255,17 @@ bool DenseBase<Derived>::isConstant
* \sa setConstant(), Constant(), class CwiseNullaryOp
*/
template<typename Derived>
-EIGEN_STRONG_INLINE void DenseBase<Derived>::fill(const Scalar& value)
+EIGEN_STRONG_INLINE void MatrixBase<Derived>::fill(const Scalar& value)
{
setConstant(value);
}
/** Sets all coefficients in this expression to \a value.
*
- * \sa fill(), setConstant(Index,const Scalar&), setConstant(Index,Index,const Scalar&), setZero(), setOnes(), Constant(), class CwiseNullaryOp, setZero(), setOnes()
+ * \sa fill(), setConstant(int,const Scalar&), setConstant(int,int,const Scalar&), setZero(), setOnes(), Constant(), class CwiseNullaryOp, setZero(), setOnes()
*/
template<typename Derived>
-EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setConstant(const Scalar& value)
+EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setConstant(const Scalar& value)
{
return derived() = Constant(rows(), cols(), value);
}
@@ -345,14 +274,14 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setConstant(const Scalar& value
*
* \only_for_vectors
*
- * Example: \include Matrix_setConstant_int.cpp
+ * Example: \include Matrix_set_int.cpp
* Output: \verbinclude Matrix_setConstant_int.out
*
- * \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&)
+ * \sa MatrixBase::setConstant(const Scalar&), setConstant(int,int,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&)
*/
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setConstant(Index size, const Scalar& value)
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
+Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setConstant(int size, const Scalar& value)
{
resize(size);
return setConstant(value);
@@ -362,39 +291,20 @@ PlainObjectBase<Derived>::setConstant(Index size, const Scalar& value)
*
* \param rows the new number of rows
* \param cols the new number of columns
- * \param value the value to which all coefficients are set
*
* Example: \include Matrix_setConstant_int_int.cpp
* Output: \verbinclude Matrix_setConstant_int_int.out
*
- * \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&)
+ * \sa MatrixBase::setConstant(const Scalar&), setConstant(int,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&)
*/
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setConstant(Index rows, Index cols, const Scalar& value)
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
+Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setConstant(int rows, int cols, const Scalar& value)
{
resize(rows, cols);
return setConstant(value);
}
-/**
- * \brief Sets a linearly space vector.
- *
- * The function generates 'size' equally spaced values in the closed interval [low,high].
- *
- * \only_for_vectors
- *
- * Example: \include DenseBase_setLinSpaced.cpp
- * Output: \verbinclude DenseBase_setLinSpaced.out
- *
- * \sa CwiseNullaryOp
- */
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index size, const Scalar& low, const Scalar& high)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return derived() = Derived::NullaryExpr(size, internal::linspaced_op<Scalar,false>(low,high,size));
-}
// zero:
@@ -407,14 +317,16 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index size, const
* it is redundant to pass \a rows and \a cols as arguments, so Zero() should be used
* instead.
*
+ * \addexample Zero \label How to take get a zero matrix
+ *
* Example: \include MatrixBase_zero_int_int.cpp
* Output: \verbinclude MatrixBase_zero_int_int.out
*
- * \sa Zero(), Zero(Index)
+ * \sa Zero(), Zero(int)
*/
template<typename Derived>
-EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
-DenseBase<Derived>::Zero(Index rows, Index cols)
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
+MatrixBase<Derived>::Zero(int rows, int cols)
{
return Constant(rows, cols, Scalar(0));
}
@@ -433,11 +345,11 @@ DenseBase<Derived>::Zero(Index rows, Index cols)
* Example: \include MatrixBase_zero_int.cpp
* Output: \verbinclude MatrixBase_zero_int.out
*
- * \sa Zero(), Zero(Index,Index)
+ * \sa Zero(), Zero(int,int)
*/
template<typename Derived>
-EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
-DenseBase<Derived>::Zero(Index size)
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
+MatrixBase<Derived>::Zero(int size)
{
return Constant(size, Scalar(0));
}
@@ -450,11 +362,11 @@ DenseBase<Derived>::Zero(Index size)
* Example: \include MatrixBase_zero.cpp
* Output: \verbinclude MatrixBase_zero.out
*
- * \sa Zero(Index), Zero(Index,Index)
+ * \sa Zero(int), Zero(int,int)
*/
template<typename Derived>
-EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
-DenseBase<Derived>::Zero()
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
+MatrixBase<Derived>::Zero()
{
return Constant(Scalar(0));
}
@@ -468,11 +380,11 @@ DenseBase<Derived>::Zero()
* \sa class CwiseNullaryOp, Zero()
*/
template<typename Derived>
-bool DenseBase<Derived>::isZero(RealScalar prec) const
+bool MatrixBase<Derived>::isZero(RealScalar prec) const
{
- for(Index j = 0; j < cols(); ++j)
- for(Index i = 0; i < rows(); ++i)
- if(!internal::isMuchSmallerThan(this->coeff(i, j), static_cast<Scalar>(1), prec))
+ for(int j = 0; j < cols(); ++j)
+ for(int i = 0; i < rows(); ++i)
+ if(!ei_isMuchSmallerThan(coeff(i, j), static_cast<Scalar>(1), prec))
return false;
return true;
}
@@ -485,7 +397,7 @@ bool DenseBase<Derived>::isZero(RealScalar prec) const
* \sa class CwiseNullaryOp, Zero()
*/
template<typename Derived>
-EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setZero()
+EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setZero()
{
return setConstant(Scalar(0));
}
@@ -497,11 +409,11 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setZero()
* Example: \include Matrix_setZero_int.cpp
* Output: \verbinclude Matrix_setZero_int.out
*
- * \sa DenseBase::setZero(), setZero(Index,Index), class CwiseNullaryOp, DenseBase::Zero()
+ * \sa MatrixBase::setZero(), setZero(int,int), class CwiseNullaryOp, MatrixBase::Zero()
*/
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setZero(Index size)
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
+Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setZero(int size)
{
resize(size);
return setConstant(Scalar(0));
@@ -515,11 +427,11 @@ PlainObjectBase<Derived>::setZero(Index size)
* Example: \include Matrix_setZero_int_int.cpp
* Output: \verbinclude Matrix_setZero_int_int.out
*
- * \sa DenseBase::setZero(), setZero(Index), class CwiseNullaryOp, DenseBase::Zero()
+ * \sa MatrixBase::setZero(), setZero(int), class CwiseNullaryOp, MatrixBase::Zero()
*/
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setZero(Index rows, Index cols)
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
+Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setZero(int rows, int cols)
{
resize(rows, cols);
return setConstant(Scalar(0));
@@ -536,14 +448,16 @@ PlainObjectBase<Derived>::setZero(Index rows, Index cols)
* it is redundant to pass \a rows and \a cols as arguments, so Ones() should be used
* instead.
*
+ * \addexample One \label How to get a matrix with all coefficients equal one
+ *
* Example: \include MatrixBase_ones_int_int.cpp
* Output: \verbinclude MatrixBase_ones_int_int.out
*
- * \sa Ones(), Ones(Index), isOnes(), class Ones
+ * \sa Ones(), Ones(int), isOnes(), class Ones
*/
template<typename Derived>
-EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
-DenseBase<Derived>::Ones(Index rows, Index cols)
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
+MatrixBase<Derived>::Ones(int rows, int cols)
{
return Constant(rows, cols, Scalar(1));
}
@@ -562,11 +476,11 @@ DenseBase<Derived>::Ones(Index rows, Index cols)
* Example: \include MatrixBase_ones_int.cpp
* Output: \verbinclude MatrixBase_ones_int.out
*
- * \sa Ones(), Ones(Index,Index), isOnes(), class Ones
+ * \sa Ones(), Ones(int,int), isOnes(), class Ones
*/
template<typename Derived>
-EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
-DenseBase<Derived>::Ones(Index size)
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
+MatrixBase<Derived>::Ones(int size)
{
return Constant(size, Scalar(1));
}
@@ -579,11 +493,11 @@ DenseBase<Derived>::Ones(Index size)
* Example: \include MatrixBase_ones.cpp
* Output: \verbinclude MatrixBase_ones.out
*
- * \sa Ones(Index), Ones(Index,Index), isOnes(), class Ones
+ * \sa Ones(int), Ones(int,int), isOnes(), class Ones
*/
template<typename Derived>
-EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
-DenseBase<Derived>::Ones()
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ConstantReturnType
+MatrixBase<Derived>::Ones()
{
return Constant(Scalar(1));
}
@@ -597,7 +511,7 @@ DenseBase<Derived>::Ones()
* \sa class CwiseNullaryOp, Ones()
*/
template<typename Derived>
-bool DenseBase<Derived>::isOnes
+bool MatrixBase<Derived>::isOnes
(RealScalar prec) const
{
return isApproxToConstant(Scalar(1), prec);
@@ -611,7 +525,7 @@ bool DenseBase<Derived>::isOnes
* \sa class CwiseNullaryOp, Ones()
*/
template<typename Derived>
-EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setOnes()
+EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setOnes()
{
return setConstant(Scalar(1));
}
@@ -623,11 +537,11 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setOnes()
* Example: \include Matrix_setOnes_int.cpp
* Output: \verbinclude Matrix_setOnes_int.out
*
- * \sa MatrixBase::setOnes(), setOnes(Index,Index), class CwiseNullaryOp, MatrixBase::Ones()
+ * \sa MatrixBase::setOnes(), setOnes(int,int), class CwiseNullaryOp, MatrixBase::Ones()
*/
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setOnes(Index size)
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
+Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setOnes(int size)
{
resize(size);
return setConstant(Scalar(1));
@@ -641,11 +555,11 @@ PlainObjectBase<Derived>::setOnes(Index size)
* Example: \include Matrix_setOnes_int_int.cpp
* Output: \verbinclude Matrix_setOnes_int_int.out
*
- * \sa MatrixBase::setOnes(), setOnes(Index), class CwiseNullaryOp, MatrixBase::Ones()
+ * \sa MatrixBase::setOnes(), setOnes(int), class CwiseNullaryOp, MatrixBase::Ones()
*/
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived&
-PlainObjectBase<Derived>::setOnes(Index rows, Index cols)
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
+Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setOnes(int rows, int cols)
{
resize(rows, cols);
return setConstant(Scalar(1));
@@ -662,6 +576,8 @@ PlainObjectBase<Derived>::setOnes(Index rows, Index cols)
* it is redundant to pass \a rows and \a cols as arguments, so Identity() should be used
* instead.
*
+ * \addexample Identity \label How to get an identity matrix
+ *
* Example: \include MatrixBase_identity_int_int.cpp
* Output: \verbinclude MatrixBase_identity_int_int.out
*
@@ -669,9 +585,9 @@ PlainObjectBase<Derived>::setOnes(Index rows, Index cols)
*/
template<typename Derived>
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::IdentityReturnType
-MatrixBase<Derived>::Identity(Index rows, Index cols)
+MatrixBase<Derived>::Identity(int rows, int cols)
{
- return DenseBase<Derived>::NullaryExpr(rows, cols, internal::scalar_identity_op<Scalar>());
+ return NullaryExpr(rows, cols, ei_scalar_identity_op<Scalar>());
}
/** \returns an expression of the identity matrix (not necessarily square).
@@ -682,14 +598,14 @@ MatrixBase<Derived>::Identity(Index rows, Index cols)
* Example: \include MatrixBase_identity.cpp
* Output: \verbinclude MatrixBase_identity.out
*
- * \sa Identity(Index,Index), setIdentity(), isIdentity()
+ * \sa Identity(int,int), setIdentity(), isIdentity()
*/
template<typename Derived>
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::IdentityReturnType
MatrixBase<Derived>::Identity()
{
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
- return MatrixBase<Derived>::NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, internal::scalar_identity_op<Scalar>());
+ return NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, ei_scalar_identity_op<Scalar>());
}
/** \returns true if *this is approximately equal to the identity matrix
@@ -699,24 +615,24 @@ MatrixBase<Derived>::Identity()
* Example: \include MatrixBase_isIdentity.cpp
* Output: \verbinclude MatrixBase_isIdentity.out
*
- * \sa class CwiseNullaryOp, Identity(), Identity(Index,Index), setIdentity()
+ * \sa class CwiseNullaryOp, Identity(), Identity(int,int), setIdentity()
*/
template<typename Derived>
bool MatrixBase<Derived>::isIdentity
(RealScalar prec) const
{
- for(Index j = 0; j < cols(); ++j)
+ for(int j = 0; j < cols(); ++j)
{
- for(Index i = 0; i < rows(); ++i)
+ for(int i = 0; i < rows(); ++i)
{
if(i == j)
{
- if(!internal::isApprox(this->coeff(i, j), static_cast<Scalar>(1), prec))
+ if(!ei_isApprox(coeff(i, j), static_cast<Scalar>(1), prec))
return false;
}
else
{
- if(!internal::isMuchSmallerThan(this->coeff(i, j), static_cast<RealScalar>(1), prec))
+ if(!ei_isMuchSmallerThan(coeff(i, j), static_cast<RealScalar>(1), prec))
return false;
}
}
@@ -724,10 +640,8 @@ bool MatrixBase<Derived>::isIdentity
return true;
}
-namespace internal {
-
template<typename Derived, bool Big = (Derived::SizeAtCompileTime>=16)>
-struct setIdentity_impl
+struct ei_setIdentity_impl
{
static EIGEN_STRONG_INLINE Derived& run(Derived& m)
{
@@ -736,34 +650,31 @@ struct setIdentity_impl
};
template<typename Derived>
-struct setIdentity_impl<Derived, true>
+struct ei_setIdentity_impl<Derived, true>
{
- typedef typename Derived::Index Index;
static EIGEN_STRONG_INLINE Derived& run(Derived& m)
{
m.setZero();
- const Index size = (std::min)(m.rows(), m.cols());
- for(Index i = 0; i < size; ++i) m.coeffRef(i,i) = typename Derived::Scalar(1);
+ const int size = std::min(m.rows(), m.cols());
+ for(int i = 0; i < size; ++i) m.coeffRef(i,i) = typename Derived::Scalar(1);
return m;
}
};
-} // end namespace internal
-
/** Writes the identity expression (not necessarily square) into *this.
*
* Example: \include MatrixBase_setIdentity.cpp
* Output: \verbinclude MatrixBase_setIdentity.out
*
- * \sa class CwiseNullaryOp, Identity(), Identity(Index,Index), isIdentity()
+ * \sa class CwiseNullaryOp, Identity(), Identity(int,int), isIdentity()
*/
template<typename Derived>
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity()
{
- return internal::setIdentity_impl<Derived>::run(derived());
+ return ei_setIdentity_impl<Derived>::run(derived());
}
-/** \brief Resizes to the given size, and writes the identity expression (not necessarily square) into *this.
+/** Resizes to the given size, and writes the identity expression (not necessarily square) into *this.
*
* \param rows the new number of rows
* \param cols the new number of columns
@@ -773,10 +684,11 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity()
*
* \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Identity()
*/
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity(Index rows, Index cols)
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+EIGEN_STRONG_INLINE Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&
+Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::setIdentity(int rows, int cols)
{
- derived().resize(rows, cols);
+ resize(rows, cols);
return setIdentity();
}
@@ -784,10 +696,10 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity(Index rows, Index
*
* \only_for_vectors
*
- * \sa MatrixBase::Unit(Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
+ * \sa MatrixBase::Unit(int), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
*/
template<typename Derived>
-EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(Index size, Index i)
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(int size, int i)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return BasisReturnType(SquareMatrixType::Identity(size,size), i);
@@ -799,10 +711,10 @@ EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBa
*
* This variant is for fixed-size vector only.
*
- * \sa MatrixBase::Unit(Index,Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
+ * \sa MatrixBase::Unit(int,int), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
*/
template<typename Derived>
-EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(Index i)
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(int i)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
return BasisReturnType(SquareMatrixType::Identity(),i);
@@ -812,7 +724,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBa
*
* \only_for_vectors
*
- * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
+ * \sa MatrixBase::Unit(int,int), MatrixBase::Unit(int), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
*/
template<typename Derived>
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitX()
@@ -822,7 +734,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBa
*
* \only_for_vectors
*
- * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
+ * \sa MatrixBase::Unit(int,int), MatrixBase::Unit(int), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
*/
template<typename Derived>
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitY()
@@ -832,7 +744,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBa
*
* \only_for_vectors
*
- * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
+ * \sa MatrixBase::Unit(int,int), MatrixBase::Unit(int), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
*/
template<typename Derived>
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitZ()
@@ -842,7 +754,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBa
*
* \only_for_vectors
*
- * \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
+ * \sa MatrixBase::Unit(int,int), MatrixBase::Unit(int), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW()
*/
template<typename Derived>
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitW()
diff --git a/extern/Eigen2/Eigen/src/Core/CwiseUnaryOp.h b/extern/Eigen2/Eigen/src/Core/CwiseUnaryOp.h
new file mode 100644
index 00000000000..076d568e023
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/CwiseUnaryOp.h
@@ -0,0 +1,229 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_CWISE_UNARY_OP_H
+#define EIGEN_CWISE_UNARY_OP_H
+
+/** \class CwiseUnaryOp
+ *
+ * \brief Generic expression of a coefficient-wise unary operator of a matrix or a vector
+ *
+ * \param UnaryOp template functor implementing the operator
+ * \param MatrixType the type of the matrix we are applying the unary operator
+ *
+ * This class represents an expression of a generic unary operator of a matrix or a vector.
+ * It is the return type of the unary operator-, of a matrix or a vector, and most
+ * of the time this is the only way it is used.
+ *
+ * \sa MatrixBase::unaryExpr(const CustomUnaryOp &) const, class CwiseBinaryOp, class CwiseNullaryOp
+ */
+template<typename UnaryOp, typename MatrixType>
+struct ei_traits<CwiseUnaryOp<UnaryOp, MatrixType> >
+ : ei_traits<MatrixType>
+{
+ typedef typename ei_result_of<
+ UnaryOp(typename MatrixType::Scalar)
+ >::type Scalar;
+ typedef typename MatrixType::Nested MatrixTypeNested;
+ typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
+ enum {
+ Flags = (_MatrixTypeNested::Flags & (
+ HereditaryBits | LinearAccessBit | AlignedBit
+ | (ei_functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0))),
+ CoeffReadCost = _MatrixTypeNested::CoeffReadCost + ei_functor_traits<UnaryOp>::Cost
+ };
+};
+
+template<typename UnaryOp, typename MatrixType>
+class CwiseUnaryOp : ei_no_assignment_operator,
+ public MatrixBase<CwiseUnaryOp<UnaryOp, MatrixType> >
+{
+ public:
+
+ EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseUnaryOp)
+
+ inline CwiseUnaryOp(const MatrixType& mat, const UnaryOp& func = UnaryOp())
+ : m_matrix(mat), m_functor(func) {}
+
+ EIGEN_STRONG_INLINE int rows() const { return m_matrix.rows(); }
+ EIGEN_STRONG_INLINE int cols() const { return m_matrix.cols(); }
+
+ EIGEN_STRONG_INLINE const Scalar coeff(int row, int col) const
+ {
+ return m_functor(m_matrix.coeff(row, col));
+ }
+
+ template<int LoadMode>
+ EIGEN_STRONG_INLINE PacketScalar packet(int row, int col) const
+ {
+ return m_functor.packetOp(m_matrix.template packet<LoadMode>(row, col));
+ }
+
+ EIGEN_STRONG_INLINE const Scalar coeff(int index) const
+ {
+ return m_functor(m_matrix.coeff(index));
+ }
+
+ template<int LoadMode>
+ EIGEN_STRONG_INLINE PacketScalar packet(int index) const
+ {
+ return m_functor.packetOp(m_matrix.template packet<LoadMode>(index));
+ }
+
+ protected:
+ const typename MatrixType::Nested m_matrix;
+ const UnaryOp m_functor;
+};
+
+/** \returns an expression of a custom coefficient-wise unary operator \a func of *this
+ *
+ * The template parameter \a CustomUnaryOp is the type of the functor
+ * of the custom unary operator.
+ *
+ * \addexample CustomCwiseUnaryFunctors \label How to use custom coeff wise unary functors
+ *
+ * Example:
+ * \include class_CwiseUnaryOp.cpp
+ * Output: \verbinclude class_CwiseUnaryOp.out
+ *
+ * \sa class CwiseUnaryOp, class CwiseBinarOp, MatrixBase::operator-, Cwise::abs
+ */
+template<typename Derived>
+template<typename CustomUnaryOp>
+EIGEN_STRONG_INLINE const CwiseUnaryOp<CustomUnaryOp, Derived>
+MatrixBase<Derived>::unaryExpr(const CustomUnaryOp& func) const
+{
+ return CwiseUnaryOp<CustomUnaryOp, Derived>(derived(), func);
+}
+
+/** \returns an expression of the opposite of \c *this
+ */
+template<typename Derived>
+EIGEN_STRONG_INLINE const CwiseUnaryOp<ei_scalar_opposite_op<typename ei_traits<Derived>::Scalar>,Derived>
+MatrixBase<Derived>::operator-() const
+{
+ return derived();
+}
+
+/** \returns an expression of the coefficient-wise absolute value of \c *this
+ *
+ * Example: \include Cwise_abs.cpp
+ * Output: \verbinclude Cwise_abs.out
+ *
+ * \sa abs2()
+ */
+template<typename ExpressionType>
+EIGEN_STRONG_INLINE const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs_op)
+Cwise<ExpressionType>::abs() const
+{
+ return _expression();
+}
+
+/** \returns an expression of the coefficient-wise squared absolute value of \c *this
+ *
+ * Example: \include Cwise_abs2.cpp
+ * Output: \verbinclude Cwise_abs2.out
+ *
+ * \sa abs(), square()
+ */
+template<typename ExpressionType>
+EIGEN_STRONG_INLINE const EIGEN_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs2_op)
+Cwise<ExpressionType>::abs2() const
+{
+ return _expression();
+}
+
+/** \returns an expression of the complex conjugate of \c *this.
+ *
+ * \sa adjoint() */
+template<typename Derived>
+EIGEN_STRONG_INLINE typename MatrixBase<Derived>::ConjugateReturnType
+MatrixBase<Derived>::conjugate() const
+{
+ return ConjugateReturnType(derived());
+}
+
+/** \returns an expression of the real part of \c *this.
+ *
+ * \sa imag() */
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::RealReturnType
+MatrixBase<Derived>::real() const { return derived(); }
+
+/** \returns an expression of the imaginary part of \c *this.
+ *
+ * \sa real() */
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ImagReturnType
+MatrixBase<Derived>::imag() const { return derived(); }
+
+/** \returns an expression of *this with the \a Scalar type casted to
+ * \a NewScalar.
+ *
+ * The template parameter \a NewScalar is the type we are casting the scalars to.
+ *
+ * \sa class CwiseUnaryOp
+ */
+template<typename Derived>
+template<typename NewType>
+EIGEN_STRONG_INLINE const CwiseUnaryOp<ei_scalar_cast_op<typename ei_traits<Derived>::Scalar, NewType>, Derived>
+MatrixBase<Derived>::cast() const
+{
+ return derived();
+}
+
+/** \relates MatrixBase */
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::ScalarMultipleReturnType
+MatrixBase<Derived>::operator*(const Scalar& scalar) const
+{
+ return CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, Derived>
+ (derived(), ei_scalar_multiple_op<Scalar>(scalar));
+}
+
+/** \relates MatrixBase */
+template<typename Derived>
+EIGEN_STRONG_INLINE const CwiseUnaryOp<ei_scalar_quotient1_op<typename ei_traits<Derived>::Scalar>, Derived>
+MatrixBase<Derived>::operator/(const Scalar& scalar) const
+{
+ return CwiseUnaryOp<ei_scalar_quotient1_op<Scalar>, Derived>
+ (derived(), ei_scalar_quotient1_op<Scalar>(scalar));
+}
+
+template<typename Derived>
+EIGEN_STRONG_INLINE Derived&
+MatrixBase<Derived>::operator*=(const Scalar& other)
+{
+ return *this = *this * other;
+}
+
+template<typename Derived>
+EIGEN_STRONG_INLINE Derived&
+MatrixBase<Derived>::operator/=(const Scalar& other)
+{
+ return *this = *this / other;
+}
+
+#endif // EIGEN_CWISE_UNARY_OP_H
diff --git a/extern/Eigen2/Eigen/src/Core/DiagonalCoeffs.h b/extern/Eigen2/Eigen/src/Core/DiagonalCoeffs.h
new file mode 100644
index 00000000000..767fe5fb7c0
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/DiagonalCoeffs.h
@@ -0,0 +1,124 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_DIAGONALCOEFFS_H
+#define EIGEN_DIAGONALCOEFFS_H
+
+/** \class DiagonalCoeffs
+ *
+ * \brief Expression of the main diagonal of a matrix
+ *
+ * \param MatrixType the type of the object in which we are taking the main diagonal
+ *
+ * The matrix is not required to be square.
+ *
+ * This class represents an expression of the main diagonal of a square matrix.
+ * It is the return type of MatrixBase::diagonal() and most of the time this is
+ * the only way it is used.
+ *
+ * \sa MatrixBase::diagonal()
+ */
+template<typename MatrixType>
+struct ei_traits<DiagonalCoeffs<MatrixType> >
+{
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
+ typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
+ enum {
+ RowsAtCompileTime = int(MatrixType::SizeAtCompileTime) == Dynamic ? Dynamic
+ : EIGEN_ENUM_MIN(MatrixType::RowsAtCompileTime,
+ MatrixType::ColsAtCompileTime),
+ ColsAtCompileTime = 1,
+ MaxRowsAtCompileTime = int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic
+ : EIGEN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime,
+ MatrixType::MaxColsAtCompileTime),
+ MaxColsAtCompileTime = 1,
+ Flags = (unsigned int)_MatrixTypeNested::Flags & (HereditaryBits | LinearAccessBit),
+ CoeffReadCost = _MatrixTypeNested::CoeffReadCost
+ };
+};
+
+template<typename MatrixType> class DiagonalCoeffs
+ : public MatrixBase<DiagonalCoeffs<MatrixType> >
+{
+ public:
+
+ EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalCoeffs)
+
+ inline DiagonalCoeffs(const MatrixType& matrix) : m_matrix(matrix) {}
+
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(DiagonalCoeffs)
+
+ inline int rows() const { return std::min(m_matrix.rows(), m_matrix.cols()); }
+ inline int cols() const { return 1; }
+
+ inline Scalar& coeffRef(int row, int)
+ {
+ return m_matrix.const_cast_derived().coeffRef(row, row);
+ }
+
+ inline const Scalar coeff(int row, int) const
+ {
+ return m_matrix.coeff(row, row);
+ }
+
+ inline Scalar& coeffRef(int index)
+ {
+ return m_matrix.const_cast_derived().coeffRef(index, index);
+ }
+
+ inline const Scalar coeff(int index) const
+ {
+ return m_matrix.coeff(index, index);
+ }
+
+ protected:
+
+ const typename MatrixType::Nested m_matrix;
+};
+
+/** \returns an expression of the main diagonal of the matrix \c *this
+ *
+ * \c *this is not required to be square.
+ *
+ * Example: \include MatrixBase_diagonal.cpp
+ * Output: \verbinclude MatrixBase_diagonal.out
+ *
+ * \sa class DiagonalCoeffs */
+template<typename Derived>
+inline DiagonalCoeffs<Derived>
+MatrixBase<Derived>::diagonal()
+{
+ return DiagonalCoeffs<Derived>(derived());
+}
+
+/** This is the const version of diagonal(). */
+template<typename Derived>
+inline const DiagonalCoeffs<Derived>
+MatrixBase<Derived>::diagonal() const
+{
+ return DiagonalCoeffs<Derived>(derived());
+}
+
+#endif // EIGEN_DIAGONALCOEFFS_H
diff --git a/extern/Eigen2/Eigen/src/Core/DiagonalMatrix.h b/extern/Eigen2/Eigen/src/Core/DiagonalMatrix.h
new file mode 100644
index 00000000000..01f01fdf259
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/DiagonalMatrix.h
@@ -0,0 +1,144 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_DIAGONALMATRIX_H
+#define EIGEN_DIAGONALMATRIX_H
+
+/** \class DiagonalMatrix
+ * \nonstableyet
+ *
+ * \brief Expression of a diagonal matrix
+ *
+ * \param CoeffsVectorType the type of the vector of diagonal coefficients
+ *
+ * This class is an expression of a diagonal matrix with given vector of diagonal
+ * coefficients. It is the return
+ * type of MatrixBase::diagonal(const OtherDerived&) and most of the time this is
+ * the only way it is used.
+ *
+ * \sa MatrixBase::diagonal(const OtherDerived&)
+ */
+template<typename CoeffsVectorType>
+struct ei_traits<DiagonalMatrix<CoeffsVectorType> >
+{
+ typedef typename CoeffsVectorType::Scalar Scalar;
+ typedef typename ei_nested<CoeffsVectorType>::type CoeffsVectorTypeNested;
+ typedef typename ei_unref<CoeffsVectorTypeNested>::type _CoeffsVectorTypeNested;
+ enum {
+ RowsAtCompileTime = CoeffsVectorType::SizeAtCompileTime,
+ ColsAtCompileTime = CoeffsVectorType::SizeAtCompileTime,
+ MaxRowsAtCompileTime = CoeffsVectorType::MaxSizeAtCompileTime,
+ MaxColsAtCompileTime = CoeffsVectorType::MaxSizeAtCompileTime,
+ Flags = (_CoeffsVectorTypeNested::Flags & HereditaryBits) | Diagonal,
+ CoeffReadCost = _CoeffsVectorTypeNested::CoeffReadCost
+ };
+};
+
+template<typename CoeffsVectorType>
+class DiagonalMatrix : ei_no_assignment_operator,
+ public MatrixBase<DiagonalMatrix<CoeffsVectorType> >
+{
+ public:
+
+ EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrix)
+ typedef CoeffsVectorType _CoeffsVectorType;
+
+ // needed to evaluate a DiagonalMatrix<Xpr> to a DiagonalMatrix<NestByValue<Vector> >
+ template<typename OtherCoeffsVectorType>
+ inline DiagonalMatrix(const DiagonalMatrix<OtherCoeffsVectorType>& other) : m_coeffs(other.diagonal())
+ {
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(CoeffsVectorType);
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherCoeffsVectorType);
+ ei_assert(m_coeffs.size() > 0);
+ }
+
+ inline DiagonalMatrix(const CoeffsVectorType& coeffs) : m_coeffs(coeffs)
+ {
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(CoeffsVectorType);
+ ei_assert(coeffs.size() > 0);
+ }
+
+ inline int rows() const { return m_coeffs.size(); }
+ inline int cols() const { return m_coeffs.size(); }
+
+ inline const Scalar coeff(int row, int col) const
+ {
+ return row == col ? m_coeffs.coeff(row) : static_cast<Scalar>(0);
+ }
+
+ inline const CoeffsVectorType& diagonal() const { return m_coeffs; }
+
+ protected:
+ const typename CoeffsVectorType::Nested m_coeffs;
+};
+
+/** \nonstableyet
+ * \returns an expression of a diagonal matrix with *this as vector of diagonal coefficients
+ *
+ * \only_for_vectors
+ *
+ * \addexample AsDiagonalExample \label How to build a diagonal matrix from a vector
+ *
+ * Example: \include MatrixBase_asDiagonal.cpp
+ * Output: \verbinclude MatrixBase_asDiagonal.out
+ *
+ * \sa class DiagonalMatrix, isDiagonal()
+ **/
+template<typename Derived>
+inline const DiagonalMatrix<Derived>
+MatrixBase<Derived>::asDiagonal() const
+{
+ return derived();
+}
+
+/** \nonstableyet
+ * \returns true if *this is approximately equal to a diagonal matrix,
+ * within the precision given by \a prec.
+ *
+ * Example: \include MatrixBase_isDiagonal.cpp
+ * Output: \verbinclude MatrixBase_isDiagonal.out
+ *
+ * \sa asDiagonal()
+ */
+template<typename Derived>
+bool MatrixBase<Derived>::isDiagonal
+(RealScalar prec) const
+{
+ if(cols() != rows()) return false;
+ RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1);
+ for(int j = 0; j < cols(); ++j)
+ {
+ RealScalar absOnDiagonal = ei_abs(coeff(j,j));
+ if(absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal;
+ }
+ for(int j = 0; j < cols(); ++j)
+ for(int i = 0; i < j; ++i)
+ {
+ if(!ei_isMuchSmallerThan(coeff(i, j), maxAbsOnDiagonal, prec)) return false;
+ if(!ei_isMuchSmallerThan(coeff(j, i), maxAbsOnDiagonal, prec)) return false;
+ }
+ return true;
+}
+
+#endif // EIGEN_DIAGONALMATRIX_H
diff --git a/extern/Eigen2/Eigen/src/Core/DiagonalProduct.h b/extern/Eigen2/Eigen/src/Core/DiagonalProduct.h
new file mode 100644
index 00000000000..f33a26f98b0
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/DiagonalProduct.h
@@ -0,0 +1,130 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_DIAGONALPRODUCT_H
+#define EIGEN_DIAGONALPRODUCT_H
+
+/** \internal Specialization of ei_nested for DiagonalMatrix.
+ * Unlike ei_nested, if the argument is a DiagonalMatrix and if it must be evaluated,
+ * then it evaluated to a DiagonalMatrix having its own argument evaluated.
+ */
+template<typename T, int N> struct ei_nested_diagonal : ei_nested<T,N> {};
+template<typename T, int N> struct ei_nested_diagonal<DiagonalMatrix<T>,N >
+ : ei_nested<DiagonalMatrix<T>, N, DiagonalMatrix<NestByValue<typename ei_plain_matrix_type<T>::type> > >
+{};
+
+// specialization of ProductReturnType
+template<typename Lhs, typename Rhs>
+struct ProductReturnType<Lhs,Rhs,DiagonalProduct>
+{
+ typedef typename ei_nested_diagonal<Lhs,Rhs::ColsAtCompileTime>::type LhsNested;
+ typedef typename ei_nested_diagonal<Rhs,Lhs::RowsAtCompileTime>::type RhsNested;
+
+ typedef Product<LhsNested, RhsNested, DiagonalProduct> Type;
+};
+
+template<typename LhsNested, typename RhsNested>
+struct ei_traits<Product<LhsNested, RhsNested, DiagonalProduct> >
+{
+ // clean the nested types:
+ typedef typename ei_cleantype<LhsNested>::type _LhsNested;
+ typedef typename ei_cleantype<RhsNested>::type _RhsNested;
+ typedef typename _LhsNested::Scalar Scalar;
+
+ enum {
+ LhsFlags = _LhsNested::Flags,
+ RhsFlags = _RhsNested::Flags,
+ RowsAtCompileTime = _LhsNested::RowsAtCompileTime,
+ ColsAtCompileTime = _RhsNested::ColsAtCompileTime,
+ MaxRowsAtCompileTime = _LhsNested::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = _RhsNested::MaxColsAtCompileTime,
+
+ LhsIsDiagonal = (_LhsNested::Flags&Diagonal)==Diagonal,
+ RhsIsDiagonal = (_RhsNested::Flags&Diagonal)==Diagonal,
+
+ CanVectorizeRhs = (!RhsIsDiagonal) && (RhsFlags & RowMajorBit) && (RhsFlags & PacketAccessBit)
+ && (ColsAtCompileTime % ei_packet_traits<Scalar>::size == 0),
+
+ CanVectorizeLhs = (!LhsIsDiagonal) && (!(LhsFlags & RowMajorBit)) && (LhsFlags & PacketAccessBit)
+ && (RowsAtCompileTime % ei_packet_traits<Scalar>::size == 0),
+
+ RemovedBits = ~((RhsFlags & RowMajorBit) && (!CanVectorizeLhs) ? 0 : RowMajorBit),
+
+ Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
+ | (((CanVectorizeLhs&&RhsIsDiagonal) || (CanVectorizeRhs&&LhsIsDiagonal)) ? PacketAccessBit : 0),
+
+ CoeffReadCost = NumTraits<Scalar>::MulCost + _LhsNested::CoeffReadCost + _RhsNested::CoeffReadCost
+ };
+};
+
+template<typename LhsNested, typename RhsNested> class Product<LhsNested, RhsNested, DiagonalProduct> : ei_no_assignment_operator,
+ public MatrixBase<Product<LhsNested, RhsNested, DiagonalProduct> >
+{
+ typedef typename ei_traits<Product>::_LhsNested _LhsNested;
+ typedef typename ei_traits<Product>::_RhsNested _RhsNested;
+
+ enum {
+ RhsIsDiagonal = (_RhsNested::Flags&Diagonal)==Diagonal
+ };
+
+ public:
+
+ EIGEN_GENERIC_PUBLIC_INTERFACE(Product)
+
+ template<typename Lhs, typename Rhs>
+ inline Product(const Lhs& lhs, const Rhs& rhs)
+ : m_lhs(lhs), m_rhs(rhs)
+ {
+ ei_assert(lhs.cols() == rhs.rows());
+ }
+
+ inline int rows() const { return m_lhs.rows(); }
+ inline int cols() const { return m_rhs.cols(); }
+
+ const Scalar coeff(int row, int col) const
+ {
+ const int unique = RhsIsDiagonal ? col : row;
+ return m_lhs.coeff(row, unique) * m_rhs.coeff(unique, col);
+ }
+
+ template<int LoadMode>
+ const PacketScalar packet(int row, int col) const
+ {
+ if (RhsIsDiagonal)
+ {
+ return ei_pmul(m_lhs.template packet<LoadMode>(row, col), ei_pset1(m_rhs.coeff(col, col)));
+ }
+ else
+ {
+ return ei_pmul(ei_pset1(m_lhs.coeff(row, row)), m_rhs.template packet<LoadMode>(row, col));
+ }
+ }
+
+ protected:
+ const LhsNested m_lhs;
+ const RhsNested m_rhs;
+};
+
+#endif // EIGEN_DIAGONALPRODUCT_H
diff --git a/extern/Eigen2/Eigen/src/Core/Dot.h b/extern/Eigen2/Eigen/src/Core/Dot.h
new file mode 100644
index 00000000000..5838af70d4a
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/Dot.h
@@ -0,0 +1,361 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_DOT_H
+#define EIGEN_DOT_H
+
+/***************************************************************************
+* Part 1 : the logic deciding a strategy for vectorization and unrolling
+***************************************************************************/
+
+template<typename Derived1, typename Derived2>
+struct ei_dot_traits
+{
+public:
+ enum {
+ Vectorization = (int(Derived1::Flags)&int(Derived2::Flags)&ActualPacketAccessBit)
+ && (int(Derived1::Flags)&int(Derived2::Flags)&LinearAccessBit)
+ ? LinearVectorization
+ : NoVectorization
+ };
+
+private:
+ typedef typename Derived1::Scalar Scalar;
+ enum {
+ PacketSize = ei_packet_traits<Scalar>::size,
+ Cost = Derived1::SizeAtCompileTime * (Derived1::CoeffReadCost + Derived2::CoeffReadCost + NumTraits<Scalar>::MulCost)
+ + (Derived1::SizeAtCompileTime-1) * NumTraits<Scalar>::AddCost,
+ UnrollingLimit = EIGEN_UNROLLING_LIMIT * (int(Vectorization) == int(NoVectorization) ? 1 : int(PacketSize))
+ };
+
+public:
+ enum {
+ Unrolling = Cost <= UnrollingLimit
+ ? CompleteUnrolling
+ : NoUnrolling
+ };
+};
+
+/***************************************************************************
+* Part 2 : unrollers
+***************************************************************************/
+
+/*** no vectorization ***/
+
+template<typename Derived1, typename Derived2, int Start, int Length>
+struct ei_dot_novec_unroller
+{
+ enum {
+ HalfLength = Length/2
+ };
+
+ typedef typename Derived1::Scalar Scalar;
+
+ inline static Scalar run(const Derived1& v1, const Derived2& v2)
+ {
+ return ei_dot_novec_unroller<Derived1, Derived2, Start, HalfLength>::run(v1, v2)
+ + ei_dot_novec_unroller<Derived1, Derived2, Start+HalfLength, Length-HalfLength>::run(v1, v2);
+ }
+};
+
+template<typename Derived1, typename Derived2, int Start>
+struct ei_dot_novec_unroller<Derived1, Derived2, Start, 1>
+{
+ typedef typename Derived1::Scalar Scalar;
+
+ inline static Scalar run(const Derived1& v1, const Derived2& v2)
+ {
+ return v1.coeff(Start) * ei_conj(v2.coeff(Start));
+ }
+};
+
+/*** vectorization ***/
+
+template<typename Derived1, typename Derived2, int Index, int Stop,
+ bool LastPacket = (Stop-Index == ei_packet_traits<typename Derived1::Scalar>::size)>
+struct ei_dot_vec_unroller
+{
+ typedef typename Derived1::Scalar Scalar;
+ typedef typename ei_packet_traits<Scalar>::type PacketScalar;
+
+ enum {
+ row1 = Derived1::RowsAtCompileTime == 1 ? 0 : Index,
+ col1 = Derived1::RowsAtCompileTime == 1 ? Index : 0,
+ row2 = Derived2::RowsAtCompileTime == 1 ? 0 : Index,
+ col2 = Derived2::RowsAtCompileTime == 1 ? Index : 0
+ };
+
+ inline static PacketScalar run(const Derived1& v1, const Derived2& v2)
+ {
+ return ei_pmadd(
+ v1.template packet<Aligned>(row1, col1),
+ v2.template packet<Aligned>(row2, col2),
+ ei_dot_vec_unroller<Derived1, Derived2, Index+ei_packet_traits<Scalar>::size, Stop>::run(v1, v2)
+ );
+ }
+};
+
+template<typename Derived1, typename Derived2, int Index, int Stop>
+struct ei_dot_vec_unroller<Derived1, Derived2, Index, Stop, true>
+{
+ enum {
+ row1 = Derived1::RowsAtCompileTime == 1 ? 0 : Index,
+ col1 = Derived1::RowsAtCompileTime == 1 ? Index : 0,
+ row2 = Derived2::RowsAtCompileTime == 1 ? 0 : Index,
+ col2 = Derived2::RowsAtCompileTime == 1 ? Index : 0,
+ alignment1 = (Derived1::Flags & AlignedBit) ? Aligned : Unaligned,
+ alignment2 = (Derived2::Flags & AlignedBit) ? Aligned : Unaligned
+ };
+
+ typedef typename Derived1::Scalar Scalar;
+ typedef typename ei_packet_traits<Scalar>::type PacketScalar;
+
+ inline static PacketScalar run(const Derived1& v1, const Derived2& v2)
+ {
+ return ei_pmul(v1.template packet<alignment1>(row1, col1), v2.template packet<alignment2>(row2, col2));
+ }
+};
+
+/***************************************************************************
+* Part 3 : implementation of all cases
+***************************************************************************/
+
+template<typename Derived1, typename Derived2,
+ int Vectorization = ei_dot_traits<Derived1, Derived2>::Vectorization,
+ int Unrolling = ei_dot_traits<Derived1, Derived2>::Unrolling
+>
+struct ei_dot_impl;
+
+template<typename Derived1, typename Derived2>
+struct ei_dot_impl<Derived1, Derived2, NoVectorization, NoUnrolling>
+{
+ typedef typename Derived1::Scalar Scalar;
+ static Scalar run(const Derived1& v1, const Derived2& v2)
+ {
+ ei_assert(v1.size()>0 && "you are using a non initialized vector");
+ Scalar res;
+ res = v1.coeff(0) * ei_conj(v2.coeff(0));
+ for(int i = 1; i < v1.size(); ++i)
+ res += v1.coeff(i) * ei_conj(v2.coeff(i));
+ return res;
+ }
+};
+
+template<typename Derived1, typename Derived2>
+struct ei_dot_impl<Derived1, Derived2, NoVectorization, CompleteUnrolling>
+ : public ei_dot_novec_unroller<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
+{};
+
+template<typename Derived1, typename Derived2>
+struct ei_dot_impl<Derived1, Derived2, LinearVectorization, NoUnrolling>
+{
+ typedef typename Derived1::Scalar Scalar;
+ typedef typename ei_packet_traits<Scalar>::type PacketScalar;
+
+ static Scalar run(const Derived1& v1, const Derived2& v2)
+ {
+ const int size = v1.size();
+ const int packetSize = ei_packet_traits<Scalar>::size;
+ const int alignedSize = (size/packetSize)*packetSize;
+ enum {
+ alignment1 = (Derived1::Flags & AlignedBit) ? Aligned : Unaligned,
+ alignment2 = (Derived2::Flags & AlignedBit) ? Aligned : Unaligned
+ };
+ Scalar res;
+
+ // do the vectorizable part of the sum
+ if(size >= packetSize)
+ {
+ PacketScalar packet_res = ei_pmul(
+ v1.template packet<alignment1>(0),
+ v2.template packet<alignment2>(0)
+ );
+ for(int index = packetSize; index<alignedSize; index += packetSize)
+ {
+ packet_res = ei_pmadd(
+ v1.template packet<alignment1>(index),
+ v2.template packet<alignment2>(index),
+ packet_res
+ );
+ }
+ res = ei_predux(packet_res);
+
+ // now we must do the rest without vectorization.
+ if(alignedSize == size) return res;
+ }
+ else // too small to vectorize anything.
+ // since this is dynamic-size hence inefficient anyway for such small sizes, don't try to optimize.
+ {
+ res = Scalar(0);
+ }
+
+ // do the remainder of the vector
+ for(int index = alignedSize; index < size; ++index)
+ {
+ res += v1.coeff(index) * v2.coeff(index);
+ }
+
+ return res;
+ }
+};
+
+template<typename Derived1, typename Derived2>
+struct ei_dot_impl<Derived1, Derived2, LinearVectorization, CompleteUnrolling>
+{
+ typedef typename Derived1::Scalar Scalar;
+ typedef typename ei_packet_traits<Scalar>::type PacketScalar;
+ enum {
+ PacketSize = ei_packet_traits<Scalar>::size,
+ Size = Derived1::SizeAtCompileTime,
+ VectorizationSize = (Size / PacketSize) * PacketSize
+ };
+ static Scalar run(const Derived1& v1, const Derived2& v2)
+ {
+ Scalar res = ei_predux(ei_dot_vec_unroller<Derived1, Derived2, 0, VectorizationSize>::run(v1, v2));
+ if (VectorizationSize != Size)
+ res += ei_dot_novec_unroller<Derived1, Derived2, VectorizationSize, Size-VectorizationSize>::run(v1, v2);
+ return res;
+ }
+};
+
+/***************************************************************************
+* Part 4 : implementation of MatrixBase methods
+***************************************************************************/
+
+/** \returns the dot product of *this with other.
+ *
+ * \only_for_vectors
+ *
+ * \note If the scalar type is complex numbers, then this function returns the hermitian
+ * (sesquilinear) dot product, linear in the first variable and conjugate-linear in the
+ * second variable.
+ *
+ * \sa squaredNorm(), norm()
+ */
+template<typename Derived>
+template<typename OtherDerived>
+typename ei_traits<Derived>::Scalar
+MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
+ EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
+ EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
+ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
+
+ ei_assert(size() == other.size());
+
+ return ei_dot_impl<Derived, OtherDerived>::run(derived(), other.derived());
+}
+
+/** \returns the squared \em l2 norm of *this, i.e., for vectors, the dot product of *this with itself.
+ *
+ * \sa dot(), norm()
+ */
+template<typename Derived>
+inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::squaredNorm() const
+{
+ return ei_real((*this).cwise().abs2().sum());
+}
+
+/** \returns the \em l2 norm of *this, i.e., for vectors, the square root of the dot product of *this with itself.
+ *
+ * \sa dot(), squaredNorm()
+ */
+template<typename Derived>
+inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const
+{
+ return ei_sqrt(squaredNorm());
+}
+
+/** \returns an expression of the quotient of *this by its own norm.
+ *
+ * \only_for_vectors
+ *
+ * \sa norm(), normalize()
+ */
+template<typename Derived>
+inline const typename MatrixBase<Derived>::PlainMatrixType
+MatrixBase<Derived>::normalized() const
+{
+ typedef typename ei_nested<Derived>::type Nested;
+ typedef typename ei_unref<Nested>::type _Nested;
+ _Nested n(derived());
+ return n / n.norm();
+}
+
+/** Normalizes the vector, i.e. divides it by its own norm.
+ *
+ * \only_for_vectors
+ *
+ * \sa norm(), normalized()
+ */
+template<typename Derived>
+inline void MatrixBase<Derived>::normalize()
+{
+ *this /= norm();
+}
+
+/** \returns true if *this is approximately orthogonal to \a other,
+ * within the precision given by \a prec.
+ *
+ * Example: \include MatrixBase_isOrthogonal.cpp
+ * Output: \verbinclude MatrixBase_isOrthogonal.out
+ */
+template<typename Derived>
+template<typename OtherDerived>
+bool MatrixBase<Derived>::isOrthogonal
+(const MatrixBase<OtherDerived>& other, RealScalar prec) const
+{
+ typename ei_nested<Derived,2>::type nested(derived());
+ typename ei_nested<OtherDerived,2>::type otherNested(other.derived());
+ return ei_abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm();
+}
+
+/** \returns true if *this is approximately an unitary matrix,
+ * within the precision given by \a prec. In the case where the \a Scalar
+ * type is real numbers, a unitary matrix is an orthogonal matrix, whence the name.
+ *
+ * \note This can be used to check whether a family of vectors forms an orthonormal basis.
+ * Indeed, \c m.isUnitary() returns true if and only if the columns (equivalently, the rows) of m form an
+ * orthonormal basis.
+ *
+ * Example: \include MatrixBase_isUnitary.cpp
+ * Output: \verbinclude MatrixBase_isUnitary.out
+ */
+template<typename Derived>
+bool MatrixBase<Derived>::isUnitary(RealScalar prec) const
+{
+ typename Derived::Nested nested(derived());
+ for(int i = 0; i < cols(); ++i)
+ {
+ if(!ei_isApprox(nested.col(i).squaredNorm(), static_cast<Scalar>(1), prec))
+ return false;
+ for(int j = 0; j < i; ++j)
+ if(!ei_isMuchSmallerThan(nested.col(i).dot(nested.col(j)), static_cast<Scalar>(1), prec))
+ return false;
+ }
+ return true;
+}
+#endif // EIGEN_DOT_H
diff --git a/extern/Eigen3/Eigen/src/Core/Flagged.h b/extern/Eigen2/Eigen/src/Core/Flagged.h
index 458213ab553..e3d25341d9e 100644
--- a/extern/Eigen3/Eigen/src/Core/Flagged.h
+++ b/extern/Eigen2/Eigen/src/Core/Flagged.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
@@ -26,7 +26,6 @@
#define EIGEN_FLAGGED_H
/** \class Flagged
- * \ingroup Core_Module
*
* \brief Expression with modified flags
*
@@ -40,110 +39,109 @@
*
* \sa MatrixBase::flagged()
*/
-
-namespace internal {
template<typename ExpressionType, unsigned int Added, unsigned int Removed>
-struct traits<Flagged<ExpressionType, Added, Removed> > : traits<ExpressionType>
+struct ei_traits<Flagged<ExpressionType, Added, Removed> > : ei_traits<ExpressionType>
{
enum { Flags = (ExpressionType::Flags | Added) & ~Removed };
};
-}
template<typename ExpressionType, unsigned int Added, unsigned int Removed> class Flagged
: public MatrixBase<Flagged<ExpressionType, Added, Removed> >
{
public:
- typedef MatrixBase<Flagged> Base;
-
- EIGEN_DENSE_PUBLIC_INTERFACE(Flagged)
- typedef typename internal::conditional<internal::must_nest_by_value<ExpressionType>::ret,
- ExpressionType, const ExpressionType&>::type ExpressionTypeNested;
+ EIGEN_GENERIC_PUBLIC_INTERFACE(Flagged)
+ typedef typename ei_meta_if<ei_must_nest_by_value<ExpressionType>::ret,
+ ExpressionType, const ExpressionType&>::ret ExpressionTypeNested;
typedef typename ExpressionType::InnerIterator InnerIterator;
inline Flagged(const ExpressionType& matrix) : m_matrix(matrix) {}
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
- inline Index outerStride() const { return m_matrix.outerStride(); }
- inline Index innerStride() const { return m_matrix.innerStride(); }
+ inline int rows() const { return m_matrix.rows(); }
+ inline int cols() const { return m_matrix.cols(); }
+ inline int stride() const { return m_matrix.stride(); }
- inline CoeffReturnType coeff(Index row, Index col) const
+ inline const Scalar coeff(int row, int col) const
{
return m_matrix.coeff(row, col);
}
- inline CoeffReturnType coeff(Index index) const
- {
- return m_matrix.coeff(index);
- }
-
- inline const Scalar& coeffRef(Index row, Index col) const
+ inline Scalar& coeffRef(int row, int col)
{
return m_matrix.const_cast_derived().coeffRef(row, col);
}
- inline const Scalar& coeffRef(Index index) const
- {
- return m_matrix.const_cast_derived().coeffRef(index);
- }
-
- inline Scalar& coeffRef(Index row, Index col)
+ inline const Scalar coeff(int index) const
{
- return m_matrix.const_cast_derived().coeffRef(row, col);
+ return m_matrix.coeff(index);
}
- inline Scalar& coeffRef(Index index)
+ inline Scalar& coeffRef(int index)
{
return m_matrix.const_cast_derived().coeffRef(index);
}
template<int LoadMode>
- inline const PacketScalar packet(Index row, Index col) const
+ inline const PacketScalar packet(int row, int col) const
{
return m_matrix.template packet<LoadMode>(row, col);
}
template<int LoadMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
+ inline void writePacket(int row, int col, const PacketScalar& x)
{
m_matrix.const_cast_derived().template writePacket<LoadMode>(row, col, x);
}
template<int LoadMode>
- inline const PacketScalar packet(Index index) const
+ inline const PacketScalar packet(int index) const
{
return m_matrix.template packet<LoadMode>(index);
}
template<int LoadMode>
- inline void writePacket(Index index, const PacketScalar& x)
+ inline void writePacket(int index, const PacketScalar& x)
{
m_matrix.const_cast_derived().template writePacket<LoadMode>(index, x);
}
const ExpressionType& _expression() const { return m_matrix; }
- template<typename OtherDerived>
- typename ExpressionType::PlainObject solveTriangular(const MatrixBase<OtherDerived>& other) const;
-
- template<typename OtherDerived>
- void solveTriangularInPlace(const MatrixBase<OtherDerived>& other) const;
-
protected:
ExpressionTypeNested m_matrix;
+
+private:
+ Flagged& operator=(const Flagged&);
};
-/** \returns an expression of *this with added and removed flags
+/** \returns an expression of *this with added flags
+ *
+ * \addexample MarkExample \label How to mark a triangular matrix as triangular
+ *
+ * Example: \include MatrixBase_marked.cpp
+ * Output: \verbinclude MatrixBase_marked.out
+ *
+ * \sa class Flagged, extract(), part()
+ */
+template<typename Derived>
+template<unsigned int Added>
+inline const Flagged<Derived, Added, 0>
+MatrixBase<Derived>::marked() const
+{
+ return derived();
+}
+
+/** \returns an expression of *this with the following flags removed:
+ * EvalBeforeNestingBit and EvalBeforeAssigningBit.
*
- * This is mostly for internal use.
+ * Example: \include MatrixBase_lazy.cpp
+ * Output: \verbinclude MatrixBase_lazy.out
*
- * \sa class Flagged
+ * \sa class Flagged, marked()
*/
template<typename Derived>
-template<unsigned int Added,unsigned int Removed>
-inline const Flagged<Derived, Added, Removed>
-DenseBase<Derived>::flagged() const
+inline const Flagged<Derived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>
+MatrixBase<Derived>::lazy() const
{
return derived();
}
diff --git a/extern/Eigen2/Eigen/src/Core/Functors.h b/extern/Eigen2/Eigen/src/Core/Functors.h
new file mode 100644
index 00000000000..969cad78d8f
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/Functors.h
@@ -0,0 +1,378 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_FUNCTORS_H
+#define EIGEN_FUNCTORS_H
+
+// associative functors:
+
+/** \internal
+ * \brief Template functor to compute the sum of two scalars
+ *
+ * \sa class CwiseBinaryOp, MatrixBase::operator+, class PartialRedux, MatrixBase::sum()
+ */
+template<typename Scalar> struct ei_scalar_sum_op EIGEN_EMPTY_STRUCT {
+ EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a + b; }
+ template<typename PacketScalar>
+ EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
+ { return ei_padd(a,b); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_sum_op<Scalar> > {
+ enum {
+ Cost = NumTraits<Scalar>::AddCost,
+ PacketAccess = ei_packet_traits<Scalar>::size>1
+ };
+};
+
+/** \internal
+ * \brief Template functor to compute the product of two scalars
+ *
+ * \sa class CwiseBinaryOp, Cwise::operator*(), class PartialRedux, MatrixBase::redux()
+ */
+template<typename Scalar> struct ei_scalar_product_op EIGEN_EMPTY_STRUCT {
+ EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a * b; }
+ template<typename PacketScalar>
+ EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
+ { return ei_pmul(a,b); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_product_op<Scalar> > {
+ enum {
+ Cost = NumTraits<Scalar>::MulCost,
+ PacketAccess = ei_packet_traits<Scalar>::size>1
+ };
+};
+
+/** \internal
+ * \brief Template functor to compute the min of two scalars
+ *
+ * \sa class CwiseBinaryOp, MatrixBase::cwiseMin, class PartialRedux, MatrixBase::minCoeff()
+ */
+template<typename Scalar> struct ei_scalar_min_op EIGEN_EMPTY_STRUCT {
+ EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return std::min(a, b); }
+ template<typename PacketScalar>
+ EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
+ { return ei_pmin(a,b); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_min_op<Scalar> > {
+ enum {
+ Cost = NumTraits<Scalar>::AddCost,
+ PacketAccess = ei_packet_traits<Scalar>::size>1
+ };
+};
+
+/** \internal
+ * \brief Template functor to compute the max of two scalars
+ *
+ * \sa class CwiseBinaryOp, MatrixBase::cwiseMax, class PartialRedux, MatrixBase::maxCoeff()
+ */
+template<typename Scalar> struct ei_scalar_max_op EIGEN_EMPTY_STRUCT {
+ EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return std::max(a, b); }
+ template<typename PacketScalar>
+ EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
+ { return ei_pmax(a,b); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_max_op<Scalar> > {
+ enum {
+ Cost = NumTraits<Scalar>::AddCost,
+ PacketAccess = ei_packet_traits<Scalar>::size>1
+ };
+};
+
+
+// other binary functors:
+
+/** \internal
+ * \brief Template functor to compute the difference of two scalars
+ *
+ * \sa class CwiseBinaryOp, MatrixBase::operator-
+ */
+template<typename Scalar> struct ei_scalar_difference_op EIGEN_EMPTY_STRUCT {
+ EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a - b; }
+ template<typename PacketScalar>
+ EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
+ { return ei_psub(a,b); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_difference_op<Scalar> > {
+ enum {
+ Cost = NumTraits<Scalar>::AddCost,
+ PacketAccess = ei_packet_traits<Scalar>::size>1
+ };
+};
+
+/** \internal
+ * \brief Template functor to compute the quotient of two scalars
+ *
+ * \sa class CwiseBinaryOp, Cwise::operator/()
+ */
+template<typename Scalar> struct ei_scalar_quotient_op EIGEN_EMPTY_STRUCT {
+ EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a / b; }
+ template<typename PacketScalar>
+ EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a, const PacketScalar& b) const
+ { return ei_pdiv(a,b); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_quotient_op<Scalar> > {
+ enum {
+ Cost = 2 * NumTraits<Scalar>::MulCost,
+ PacketAccess = ei_packet_traits<Scalar>::size>1
+ #if (defined EIGEN_VECTORIZE_SSE)
+ && NumTraits<Scalar>::HasFloatingPoint
+ #endif
+ };
+};
+
+// unary functors:
+
+/** \internal
+ * \brief Template functor to compute the opposite of a scalar
+ *
+ * \sa class CwiseUnaryOp, MatrixBase::operator-
+ */
+template<typename Scalar> struct ei_scalar_opposite_op EIGEN_EMPTY_STRUCT {
+ EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return -a; }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_opposite_op<Scalar> >
+{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false }; };
+
+/** \internal
+ * \brief Template functor to compute the absolute value of a scalar
+ *
+ * \sa class CwiseUnaryOp, Cwise::abs
+ */
+template<typename Scalar> struct ei_scalar_abs_op EIGEN_EMPTY_STRUCT {
+ typedef typename NumTraits<Scalar>::Real result_type;
+ EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return ei_abs(a); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_abs_op<Scalar> >
+{
+ enum {
+ Cost = NumTraits<Scalar>::AddCost,
+ PacketAccess = false // this could actually be vectorized with SSSE3.
+ };
+};
+
+/** \internal
+ * \brief Template functor to compute the squared absolute value of a scalar
+ *
+ * \sa class CwiseUnaryOp, Cwise::abs2
+ */
+template<typename Scalar> struct ei_scalar_abs2_op EIGEN_EMPTY_STRUCT {
+ typedef typename NumTraits<Scalar>::Real result_type;
+ EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return ei_abs2(a); }
+ template<typename PacketScalar>
+ EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a) const
+ { return ei_pmul(a,a); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_abs2_op<Scalar> >
+{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = int(ei_packet_traits<Scalar>::size)>1 }; };
+
+/** \internal
+ * \brief Template functor to compute the conjugate of a complex value
+ *
+ * \sa class CwiseUnaryOp, MatrixBase::conjugate()
+ */
+template<typename Scalar> struct ei_scalar_conjugate_op EIGEN_EMPTY_STRUCT {
+ EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return ei_conj(a); }
+ template<typename PacketScalar>
+ EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a) const { return a; }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_conjugate_op<Scalar> >
+{
+ enum {
+ Cost = NumTraits<Scalar>::IsComplex ? NumTraits<Scalar>::AddCost : 0,
+ PacketAccess = int(ei_packet_traits<Scalar>::size)>1
+ };
+};
+
+/** \internal
+ * \brief Template functor to cast a scalar to another type
+ *
+ * \sa class CwiseUnaryOp, MatrixBase::cast()
+ */
+template<typename Scalar, typename NewType>
+struct ei_scalar_cast_op EIGEN_EMPTY_STRUCT {
+ typedef NewType result_type;
+ EIGEN_STRONG_INLINE const NewType operator() (const Scalar& a) const { return static_cast<NewType>(a); }
+};
+template<typename Scalar, typename NewType>
+struct ei_functor_traits<ei_scalar_cast_op<Scalar,NewType> >
+{ enum { Cost = ei_is_same_type<Scalar, NewType>::ret ? 0 : NumTraits<NewType>::AddCost, PacketAccess = false }; };
+
+/** \internal
+ * \brief Template functor to extract the real part of a complex
+ *
+ * \sa class CwiseUnaryOp, MatrixBase::real()
+ */
+template<typename Scalar>
+struct ei_scalar_real_op EIGEN_EMPTY_STRUCT {
+ typedef typename NumTraits<Scalar>::Real result_type;
+ EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return ei_real(a); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_real_op<Scalar> >
+{ enum { Cost = 0, PacketAccess = false }; };
+
+/** \internal
+ * \brief Template functor to extract the imaginary part of a complex
+ *
+ * \sa class CwiseUnaryOp, MatrixBase::imag()
+ */
+template<typename Scalar>
+struct ei_scalar_imag_op EIGEN_EMPTY_STRUCT {
+ typedef typename NumTraits<Scalar>::Real result_type;
+ EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return ei_imag(a); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_imag_op<Scalar> >
+{ enum { Cost = 0, PacketAccess = false }; };
+
+/** \internal
+ * \brief Template functor to multiply a scalar by a fixed other one
+ *
+ * \sa class CwiseUnaryOp, MatrixBase::operator*, MatrixBase::operator/
+ */
+/* NOTE why doing the ei_pset1() in packetOp *is* an optimization ?
+ * indeed it seems better to declare m_other as a PacketScalar and do the ei_pset1() once
+ * in the constructor. However, in practice:
+ * - GCC does not like m_other as a PacketScalar and generate a load every time it needs it
+ * - one the other hand GCC is able to moves the ei_pset1() away the loop :)
+ * - simpler code ;)
+ * (ICC and gcc 4.4 seems to perform well in both cases, the issue is visible with y = a*x + b*y)
+ */
+template<typename Scalar>
+struct ei_scalar_multiple_op {
+ typedef typename ei_packet_traits<Scalar>::type PacketScalar;
+ // FIXME default copy constructors seems bugged with std::complex<>
+ EIGEN_STRONG_INLINE ei_scalar_multiple_op(const ei_scalar_multiple_op& other) : m_other(other.m_other) { }
+ EIGEN_STRONG_INLINE ei_scalar_multiple_op(const Scalar& other) : m_other(other) { }
+ EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
+ EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a) const
+ { return ei_pmul(a, ei_pset1(m_other)); }
+ const Scalar m_other;
+private:
+ ei_scalar_multiple_op& operator=(const ei_scalar_multiple_op&);
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_multiple_op<Scalar> >
+{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = ei_packet_traits<Scalar>::size>1 }; };
+
+template<typename Scalar, bool HasFloatingPoint>
+struct ei_scalar_quotient1_impl {
+ typedef typename ei_packet_traits<Scalar>::type PacketScalar;
+ // FIXME default copy constructors seems bugged with std::complex<>
+ EIGEN_STRONG_INLINE ei_scalar_quotient1_impl(const ei_scalar_quotient1_impl& other) : m_other(other.m_other) { }
+ EIGEN_STRONG_INLINE ei_scalar_quotient1_impl(const Scalar& other) : m_other(static_cast<Scalar>(1) / other) {}
+ EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
+ EIGEN_STRONG_INLINE const PacketScalar packetOp(const PacketScalar& a) const
+ { return ei_pmul(a, ei_pset1(m_other)); }
+ const Scalar m_other;
+private:
+ ei_scalar_quotient1_impl& operator=(const ei_scalar_quotient1_impl&);
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_quotient1_impl<Scalar,true> >
+{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = ei_packet_traits<Scalar>::size>1 }; };
+
+template<typename Scalar>
+struct ei_scalar_quotient1_impl<Scalar,false> {
+ // FIXME default copy constructors seems bugged with std::complex<>
+ EIGEN_STRONG_INLINE ei_scalar_quotient1_impl(const ei_scalar_quotient1_impl& other) : m_other(other.m_other) { }
+ EIGEN_STRONG_INLINE ei_scalar_quotient1_impl(const Scalar& other) : m_other(other) {}
+ EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; }
+ const Scalar m_other;
+private:
+ ei_scalar_quotient1_impl& operator=(const ei_scalar_quotient1_impl&);
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_quotient1_impl<Scalar,false> >
+{ enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
+
+/** \internal
+ * \brief Template functor to divide a scalar by a fixed other one
+ *
+ * This functor is used to implement the quotient of a matrix by
+ * a scalar where the scalar type is not necessarily a floating point type.
+ *
+ * \sa class CwiseUnaryOp, MatrixBase::operator/
+ */
+template<typename Scalar>
+struct ei_scalar_quotient1_op : ei_scalar_quotient1_impl<Scalar, NumTraits<Scalar>::HasFloatingPoint > {
+ EIGEN_STRONG_INLINE ei_scalar_quotient1_op(const Scalar& other)
+ : ei_scalar_quotient1_impl<Scalar, NumTraits<Scalar>::HasFloatingPoint >(other) {}
+private:
+ ei_scalar_quotient1_op& operator=(const ei_scalar_quotient1_op&);
+};
+
+// nullary functors
+
+template<typename Scalar>
+struct ei_scalar_constant_op {
+ typedef typename ei_packet_traits<Scalar>::type PacketScalar;
+ EIGEN_STRONG_INLINE ei_scalar_constant_op(const ei_scalar_constant_op& other) : m_other(other.m_other) { }
+ EIGEN_STRONG_INLINE ei_scalar_constant_op(const Scalar& other) : m_other(other) { }
+ EIGEN_STRONG_INLINE const Scalar operator() (int, int = 0) const { return m_other; }
+ EIGEN_STRONG_INLINE const PacketScalar packetOp() const { return ei_pset1(m_other); }
+ const Scalar m_other;
+private:
+ ei_scalar_constant_op& operator=(const ei_scalar_constant_op&);
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_constant_op<Scalar> >
+{ enum { Cost = 1, PacketAccess = ei_packet_traits<Scalar>::size>1, IsRepeatable = true }; };
+
+template<typename Scalar> struct ei_scalar_identity_op EIGEN_EMPTY_STRUCT {
+ EIGEN_STRONG_INLINE ei_scalar_identity_op(void) {}
+ EIGEN_STRONG_INLINE const Scalar operator() (int row, int col) const { return row==col ? Scalar(1) : Scalar(0); }
+};
+template<typename Scalar>
+struct ei_functor_traits<ei_scalar_identity_op<Scalar> >
+{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true }; };
+
+// allow to add new functors and specializations of ei_functor_traits from outside Eigen.
+// this macro is really needed because ei_functor_traits must be specialized after it is declared but before it is used...
+#ifdef EIGEN_FUNCTORS_PLUGIN
+#include EIGEN_FUNCTORS_PLUGIN
+#endif
+
+// all functors allow linear access, except ei_scalar_identity_op. So we fix here a quick meta
+// to indicate whether a functor allows linear access, just always answering 'yes' except for
+// ei_scalar_identity_op.
+template<typename Functor> struct ei_functor_has_linear_access { enum { ret = 1 }; };
+template<typename Scalar> struct ei_functor_has_linear_access<ei_scalar_identity_op<Scalar> > { enum { ret = 0 }; };
+
+// in CwiseBinaryOp, we require the Lhs and Rhs to have the same scalar type, except for multiplication
+// where we only require them to have the same _real_ scalar type so one may multiply, say, float by complex<float>.
+template<typename Functor> struct ei_functor_allows_mixing_real_and_complex { enum { ret = 0 }; };
+template<typename Scalar> struct ei_functor_allows_mixing_real_and_complex<ei_scalar_product_op<Scalar> > { enum { ret = 1 }; };
+
+#endif // EIGEN_FUNCTORS_H
diff --git a/extern/Eigen2/Eigen/src/Core/Fuzzy.h b/extern/Eigen2/Eigen/src/Core/Fuzzy.h
new file mode 100644
index 00000000000..1285542966c
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/Fuzzy.h
@@ -0,0 +1,234 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_FUZZY_H
+#define EIGEN_FUZZY_H
+
+#ifndef EIGEN_LEGACY_COMPARES
+
+/** \returns \c true if \c *this is approximately equal to \a other, within the precision
+ * determined by \a prec.
+ *
+ * \note The fuzzy compares are done multiplicatively. Two vectors \f$ v \f$ and \f$ w \f$
+ * are considered to be approximately equal within precision \f$ p \f$ if
+ * \f[ \Vert v - w \Vert \leqslant p\,\min(\Vert v\Vert, \Vert w\Vert). \f]
+ * For matrices, the comparison is done using the Hilbert-Schmidt norm (aka Frobenius norm
+ * L2 norm).
+ *
+ * \note Because of the multiplicativeness of this comparison, one can't use this function
+ * to check whether \c *this is approximately equal to the zero matrix or vector.
+ * Indeed, \c isApprox(zero) returns false unless \c *this itself is exactly the zero matrix
+ * or vector. If you want to test whether \c *this is zero, use ei_isMuchSmallerThan(const
+ * RealScalar&, RealScalar) instead.
+ *
+ * \sa ei_isMuchSmallerThan(const RealScalar&, RealScalar) const
+ */
+template<typename Derived>
+template<typename OtherDerived>
+bool MatrixBase<Derived>::isApprox(
+ const MatrixBase<OtherDerived>& other,
+ typename NumTraits<Scalar>::Real prec
+) const
+{
+ const typename ei_nested<Derived,2>::type nested(derived());
+ const typename ei_nested<OtherDerived,2>::type otherNested(other.derived());
+ return (nested - otherNested).cwise().abs2().sum() <= prec * prec * std::min(nested.cwise().abs2().sum(), otherNested.cwise().abs2().sum());
+}
+
+/** \returns \c true if the norm of \c *this is much smaller than \a other,
+ * within the precision determined by \a prec.
+ *
+ * \note The fuzzy compares are done multiplicatively. A vector \f$ v \f$ is
+ * considered to be much smaller than \f$ x \f$ within precision \f$ p \f$ if
+ * \f[ \Vert v \Vert \leqslant p\,\vert x\vert. \f]
+ *
+ * For matrices, the comparison is done using the Hilbert-Schmidt norm. For this reason,
+ * the value of the reference scalar \a other should come from the Hilbert-Schmidt norm
+ * of a reference matrix of same dimensions.
+ *
+ * \sa isApprox(), isMuchSmallerThan(const MatrixBase<OtherDerived>&, RealScalar) const
+ */
+template<typename Derived>
+bool MatrixBase<Derived>::isMuchSmallerThan(
+ const typename NumTraits<Scalar>::Real& other,
+ typename NumTraits<Scalar>::Real prec
+) const
+{
+ return cwise().abs2().sum() <= prec * prec * other * other;
+}
+
+/** \returns \c true if the norm of \c *this is much smaller than the norm of \a other,
+ * within the precision determined by \a prec.
+ *
+ * \note The fuzzy compares are done multiplicatively. A vector \f$ v \f$ is
+ * considered to be much smaller than a vector \f$ w \f$ within precision \f$ p \f$ if
+ * \f[ \Vert v \Vert \leqslant p\,\Vert w\Vert. \f]
+ * For matrices, the comparison is done using the Hilbert-Schmidt norm.
+ *
+ * \sa isApprox(), isMuchSmallerThan(const RealScalar&, RealScalar) const
+ */
+template<typename Derived>
+template<typename OtherDerived>
+bool MatrixBase<Derived>::isMuchSmallerThan(
+ const MatrixBase<OtherDerived>& other,
+ typename NumTraits<Scalar>::Real prec
+) const
+{
+ return this->cwise().abs2().sum() <= prec * prec * other.cwise().abs2().sum();
+}
+
+#else
+
+template<typename Derived, typename OtherDerived=Derived, bool IsVector=Derived::IsVectorAtCompileTime>
+struct ei_fuzzy_selector;
+
+/** \returns \c true if \c *this is approximately equal to \a other, within the precision
+ * determined by \a prec.
+ *
+ * \note The fuzzy compares are done multiplicatively. Two vectors \f$ v \f$ and \f$ w \f$
+ * are considered to be approximately equal within precision \f$ p \f$ if
+ * \f[ \Vert v - w \Vert \leqslant p\,\min(\Vert v\Vert, \Vert w\Vert). \f]
+ * For matrices, the comparison is done on all columns.
+ *
+ * \note Because of the multiplicativeness of this comparison, one can't use this function
+ * to check whether \c *this is approximately equal to the zero matrix or vector.
+ * Indeed, \c isApprox(zero) returns false unless \c *this itself is exactly the zero matrix
+ * or vector. If you want to test whether \c *this is zero, use ei_isMuchSmallerThan(const
+ * RealScalar&, RealScalar) instead.
+ *
+ * \sa ei_isMuchSmallerThan(const RealScalar&, RealScalar) const
+ */
+template<typename Derived>
+template<typename OtherDerived>
+bool MatrixBase<Derived>::isApprox(
+ const MatrixBase<OtherDerived>& other,
+ typename NumTraits<Scalar>::Real prec
+) const
+{
+ return ei_fuzzy_selector<Derived,OtherDerived>::isApprox(derived(), other.derived(), prec);
+}
+
+/** \returns \c true if the norm of \c *this is much smaller than \a other,
+ * within the precision determined by \a prec.
+ *
+ * \note The fuzzy compares are done multiplicatively. A vector \f$ v \f$ is
+ * considered to be much smaller than \f$ x \f$ within precision \f$ p \f$ if
+ * \f[ \Vert v \Vert \leqslant p\,\vert x\vert. \f]
+ * For matrices, the comparison is done on all columns.
+ *
+ * \sa isApprox(), isMuchSmallerThan(const MatrixBase<OtherDerived>&, RealScalar) const
+ */
+template<typename Derived>
+bool MatrixBase<Derived>::isMuchSmallerThan(
+ const typename NumTraits<Scalar>::Real& other,
+ typename NumTraits<Scalar>::Real prec
+) const
+{
+ return ei_fuzzy_selector<Derived>::isMuchSmallerThan(derived(), other, prec);
+}
+
+/** \returns \c true if the norm of \c *this is much smaller than the norm of \a other,
+ * within the precision determined by \a prec.
+ *
+ * \note The fuzzy compares are done multiplicatively. A vector \f$ v \f$ is
+ * considered to be much smaller than a vector \f$ w \f$ within precision \f$ p \f$ if
+ * \f[ \Vert v \Vert \leqslant p\,\Vert w\Vert. \f]
+ * For matrices, the comparison is done on all columns.
+ *
+ * \sa isApprox(), isMuchSmallerThan(const RealScalar&, RealScalar) const
+ */
+template<typename Derived>
+template<typename OtherDerived>
+bool MatrixBase<Derived>::isMuchSmallerThan(
+ const MatrixBase<OtherDerived>& other,
+ typename NumTraits<Scalar>::Real prec
+) const
+{
+ return ei_fuzzy_selector<Derived,OtherDerived>::isMuchSmallerThan(derived(), other.derived(), prec);
+}
+
+
+template<typename Derived, typename OtherDerived>
+struct ei_fuzzy_selector<Derived,OtherDerived,true>
+{
+ typedef typename Derived::RealScalar RealScalar;
+ static bool isApprox(const Derived& self, const OtherDerived& other, RealScalar prec)
+ {
+ EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
+ ei_assert(self.size() == other.size());
+ return((self - other).squaredNorm() <= std::min(self.squaredNorm(), other.squaredNorm()) * prec * prec);
+ }
+ static bool isMuchSmallerThan(const Derived& self, const RealScalar& other, RealScalar prec)
+ {
+ return(self.squaredNorm() <= ei_abs2(other * prec));
+ }
+ static bool isMuchSmallerThan(const Derived& self, const OtherDerived& other, RealScalar prec)
+ {
+ EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
+ ei_assert(self.size() == other.size());
+ return(self.squaredNorm() <= other.squaredNorm() * prec * prec);
+ }
+};
+
+template<typename Derived, typename OtherDerived>
+struct ei_fuzzy_selector<Derived,OtherDerived,false>
+{
+ typedef typename Derived::RealScalar RealScalar;
+ static bool isApprox(const Derived& self, const OtherDerived& other, RealScalar prec)
+ {
+ EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived)
+ ei_assert(self.rows() == other.rows() && self.cols() == other.cols());
+ typename Derived::Nested nested(self);
+ typename OtherDerived::Nested otherNested(other);
+ for(int i = 0; i < self.cols(); ++i)
+ if((nested.col(i) - otherNested.col(i)).squaredNorm()
+ > std::min(nested.col(i).squaredNorm(), otherNested.col(i).squaredNorm()) * prec * prec)
+ return false;
+ return true;
+ }
+ static bool isMuchSmallerThan(const Derived& self, const RealScalar& other, RealScalar prec)
+ {
+ typename Derived::Nested nested(self);
+ for(int i = 0; i < self.cols(); ++i)
+ if(nested.col(i).squaredNorm() > ei_abs2(other * prec))
+ return false;
+ return true;
+ }
+ static bool isMuchSmallerThan(const Derived& self, const OtherDerived& other, RealScalar prec)
+ {
+ EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived)
+ ei_assert(self.rows() == other.rows() && self.cols() == other.cols());
+ typename Derived::Nested nested(self);
+ typename OtherDerived::Nested otherNested(other);
+ for(int i = 0; i < self.cols(); ++i)
+ if(nested.col(i).squaredNorm() > otherNested.col(i).squaredNorm() * prec * prec)
+ return false;
+ return true;
+ }
+};
+
+#endif
+
+#endif // EIGEN_FUZZY_H
diff --git a/extern/Eigen2/Eigen/src/Core/GenericPacketMath.h b/extern/Eigen2/Eigen/src/Core/GenericPacketMath.h
new file mode 100644
index 00000000000..b0eee29f70f
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/GenericPacketMath.h
@@ -0,0 +1,150 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_GENERIC_PACKET_MATH_H
+#define EIGEN_GENERIC_PACKET_MATH_H
+
+/** \internal
+ * \file GenericPacketMath.h
+ *
+ * Default implementation for types not supported by the vectorization.
+ * In practice these functions are provided to make easier the writing
+ * of generic vectorized code.
+ */
+
+/** \internal \returns a + b (coeff-wise) */
+template<typename Packet> inline Packet
+ei_padd(const Packet& a,
+ const Packet& b) { return a+b; }
+
+/** \internal \returns a - b (coeff-wise) */
+template<typename Packet> inline Packet
+ei_psub(const Packet& a,
+ const Packet& b) { return a-b; }
+
+/** \internal \returns a * b (coeff-wise) */
+template<typename Packet> inline Packet
+ei_pmul(const Packet& a,
+ const Packet& b) { return a*b; }
+
+/** \internal \returns a / b (coeff-wise) */
+template<typename Packet> inline Packet
+ei_pdiv(const Packet& a,
+ const Packet& b) { return a/b; }
+
+/** \internal \returns the min of \a a and \a b (coeff-wise) */
+template<typename Packet> inline Packet
+ei_pmin(const Packet& a,
+ const Packet& b) { return std::min(a, b); }
+
+/** \internal \returns the max of \a a and \a b (coeff-wise) */
+template<typename Packet> inline Packet
+ei_pmax(const Packet& a,
+ const Packet& b) { return std::max(a, b); }
+
+/** \internal \returns a packet version of \a *from, from must be 16 bytes aligned */
+template<typename Scalar> inline typename ei_packet_traits<Scalar>::type
+ei_pload(const Scalar* from) { return *from; }
+
+/** \internal \returns a packet version of \a *from, (un-aligned load) */
+template<typename Scalar> inline typename ei_packet_traits<Scalar>::type
+ei_ploadu(const Scalar* from) { return *from; }
+
+/** \internal \returns a packet with constant coefficients \a a, e.g.: (a,a,a,a) */
+template<typename Scalar> inline typename ei_packet_traits<Scalar>::type
+ei_pset1(const Scalar& a) { return a; }
+
+/** \internal copy the packet \a from to \a *to, \a to must be 16 bytes aligned */
+template<typename Scalar, typename Packet> inline void ei_pstore(Scalar* to, const Packet& from)
+{ (*to) = from; }
+
+/** \internal copy the packet \a from to \a *to, (un-aligned store) */
+template<typename Scalar, typename Packet> inline void ei_pstoreu(Scalar* to, const Packet& from)
+{ (*to) = from; }
+
+/** \internal \returns the first element of a packet */
+template<typename Packet> inline typename ei_unpacket_traits<Packet>::type ei_pfirst(const Packet& a)
+{ return a; }
+
+/** \internal \returns a packet where the element i contains the sum of the packet of \a vec[i] */
+template<typename Packet> inline Packet
+ei_preduxp(const Packet* vecs) { return vecs[0]; }
+
+/** \internal \returns the sum of the elements of \a a*/
+template<typename Packet> inline typename ei_unpacket_traits<Packet>::type ei_predux(const Packet& a)
+{ return a; }
+
+
+/***************************************************************************
+* The following functions might not have to be overwritten for vectorized types
+***************************************************************************/
+
+/** \internal \returns a * b + c (coeff-wise) */
+template<typename Packet> inline Packet
+ei_pmadd(const Packet& a,
+ const Packet& b,
+ const Packet& c)
+{ return ei_padd(ei_pmul(a, b),c); }
+
+/** \internal \returns a packet version of \a *from.
+ * \If LoadMode equals Aligned, \a from must be 16 bytes aligned */
+template<typename Scalar, int LoadMode>
+inline typename ei_packet_traits<Scalar>::type ei_ploadt(const Scalar* from)
+{
+ if(LoadMode == Aligned)
+ return ei_pload(from);
+ else
+ return ei_ploadu(from);
+}
+
+/** \internal copy the packet \a from to \a *to.
+ * If StoreMode equals Aligned, \a to must be 16 bytes aligned */
+template<typename Scalar, typename Packet, int LoadMode>
+inline void ei_pstoret(Scalar* to, const Packet& from)
+{
+ if(LoadMode == Aligned)
+ ei_pstore(to, from);
+ else
+ ei_pstoreu(to, from);
+}
+
+/** \internal default implementation of ei_palign() allowing partial specialization */
+template<int Offset,typename PacketType>
+struct ei_palign_impl
+{
+ // by default data are aligned, so there is nothing to be done :)
+ inline static void run(PacketType&, const PacketType&) {}
+};
+
+/** \internal update \a first using the concatenation of the \a Offset last elements
+ * of \a first and packet_size minus \a Offset first elements of \a second */
+template<int Offset,typename PacketType>
+inline void ei_palign(PacketType& first, const PacketType& second)
+{
+ ei_palign_impl<Offset,PacketType>::run(first,second);
+}
+
+#endif // EIGEN_GENERIC_PACKET_MATH_H
+
diff --git a/extern/Eigen3/Eigen/src/Core/IO.h b/extern/Eigen2/Eigen/src/Core/IO.h
index f3cfcdbf4a3..2b00d5bc509 100644
--- a/extern/Eigen3/Eigen/src/Core/IO.h
+++ b/extern/Eigen2/Eigen/src/Core/IO.h
@@ -1,8 +1,8 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -26,28 +26,15 @@
#ifndef EIGEN_IO_H
#define EIGEN_IO_H
-enum { DontAlignCols = 1 };
-enum { StreamPrecision = -1,
- FullPrecision = -2 };
-
-namespace internal {
-template<typename Derived>
-std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat& fmt);
-}
+enum { Raw, AlignCols };
/** \class IOFormat
- * \ingroup Core_Module
*
* \brief Stores a set of parameters controlling the way matrices are printed
*
* List of available parameters:
- * - \b precision number of digits for floating point values, or one of the special constants \c StreamPrecision and \c FullPrecision.
- * The default is the special value \c StreamPrecision which means to use the
- * stream's own precision setting, as set for instance using \c cout.precision(3). The other special value
- * \c FullPrecision means that the number of digits will be computed to match the full precision of each floating-point
- * type.
- * - \b flags an OR-ed combination of flags, the default value is 0, the only currently available flag is \c DontAlignCols which
- * allows to disable the alignment of columns, resulting in faster code.
+ * - \b precision number of digits for floating point values
+ * - \b flags can be either Raw (default) or AlignCols which aligns all the columns
* - \b coeffSeparator string printed between two coefficients of the same row
* - \b rowSeparator string printed between two rows
* - \b rowPrefix string printed at the beginning of each row
@@ -58,12 +45,12 @@ std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat&
* Example: \include IOFormat.cpp
* Output: \verbinclude IOFormat.out
*
- * \sa DenseBase::format(), class WithFormat
+ * \sa MatrixBase::format(), class WithFormat
*/
struct IOFormat
{
/** Default contructor, see class IOFormat for the meaning of the parameters */
- IOFormat(int _precision = StreamPrecision, int _flags = 0,
+ IOFormat(int _precision=4, int _flags=Raw,
const std::string& _coeffSeparator = " ",
const std::string& _rowSeparator = "\n", const std::string& _rowPrefix="", const std::string& _rowSuffix="",
const std::string& _matPrefix="", const std::string& _matSuffix="")
@@ -86,19 +73,18 @@ struct IOFormat
};
/** \class WithFormat
- * \ingroup Core_Module
*
* \brief Pseudo expression providing matrix output with given format
*
* \param ExpressionType the type of the object on which IO stream operations are performed
*
* This class represents an expression with stream operators controlled by a given IOFormat.
- * It is the return type of DenseBase::format()
+ * It is the return type of MatrixBase::format()
* and most of the time this is the only way it is used.
*
* See class IOFormat for some examples.
*
- * \sa DenseBase::format(), class IOFormat
+ * \sa MatrixBase::format(), class IOFormat
*/
template<typename ExpressionType>
class WithFormat
@@ -111,7 +97,7 @@ class WithFormat
friend std::ostream & operator << (std::ostream & s, const WithFormat& wf)
{
- return internal::print_matrix(s, wf.m_matrix.eval(), wf.m_format);
+ return ei_print_matrix(s, wf.m_matrix.eval(), wf.m_format);
}
protected:
@@ -128,100 +114,41 @@ class WithFormat
*/
template<typename Derived>
inline const WithFormat<Derived>
-DenseBase<Derived>::format(const IOFormat& fmt) const
+MatrixBase<Derived>::format(const IOFormat& fmt) const
{
return WithFormat<Derived>(derived(), fmt);
}
-namespace internal {
-
-template<typename Scalar, bool IsInteger>
-struct significant_decimals_default_impl
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- static inline int run()
- {
- using std::ceil;
- return cast<RealScalar,int>(ceil(-log(NumTraits<RealScalar>::epsilon())/log(RealScalar(10))));
- }
-};
-
-template<typename Scalar>
-struct significant_decimals_default_impl<Scalar, true>
-{
- static inline int run()
- {
- return 0;
- }
-};
-
-template<typename Scalar>
-struct significant_decimals_impl
- : significant_decimals_default_impl<Scalar, NumTraits<Scalar>::IsInteger>
-{};
-
/** \internal
* print the matrix \a _m to the output stream \a s using the output format \a fmt */
template<typename Derived>
-std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat& fmt)
+std::ostream & ei_print_matrix(std::ostream & s, const Derived& _m, const IOFormat& fmt)
{
- if(_m.size() == 0)
- {
- s << fmt.matPrefix << fmt.matSuffix;
- return s;
- }
-
const typename Derived::Nested m = _m;
- typedef typename Derived::Scalar Scalar;
- typedef typename Derived::Index Index;
- Index width = 0;
-
- std::streamsize explicit_precision;
- if(fmt.precision == StreamPrecision)
- {
- explicit_precision = 0;
- }
- else if(fmt.precision == FullPrecision)
- {
- if (NumTraits<Scalar>::IsInteger)
- {
- explicit_precision = 0;
- }
- else
- {
- explicit_precision = significant_decimals_impl<Scalar>::run();
- }
- }
- else
- {
- explicit_precision = fmt.precision;
- }
-
- bool align_cols = !(fmt.flags & DontAlignCols);
- if(align_cols)
+ int width = 0;
+ if (fmt.flags & AlignCols)
{
// compute the largest width
- for(Index j = 1; j < m.cols(); ++j)
- for(Index i = 0; i < m.rows(); ++i)
+ for(int j = 1; j < m.cols(); ++j)
+ for(int i = 0; i < m.rows(); ++i)
{
std::stringstream sstr;
- if(explicit_precision) sstr.precision(explicit_precision);
+ sstr.precision(fmt.precision);
sstr << m.coeff(i,j);
- width = std::max<Index>(width, Index(sstr.str().length()));
+ width = std::max<int>(width, int(sstr.str().length()));
}
}
- std::streamsize old_precision = 0;
- if(explicit_precision) old_precision = s.precision(explicit_precision);
+ s.precision(fmt.precision);
s << fmt.matPrefix;
- for(Index i = 0; i < m.rows(); ++i)
+ for(int i = 0; i < m.rows(); ++i)
{
if (i)
s << fmt.rowSpacer;
s << fmt.rowPrefix;
if(width) s.width(width);
s << m.coeff(i, 0);
- for(Index j = 1; j < m.cols(); ++j)
+ for(int j = 1; j < m.cols(); ++j)
{
s << fmt.coeffSeparator;
if (width) s.width(width);
@@ -232,29 +159,26 @@ std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat&
s << fmt.rowSeparator;
}
s << fmt.matSuffix;
- if(explicit_precision) s.precision(old_precision);
return s;
}
-} // end namespace internal
-
-/** \relates DenseBase
+/** \relates MatrixBase
*
* Outputs the matrix, to the given stream.
*
- * If you wish to print the matrix with a format different than the default, use DenseBase::format().
+ * If you wish to print the matrix with a format different than the default, use MatrixBase::format().
*
* It is also possible to change the default format by defining EIGEN_DEFAULT_IO_FORMAT before including Eigen headers.
* If not defined, this will automatically be defined to Eigen::IOFormat(), that is the Eigen::IOFormat with default parameters.
*
- * \sa DenseBase::format()
+ * \sa MatrixBase::format()
*/
template<typename Derived>
std::ostream & operator <<
(std::ostream & s,
- const DenseBase<Derived> & m)
+ const MatrixBase<Derived> & m)
{
- return internal::print_matrix(s, m.eval(), EIGEN_DEFAULT_IO_FORMAT);
+ return ei_print_matrix(s, m.eval(), EIGEN_DEFAULT_IO_FORMAT);
}
#endif // EIGEN_IO_H
diff --git a/extern/Eigen2/Eigen/src/Core/Map.h b/extern/Eigen2/Eigen/src/Core/Map.h
new file mode 100644
index 00000000000..5f44a87e685
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/Map.h
@@ -0,0 +1,111 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_MAP_H
+#define EIGEN_MAP_H
+
+/** \class Map
+ *
+ * \brief A matrix or vector expression mapping an existing array of data.
+ *
+ * \param MatrixType the equivalent matrix type of the mapped data
+ * \param _PacketAccess allows to enforce aligned loads and stores if set to ForceAligned.
+ * The default is AsRequested. This parameter is internaly used by Eigen
+ * in expressions such as \code Map<...>(...) += other; \endcode and most
+ * of the time this is the only way it is used.
+ *
+ * This class represents a matrix or vector expression mapping an existing array of data.
+ * It can be used to let Eigen interface without any overhead with non-Eigen data structures,
+ * such as plain C arrays or structures from other libraries.
+ *
+ * This class is the return type of Matrix::Map() but can also be used directly.
+ *
+ * \sa Matrix::Map()
+ */
+template<typename MatrixType, int _PacketAccess>
+struct ei_traits<Map<MatrixType, _PacketAccess> > : public ei_traits<MatrixType>
+{
+ enum {
+ PacketAccess = _PacketAccess,
+ Flags = ei_traits<MatrixType>::Flags & ~AlignedBit
+ };
+ typedef typename ei_meta_if<int(PacketAccess)==ForceAligned,
+ Map<MatrixType, _PacketAccess>&,
+ Map<MatrixType, ForceAligned> >::ret AlignedDerivedType;
+};
+
+template<typename MatrixType, int PacketAccess> class Map
+ : public MapBase<Map<MatrixType, PacketAccess> >
+{
+ public:
+
+ _EIGEN_GENERIC_PUBLIC_INTERFACE(Map, MapBase<Map>)
+ typedef typename ei_traits<Map>::AlignedDerivedType AlignedDerivedType;
+
+ inline int stride() const { return this->innerSize(); }
+
+ AlignedDerivedType _convertToForceAligned()
+ {
+ return Map<MatrixType,ForceAligned>(Base::m_data, Base::m_rows.value(), Base::m_cols.value());
+ }
+
+ inline Map(const Scalar* data) : Base(data) {}
+
+ inline Map(const Scalar* data, int size) : Base(data, size) {}
+
+ inline Map(const Scalar* data, int rows, int cols) : Base(data, rows, cols) {}
+
+ inline void resize(int rows, int cols)
+ {
+ EIGEN_ONLY_USED_FOR_DEBUG(rows);
+ EIGEN_ONLY_USED_FOR_DEBUG(cols);
+ ei_assert(rows == this->rows());
+ ei_assert(cols == this->cols());
+ }
+
+ inline void resize(int size)
+ {
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(MatrixType)
+ EIGEN_ONLY_USED_FOR_DEBUG(size);
+ ei_assert(size == this->size());
+ }
+
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
+};
+
+/** Constructor copying an existing array of data.
+ * Only for fixed-size matrices and vectors.
+ * \param data The array of data to copy
+ *
+ * \sa Matrix::Map(const Scalar *)
+ */
+template<typename _Scalar, int _Rows, int _Cols, int _StorageOrder, int _MaxRows, int _MaxCols>
+inline Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols>
+ ::Matrix(const Scalar *data)
+{
+ _set_noalias(Eigen::Map<Matrix>(data));
+}
+
+#endif // EIGEN_MAP_H
diff --git a/extern/Eigen2/Eigen/src/Core/MapBase.h b/extern/Eigen2/Eigen/src/Core/MapBase.h
new file mode 100644
index 00000000000..c923bc34034
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/MapBase.h
@@ -0,0 +1,202 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_MAPBASE_H
+#define EIGEN_MAPBASE_H
+
+/** \class MapBase
+ *
+ * \brief Base class for Map and Block expression with direct access
+ *
+ * Expression classes inheriting MapBase must define the constant \c PacketAccess,
+ * and type \c AlignedDerivedType in their respective ei_traits<> specialization structure.
+ * The value of \c PacketAccess can be either:
+ * - \b ForceAligned which enforces both aligned loads and stores
+ * - \b AsRequested which is the default behavior
+ * The type \c AlignedDerivedType should correspond to the equivalent expression type
+ * with \c PacketAccess being \c ForceAligned.
+ *
+ * \sa class Map, class Block
+ */
+template<typename Derived> class MapBase
+ : public MatrixBase<Derived>
+{
+ public:
+
+ typedef MatrixBase<Derived> Base;
+ enum {
+ IsRowMajor = (int(ei_traits<Derived>::Flags) & RowMajorBit) ? 1 : 0,
+ PacketAccess = ei_traits<Derived>::PacketAccess,
+ RowsAtCompileTime = ei_traits<Derived>::RowsAtCompileTime,
+ ColsAtCompileTime = ei_traits<Derived>::ColsAtCompileTime,
+ SizeAtCompileTime = Base::SizeAtCompileTime
+ };
+
+ typedef typename ei_traits<Derived>::AlignedDerivedType AlignedDerivedType;
+ typedef typename ei_traits<Derived>::Scalar Scalar;
+ typedef typename Base::PacketScalar PacketScalar;
+ using Base::derived;
+
+ inline int rows() const { return m_rows.value(); }
+ inline int cols() const { return m_cols.value(); }
+
+ inline int stride() const { return derived().stride(); }
+ inline const Scalar* data() const { return m_data; }
+
+ template<bool IsForceAligned,typename Dummy> struct force_aligned_impl {
+ AlignedDerivedType static run(MapBase& a) { return a.derived(); }
+ };
+
+ template<typename Dummy> struct force_aligned_impl<false,Dummy> {
+ AlignedDerivedType static run(MapBase& a) { return a.derived()._convertToForceAligned(); }
+ };
+
+ /** \returns an expression equivalent to \c *this but having the \c PacketAccess constant
+ * set to \c ForceAligned. Must be reimplemented by the derived class. */
+ AlignedDerivedType forceAligned()
+ {
+ return force_aligned_impl<int(PacketAccess)==int(ForceAligned),Derived>::run(*this);
+ }
+
+ inline const Scalar& coeff(int row, int col) const
+ {
+ if(IsRowMajor)
+ return m_data[col + row * stride()];
+ else // column-major
+ return m_data[row + col * stride()];
+ }
+
+ inline Scalar& coeffRef(int row, int col)
+ {
+ if(IsRowMajor)
+ return const_cast<Scalar*>(m_data)[col + row * stride()];
+ else // column-major
+ return const_cast<Scalar*>(m_data)[row + col * stride()];
+ }
+
+ inline const Scalar coeff(int index) const
+ {
+ ei_assert(Derived::IsVectorAtCompileTime || (ei_traits<Derived>::Flags & LinearAccessBit));
+ if ( ((RowsAtCompileTime == 1) == IsRowMajor) )
+ return m_data[index];
+ else
+ return m_data[index*stride()];
+ }
+
+ inline Scalar& coeffRef(int index)
+ {
+ ei_assert(Derived::IsVectorAtCompileTime || (ei_traits<Derived>::Flags & LinearAccessBit));
+ if ( ((RowsAtCompileTime == 1) == IsRowMajor) )
+ return const_cast<Scalar*>(m_data)[index];
+ else
+ return const_cast<Scalar*>(m_data)[index*stride()];
+ }
+
+ template<int LoadMode>
+ inline PacketScalar packet(int row, int col) const
+ {
+ return ei_ploadt<Scalar, int(PacketAccess) == ForceAligned ? Aligned : LoadMode>
+ (m_data + (IsRowMajor ? col + row * stride()
+ : row + col * stride()));
+ }
+
+ template<int LoadMode>
+ inline PacketScalar packet(int index) const
+ {
+ return ei_ploadt<Scalar, int(PacketAccess) == ForceAligned ? Aligned : LoadMode>(m_data + index);
+ }
+
+ template<int StoreMode>
+ inline void writePacket(int row, int col, const PacketScalar& x)
+ {
+ ei_pstoret<Scalar, PacketScalar, int(PacketAccess) == ForceAligned ? Aligned : StoreMode>
+ (const_cast<Scalar*>(m_data) + (IsRowMajor ? col + row * stride()
+ : row + col * stride()), x);
+ }
+
+ template<int StoreMode>
+ inline void writePacket(int index, const PacketScalar& x)
+ {
+ ei_pstoret<Scalar, PacketScalar, int(PacketAccess) == ForceAligned ? Aligned : StoreMode>
+ (const_cast<Scalar*>(m_data) + index, x);
+ }
+
+ inline MapBase(const Scalar* data) : m_data(data), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
+ {
+ EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
+ }
+
+ inline MapBase(const Scalar* data, int size)
+ : m_data(data),
+ m_rows(RowsAtCompileTime == Dynamic ? size : RowsAtCompileTime),
+ m_cols(ColsAtCompileTime == Dynamic ? size : ColsAtCompileTime)
+ {
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ ei_assert(size > 0 || data == 0);
+ ei_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
+ }
+
+ inline MapBase(const Scalar* data, int rows, int cols)
+ : m_data(data), m_rows(rows), m_cols(cols)
+ {
+ ei_assert( (data == 0)
+ || ( rows > 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
+ && cols > 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)));
+ }
+
+ Derived& operator=(const MapBase& other)
+ {
+ return Base::operator=(other);
+ }
+
+ template<typename OtherDerived>
+ Derived& operator=(const MatrixBase<OtherDerived>& other)
+ {
+ return Base::operator=(other);
+ }
+
+ using Base::operator*=;
+
+ template<typename OtherDerived>
+ Derived& operator+=(const MatrixBase<OtherDerived>& other)
+ { return derived() = forceAligned() + other; }
+
+ template<typename OtherDerived>
+ Derived& operator-=(const MatrixBase<OtherDerived>& other)
+ { return derived() = forceAligned() - other; }
+
+ Derived& operator*=(const Scalar& other)
+ { return derived() = forceAligned() * other; }
+
+ Derived& operator/=(const Scalar& other)
+ { return derived() = forceAligned() / other; }
+
+ protected:
+ const Scalar* EIGEN_RESTRICT m_data;
+ const ei_int_if_dynamic<RowsAtCompileTime> m_rows;
+ const ei_int_if_dynamic<ColsAtCompileTime> m_cols;
+};
+
+#endif // EIGEN_MAPBASE_H
diff --git a/extern/Eigen2/Eigen/src/Core/MathFunctions.h b/extern/Eigen2/Eigen/src/Core/MathFunctions.h
new file mode 100644
index 00000000000..1ee64af02c6
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/MathFunctions.h
@@ -0,0 +1,295 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_MATHFUNCTIONS_H
+#define EIGEN_MATHFUNCTIONS_H
+
+template<typename T> inline typename NumTraits<T>::Real precision();
+template<typename T> inline typename NumTraits<T>::Real machine_epsilon();
+template<typename T> inline T ei_random(T a, T b);
+template<typename T> inline T ei_random();
+template<typename T> inline T ei_random_amplitude()
+{
+ if(NumTraits<T>::HasFloatingPoint) return static_cast<T>(1);
+ else return static_cast<T>(10);
+}
+
+template<typename T> inline T ei_hypot(T x, T y)
+{
+ T _x = ei_abs(x);
+ T _y = ei_abs(y);
+ T p = std::max(_x, _y);
+ T q = std::min(_x, _y);
+ T qp = q/p;
+ return p * ei_sqrt(T(1) + qp*qp);
+}
+
+/**************
+*** int ***
+**************/
+
+template<> inline int precision<int>() { return 0; }
+template<> inline int machine_epsilon<int>() { return 0; }
+inline int ei_real(int x) { return x; }
+inline int ei_imag(int) { return 0; }
+inline int ei_conj(int x) { return x; }
+inline int ei_abs(int x) { return abs(x); }
+inline int ei_abs2(int x) { return x*x; }
+inline int ei_sqrt(int) { ei_assert(false); return 0; }
+inline int ei_exp(int) { ei_assert(false); return 0; }
+inline int ei_log(int) { ei_assert(false); return 0; }
+inline int ei_sin(int) { ei_assert(false); return 0; }
+inline int ei_cos(int) { ei_assert(false); return 0; }
+inline int ei_atan2(int, int) { ei_assert(false); return 0; }
+inline int ei_pow(int x, int y) { return int(std::pow(double(x), y)); }
+
+template<> inline int ei_random(int a, int b)
+{
+ // We can't just do rand()%n as only the high-order bits are really random
+ return a + static_cast<int>((b-a+1) * (rand() / (RAND_MAX + 1.0)));
+}
+template<> inline int ei_random()
+{
+ return ei_random<int>(-ei_random_amplitude<int>(), ei_random_amplitude<int>());
+}
+inline bool ei_isMuchSmallerThan(int a, int, int = precision<int>())
+{
+ return a == 0;
+}
+inline bool ei_isApprox(int a, int b, int = precision<int>())
+{
+ return a == b;
+}
+inline bool ei_isApproxOrLessThan(int a, int b, int = precision<int>())
+{
+ return a <= b;
+}
+
+/**************
+*** float ***
+**************/
+
+template<> inline float precision<float>() { return 1e-5f; }
+template<> inline float machine_epsilon<float>() { return 1.192e-07f; }
+inline float ei_real(float x) { return x; }
+inline float ei_imag(float) { return 0.f; }
+inline float ei_conj(float x) { return x; }
+inline float ei_abs(float x) { return std::abs(x); }
+inline float ei_abs2(float x) { return x*x; }
+inline float ei_sqrt(float x) { return std::sqrt(x); }
+inline float ei_exp(float x) { return std::exp(x); }
+inline float ei_log(float x) { return std::log(x); }
+inline float ei_sin(float x) { return std::sin(x); }
+inline float ei_cos(float x) { return std::cos(x); }
+inline float ei_atan2(float y, float x) { return std::atan2(y,x); }
+inline float ei_pow(float x, float y) { return std::pow(x, y); }
+
+template<> inline float ei_random(float a, float b)
+{
+#ifdef EIGEN_NICE_RANDOM
+ int i;
+ do { i = ei_random<int>(256*int(a),256*int(b));
+ } while(i==0);
+ return float(i)/256.f;
+#else
+ return a + (b-a) * float(std::rand()) / float(RAND_MAX);
+#endif
+}
+template<> inline float ei_random()
+{
+ return ei_random<float>(-ei_random_amplitude<float>(), ei_random_amplitude<float>());
+}
+inline bool ei_isMuchSmallerThan(float a, float b, float prec = precision<float>())
+{
+ return ei_abs(a) <= ei_abs(b) * prec;
+}
+inline bool ei_isApprox(float a, float b, float prec = precision<float>())
+{
+ return ei_abs(a - b) <= std::min(ei_abs(a), ei_abs(b)) * prec;
+}
+inline bool ei_isApproxOrLessThan(float a, float b, float prec = precision<float>())
+{
+ return a <= b || ei_isApprox(a, b, prec);
+}
+
+/**************
+*** double ***
+**************/
+
+template<> inline double precision<double>() { return 1e-11; }
+template<> inline double machine_epsilon<double>() { return 2.220e-16; }
+
+inline double ei_real(double x) { return x; }
+inline double ei_imag(double) { return 0.; }
+inline double ei_conj(double x) { return x; }
+inline double ei_abs(double x) { return std::abs(x); }
+inline double ei_abs2(double x) { return x*x; }
+inline double ei_sqrt(double x) { return std::sqrt(x); }
+inline double ei_exp(double x) { return std::exp(x); }
+inline double ei_log(double x) { return std::log(x); }
+inline double ei_sin(double x) { return std::sin(x); }
+inline double ei_cos(double x) { return std::cos(x); }
+inline double ei_atan2(double y, double x) { return std::atan2(y,x); }
+inline double ei_pow(double x, double y) { return std::pow(x, y); }
+
+template<> inline double ei_random(double a, double b)
+{
+#ifdef EIGEN_NICE_RANDOM
+ int i;
+ do { i= ei_random<int>(256*int(a),256*int(b));
+ } while(i==0);
+ return i/256.;
+#else
+ return a + (b-a) * std::rand() / RAND_MAX;
+#endif
+}
+template<> inline double ei_random()
+{
+ return ei_random<double>(-ei_random_amplitude<double>(), ei_random_amplitude<double>());
+}
+inline bool ei_isMuchSmallerThan(double a, double b, double prec = precision<double>())
+{
+ return ei_abs(a) <= ei_abs(b) * prec;
+}
+inline bool ei_isApprox(double a, double b, double prec = precision<double>())
+{
+ return ei_abs(a - b) <= std::min(ei_abs(a), ei_abs(b)) * prec;
+}
+inline bool ei_isApproxOrLessThan(double a, double b, double prec = precision<double>())
+{
+ return a <= b || ei_isApprox(a, b, prec);
+}
+
+/*********************
+*** complex<float> ***
+*********************/
+
+template<> inline float precision<std::complex<float> >() { return precision<float>(); }
+template<> inline float machine_epsilon<std::complex<float> >() { return machine_epsilon<float>(); }
+inline float ei_real(const std::complex<float>& x) { return std::real(x); }
+inline float ei_imag(const std::complex<float>& x) { return std::imag(x); }
+inline std::complex<float> ei_conj(const std::complex<float>& x) { return std::conj(x); }
+inline float ei_abs(const std::complex<float>& x) { return std::abs(x); }
+inline float ei_abs2(const std::complex<float>& x) { return std::norm(x); }
+inline std::complex<float> ei_exp(std::complex<float> x) { return std::exp(x); }
+inline std::complex<float> ei_sin(std::complex<float> x) { return std::sin(x); }
+inline std::complex<float> ei_cos(std::complex<float> x) { return std::cos(x); }
+inline std::complex<float> ei_atan2(std::complex<float>, std::complex<float> ) { ei_assert(false); return 0; }
+
+template<> inline std::complex<float> ei_random()
+{
+ return std::complex<float>(ei_random<float>(), ei_random<float>());
+}
+inline bool ei_isMuchSmallerThan(const std::complex<float>& a, const std::complex<float>& b, float prec = precision<float>())
+{
+ return ei_abs2(a) <= ei_abs2(b) * prec * prec;
+}
+inline bool ei_isMuchSmallerThan(const std::complex<float>& a, float b, float prec = precision<float>())
+{
+ return ei_abs2(a) <= ei_abs2(b) * prec * prec;
+}
+inline bool ei_isApprox(const std::complex<float>& a, const std::complex<float>& b, float prec = precision<float>())
+{
+ return ei_isApprox(ei_real(a), ei_real(b), prec)
+ && ei_isApprox(ei_imag(a), ei_imag(b), prec);
+}
+// ei_isApproxOrLessThan wouldn't make sense for complex numbers
+
+/**********************
+*** complex<double> ***
+**********************/
+
+template<> inline double precision<std::complex<double> >() { return precision<double>(); }
+template<> inline double machine_epsilon<std::complex<double> >() { return machine_epsilon<double>(); }
+inline double ei_real(const std::complex<double>& x) { return std::real(x); }
+inline double ei_imag(const std::complex<double>& x) { return std::imag(x); }
+inline std::complex<double> ei_conj(const std::complex<double>& x) { return std::conj(x); }
+inline double ei_abs(const std::complex<double>& x) { return std::abs(x); }
+inline double ei_abs2(const std::complex<double>& x) { return std::norm(x); }
+inline std::complex<double> ei_exp(std::complex<double> x) { return std::exp(x); }
+inline std::complex<double> ei_sin(std::complex<double> x) { return std::sin(x); }
+inline std::complex<double> ei_cos(std::complex<double> x) { return std::cos(x); }
+inline std::complex<double> ei_atan2(std::complex<double>, std::complex<double>) { ei_assert(false); return 0; }
+
+template<> inline std::complex<double> ei_random()
+{
+ return std::complex<double>(ei_random<double>(), ei_random<double>());
+}
+inline bool ei_isMuchSmallerThan(const std::complex<double>& a, const std::complex<double>& b, double prec = precision<double>())
+{
+ return ei_abs2(a) <= ei_abs2(b) * prec * prec;
+}
+inline bool ei_isMuchSmallerThan(const std::complex<double>& a, double b, double prec = precision<double>())
+{
+ return ei_abs2(a) <= ei_abs2(b) * prec * prec;
+}
+inline bool ei_isApprox(const std::complex<double>& a, const std::complex<double>& b, double prec = precision<double>())
+{
+ return ei_isApprox(ei_real(a), ei_real(b), prec)
+ && ei_isApprox(ei_imag(a), ei_imag(b), prec);
+}
+// ei_isApproxOrLessThan wouldn't make sense for complex numbers
+
+
+/******************
+*** long double ***
+******************/
+
+template<> inline long double precision<long double>() { return precision<double>(); }
+template<> inline long double machine_epsilon<long double>() { return 1.084e-19l; }
+inline long double ei_real(long double x) { return x; }
+inline long double ei_imag(long double) { return 0.; }
+inline long double ei_conj(long double x) { return x; }
+inline long double ei_abs(long double x) { return std::abs(x); }
+inline long double ei_abs2(long double x) { return x*x; }
+inline long double ei_sqrt(long double x) { return std::sqrt(x); }
+inline long double ei_exp(long double x) { return std::exp(x); }
+inline long double ei_log(long double x) { return std::log(x); }
+inline long double ei_sin(long double x) { return std::sin(x); }
+inline long double ei_cos(long double x) { return std::cos(x); }
+inline long double ei_atan2(long double y, long double x) { return std::atan2(y,x); }
+inline long double ei_pow(long double x, long double y) { return std::pow(x, y); }
+
+template<> inline long double ei_random(long double a, long double b)
+{
+ return ei_random<double>(static_cast<double>(a),static_cast<double>(b));
+}
+template<> inline long double ei_random()
+{
+ return ei_random<double>(-ei_random_amplitude<double>(), ei_random_amplitude<double>());
+}
+inline bool ei_isMuchSmallerThan(long double a, long double b, long double prec = precision<long double>())
+{
+ return ei_abs(a) <= ei_abs(b) * prec;
+}
+inline bool ei_isApprox(long double a, long double b, long double prec = precision<long double>())
+{
+ return ei_abs(a - b) <= std::min(ei_abs(a), ei_abs(b)) * prec;
+}
+inline bool ei_isApproxOrLessThan(long double a, long double b, long double prec = precision<long double>())
+{
+ return a <= b || ei_isApprox(a, b, prec);
+}
+
+#endif // EIGEN_MATHFUNCTIONS_H
diff --git a/extern/Eigen2/Eigen/src/Core/Matrix.h b/extern/Eigen2/Eigen/src/Core/Matrix.h
new file mode 100644
index 00000000000..22090c777da
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/Matrix.h
@@ -0,0 +1,639 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_MATRIX_H
+#define EIGEN_MATRIX_H
+
+
+/** \class Matrix
+ *
+ * \brief The matrix class, also used for vectors and row-vectors
+ *
+ * The %Matrix class is the work-horse for all \em dense (\ref dense "note") matrices and vectors within Eigen.
+ * Vectors are matrices with one column, and row-vectors are matrices with one row.
+ *
+ * The %Matrix class encompasses \em both fixed-size and dynamic-size objects (\ref fixedsize "note").
+ *
+ * The first three template parameters are required:
+ * \param _Scalar Numeric type, i.e. float, double, int
+ * \param _Rows Number of rows, or \b Dynamic
+ * \param _Cols Number of columns, or \b Dynamic
+ *
+ * The remaining template parameters are optional -- in most cases you don't have to worry about them.
+ * \param _Options A combination of either \b RowMajor or \b ColMajor, and of either
+ * \b AutoAlign or \b DontAlign.
+ * The former controls storage order, and defaults to column-major. The latter controls alignment, which is required
+ * for vectorization. It defaults to aligning matrices except for fixed sizes that aren't a multiple of the packet size.
+ * \param _MaxRows Maximum number of rows. Defaults to \a _Rows (\ref maxrows "note").
+ * \param _MaxCols Maximum number of columns. Defaults to \a _Cols (\ref maxrows "note").
+ *
+ * Eigen provides a number of typedefs covering the usual cases. Here are some examples:
+ *
+ * \li \c Matrix2d is a 2x2 square matrix of doubles (\c Matrix<double, 2, 2>)
+ * \li \c Vector4f is a vector of 4 floats (\c Matrix<float, 4, 1>)
+ * \li \c RowVector3i is a row-vector of 3 ints (\c Matrix<int, 1, 3>)
+ *
+ * \li \c MatrixXf is a dynamic-size matrix of floats (\c Matrix<float, Dynamic, Dynamic>)
+ * \li \c VectorXf is a dynamic-size vector of floats (\c Matrix<float, Dynamic, 1>)
+ *
+ * See \link matrixtypedefs this page \endlink for a complete list of predefined \em %Matrix and \em Vector typedefs.
+ *
+ * You can access elements of vectors and matrices using normal subscripting:
+ *
+ * \code
+ * Eigen::VectorXd v(10);
+ * v[0] = 0.1;
+ * v[1] = 0.2;
+ * v(0) = 0.3;
+ * v(1) = 0.4;
+ *
+ * Eigen::MatrixXi m(10, 10);
+ * m(0, 1) = 1;
+ * m(0, 2) = 2;
+ * m(0, 3) = 3;
+ * \endcode
+ *
+ * <i><b>Some notes:</b></i>
+ *
+ * <dl>
+ * <dt><b>\anchor dense Dense versus sparse:</b></dt>
+ * <dd>This %Matrix class handles dense, not sparse matrices and vectors. For sparse matrices and vectors, see the Sparse module.
+ *
+ * Dense matrices and vectors are plain usual arrays of coefficients. All the coefficients are stored, in an ordinary contiguous array.
+ * This is unlike Sparse matrices and vectors where the coefficients are stored as a list of nonzero coefficients.</dd>
+ *
+ * <dt><b>\anchor fixedsize Fixed-size versus dynamic-size:</b></dt>
+ * <dd>Fixed-size means that the numbers of rows and columns are known are compile-time. In this case, Eigen allocates the array
+ * of coefficients as a fixed-size array, as a class member. This makes sense for very small matrices, typically up to 4x4, sometimes up
+ * to 16x16. Larger matrices should be declared as dynamic-size even if one happens to know their size at compile-time.
+ *
+ * Dynamic-size means that the numbers of rows or columns are not necessarily known at compile-time. In this case they are runtime
+ * variables, and the array of coefficients is allocated dynamically on the heap.
+ *
+ * Note that \em dense matrices, be they Fixed-size or Dynamic-size, <em>do not</em> expand dynamically in the sense of a std::map.
+ * If you want this behavior, see the Sparse module.</dd>
+ *
+ * <dt><b>\anchor maxrows _MaxRows and _MaxCols:</b></dt>
+ * <dd>In most cases, one just leaves these parameters to the default values.
+ * These parameters mean the maximum size of rows and columns that the matrix may have. They are useful in cases
+ * when the exact numbers of rows and columns are not known are compile-time, but it is known at compile-time that they cannot
+ * exceed a certain value. This happens when taking dynamic-size blocks inside fixed-size matrices: in this case _MaxRows and _MaxCols
+ * are the dimensions of the original matrix, while _Rows and _Cols are Dynamic.</dd>
+ * </dl>
+ *
+ * \see MatrixBase for the majority of the API methods for matrices
+ */
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+struct ei_traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
+{
+ typedef _Scalar Scalar;
+ enum {
+ RowsAtCompileTime = _Rows,
+ ColsAtCompileTime = _Cols,
+ MaxRowsAtCompileTime = _MaxRows,
+ MaxColsAtCompileTime = _MaxCols,
+ Flags = ei_compute_matrix_flags<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::ret,
+ CoeffReadCost = NumTraits<Scalar>::ReadCost
+ };
+};
+
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+class Matrix
+ : public MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
+{
+ public:
+ EIGEN_GENERIC_PUBLIC_INTERFACE(Matrix)
+ enum { Options = _Options };
+ friend class Eigen::Map<Matrix, Unaligned>;
+ typedef class Eigen::Map<Matrix, Unaligned> UnalignedMapType;
+ friend class Eigen::Map<Matrix, Aligned>;
+ typedef class Eigen::Map<Matrix, Aligned> AlignedMapType;
+
+ protected:
+ ei_matrix_storage<Scalar, MaxSizeAtCompileTime, RowsAtCompileTime, ColsAtCompileTime, Options> m_storage;
+
+ public:
+ enum { NeedsToAlign = (Options&AutoAlign) == AutoAlign
+ && SizeAtCompileTime!=Dynamic && ((sizeof(Scalar)*SizeAtCompileTime)%16)==0 };
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
+
+ Base& base() { return *static_cast<Base*>(this); }
+ const Base& base() const { return *static_cast<const Base*>(this); }
+
+ EIGEN_STRONG_INLINE int rows() const { return m_storage.rows(); }
+ EIGEN_STRONG_INLINE int cols() const { return m_storage.cols(); }
+
+ EIGEN_STRONG_INLINE int stride(void) const
+ {
+ if(Flags & RowMajorBit)
+ return m_storage.cols();
+ else
+ return m_storage.rows();
+ }
+
+ EIGEN_STRONG_INLINE const Scalar& coeff(int row, int col) const
+ {
+ if(Flags & RowMajorBit)
+ return m_storage.data()[col + row * m_storage.cols()];
+ else // column-major
+ return m_storage.data()[row + col * m_storage.rows()];
+ }
+
+ EIGEN_STRONG_INLINE const Scalar& coeff(int index) const
+ {
+ return m_storage.data()[index];
+ }
+
+ EIGEN_STRONG_INLINE Scalar& coeffRef(int row, int col)
+ {
+ if(Flags & RowMajorBit)
+ return m_storage.data()[col + row * m_storage.cols()];
+ else // column-major
+ return m_storage.data()[row + col * m_storage.rows()];
+ }
+
+ EIGEN_STRONG_INLINE Scalar& coeffRef(int index)
+ {
+ return m_storage.data()[index];
+ }
+
+ template<int LoadMode>
+ EIGEN_STRONG_INLINE PacketScalar packet(int row, int col) const
+ {
+ return ei_ploadt<Scalar, LoadMode>
+ (m_storage.data() + (Flags & RowMajorBit
+ ? col + row * m_storage.cols()
+ : row + col * m_storage.rows()));
+ }
+
+ template<int LoadMode>
+ EIGEN_STRONG_INLINE PacketScalar packet(int index) const
+ {
+ return ei_ploadt<Scalar, LoadMode>(m_storage.data() + index);
+ }
+
+ template<int StoreMode>
+ EIGEN_STRONG_INLINE void writePacket(int row, int col, const PacketScalar& x)
+ {
+ ei_pstoret<Scalar, PacketScalar, StoreMode>
+ (m_storage.data() + (Flags & RowMajorBit
+ ? col + row * m_storage.cols()
+ : row + col * m_storage.rows()), x);
+ }
+
+ template<int StoreMode>
+ EIGEN_STRONG_INLINE void writePacket(int index, const PacketScalar& x)
+ {
+ ei_pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, x);
+ }
+
+ /** \returns a const pointer to the data array of this matrix */
+ EIGEN_STRONG_INLINE const Scalar *data() const
+ { return m_storage.data(); }
+
+ /** \returns a pointer to the data array of this matrix */
+ EIGEN_STRONG_INLINE Scalar *data()
+ { return m_storage.data(); }
+
+ /** Resizes \c *this to a \a rows x \a cols matrix.
+ *
+ * Makes sense for dynamic-size matrices only.
+ *
+ * If the current number of coefficients of \c *this exactly matches the
+ * product \a rows * \a cols, then no memory allocation is performed and
+ * the current values are left unchanged. In all other cases, including
+ * shrinking, the data is reallocated and all previous values are lost.
+ *
+ * \sa resize(int) for vectors.
+ */
+ inline void resize(int rows, int cols)
+ {
+ ei_assert((MaxRowsAtCompileTime == Dynamic || MaxRowsAtCompileTime >= rows)
+ && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
+ && (MaxColsAtCompileTime == Dynamic || MaxColsAtCompileTime >= cols)
+ && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
+ m_storage.resize(rows * cols, rows, cols);
+ }
+
+ /** Resizes \c *this to a vector of length \a size
+ *
+ * \sa resize(int,int) for the details.
+ */
+ inline void resize(int size)
+ {
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
+ if(RowsAtCompileTime == 1)
+ m_storage.resize(size, 1, size);
+ else
+ m_storage.resize(size, size, 1);
+ }
+
+ /** Copies the value of the expression \a other into \c *this with automatic resizing.
+ *
+ * *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized),
+ * it will be initialized.
+ *
+ * Note that copying a row-vector into a vector (and conversely) is allowed.
+ * The resizing, if any, is then done in the appropriate way so that row-vectors
+ * remain row-vectors and vectors remain vectors.
+ */
+ template<typename OtherDerived>
+ EIGEN_STRONG_INLINE Matrix& operator=(const MatrixBase<OtherDerived>& other)
+ {
+ return _set(other);
+ }
+
+ /** This is a special case of the templated operator=. Its purpose is to
+ * prevent a default operator= from hiding the templated operator=.
+ */
+ EIGEN_STRONG_INLINE Matrix& operator=(const Matrix& other)
+ {
+ return _set(other);
+ }
+
+ EIGEN_INHERIT_ASSIGNMENT_OPERATOR(Matrix, +=)
+ EIGEN_INHERIT_ASSIGNMENT_OPERATOR(Matrix, -=)
+ EIGEN_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Matrix, *=)
+ EIGEN_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Matrix, /=)
+
+ /** Default constructor.
+ *
+ * For fixed-size matrices, does nothing.
+ *
+ * For dynamic-size matrices, creates an empty matrix of size 0. Does not allocate any array. Such a matrix
+ * is called a null matrix. This constructor is the unique way to create null matrices: resizing
+ * a matrix to 0 is not supported.
+ *
+ * \sa resize(int,int)
+ */
+ EIGEN_STRONG_INLINE explicit Matrix() : m_storage()
+ {
+ _check_template_params();
+ }
+
+#ifndef EIGEN_PARSED_BY_DOXYGEN
+ /** \internal */
+ Matrix(ei_constructor_without_unaligned_array_assert)
+ : m_storage(ei_constructor_without_unaligned_array_assert())
+ {}
+#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,
+ * it is redundant to pass the dimension here, so it makes more sense to use the default
+ * constructor Matrix() instead.
+ */
+ EIGEN_STRONG_INLINE explicit Matrix(int dim)
+ : m_storage(dim, RowsAtCompileTime == 1 ? 1 : dim, ColsAtCompileTime == 1 ? 1 : dim)
+ {
+ _check_template_params();
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
+ ei_assert(dim > 0);
+ ei_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == dim);
+ }
+
+ /** This constructor has two very different behaviors, depending on the type of *this.
+ *
+ * \li When Matrix is a fixed-size vector type of size 2, this constructor constructs
+ * an initialized vector. The parameters \a x, \a y are copied into the first and second
+ * coords of the vector respectively.
+ * \li Otherwise, this constructor constructs an uninitialized matrix with \a x rows and
+ * \a y columns. This is useful for dynamic-size matrices. For fixed-size matrices,
+ * it is redundant to pass these parameters, so one should use the default constructor
+ * Matrix() instead.
+ */
+ EIGEN_STRONG_INLINE Matrix(int x, int y) : m_storage(x*y, x, y)
+ {
+ _check_template_params();
+ if((RowsAtCompileTime == 1 && ColsAtCompileTime == 2)
+ || (RowsAtCompileTime == 2 && ColsAtCompileTime == 1))
+ {
+ m_storage.data()[0] = Scalar(x);
+ m_storage.data()[1] = Scalar(y);
+ }
+ else
+ {
+ ei_assert(x > 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == x)
+ && y > 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == y));
+ }
+ }
+ /** constructs an initialized 2D vector with given coefficients */
+ EIGEN_STRONG_INLINE Matrix(const float& x, const float& y)
+ {
+ _check_template_params();
+ EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 2)
+ m_storage.data()[0] = x;
+ m_storage.data()[1] = y;
+ }
+ /** constructs an initialized 2D vector with given coefficients */
+ EIGEN_STRONG_INLINE Matrix(const double& x, const double& y)
+ {
+ _check_template_params();
+ EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 2)
+ m_storage.data()[0] = x;
+ m_storage.data()[1] = y;
+ }
+ /** constructs an initialized 3D vector with given coefficients */
+ EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z)
+ {
+ _check_template_params();
+ EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 3)
+ m_storage.data()[0] = x;
+ m_storage.data()[1] = y;
+ m_storage.data()[2] = z;
+ }
+ /** constructs an initialized 4D vector with given coefficients */
+ EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w)
+ {
+ _check_template_params();
+ EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 4)
+ m_storage.data()[0] = x;
+ m_storage.data()[1] = y;
+ m_storage.data()[2] = z;
+ m_storage.data()[3] = w;
+ }
+
+ explicit Matrix(const Scalar *data);
+
+ /** Constructor copying the value of the expression \a other */
+ template<typename OtherDerived>
+ EIGEN_STRONG_INLINE Matrix(const MatrixBase<OtherDerived>& other)
+ : m_storage(other.rows() * other.cols(), other.rows(), other.cols())
+ {
+ _check_template_params();
+ _set_noalias(other);
+ }
+ /** Copy constructor */
+ EIGEN_STRONG_INLINE Matrix(const Matrix& other)
+ : Base(), m_storage(other.rows() * other.cols(), other.rows(), other.cols())
+ {
+ _check_template_params();
+ _set_noalias(other);
+ }
+ /** Destructor */
+ inline ~Matrix() {}
+
+ /** Override MatrixBase::swap() since for dynamic-sized matrices of same type it is enough to swap the
+ * data pointers.
+ */
+ template<typename OtherDerived>
+ void swap(const MatrixBase<OtherDerived>& other);
+
+ /** \name Map
+ * These are convenience functions returning Map objects. The Map() static functions return unaligned Map objects,
+ * while the AlignedMap() functions return aligned Map objects and thus should be called only with 16-byte-aligned
+ * \a data pointers.
+ *
+ * \see class Map
+ */
+ //@{
+ inline static const UnalignedMapType Map(const Scalar* data)
+ { return UnalignedMapType(data); }
+ inline static UnalignedMapType Map(Scalar* data)
+ { return UnalignedMapType(data); }
+ inline static const UnalignedMapType Map(const Scalar* data, int size)
+ { return UnalignedMapType(data, size); }
+ inline static UnalignedMapType Map(Scalar* data, int size)
+ { return UnalignedMapType(data, size); }
+ inline static const UnalignedMapType Map(const Scalar* data, int rows, int cols)
+ { return UnalignedMapType(data, rows, cols); }
+ inline static UnalignedMapType Map(Scalar* data, int rows, int cols)
+ { return UnalignedMapType(data, rows, cols); }
+
+ inline static const AlignedMapType MapAligned(const Scalar* data)
+ { return AlignedMapType(data); }
+ inline static AlignedMapType MapAligned(Scalar* data)
+ { return AlignedMapType(data); }
+ inline static const AlignedMapType MapAligned(const Scalar* data, int size)
+ { return AlignedMapType(data, size); }
+ inline static AlignedMapType MapAligned(Scalar* data, int size)
+ { return AlignedMapType(data, size); }
+ inline static const AlignedMapType MapAligned(const Scalar* data, int rows, int cols)
+ { return AlignedMapType(data, rows, cols); }
+ inline static AlignedMapType MapAligned(Scalar* data, int rows, int cols)
+ { return AlignedMapType(data, rows, cols); }
+ //@}
+
+ using Base::setConstant;
+ Matrix& setConstant(int size, const Scalar& value);
+ Matrix& setConstant(int rows, int cols, const Scalar& value);
+
+ using Base::setZero;
+ Matrix& setZero(int size);
+ Matrix& setZero(int rows, int cols);
+
+ using Base::setOnes;
+ Matrix& setOnes(int size);
+ Matrix& setOnes(int rows, int cols);
+
+ using Base::setRandom;
+ Matrix& setRandom(int size);
+ Matrix& setRandom(int rows, int cols);
+
+ using Base::setIdentity;
+ Matrix& setIdentity(int rows, int cols);
+
+/////////// Geometry module ///////////
+
+ template<typename OtherDerived>
+ explicit Matrix(const RotationBase<OtherDerived,ColsAtCompileTime>& r);
+ template<typename OtherDerived>
+ Matrix& operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r);
+
+ // allow to extend Matrix outside Eigen
+ #ifdef EIGEN_MATRIX_PLUGIN
+ #include EIGEN_MATRIX_PLUGIN
+ #endif
+
+ private:
+ /** \internal Resizes *this in preparation for assigning \a other to it.
+ * Takes care of doing all the checking that's needed.
+ *
+ * Note that copying a row-vector into a vector (and conversely) is allowed.
+ * The resizing, if any, is then done in the appropriate way so that row-vectors
+ * remain row-vectors and vectors remain vectors.
+ */
+ template<typename OtherDerived>
+ EIGEN_STRONG_INLINE void _resize_to_match(const MatrixBase<OtherDerived>& other)
+ {
+ if(RowsAtCompileTime == 1)
+ {
+ ei_assert(other.isVector());
+ resize(1, other.size());
+ }
+ else if(ColsAtCompileTime == 1)
+ {
+ ei_assert(other.isVector());
+ resize(other.size(), 1);
+ }
+ else resize(other.rows(), other.cols());
+ }
+
+ /** \internal Copies the value of the expression \a other into \c *this with automatic resizing.
+ *
+ * *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized),
+ * it will be initialized.
+ *
+ * Note that copying a row-vector into a vector (and conversely) is allowed.
+ * The resizing, if any, is then done in the appropriate way so that row-vectors
+ * remain row-vectors and vectors remain vectors.
+ *
+ * \sa operator=(const MatrixBase<OtherDerived>&), _set_noalias()
+ */
+ template<typename OtherDerived>
+ EIGEN_STRONG_INLINE Matrix& _set(const MatrixBase<OtherDerived>& other)
+ {
+ // this enum introduced to fix compilation with gcc 3.3
+ enum { cond = int(OtherDerived::Flags) & EvalBeforeAssigningBit };
+ _set_selector(other.derived(), typename ei_meta_if<bool(cond), ei_meta_true, ei_meta_false>::ret());
+ return *this;
+ }
+
+ template<typename OtherDerived>
+ EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const ei_meta_true&) { _set_noalias(other.eval()); }
+
+ template<typename OtherDerived>
+ EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const ei_meta_false&) { _set_noalias(other); }
+
+ /** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which
+ * is the case when creating a new matrix) so one can enforce lazy evaluation.
+ *
+ * \sa operator=(const MatrixBase<OtherDerived>&), _set()
+ */
+ template<typename OtherDerived>
+ EIGEN_STRONG_INLINE Matrix& _set_noalias(const MatrixBase<OtherDerived>& other)
+ {
+ _resize_to_match(other);
+ // the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because
+ // it wouldn't allow to copy a row-vector into a column-vector.
+ return ei_assign_selector<Matrix,OtherDerived,false>::run(*this, other.derived());
+ }
+
+ static EIGEN_STRONG_INLINE void _check_template_params()
+ {
+ EIGEN_STATIC_ASSERT((_Rows > 0
+ && _Cols > 0
+ && _MaxRows <= _Rows
+ && _MaxCols <= _Cols
+ && (_Options & (AutoAlign|RowMajor)) == _Options),
+ INVALID_MATRIX_TEMPLATE_PARAMETERS)
+ }
+
+ template<typename MatrixType, typename OtherDerived, bool IsSameType, bool IsDynamicSize>
+ friend struct ei_matrix_swap_impl;
+};
+
+template<typename MatrixType, typename OtherDerived,
+ bool IsSameType = ei_is_same_type<MatrixType, OtherDerived>::ret,
+ bool IsDynamicSize = MatrixType::SizeAtCompileTime==Dynamic>
+struct ei_matrix_swap_impl
+{
+ static inline void run(MatrixType& matrix, MatrixBase<OtherDerived>& other)
+ {
+ matrix.base().swap(other);
+ }
+};
+
+template<typename MatrixType, typename OtherDerived>
+struct ei_matrix_swap_impl<MatrixType, OtherDerived, true, true>
+{
+ static inline void run(MatrixType& matrix, MatrixBase<OtherDerived>& other)
+ {
+ matrix.m_storage.swap(other.derived().m_storage);
+ }
+};
+
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+template<typename OtherDerived>
+inline void Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::swap(const MatrixBase<OtherDerived>& other)
+{
+ ei_matrix_swap_impl<Matrix, OtherDerived>::run(*this, *const_cast<MatrixBase<OtherDerived>*>(&other));
+}
+
+
+/** \defgroup matrixtypedefs Global matrix typedefs
+ *
+ * \ingroup Core_Module
+ *
+ * Eigen defines several typedef shortcuts for most common matrix and vector types.
+ *
+ * The general patterns are the following:
+ *
+ * \c MatrixSizeType where \c Size can be \c 2,\c 3,\c 4 for fixed size square matrices or \c X for dynamic size,
+ * and where \c Type can be \c i for integer, \c f for float, \c d for double, \c cf for complex float, \c cd
+ * for complex double.
+ *
+ * For example, \c Matrix3d is a fixed-size 3x3 matrix type of doubles, and \c MatrixXf is a dynamic-size matrix of floats.
+ *
+ * There are also \c VectorSizeType and \c RowVectorSizeType which are self-explanatory. For example, \c Vector4cf is
+ * a fixed-size vector of 4 complex floats.
+ *
+ * \sa class Matrix
+ */
+
+#define EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \
+/** \ingroup matrixtypedefs */ \
+typedef Matrix<Type, Size, Size> Matrix##SizeSuffix##TypeSuffix; \
+/** \ingroup matrixtypedefs */ \
+typedef Matrix<Type, Size, 1> Vector##SizeSuffix##TypeSuffix; \
+/** \ingroup matrixtypedefs */ \
+typedef Matrix<Type, 1, Size> RowVector##SizeSuffix##TypeSuffix;
+
+#define EIGEN_MAKE_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \
+EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 2, 2) \
+EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 3, 3) \
+EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 4, 4) \
+EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Dynamic, X)
+
+EIGEN_MAKE_TYPEDEFS_ALL_SIZES(int, i)
+EIGEN_MAKE_TYPEDEFS_ALL_SIZES(float, f)
+EIGEN_MAKE_TYPEDEFS_ALL_SIZES(double, d)
+EIGEN_MAKE_TYPEDEFS_ALL_SIZES(std::complex<float>, cf)
+EIGEN_MAKE_TYPEDEFS_ALL_SIZES(std::complex<double>, cd)
+
+#undef EIGEN_MAKE_TYPEDEFS_ALL_SIZES
+#undef EIGEN_MAKE_TYPEDEFS
+
+#undef EIGEN_MAKE_TYPEDEFS_LARGE
+
+#define EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, SizeSuffix) \
+using Eigen::Matrix##SizeSuffix##TypeSuffix; \
+using Eigen::Vector##SizeSuffix##TypeSuffix; \
+using Eigen::RowVector##SizeSuffix##TypeSuffix;
+
+#define EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(TypeSuffix) \
+EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 2) \
+EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 3) \
+EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 4) \
+EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, X) \
+
+#define EIGEN_USING_MATRIX_TYPEDEFS \
+EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(i) \
+EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(f) \
+EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(d) \
+EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cf) \
+EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cd)
+
+#endif // EIGEN_MATRIX_H
diff --git a/extern/Eigen2/Eigen/src/Core/MatrixBase.h b/extern/Eigen2/Eigen/src/Core/MatrixBase.h
new file mode 100644
index 00000000000..7935a7554ea
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/MatrixBase.h
@@ -0,0 +1,632 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_MATRIXBASE_H
+#define EIGEN_MATRIXBASE_H
+
+/** \class MatrixBase
+ *
+ * \brief Base class for all matrices, vectors, and expressions
+ *
+ * This class is the base that is inherited by all matrix, vector, and expression
+ * types. Most of the Eigen API is contained in this class. Other important classes for
+ * the Eigen API are Matrix, Cwise, and PartialRedux.
+ *
+ * Note that some methods are defined in the \ref Array module.
+ *
+ * \param Derived is the derived type, e.g. a matrix type, or an expression, etc.
+ *
+ * When writing a function taking Eigen objects as argument, if you want your function
+ * to take as argument any matrix, vector, or expression, just let it take a
+ * MatrixBase argument. As an example, here is a function printFirstRow which, given
+ * a matrix, vector, or expression \a x, prints the first row of \a x.
+ *
+ * \code
+ template<typename Derived>
+ void printFirstRow(const Eigen::MatrixBase<Derived>& x)
+ {
+ cout << x.row(0) << endl;
+ }
+ * \endcode
+ *
+ */
+template<typename Derived> class MatrixBase
+{
+ public:
+
+#ifndef EIGEN_PARSED_BY_DOXYGEN
+ class InnerIterator;
+
+ typedef typename ei_traits<Derived>::Scalar Scalar;
+ typedef typename ei_packet_traits<Scalar>::type PacketScalar;
+#endif // not EIGEN_PARSED_BY_DOXYGEN
+
+ enum {
+
+ RowsAtCompileTime = ei_traits<Derived>::RowsAtCompileTime,
+ /**< The number of rows at compile-time. This is just a copy of the value provided
+ * by the \a Derived type. If a value is not known at compile-time,
+ * it is set to the \a Dynamic constant.
+ * \sa MatrixBase::rows(), MatrixBase::cols(), ColsAtCompileTime, SizeAtCompileTime */
+
+ ColsAtCompileTime = ei_traits<Derived>::ColsAtCompileTime,
+ /**< The number of columns at compile-time. This is just a copy of the value provided
+ * by the \a Derived type. If a value is not known at compile-time,
+ * it is set to the \a Dynamic constant.
+ * \sa MatrixBase::rows(), MatrixBase::cols(), RowsAtCompileTime, SizeAtCompileTime */
+
+
+ SizeAtCompileTime = (ei_size_at_compile_time<ei_traits<Derived>::RowsAtCompileTime,
+ ei_traits<Derived>::ColsAtCompileTime>::ret),
+ /**< This is equal to the number of coefficients, i.e. the number of
+ * rows times the number of columns, or to \a Dynamic if this is not
+ * known at compile-time. \sa RowsAtCompileTime, ColsAtCompileTime */
+
+ MaxRowsAtCompileTime = ei_traits<Derived>::MaxRowsAtCompileTime,
+ /**< This value is equal to the maximum possible number of rows that this expression
+ * might have. If this expression might have an arbitrarily high number of rows,
+ * this value is set to \a Dynamic.
+ *
+ * This value is useful to know when evaluating an expression, in order to determine
+ * whether it is possible to avoid doing a dynamic memory allocation.
+ *
+ * \sa RowsAtCompileTime, MaxColsAtCompileTime, MaxSizeAtCompileTime
+ */
+
+ MaxColsAtCompileTime = ei_traits<Derived>::MaxColsAtCompileTime,
+ /**< This value is equal to the maximum possible number of columns that this expression
+ * might have. If this expression might have an arbitrarily high number of columns,
+ * this value is set to \a Dynamic.
+ *
+ * This value is useful to know when evaluating an expression, in order to determine
+ * whether it is possible to avoid doing a dynamic memory allocation.
+ *
+ * \sa ColsAtCompileTime, MaxRowsAtCompileTime, MaxSizeAtCompileTime
+ */
+
+ MaxSizeAtCompileTime = (ei_size_at_compile_time<ei_traits<Derived>::MaxRowsAtCompileTime,
+ ei_traits<Derived>::MaxColsAtCompileTime>::ret),
+ /**< This value is equal to the maximum possible number of coefficients that this expression
+ * might have. If this expression might have an arbitrarily high number of coefficients,
+ * this value is set to \a Dynamic.
+ *
+ * This value is useful to know when evaluating an expression, in order to determine
+ * whether it is possible to avoid doing a dynamic memory allocation.
+ *
+ * \sa SizeAtCompileTime, MaxRowsAtCompileTime, MaxColsAtCompileTime
+ */
+
+ IsVectorAtCompileTime = ei_traits<Derived>::RowsAtCompileTime == 1
+ || ei_traits<Derived>::ColsAtCompileTime == 1,
+ /**< This is set to true if either the number of rows or the number of
+ * columns is known at compile-time to be equal to 1. Indeed, in that case,
+ * we are dealing with a column-vector (if there is only one column) or with
+ * a row-vector (if there is only one row). */
+
+ Flags = ei_traits<Derived>::Flags,
+ /**< This stores expression \ref flags flags which may or may not be inherited by new expressions
+ * constructed from this one. See the \ref flags "list of flags".
+ */
+
+ CoeffReadCost = ei_traits<Derived>::CoeffReadCost
+ /**< This is a rough measure of how expensive it is to read one coefficient from
+ * this expression.
+ */
+ };
+
+ /** Default constructor. Just checks at compile-time for self-consistency of the flags. */
+ MatrixBase()
+ {
+ ei_assert(ei_are_flags_consistent<Flags>::ret);
+ }
+
+#ifndef EIGEN_PARSED_BY_DOXYGEN
+ /** This is the "real scalar" type; if the \a Scalar type is already real numbers
+ * (e.g. int, float or double) then \a RealScalar is just the same as \a Scalar. If
+ * \a Scalar is \a std::complex<T> then RealScalar is \a T.
+ *
+ * \sa class NumTraits
+ */
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+
+ /** type of the equivalent square matrix */
+ typedef Matrix<Scalar,EIGEN_ENUM_MAX(RowsAtCompileTime,ColsAtCompileTime),
+ EIGEN_ENUM_MAX(RowsAtCompileTime,ColsAtCompileTime)> SquareMatrixType;
+#endif // not EIGEN_PARSED_BY_DOXYGEN
+
+ /** \returns the number of rows. \sa cols(), RowsAtCompileTime */
+ inline int rows() const { return derived().rows(); }
+ /** \returns the number of columns. \sa rows(), ColsAtCompileTime*/
+ inline int cols() const { return derived().cols(); }
+ /** \returns the number of coefficients, which is \a rows()*cols().
+ * \sa rows(), cols(), SizeAtCompileTime. */
+ inline int size() const { return rows() * cols(); }
+ /** \returns the number of nonzero coefficients which is in practice the number
+ * of stored coefficients. */
+ inline int nonZeros() const { return derived.nonZeros(); }
+ /** \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. */
+ inline bool isVector() const { return rows()==1 || cols()==1; }
+ /** \returns the size of the storage major dimension,
+ * i.e., the number of columns for a columns major matrix, and the number of rows otherwise */
+ int outerSize() const { return (int(Flags)&RowMajorBit) ? this->rows() : this->cols(); }
+ /** \returns the size of the inner dimension according to the storage order,
+ * i.e., the number of rows for a columns major matrix, and the number of cols otherwise */
+ int innerSize() const { return (int(Flags)&RowMajorBit) ? this->cols() : this->rows(); }
+
+#ifndef EIGEN_PARSED_BY_DOXYGEN
+ /** \internal the plain matrix type corresponding to this expression. Note that is not necessarily
+ * exactly the return type of eval(): in the case of plain matrices, the return type of eval() is a const
+ * reference to a matrix, not a matrix! It guaranteed however, that the return type of eval() is either
+ * PlainMatrixType or const PlainMatrixType&.
+ */
+ typedef typename ei_plain_matrix_type<Derived>::type PlainMatrixType;
+ /** \internal the column-major plain matrix type corresponding to this expression. Note that is not necessarily
+ * exactly the return type of eval(): in the case of plain matrices, the return type of eval() is a const
+ * reference to a matrix, not a matrix!
+ * The only difference from PlainMatrixType is that PlainMatrixType_ColMajor is guaranteed to be column-major.
+ */
+ typedef typename ei_plain_matrix_type<Derived>::type PlainMatrixType_ColMajor;
+
+ /** \internal Represents a matrix with all coefficients equal to one another*/
+ typedef CwiseNullaryOp<ei_scalar_constant_op<Scalar>,Derived> ConstantReturnType;
+ /** \internal Represents a scalar multiple of a matrix */
+ typedef CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, Derived> ScalarMultipleReturnType;
+ /** \internal Represents a quotient of a matrix by a scalar*/
+ typedef CwiseUnaryOp<ei_scalar_quotient1_op<Scalar>, Derived> ScalarQuotient1ReturnType;
+ /** \internal the return type of MatrixBase::conjugate() */
+ typedef typename ei_meta_if<NumTraits<Scalar>::IsComplex,
+ const CwiseUnaryOp<ei_scalar_conjugate_op<Scalar>, Derived>,
+ const Derived&
+ >::ret ConjugateReturnType;
+ /** \internal the return type of MatrixBase::real() */
+ typedef CwiseUnaryOp<ei_scalar_real_op<Scalar>, Derived> RealReturnType;
+ /** \internal the return type of MatrixBase::imag() */
+ typedef CwiseUnaryOp<ei_scalar_imag_op<Scalar>, Derived> ImagReturnType;
+ /** \internal the return type of MatrixBase::adjoint() */
+ typedef Eigen::Transpose<NestByValue<typename ei_cleantype<ConjugateReturnType>::type> >
+ AdjointReturnType;
+ /** \internal the return type of MatrixBase::eigenvalues() */
+ typedef Matrix<typename NumTraits<typename ei_traits<Derived>::Scalar>::Real, ei_traits<Derived>::ColsAtCompileTime, 1> EigenvaluesReturnType;
+ /** \internal expression tyepe of a column */
+ typedef Block<Derived, ei_traits<Derived>::RowsAtCompileTime, 1> ColXpr;
+ /** \internal expression tyepe of a column */
+ typedef Block<Derived, 1, ei_traits<Derived>::ColsAtCompileTime> RowXpr;
+ /** \internal the return type of identity */
+ typedef CwiseNullaryOp<ei_scalar_identity_op<Scalar>,Derived> IdentityReturnType;
+ /** \internal the return type of unit vectors */
+ typedef Block<CwiseNullaryOp<ei_scalar_identity_op<Scalar>, SquareMatrixType>,
+ ei_traits<Derived>::RowsAtCompileTime,
+ ei_traits<Derived>::ColsAtCompileTime> BasisReturnType;
+#endif // not EIGEN_PARSED_BY_DOXYGEN
+
+
+ /** Copies \a other into *this. \returns a reference to *this. */
+ template<typename OtherDerived>
+ Derived& operator=(const MatrixBase<OtherDerived>& other);
+
+ /** Special case of the template operator=, in order to prevent the compiler
+ * from generating a default operator= (issue hit with g++ 4.1)
+ */
+ inline Derived& operator=(const MatrixBase& other)
+ {
+ return this->operator=<Derived>(other);
+ }
+
+#ifndef EIGEN_PARSED_BY_DOXYGEN
+ /** Copies \a other into *this without evaluating other. \returns a reference to *this. */
+ template<typename OtherDerived>
+ Derived& lazyAssign(const MatrixBase<OtherDerived>& other);
+
+ /** Overloaded for cache friendly product evaluation */
+ template<typename Lhs, typename Rhs>
+ Derived& lazyAssign(const Product<Lhs,Rhs,CacheFriendlyProduct>& product);
+
+ /** Overloaded for cache friendly product evaluation */
+ template<typename OtherDerived>
+ Derived& lazyAssign(const Flagged<OtherDerived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other)
+ { return lazyAssign(other._expression()); }
+#endif // not EIGEN_PARSED_BY_DOXYGEN
+
+ CommaInitializer<Derived> operator<< (const Scalar& s);
+
+ template<typename OtherDerived>
+ CommaInitializer<Derived> operator<< (const MatrixBase<OtherDerived>& other);
+
+ const Scalar coeff(int row, int col) const;
+ const Scalar operator()(int row, int col) const;
+
+ Scalar& coeffRef(int row, int col);
+ Scalar& operator()(int row, int col);
+
+ const Scalar coeff(int index) const;
+ const Scalar operator[](int index) const;
+ const Scalar operator()(int index) const;
+
+ Scalar& coeffRef(int index);
+ Scalar& operator[](int index);
+ Scalar& operator()(int index);
+
+#ifndef EIGEN_PARSED_BY_DOXYGEN
+ template<typename OtherDerived>
+ void copyCoeff(int row, int col, const MatrixBase<OtherDerived>& other);
+ template<typename OtherDerived>
+ void copyCoeff(int index, const MatrixBase<OtherDerived>& other);
+ template<typename OtherDerived, int StoreMode, int LoadMode>
+ void copyPacket(int row, int col, const MatrixBase<OtherDerived>& other);
+ template<typename OtherDerived, int StoreMode, int LoadMode>
+ void copyPacket(int index, const MatrixBase<OtherDerived>& other);
+#endif // not EIGEN_PARSED_BY_DOXYGEN
+
+ template<int LoadMode>
+ PacketScalar packet(int row, int col) const;
+ template<int StoreMode>
+ void writePacket(int row, int col, const PacketScalar& x);
+
+ template<int LoadMode>
+ PacketScalar packet(int index) const;
+ template<int StoreMode>
+ void writePacket(int index, const PacketScalar& x);
+
+ const Scalar x() const;
+ const Scalar y() const;
+ const Scalar z() const;
+ const Scalar w() const;
+ Scalar& x();
+ Scalar& y();
+ Scalar& z();
+ Scalar& w();
+
+
+ const CwiseUnaryOp<ei_scalar_opposite_op<typename ei_traits<Derived>::Scalar>,Derived> operator-() const;
+
+ template<typename OtherDerived>
+ const CwiseBinaryOp<ei_scalar_sum_op<typename ei_traits<Derived>::Scalar>, Derived, OtherDerived>
+ operator+(const MatrixBase<OtherDerived> &other) const;
+
+ template<typename OtherDerived>
+ const CwiseBinaryOp<ei_scalar_difference_op<typename ei_traits<Derived>::Scalar>, Derived, OtherDerived>
+ operator-(const MatrixBase<OtherDerived> &other) const;
+
+ template<typename OtherDerived>
+ Derived& operator+=(const MatrixBase<OtherDerived>& other);
+ template<typename OtherDerived>
+ Derived& operator-=(const MatrixBase<OtherDerived>& other);
+
+ template<typename Lhs,typename Rhs>
+ Derived& operator+=(const Flagged<Product<Lhs,Rhs,CacheFriendlyProduct>, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other);
+
+ Derived& operator*=(const Scalar& other);
+ Derived& operator/=(const Scalar& other);
+
+ const ScalarMultipleReturnType operator*(const Scalar& scalar) const;
+ const CwiseUnaryOp<ei_scalar_quotient1_op<typename ei_traits<Derived>::Scalar>, Derived>
+ operator/(const Scalar& scalar) const;
+
+ inline friend const CwiseUnaryOp<ei_scalar_multiple_op<typename ei_traits<Derived>::Scalar>, Derived>
+ operator*(const Scalar& scalar, const MatrixBase& matrix)
+ { return matrix*scalar; }
+
+
+ template<typename OtherDerived>
+ const typename ProductReturnType<Derived,OtherDerived>::Type
+ operator*(const MatrixBase<OtherDerived> &other) const;
+
+ template<typename OtherDerived>
+ Derived& operator*=(const MatrixBase<OtherDerived>& other);
+
+ template<typename OtherDerived>
+ typename ei_plain_matrix_type_column_major<OtherDerived>::type
+ solveTriangular(const MatrixBase<OtherDerived>& other) const;
+
+ template<typename OtherDerived>
+ void solveTriangularInPlace(const MatrixBase<OtherDerived>& other) const;
+
+
+ template<typename OtherDerived>
+ Scalar dot(const MatrixBase<OtherDerived>& other) const;
+ RealScalar squaredNorm() const;
+ RealScalar norm() const;
+ const PlainMatrixType normalized() const;
+ void normalize();
+
+ Eigen::Transpose<Derived> transpose();
+ const Eigen::Transpose<Derived> transpose() const;
+ void transposeInPlace();
+ const AdjointReturnType adjoint() const;
+
+
+ RowXpr row(int i);
+ const RowXpr row(int i) const;
+
+ ColXpr col(int i);
+ const ColXpr col(int i) const;
+
+ Minor<Derived> minor(int row, int col);
+ const Minor<Derived> minor(int row, int col) const;
+
+ typename BlockReturnType<Derived>::Type block(int startRow, int startCol, int blockRows, int blockCols);
+ const typename BlockReturnType<Derived>::Type
+ block(int startRow, int startCol, int blockRows, int blockCols) const;
+
+ typename BlockReturnType<Derived>::SubVectorType segment(int start, int size);
+ const typename BlockReturnType<Derived>::SubVectorType segment(int start, int size) const;
+
+ typename BlockReturnType<Derived,Dynamic>::SubVectorType start(int size);
+ const typename BlockReturnType<Derived,Dynamic>::SubVectorType start(int size) const;
+
+ typename BlockReturnType<Derived,Dynamic>::SubVectorType end(int size);
+ const typename BlockReturnType<Derived,Dynamic>::SubVectorType end(int size) const;
+
+ typename BlockReturnType<Derived>::Type corner(CornerType type, int cRows, int cCols);
+ const typename BlockReturnType<Derived>::Type corner(CornerType type, int cRows, int cCols) const;
+
+ template<int BlockRows, int BlockCols>
+ typename BlockReturnType<Derived, BlockRows, BlockCols>::Type block(int startRow, int startCol);
+ template<int BlockRows, int BlockCols>
+ const typename BlockReturnType<Derived, BlockRows, BlockCols>::Type block(int startRow, int startCol) const;
+
+ template<int CRows, int CCols>
+ typename BlockReturnType<Derived, CRows, CCols>::Type corner(CornerType type);
+ template<int CRows, int CCols>
+ const typename BlockReturnType<Derived, CRows, CCols>::Type corner(CornerType type) const;
+
+ template<int Size> typename BlockReturnType<Derived,Size>::SubVectorType start(void);
+ template<int Size> const typename BlockReturnType<Derived,Size>::SubVectorType start() const;
+
+ template<int Size> typename BlockReturnType<Derived,Size>::SubVectorType end();
+ template<int Size> const typename BlockReturnType<Derived,Size>::SubVectorType end() const;
+
+ template<int Size> typename BlockReturnType<Derived,Size>::SubVectorType segment(int start);
+ template<int Size> const typename BlockReturnType<Derived,Size>::SubVectorType segment(int start) const;
+
+ DiagonalCoeffs<Derived> diagonal();
+ const DiagonalCoeffs<Derived> diagonal() const;
+
+ template<unsigned int Mode> Part<Derived, Mode> part();
+ template<unsigned int Mode> const Part<Derived, Mode> part() const;
+
+
+ static const ConstantReturnType
+ Constant(int rows, int cols, const Scalar& value);
+ static const ConstantReturnType
+ Constant(int size, const Scalar& value);
+ static const ConstantReturnType
+ Constant(const Scalar& value);
+
+ template<typename CustomNullaryOp>
+ static const CwiseNullaryOp<CustomNullaryOp, Derived>
+ NullaryExpr(int rows, int cols, const CustomNullaryOp& func);
+ template<typename CustomNullaryOp>
+ static const CwiseNullaryOp<CustomNullaryOp, Derived>
+ NullaryExpr(int size, const CustomNullaryOp& func);
+ template<typename CustomNullaryOp>
+ static const CwiseNullaryOp<CustomNullaryOp, Derived>
+ NullaryExpr(const CustomNullaryOp& func);
+
+ static const ConstantReturnType Zero(int rows, int cols);
+ static const ConstantReturnType Zero(int size);
+ static const ConstantReturnType Zero();
+ static const ConstantReturnType Ones(int rows, int cols);
+ static const ConstantReturnType Ones(int size);
+ static const ConstantReturnType Ones();
+ static const IdentityReturnType Identity();
+ static const IdentityReturnType Identity(int rows, int cols);
+ static const BasisReturnType Unit(int size, int i);
+ static const BasisReturnType Unit(int i);
+ static const BasisReturnType UnitX();
+ static const BasisReturnType UnitY();
+ static const BasisReturnType UnitZ();
+ static const BasisReturnType UnitW();
+
+ const DiagonalMatrix<Derived> asDiagonal() const;
+
+ void fill(const Scalar& value);
+ Derived& setConstant(const Scalar& value);
+ Derived& setZero();
+ Derived& setOnes();
+ Derived& setRandom();
+ Derived& setIdentity();
+
+
+ template<typename OtherDerived>
+ bool isApprox(const MatrixBase<OtherDerived>& other,
+ RealScalar prec = precision<Scalar>()) const;
+ bool isMuchSmallerThan(const RealScalar& other,
+ RealScalar prec = precision<Scalar>()) const;
+ template<typename OtherDerived>
+ bool isMuchSmallerThan(const MatrixBase<OtherDerived>& other,
+ RealScalar prec = precision<Scalar>()) const;
+
+ bool isApproxToConstant(const Scalar& value, RealScalar prec = precision<Scalar>()) const;
+ bool isConstant(const Scalar& value, RealScalar prec = precision<Scalar>()) const;
+ bool isZero(RealScalar prec = precision<Scalar>()) const;
+ bool isOnes(RealScalar prec = precision<Scalar>()) const;
+ bool isIdentity(RealScalar prec = precision<Scalar>()) const;
+ bool isDiagonal(RealScalar prec = precision<Scalar>()) const;
+
+ bool isUpperTriangular(RealScalar prec = precision<Scalar>()) const;
+ bool isLowerTriangular(RealScalar prec = precision<Scalar>()) const;
+
+ template<typename OtherDerived>
+ bool isOrthogonal(const MatrixBase<OtherDerived>& other,
+ RealScalar prec = precision<Scalar>()) const;
+ bool isUnitary(RealScalar prec = precision<Scalar>()) const;
+
+ template<typename OtherDerived>
+ inline bool operator==(const MatrixBase<OtherDerived>& other) const
+ { return (cwise() == other).all(); }
+
+ template<typename OtherDerived>
+ inline bool operator!=(const MatrixBase<OtherDerived>& other) const
+ { return (cwise() != other).any(); }
+
+
+ template<typename NewType>
+ const CwiseUnaryOp<ei_scalar_cast_op<typename ei_traits<Derived>::Scalar, NewType>, Derived> cast() const;
+
+ /** \returns the matrix or vector obtained by evaluating this expression.
+ *
+ * Notice that in the case of a plain matrix or vector (not an expression) this function just returns
+ * a const reference, in order to avoid a useless copy.
+ */
+ EIGEN_STRONG_INLINE const typename ei_eval<Derived>::type eval() const
+ { return typename ei_eval<Derived>::type(derived()); }
+
+ template<typename OtherDerived>
+ void swap(const MatrixBase<OtherDerived>& other);
+
+ template<unsigned int Added>
+ const Flagged<Derived, Added, 0> marked() const;
+ const Flagged<Derived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit> lazy() const;
+
+ /** \returns number of elements to skip to pass from one row (resp. column) to another
+ * for a row-major (resp. column-major) matrix.
+ * Combined with coeffRef() and the \ref flags flags, it allows a direct access to the data
+ * of the underlying matrix.
+ */
+ inline int stride(void) const { return derived().stride(); }
+
+ inline const NestByValue<Derived> nestByValue() const;
+
+
+ ConjugateReturnType conjugate() const;
+ const RealReturnType real() const;
+ const ImagReturnType imag() const;
+
+ template<typename CustomUnaryOp>
+ const CwiseUnaryOp<CustomUnaryOp, Derived> unaryExpr(const CustomUnaryOp& func = CustomUnaryOp()) const;
+
+ template<typename CustomBinaryOp, typename OtherDerived>
+ const CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>
+ binaryExpr(const MatrixBase<OtherDerived> &other, const CustomBinaryOp& func = CustomBinaryOp()) const;
+
+
+ Scalar sum() const;
+ Scalar trace() const;
+
+ typename ei_traits<Derived>::Scalar minCoeff() const;
+ typename ei_traits<Derived>::Scalar maxCoeff() const;
+
+ typename ei_traits<Derived>::Scalar minCoeff(int* row, int* col) const;
+ typename ei_traits<Derived>::Scalar maxCoeff(int* row, int* col) const;
+
+ typename ei_traits<Derived>::Scalar minCoeff(int* index) const;
+ typename ei_traits<Derived>::Scalar maxCoeff(int* index) const;
+
+ template<typename BinaryOp>
+ typename ei_result_of<BinaryOp(typename ei_traits<Derived>::Scalar)>::type
+ redux(const BinaryOp& func) const;
+
+ template<typename Visitor>
+ void visit(Visitor& func) const;
+
+#ifndef EIGEN_PARSED_BY_DOXYGEN
+ inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
+ inline Derived& derived() { return *static_cast<Derived*>(this); }
+ inline Derived& const_cast_derived() const
+ { return *static_cast<Derived*>(const_cast<MatrixBase*>(this)); }
+#endif // not EIGEN_PARSED_BY_DOXYGEN
+
+ const Cwise<Derived> cwise() const;
+ Cwise<Derived> cwise();
+
+ inline const WithFormat<Derived> format(const IOFormat& fmt) const;
+
+/////////// Array module ///////////
+
+ bool all(void) const;
+ bool any(void) const;
+ int count() const;
+
+ const PartialRedux<Derived,Horizontal> rowwise() const;
+ const PartialRedux<Derived,Vertical> colwise() const;
+
+ static const CwiseNullaryOp<ei_scalar_random_op<Scalar>,Derived> Random(int rows, int cols);
+ static const CwiseNullaryOp<ei_scalar_random_op<Scalar>,Derived> Random(int size);
+ static const CwiseNullaryOp<ei_scalar_random_op<Scalar>,Derived> Random();
+
+ template<typename ThenDerived,typename ElseDerived>
+ const Select<Derived,ThenDerived,ElseDerived>
+ select(const MatrixBase<ThenDerived>& thenMatrix,
+ const MatrixBase<ElseDerived>& elseMatrix) const;
+
+ template<typename ThenDerived>
+ inline const Select<Derived,ThenDerived, NestByValue<typename ThenDerived::ConstantReturnType> >
+ select(const MatrixBase<ThenDerived>& thenMatrix, typename ThenDerived::Scalar elseScalar) const;
+
+ template<typename ElseDerived>
+ inline const Select<Derived, NestByValue<typename ElseDerived::ConstantReturnType>, ElseDerived >
+ select(typename ElseDerived::Scalar thenScalar, const MatrixBase<ElseDerived>& elseMatrix) const;
+
+ template<int p> RealScalar lpNorm() const;
+
+/////////// LU module ///////////
+
+ const LU<PlainMatrixType> lu() const;
+ const PlainMatrixType inverse() const;
+ void computeInverse(PlainMatrixType *result) const;
+ Scalar determinant() const;
+
+/////////// Cholesky module ///////////
+
+ const LLT<PlainMatrixType> llt() const;
+ const LDLT<PlainMatrixType> ldlt() const;
+
+/////////// QR module ///////////
+
+ const QR<PlainMatrixType> qr() const;
+
+ EigenvaluesReturnType eigenvalues() const;
+ RealScalar operatorNorm() const;
+
+/////////// SVD module ///////////
+
+ SVD<PlainMatrixType> svd() const;
+
+/////////// Geometry module ///////////
+
+ template<typename OtherDerived>
+ PlainMatrixType cross(const MatrixBase<OtherDerived>& other) const;
+ PlainMatrixType unitOrthogonal(void) const;
+ Matrix<Scalar,3,1> eulerAngles(int a0, int a1, int a2) const;
+
+/////////// Sparse module ///////////
+
+ // dense = spasre * dense
+ template<typename Derived1, typename Derived2>
+ Derived& lazyAssign(const SparseProduct<Derived1,Derived2,SparseTimeDenseProduct>& product);
+ // dense = dense * spasre
+ template<typename Derived1, typename Derived2>
+ Derived& lazyAssign(const SparseProduct<Derived1,Derived2,DenseTimeSparseProduct>& product);
+
+ #ifdef EIGEN_MATRIXBASE_PLUGIN
+ #include EIGEN_MATRIXBASE_PLUGIN
+ #endif
+};
+
+#endif // EIGEN_MATRIXBASE_H
diff --git a/extern/Eigen2/Eigen/src/Core/MatrixStorage.h b/extern/Eigen2/Eigen/src/Core/MatrixStorage.h
new file mode 100644
index 00000000000..ba2355b8e60
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/MatrixStorage.h
@@ -0,0 +1,249 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_MATRIXSTORAGE_H
+#define EIGEN_MATRIXSTORAGE_H
+
+struct ei_constructor_without_unaligned_array_assert {};
+
+/** \internal
+ * Static array automatically aligned if the total byte size is a multiple of 16 and the matrix options require auto alignment
+ */
+template <typename T, int Size, int MatrixOptions,
+ bool Align = (MatrixOptions&AutoAlign) && (((Size*sizeof(T))&0xf)==0)
+> struct ei_matrix_array
+{
+ EIGEN_ALIGN_128 T array[Size];
+
+ ei_matrix_array()
+ {
+ #ifndef EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
+ ei_assert((reinterpret_cast<size_t>(array) & 0xf) == 0
+ && "this assertion is explained here: http://eigen.tuxfamily.org/dox/UnalignedArrayAssert.html **** READ THIS WEB PAGE !!! ****");
+ #endif
+ }
+
+ ei_matrix_array(ei_constructor_without_unaligned_array_assert) {}
+};
+
+template <typename T, int Size, int MatrixOptions> struct ei_matrix_array<T,Size,MatrixOptions,false>
+{
+ T array[Size];
+ ei_matrix_array() {}
+ ei_matrix_array(ei_constructor_without_unaligned_array_assert) {}
+};
+
+/** \internal
+ *
+ * \class ei_matrix_storage
+ *
+ * \brief Stores the data of a matrix
+ *
+ * This class stores the data of fixed-size, dynamic-size or mixed matrices
+ * in a way as compact as possible.
+ *
+ * \sa Matrix
+ */
+template<typename T, int Size, int _Rows, int _Cols, int _Options> class ei_matrix_storage;
+
+// purely fixed-size matrix
+template<typename T, int Size, int _Rows, int _Cols, int _Options> class ei_matrix_storage
+{
+ ei_matrix_array<T,Size,_Options> m_data;
+ public:
+ inline explicit ei_matrix_storage() {}
+ inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
+ : m_data(ei_constructor_without_unaligned_array_assert()) {}
+ inline ei_matrix_storage(int,int,int) {}
+ inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); }
+ inline static int rows(void) {return _Rows;}
+ inline static int cols(void) {return _Cols;}
+ inline void resize(int,int,int) {}
+ inline const T *data() const { return m_data.array; }
+ inline T *data() { return m_data.array; }
+};
+
+// dynamic-size matrix with fixed-size storage
+template<typename T, int Size, int _Options> class ei_matrix_storage<T, Size, Dynamic, Dynamic, _Options>
+{
+ ei_matrix_array<T,Size,_Options> m_data;
+ int m_rows;
+ int m_cols;
+ public:
+ inline explicit ei_matrix_storage() : m_rows(0), m_cols(0) {}
+ inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
+ : m_data(ei_constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {}
+ inline ei_matrix_storage(int, int rows, int cols) : m_rows(rows), m_cols(cols) {}
+ inline ~ei_matrix_storage() {}
+ inline void swap(ei_matrix_storage& other)
+ { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
+ inline int rows(void) const {return m_rows;}
+ inline int cols(void) const {return m_cols;}
+ inline void resize(int, int rows, int cols)
+ {
+ m_rows = rows;
+ m_cols = cols;
+ }
+ inline const T *data() const { return m_data.array; }
+ inline T *data() { return m_data.array; }
+};
+
+// dynamic-size matrix with fixed-size storage and fixed width
+template<typename T, int Size, int _Cols, int _Options> class ei_matrix_storage<T, Size, Dynamic, _Cols, _Options>
+{
+ ei_matrix_array<T,Size,_Options> m_data;
+ int m_rows;
+ public:
+ inline explicit ei_matrix_storage() : m_rows(0) {}
+ inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
+ : m_data(ei_constructor_without_unaligned_array_assert()), m_rows(0) {}
+ inline ei_matrix_storage(int, int rows, int) : m_rows(rows) {}
+ inline ~ei_matrix_storage() {}
+ inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
+ inline int rows(void) const {return m_rows;}
+ inline int cols(void) const {return _Cols;}
+ inline void resize(int /*size*/, int rows, int)
+ {
+ m_rows = rows;
+ }
+ inline const T *data() const { return m_data.array; }
+ inline T *data() { return m_data.array; }
+};
+
+// dynamic-size matrix with fixed-size storage and fixed height
+template<typename T, int Size, int _Rows, int _Options> class ei_matrix_storage<T, Size, _Rows, Dynamic, _Options>
+{
+ ei_matrix_array<T,Size,_Options> m_data;
+ int m_cols;
+ public:
+ inline explicit ei_matrix_storage() : m_cols(0) {}
+ inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
+ : m_data(ei_constructor_without_unaligned_array_assert()), m_cols(0) {}
+ inline ei_matrix_storage(int, int, int cols) : m_cols(cols) {}
+ inline ~ei_matrix_storage() {}
+ inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
+ inline int rows(void) const {return _Rows;}
+ inline int cols(void) const {return m_cols;}
+ inline void resize(int, int, int cols)
+ {
+ m_cols = cols;
+ }
+ inline const T *data() const { return m_data.array; }
+ inline T *data() { return m_data.array; }
+};
+
+// purely dynamic matrix.
+template<typename T, int _Options> class ei_matrix_storage<T, Dynamic, Dynamic, Dynamic, _Options>
+{
+ T *m_data;
+ int m_rows;
+ int m_cols;
+ public:
+ inline explicit ei_matrix_storage() : m_data(0), m_rows(0), m_cols(0) {}
+ inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert)
+ : m_data(0), m_rows(0), m_cols(0) {}
+ inline ei_matrix_storage(int size, int rows, int cols)
+ : m_data(ei_aligned_new<T>(size)), m_rows(rows), m_cols(cols) {}
+ inline ~ei_matrix_storage() { ei_aligned_delete(m_data, m_rows*m_cols); }
+ inline void swap(ei_matrix_storage& other)
+ { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
+ inline int rows(void) const {return m_rows;}
+ inline int cols(void) const {return m_cols;}
+ void resize(int size, int rows, int cols)
+ {
+ if(size != m_rows*m_cols)
+ {
+ ei_aligned_delete(m_data, m_rows*m_cols);
+ if (size)
+ m_data = ei_aligned_new<T>(size);
+ else
+ m_data = 0;
+ }
+ m_rows = rows;
+ m_cols = cols;
+ }
+ inline const T *data() const { return m_data; }
+ inline T *data() { return m_data; }
+};
+
+// matrix with dynamic width and fixed height (so that matrix has dynamic size).
+template<typename T, int _Rows, int _Options> class ei_matrix_storage<T, Dynamic, _Rows, Dynamic, _Options>
+{
+ T *m_data;
+ int m_cols;
+ public:
+ inline explicit ei_matrix_storage() : m_data(0), m_cols(0) {}
+ inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
+ inline ei_matrix_storage(int size, int, int cols) : m_data(ei_aligned_new<T>(size)), m_cols(cols) {}
+ inline ~ei_matrix_storage() { ei_aligned_delete(m_data, _Rows*m_cols); }
+ inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
+ inline static int rows(void) {return _Rows;}
+ inline int cols(void) const {return m_cols;}
+ void resize(int size, int, int cols)
+ {
+ if(size != _Rows*m_cols)
+ {
+ ei_aligned_delete(m_data, _Rows*m_cols);
+ if (size)
+ m_data = ei_aligned_new<T>(size);
+ else
+ m_data = 0;
+ }
+ m_cols = cols;
+ }
+ inline const T *data() const { return m_data; }
+ inline T *data() { return m_data; }
+};
+
+// matrix with dynamic height and fixed width (so that matrix has dynamic size).
+template<typename T, int _Cols, int _Options> class ei_matrix_storage<T, Dynamic, Dynamic, _Cols, _Options>
+{
+ T *m_data;
+ int m_rows;
+ public:
+ inline explicit ei_matrix_storage() : m_data(0), m_rows(0) {}
+ inline ei_matrix_storage(ei_constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
+ inline ei_matrix_storage(int size, int rows, int) : m_data(ei_aligned_new<T>(size)), m_rows(rows) {}
+ inline ~ei_matrix_storage() { ei_aligned_delete(m_data, _Cols*m_rows); }
+ inline void swap(ei_matrix_storage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
+ inline int rows(void) const {return m_rows;}
+ inline static int cols(void) {return _Cols;}
+ void resize(int size, int rows, int)
+ {
+ if(size != m_rows*_Cols)
+ {
+ ei_aligned_delete(m_data, _Cols*m_rows);
+ if (size)
+ m_data = ei_aligned_new<T>(size);
+ else
+ m_data = 0;
+ }
+ m_rows = rows;
+ }
+ inline const T *data() const { return m_data; }
+ inline T *data() { return m_data; }
+};
+
+#endif // EIGEN_MATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Minor.h b/extern/Eigen2/Eigen/src/Core/Minor.h
index eda91cc32be..e2d47da79c2 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Minor.h
+++ b/extern/Eigen2/Eigen/src/Core/Minor.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -25,7 +25,7 @@
#ifndef EIGEN_MINOR_H
#define EIGEN_MINOR_H
-/**
+/** \nonstableyet
* \class Minor
*
* \brief Expression of a minor
@@ -38,15 +38,12 @@
*
* \sa MatrixBase::minor()
*/
-
-namespace internal {
template<typename MatrixType>
-struct traits<Minor<MatrixType> >
- : traits<MatrixType>
+struct ei_traits<Minor<MatrixType> >
{
- typedef typename nested<MatrixType>::type MatrixTypeNested;
- typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
- typedef typename MatrixType::StorageKind StorageKind;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
+ typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
enum {
RowsAtCompileTime = (MatrixType::RowsAtCompileTime != Dynamic) ?
int(MatrixType::RowsAtCompileTime) - 1 : Dynamic,
@@ -56,50 +53,47 @@ struct traits<Minor<MatrixType> >
int(MatrixType::MaxRowsAtCompileTime) - 1 : Dynamic,
MaxColsAtCompileTime = (MatrixType::MaxColsAtCompileTime != Dynamic) ?
int(MatrixType::MaxColsAtCompileTime) - 1 : Dynamic,
- Flags = _MatrixTypeNested::Flags & (HereditaryBits | LvalueBit),
- CoeffReadCost = _MatrixTypeNested::CoeffReadCost // minor is used typically on tiny matrices,
- // where loops are unrolled and the 'if' evaluates at compile time
+ Flags = _MatrixTypeNested::Flags & HereditaryBits,
+ CoeffReadCost = _MatrixTypeNested::CoeffReadCost
};
};
-}
template<typename MatrixType> class Minor
: public MatrixBase<Minor<MatrixType> >
{
public:
- typedef MatrixBase<Minor> Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Minor)
+ EIGEN_GENERIC_PUBLIC_INTERFACE(Minor)
inline Minor(const MatrixType& matrix,
- Index row, Index col)
+ int row, int col)
: m_matrix(matrix), m_row(row), m_col(col)
{
- eigen_assert(row >= 0 && row < matrix.rows()
+ ei_assert(row >= 0 && row < matrix.rows()
&& col >= 0 && col < matrix.cols());
}
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Minor)
- inline Index rows() const { return m_matrix.rows() - 1; }
- inline Index cols() const { return m_matrix.cols() - 1; }
+ inline int rows() const { return m_matrix.rows() - 1; }
+ inline int cols() const { return m_matrix.cols() - 1; }
- inline Scalar& coeffRef(Index row, Index col)
+ inline Scalar& coeffRef(int row, int col)
{
return m_matrix.const_cast_derived().coeffRef(row + (row >= m_row), col + (col >= m_col));
}
- inline const Scalar coeff(Index row, Index col) const
+ inline const Scalar coeff(int row, int col) const
{
return m_matrix.coeff(row + (row >= m_row), col + (col >= m_col));
}
protected:
const typename MatrixType::Nested m_matrix;
- const Index m_row, m_col;
+ const int m_row, m_col;
};
-/**
+/** \nonstableyet
* \return an expression of the (\a row, \a col)-minor of *this,
* i.e. an expression constructed from *this by removing the specified
* row and column.
@@ -111,16 +105,16 @@ template<typename MatrixType> class Minor
*/
template<typename Derived>
inline Minor<Derived>
-MatrixBase<Derived>::minor(Index row, Index col)
+MatrixBase<Derived>::minor(int row, int col)
{
return Minor<Derived>(derived(), row, col);
}
-/**
+/** \nonstableyet
* This is the const version of minor(). */
template<typename Derived>
inline const Minor<Derived>
-MatrixBase<Derived>::minor(Index row, Index col) const
+MatrixBase<Derived>::minor(int row, int col) const
{
return Minor<Derived>(derived(), row, col);
}
diff --git a/extern/Eigen3/Eigen/src/Core/NestByValue.h b/extern/Eigen2/Eigen/src/Core/NestByValue.h
index a6104d2a426..2a14ab1f156 100644
--- a/extern/Eigen3/Eigen/src/Core/NestByValue.h
+++ b/extern/Eigen2/Eigen/src/Core/NestByValue.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
@@ -27,7 +27,6 @@
#define EIGEN_NESTBYVALUE_H
/** \class NestByValue
- * \ingroup Core_Module
*
* \brief Expression which must be nested by value
*
@@ -38,83 +37,79 @@
*
* \sa MatrixBase::nestByValue()
*/
-
-namespace internal {
template<typename ExpressionType>
-struct traits<NestByValue<ExpressionType> > : public traits<ExpressionType>
+struct ei_traits<NestByValue<ExpressionType> > : public ei_traits<ExpressionType>
{};
-}
template<typename ExpressionType> class NestByValue
- : public internal::dense_xpr_base< NestByValue<ExpressionType> >::type
+ : public MatrixBase<NestByValue<ExpressionType> >
{
public:
- typedef typename internal::dense_xpr_base<NestByValue>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(NestByValue)
+ EIGEN_GENERIC_PUBLIC_INTERFACE(NestByValue)
inline NestByValue(const ExpressionType& matrix) : m_expression(matrix) {}
- inline Index rows() const { return m_expression.rows(); }
- inline Index cols() const { return m_expression.cols(); }
- inline Index outerStride() const { return m_expression.outerStride(); }
- inline Index innerStride() const { return m_expression.innerStride(); }
+ inline int rows() const { return m_expression.rows(); }
+ inline int cols() const { return m_expression.cols(); }
+ inline int stride() const { return m_expression.stride(); }
- inline const CoeffReturnType coeff(Index row, Index col) const
+ inline const Scalar coeff(int row, int col) const
{
return m_expression.coeff(row, col);
}
- inline Scalar& coeffRef(Index row, Index col)
+ inline Scalar& coeffRef(int row, int col)
{
return m_expression.const_cast_derived().coeffRef(row, col);
}
- inline const CoeffReturnType coeff(Index index) const
+ inline const Scalar coeff(int index) const
{
return m_expression.coeff(index);
}
- inline Scalar& coeffRef(Index index)
+ inline Scalar& coeffRef(int index)
{
return m_expression.const_cast_derived().coeffRef(index);
}
template<int LoadMode>
- inline const PacketScalar packet(Index row, Index col) const
+ inline const PacketScalar packet(int row, int col) const
{
return m_expression.template packet<LoadMode>(row, col);
}
template<int LoadMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
+ inline void writePacket(int row, int col, const PacketScalar& x)
{
m_expression.const_cast_derived().template writePacket<LoadMode>(row, col, x);
}
template<int LoadMode>
- inline const PacketScalar packet(Index index) const
+ inline const PacketScalar packet(int index) const
{
return m_expression.template packet<LoadMode>(index);
}
template<int LoadMode>
- inline void writePacket(Index index, const PacketScalar& x)
+ inline void writePacket(int index, const PacketScalar& x)
{
m_expression.const_cast_derived().template writePacket<LoadMode>(index, x);
}
- operator const ExpressionType&() const { return m_expression; }
-
protected:
const ExpressionType m_expression;
+
+ private:
+ NestByValue& operator=(const NestByValue&);
};
/** \returns an expression of the temporary version of *this.
*/
template<typename Derived>
inline const NestByValue<Derived>
-DenseBase<Derived>::nestByValue() const
+MatrixBase<Derived>::nestByValue() const
{
return NestByValue<Derived>(derived());
}
diff --git a/extern/Eigen2/Eigen/src/Core/NumTraits.h b/extern/Eigen2/Eigen/src/Core/NumTraits.h
new file mode 100644
index 00000000000..b27284a78bc
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/NumTraits.h
@@ -0,0 +1,142 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_NUMTRAITS_H
+#define EIGEN_NUMTRAITS_H
+
+/** \class NumTraits
+ *
+ * \brief Holds some data about the various numeric (i.e. scalar) types allowed by Eigen.
+ *
+ * \param T the numeric type about which this class provides data. Recall that Eigen allows
+ * only the following types for \a T: \c int, \c float, \c double,
+ * \c std::complex<float>, \c std::complex<double>, and \c long \c double (especially
+ * useful to enforce x87 arithmetics when SSE is the default).
+ *
+ * The provided data consists of:
+ * \li A typedef \a Real, giving the "real part" type of \a T. If \a T is already real,
+ * then \a Real is just a typedef to \a T. If \a T is \c std::complex<U> then \a Real
+ * is a typedef to \a U.
+ * \li A typedef \a FloatingPoint, giving the "floating-point type" of \a T. If \a T is
+ * \c int, then \a FloatingPoint is a typedef to \c double. Otherwise, \a FloatingPoint
+ * is a typedef to \a T.
+ * \li An enum value \a IsComplex. It is equal to 1 if \a T is a \c std::complex
+ * type, and to 0 otherwise.
+ * \li An enum \a HasFloatingPoint. It is equal to \c 0 if \a T is \c int,
+ * and to \c 1 otherwise.
+ */
+template<typename T> struct NumTraits;
+
+template<> struct NumTraits<int>
+{
+ typedef int Real;
+ typedef double FloatingPoint;
+ enum {
+ IsComplex = 0,
+ HasFloatingPoint = 0,
+ ReadCost = 1,
+ AddCost = 1,
+ MulCost = 1
+ };
+};
+
+template<> struct NumTraits<float>
+{
+ typedef float Real;
+ typedef float FloatingPoint;
+ enum {
+ IsComplex = 0,
+ HasFloatingPoint = 1,
+ ReadCost = 1,
+ AddCost = 1,
+ MulCost = 1
+ };
+};
+
+template<> struct NumTraits<double>
+{
+ typedef double Real;
+ typedef double FloatingPoint;
+ enum {
+ IsComplex = 0,
+ HasFloatingPoint = 1,
+ ReadCost = 1,
+ AddCost = 1,
+ MulCost = 1
+ };
+};
+
+template<typename _Real> struct NumTraits<std::complex<_Real> >
+{
+ typedef _Real Real;
+ typedef std::complex<_Real> FloatingPoint;
+ enum {
+ IsComplex = 1,
+ HasFloatingPoint = NumTraits<Real>::HasFloatingPoint,
+ ReadCost = 2,
+ AddCost = 2 * NumTraits<Real>::AddCost,
+ MulCost = 4 * NumTraits<Real>::MulCost + 2 * NumTraits<Real>::AddCost
+ };
+};
+
+template<> struct NumTraits<long long int>
+{
+ typedef long long int Real;
+ typedef long double FloatingPoint;
+ enum {
+ IsComplex = 0,
+ HasFloatingPoint = 0,
+ ReadCost = 1,
+ AddCost = 1,
+ MulCost = 1
+ };
+};
+
+template<> struct NumTraits<long double>
+{
+ typedef long double Real;
+ typedef long double FloatingPoint;
+ enum {
+ IsComplex = 0,
+ HasFloatingPoint = 1,
+ ReadCost = 1,
+ AddCost = 1,
+ MulCost = 1
+ };
+};
+
+template<> struct NumTraits<bool>
+{
+ typedef bool Real;
+ typedef float FloatingPoint;
+ enum {
+ IsComplex = 0,
+ HasFloatingPoint = 0,
+ ReadCost = 1,
+ AddCost = 1,
+ MulCost = 1
+ };
+};
+
+#endif // EIGEN_NUMTRAITS_H
diff --git a/extern/Eigen2/Eigen/src/Core/Part.h b/extern/Eigen2/Eigen/src/Core/Part.h
new file mode 100644
index 00000000000..96229f43b68
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/Part.h
@@ -0,0 +1,377 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_PART_H
+#define EIGEN_PART_H
+
+/** \nonstableyet
+ * \class Part
+ *
+ * \brief Expression of a triangular matrix extracted from a given matrix
+ *
+ * \param MatrixType the type of the object in which we are taking the triangular part
+ * \param Mode the kind of triangular matrix expression to construct. Can be UpperTriangular, StrictlyUpperTriangular,
+ * UnitUpperTriangular, LowerTriangular, StrictlyLowerTriangular, UnitLowerTriangular. This is in fact a bit field; it must have either
+ * UpperTriangularBit or LowerTriangularBit, and additionnaly it may have either ZeroDiagBit or
+ * UnitDiagBit.
+ *
+ * This class represents an expression of the upper or lower triangular part of
+ * a square matrix, possibly with a further assumption on the diagonal. It is the return type
+ * of MatrixBase::part() and most of the time this is the only way it is used.
+ *
+ * \sa MatrixBase::part()
+ */
+template<typename MatrixType, unsigned int Mode>
+struct ei_traits<Part<MatrixType, Mode> > : ei_traits<MatrixType>
+{
+ typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
+ typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
+ enum {
+ Flags = (_MatrixTypeNested::Flags & (HereditaryBits) & (~(PacketAccessBit | DirectAccessBit | LinearAccessBit))) | Mode,
+ CoeffReadCost = _MatrixTypeNested::CoeffReadCost
+ };
+};
+
+template<typename MatrixType, unsigned int Mode> class Part
+ : public MatrixBase<Part<MatrixType, Mode> >
+{
+ public:
+
+ EIGEN_GENERIC_PUBLIC_INTERFACE(Part)
+
+ inline Part(const MatrixType& matrix) : m_matrix(matrix)
+ { ei_assert(ei_are_flags_consistent<Mode>::ret); }
+
+ /** \sa MatrixBase::operator+=() */
+ template<typename Other> Part& operator+=(const Other& other);
+ /** \sa MatrixBase::operator-=() */
+ template<typename Other> Part& operator-=(const Other& other);
+ /** \sa MatrixBase::operator*=() */
+ Part& operator*=(const typename ei_traits<MatrixType>::Scalar& other);
+ /** \sa MatrixBase::operator/=() */
+ Part& operator/=(const typename ei_traits<MatrixType>::Scalar& other);
+
+ /** \sa operator=(), MatrixBase::lazyAssign() */
+ template<typename Other> void lazyAssign(const Other& other);
+ /** \sa MatrixBase::operator=() */
+ template<typename Other> Part& operator=(const Other& other);
+
+ inline int rows() const { return m_matrix.rows(); }
+ inline int cols() const { return m_matrix.cols(); }
+ inline int stride() const { return m_matrix.stride(); }
+
+ inline Scalar coeff(int row, int col) const
+ {
+ // SelfAdjointBit doesn't play any role here: just because a matrix is selfadjoint doesn't say anything about
+ // each individual coefficient, except for the not-very-useful-here fact that diagonal coefficients are real.
+ if( ((Flags & LowerTriangularBit) && (col>row)) || ((Flags & UpperTriangularBit) && (row>col)) )
+ return (Scalar)0;
+ if(Flags & UnitDiagBit)
+ return col==row ? (Scalar)1 : m_matrix.coeff(row, col);
+ else if(Flags & ZeroDiagBit)
+ return col==row ? (Scalar)0 : m_matrix.coeff(row, col);
+ else
+ return m_matrix.coeff(row, col);
+ }
+
+ inline Scalar& coeffRef(int row, int col)
+ {
+ EIGEN_STATIC_ASSERT(!(Flags & UnitDiagBit), WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED)
+ EIGEN_STATIC_ASSERT(!(Flags & SelfAdjointBit), COEFFICIENT_WRITE_ACCESS_TO_SELFADJOINT_NOT_SUPPORTED)
+ ei_assert( (Mode==UpperTriangular && col>=row)
+ || (Mode==LowerTriangular && col<=row)
+ || (Mode==StrictlyUpperTriangular && col>row)
+ || (Mode==StrictlyLowerTriangular && col<row));
+ return m_matrix.const_cast_derived().coeffRef(row, col);
+ }
+
+ /** \internal */
+ const MatrixType& _expression() const { return m_matrix; }
+
+ /** discard any writes to a row */
+ const Block<Part, 1, ColsAtCompileTime> row(int i) { return Base::row(i); }
+ const Block<Part, 1, ColsAtCompileTime> row(int i) const { return Base::row(i); }
+ /** discard any writes to a column */
+ const Block<Part, RowsAtCompileTime, 1> col(int i) { return Base::col(i); }
+ const Block<Part, RowsAtCompileTime, 1> col(int i) const { return Base::col(i); }
+
+ template<typename OtherDerived>
+ void swap(const MatrixBase<OtherDerived>& other)
+ {
+ Part<SwapWrapper<MatrixType>,Mode>(const_cast<MatrixType&>(m_matrix)).lazyAssign(other.derived());
+ }
+
+ protected:
+ const typename MatrixType::Nested m_matrix;
+
+ private:
+ Part& operator=(const Part&);
+};
+
+/** \nonstableyet
+ * \returns an expression of a triangular matrix extracted from the current matrix
+ *
+ * The parameter \a Mode can have the following values: \c UpperTriangular, \c StrictlyUpperTriangular, \c UnitUpperTriangular,
+ * \c LowerTriangular, \c StrictlyLowerTriangular, \c UnitLowerTriangular.
+ *
+ * \addexample PartExample \label How to extract a triangular part of an arbitrary matrix
+ *
+ * Example: \include MatrixBase_extract.cpp
+ * Output: \verbinclude MatrixBase_extract.out
+ *
+ * \sa class Part, part(), marked()
+ */
+template<typename Derived>
+template<unsigned int Mode>
+const Part<Derived, Mode> MatrixBase<Derived>::part() const
+{
+ return derived();
+}
+
+template<typename MatrixType, unsigned int Mode>
+template<typename Other>
+inline Part<MatrixType, Mode>& Part<MatrixType, Mode>::operator=(const Other& other)
+{
+ if(Other::Flags & EvalBeforeAssigningBit)
+ {
+ typename MatrixBase<Other>::PlainMatrixType other_evaluated(other.rows(), other.cols());
+ other_evaluated.template part<Mode>().lazyAssign(other);
+ lazyAssign(other_evaluated);
+ }
+ else
+ lazyAssign(other.derived());
+ return *this;
+}
+
+template<typename Derived1, typename Derived2, unsigned int Mode, int UnrollCount>
+struct ei_part_assignment_impl
+{
+ enum {
+ col = (UnrollCount-1) / Derived1::RowsAtCompileTime,
+ row = (UnrollCount-1) % Derived1::RowsAtCompileTime
+ };
+
+ inline static void run(Derived1 &dst, const Derived2 &src)
+ {
+ ei_part_assignment_impl<Derived1, Derived2, Mode, UnrollCount-1>::run(dst, src);
+
+ if(Mode == SelfAdjoint)
+ {
+ if(row == col)
+ dst.coeffRef(row, col) = ei_real(src.coeff(row, col));
+ else if(row < col)
+ dst.coeffRef(col, row) = ei_conj(dst.coeffRef(row, col) = src.coeff(row, col));
+ }
+ else
+ {
+ ei_assert(Mode == UpperTriangular || Mode == LowerTriangular || Mode == StrictlyUpperTriangular || Mode == StrictlyLowerTriangular);
+ if((Mode == UpperTriangular && row <= col)
+ || (Mode == LowerTriangular && row >= col)
+ || (Mode == StrictlyUpperTriangular && row < col)
+ || (Mode == StrictlyLowerTriangular && row > col))
+ dst.copyCoeff(row, col, src);
+ }
+ }
+};
+
+template<typename Derived1, typename Derived2, unsigned int Mode>
+struct ei_part_assignment_impl<Derived1, Derived2, Mode, 1>
+{
+ inline static void run(Derived1 &dst, const Derived2 &src)
+ {
+ if(!(Mode & ZeroDiagBit))
+ dst.copyCoeff(0, 0, src);
+ }
+};
+
+// prevent buggy user code from causing an infinite recursion
+template<typename Derived1, typename Derived2, unsigned int Mode>
+struct ei_part_assignment_impl<Derived1, Derived2, Mode, 0>
+{
+ inline static void run(Derived1 &, const Derived2 &) {}
+};
+
+template<typename Derived1, typename Derived2>
+struct ei_part_assignment_impl<Derived1, Derived2, UpperTriangular, Dynamic>
+{
+ inline static void run(Derived1 &dst, const Derived2 &src)
+ {
+ for(int j = 0; j < dst.cols(); ++j)
+ for(int i = 0; i <= j; ++i)
+ dst.copyCoeff(i, j, src);
+ }
+};
+
+template<typename Derived1, typename Derived2>
+struct ei_part_assignment_impl<Derived1, Derived2, LowerTriangular, Dynamic>
+{
+ inline static void run(Derived1 &dst, const Derived2 &src)
+ {
+ for(int j = 0; j < dst.cols(); ++j)
+ for(int i = j; i < dst.rows(); ++i)
+ dst.copyCoeff(i, j, src);
+ }
+};
+
+template<typename Derived1, typename Derived2>
+struct ei_part_assignment_impl<Derived1, Derived2, StrictlyUpperTriangular, Dynamic>
+{
+ inline static void run(Derived1 &dst, const Derived2 &src)
+ {
+ for(int j = 0; j < dst.cols(); ++j)
+ for(int i = 0; i < j; ++i)
+ dst.copyCoeff(i, j, src);
+ }
+};
+template<typename Derived1, typename Derived2>
+struct ei_part_assignment_impl<Derived1, Derived2, StrictlyLowerTriangular, Dynamic>
+{
+ inline static void run(Derived1 &dst, const Derived2 &src)
+ {
+ for(int j = 0; j < dst.cols(); ++j)
+ for(int i = j+1; i < dst.rows(); ++i)
+ dst.copyCoeff(i, j, src);
+ }
+};
+template<typename Derived1, typename Derived2>
+struct ei_part_assignment_impl<Derived1, Derived2, SelfAdjoint, Dynamic>
+{
+ inline static void run(Derived1 &dst, const Derived2 &src)
+ {
+ for(int j = 0; j < dst.cols(); ++j)
+ {
+ for(int i = 0; i < j; ++i)
+ dst.coeffRef(j, i) = ei_conj(dst.coeffRef(i, j) = src.coeff(i, j));
+ dst.coeffRef(j, j) = ei_real(src.coeff(j, j));
+ }
+ }
+};
+
+template<typename MatrixType, unsigned int Mode>
+template<typename Other>
+void Part<MatrixType, Mode>::lazyAssign(const Other& other)
+{
+ const bool unroll = MatrixType::SizeAtCompileTime * Other::CoeffReadCost / 2 <= EIGEN_UNROLLING_LIMIT;
+ ei_assert(m_matrix.rows() == other.rows() && m_matrix.cols() == other.cols());
+
+ ei_part_assignment_impl
+ <MatrixType, Other, Mode,
+ unroll ? int(MatrixType::SizeAtCompileTime) : Dynamic
+ >::run(m_matrix.const_cast_derived(), other.derived());
+}
+
+/** \nonstableyet
+ * \returns a lvalue pseudo-expression allowing to perform special operations on \c *this.
+ *
+ * The \a Mode parameter can have the following values: \c UpperTriangular, \c StrictlyUpperTriangular, \c LowerTriangular,
+ * \c StrictlyLowerTriangular, \c SelfAdjoint.
+ *
+ * \addexample PartExample \label How to write to a triangular part of a matrix
+ *
+ * Example: \include MatrixBase_part.cpp
+ * Output: \verbinclude MatrixBase_part.out
+ *
+ * \sa class Part, MatrixBase::extract(), MatrixBase::marked()
+ */
+template<typename Derived>
+template<unsigned int Mode>
+inline Part<Derived, Mode> MatrixBase<Derived>::part()
+{
+ return Part<Derived, Mode>(derived());
+}
+
+/** \returns true if *this is approximately equal to an upper triangular matrix,
+ * within the precision given by \a prec.
+ *
+ * \sa isLowerTriangular(), extract(), part(), marked()
+ */
+template<typename Derived>
+bool MatrixBase<Derived>::isUpperTriangular(RealScalar prec) const
+{
+ if(cols() != rows()) return false;
+ RealScalar maxAbsOnUpperTriangularPart = static_cast<RealScalar>(-1);
+ for(int j = 0; j < cols(); ++j)
+ for(int i = 0; i <= j; ++i)
+ {
+ RealScalar absValue = ei_abs(coeff(i,j));
+ if(absValue > maxAbsOnUpperTriangularPart) maxAbsOnUpperTriangularPart = absValue;
+ }
+ for(int j = 0; j < cols()-1; ++j)
+ for(int i = j+1; i < rows(); ++i)
+ if(!ei_isMuchSmallerThan(coeff(i, j), maxAbsOnUpperTriangularPart, prec)) return false;
+ return true;
+}
+
+/** \returns true if *this is approximately equal to a lower triangular matrix,
+ * within the precision given by \a prec.
+ *
+ * \sa isUpperTriangular(), extract(), part(), marked()
+ */
+template<typename Derived>
+bool MatrixBase<Derived>::isLowerTriangular(RealScalar prec) const
+{
+ if(cols() != rows()) return false;
+ RealScalar maxAbsOnLowerTriangularPart = static_cast<RealScalar>(-1);
+ for(int j = 0; j < cols(); ++j)
+ for(int i = j; i < rows(); ++i)
+ {
+ RealScalar absValue = ei_abs(coeff(i,j));
+ if(absValue > maxAbsOnLowerTriangularPart) maxAbsOnLowerTriangularPart = absValue;
+ }
+ for(int j = 1; j < cols(); ++j)
+ for(int i = 0; i < j; ++i)
+ if(!ei_isMuchSmallerThan(coeff(i, j), maxAbsOnLowerTriangularPart, prec)) return false;
+ return true;
+}
+
+template<typename MatrixType, unsigned int Mode>
+template<typename Other>
+inline Part<MatrixType, Mode>& Part<MatrixType, Mode>::operator+=(const Other& other)
+{
+ return *this = m_matrix + other;
+}
+
+template<typename MatrixType, unsigned int Mode>
+template<typename Other>
+inline Part<MatrixType, Mode>& Part<MatrixType, Mode>::operator-=(const Other& other)
+{
+ return *this = m_matrix - other;
+}
+
+template<typename MatrixType, unsigned int Mode>
+inline Part<MatrixType, Mode>& Part<MatrixType, Mode>::operator*=
+(const typename ei_traits<MatrixType>::Scalar& other)
+{
+ return *this = m_matrix * other;
+}
+
+template<typename MatrixType, unsigned int Mode>
+inline Part<MatrixType, Mode>& Part<MatrixType, Mode>::operator/=
+(const typename ei_traits<MatrixType>::Scalar& other)
+{
+ return *this = m_matrix / other;
+}
+
+#endif // EIGEN_PART_H
diff --git a/extern/Eigen2/Eigen/src/Core/Product.h b/extern/Eigen2/Eigen/src/Core/Product.h
new file mode 100644
index 00000000000..1151b21641c
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/Product.h
@@ -0,0 +1,769 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_PRODUCT_H
+#define EIGEN_PRODUCT_H
+
+/***************************
+*** Forward declarations ***
+***************************/
+
+template<int VectorizationMode, int Index, typename Lhs, typename Rhs, typename RetScalar>
+struct ei_product_coeff_impl;
+
+template<int StorageOrder, int Index, typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
+struct ei_product_packet_impl;
+
+/** \class ProductReturnType
+ *
+ * \brief Helper class to get the correct and optimized returned type of operator*
+ *
+ * \param Lhs the type of the left-hand side
+ * \param Rhs the type of the right-hand side
+ * \param ProductMode the type of the product (determined automatically by ei_product_mode)
+ *
+ * This class defines the typename Type representing the optimized product expression
+ * between two matrix expressions. In practice, using ProductReturnType<Lhs,Rhs>::Type
+ * is the recommended way to define the result type of a function returning an expression
+ * which involve a matrix product. The class Product or DiagonalProduct should never be
+ * used directly.
+ *
+ * \sa class Product, class DiagonalProduct, MatrixBase::operator*(const MatrixBase<OtherDerived>&)
+ */
+template<typename Lhs, typename Rhs, int ProductMode>
+struct ProductReturnType
+{
+ typedef typename ei_nested<Lhs,Rhs::ColsAtCompileTime>::type LhsNested;
+ typedef typename ei_nested<Rhs,Lhs::RowsAtCompileTime>::type RhsNested;
+
+ typedef Product<LhsNested, RhsNested, ProductMode> Type;
+};
+
+// cache friendly specialization
+// note that there is a DiagonalProduct specialization in DiagonalProduct.h
+template<typename Lhs, typename Rhs>
+struct ProductReturnType<Lhs,Rhs,CacheFriendlyProduct>
+{
+ typedef typename ei_nested<Lhs,Rhs::ColsAtCompileTime>::type LhsNested;
+
+ typedef typename ei_nested<Rhs,Lhs::RowsAtCompileTime,
+ typename ei_plain_matrix_type_column_major<Rhs>::type
+ >::type RhsNested;
+
+ typedef Product<LhsNested, RhsNested, CacheFriendlyProduct> Type;
+};
+
+/* Helper class to determine the type of the product, can be either:
+ * - NormalProduct
+ * - CacheFriendlyProduct
+ * - DiagonalProduct
+ */
+template<typename Lhs, typename Rhs> struct ei_product_mode
+{
+ enum{
+
+ value = ((Rhs::Flags&Diagonal)==Diagonal) || ((Lhs::Flags&Diagonal)==Diagonal)
+ ? DiagonalProduct
+ : Lhs::MaxColsAtCompileTime == Dynamic
+ && ( Lhs::MaxRowsAtCompileTime == Dynamic
+ || Rhs::MaxColsAtCompileTime == Dynamic )
+ && (!(Rhs::IsVectorAtCompileTime && (Lhs::Flags&RowMajorBit) && (!(Lhs::Flags&DirectAccessBit))))
+ && (!(Lhs::IsVectorAtCompileTime && (!(Rhs::Flags&RowMajorBit)) && (!(Rhs::Flags&DirectAccessBit))))
+ && (ei_is_same_type<typename Lhs::Scalar, typename Rhs::Scalar>::ret)
+ ? CacheFriendlyProduct
+ : NormalProduct };
+};
+
+/** \class Product
+ *
+ * \brief Expression of the product of two matrices
+ *
+ * \param LhsNested the type used to store the left-hand side
+ * \param RhsNested the type used to store the right-hand side
+ * \param ProductMode the type of the product
+ *
+ * This class represents an expression of the product of two matrices.
+ * It is the return type of the operator* between matrices. Its template
+ * arguments are determined automatically by ProductReturnType. Therefore,
+ * Product should never be used direclty. To determine the result type of a
+ * function which involves a matrix product, use ProductReturnType::Type.
+ *
+ * \sa ProductReturnType, MatrixBase::operator*(const MatrixBase<OtherDerived>&)
+ */
+template<typename LhsNested, typename RhsNested, int ProductMode>
+struct ei_traits<Product<LhsNested, RhsNested, ProductMode> >
+{
+ // clean the nested types:
+ typedef typename ei_cleantype<LhsNested>::type _LhsNested;
+ typedef typename ei_cleantype<RhsNested>::type _RhsNested;
+ typedef typename ei_scalar_product_traits<typename _LhsNested::Scalar, typename _RhsNested::Scalar>::ReturnType Scalar;
+
+ enum {
+ LhsCoeffReadCost = _LhsNested::CoeffReadCost,
+ RhsCoeffReadCost = _RhsNested::CoeffReadCost,
+ LhsFlags = _LhsNested::Flags,
+ RhsFlags = _RhsNested::Flags,
+
+ RowsAtCompileTime = _LhsNested::RowsAtCompileTime,
+ ColsAtCompileTime = _RhsNested::ColsAtCompileTime,
+ InnerSize = EIGEN_ENUM_MIN(_LhsNested::ColsAtCompileTime, _RhsNested::RowsAtCompileTime),
+
+ MaxRowsAtCompileTime = _LhsNested::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = _RhsNested::MaxColsAtCompileTime,
+
+ LhsRowMajor = LhsFlags & RowMajorBit,
+ RhsRowMajor = RhsFlags & RowMajorBit,
+
+ CanVectorizeRhs = RhsRowMajor && (RhsFlags & PacketAccessBit)
+ && (ColsAtCompileTime % ei_packet_traits<Scalar>::size == 0),
+
+ CanVectorizeLhs = (!LhsRowMajor) && (LhsFlags & PacketAccessBit)
+ && (RowsAtCompileTime % ei_packet_traits<Scalar>::size == 0),
+
+ EvalToRowMajor = RhsRowMajor && (ProductMode==(int)CacheFriendlyProduct ? LhsRowMajor : (!CanVectorizeLhs)),
+
+ RemovedBits = ~(EvalToRowMajor ? 0 : RowMajorBit),
+
+ Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
+ | EvalBeforeAssigningBit
+ | EvalBeforeNestingBit
+ | (CanVectorizeLhs || CanVectorizeRhs ? PacketAccessBit : 0)
+ | (LhsFlags & RhsFlags & AlignedBit),
+
+ CoeffReadCost = InnerSize == Dynamic ? Dynamic
+ : InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost)
+ + (InnerSize - 1) * NumTraits<Scalar>::AddCost,
+
+ /* CanVectorizeInner deserves special explanation. It does not affect the product flags. It is not used outside
+ * of Product. If the Product itself is not a packet-access expression, there is still a chance that the inner
+ * loop of the product might be vectorized. This is the meaning of CanVectorizeInner. Since it doesn't affect
+ * the Flags, it is safe to make this value depend on ActualPacketAccessBit, that doesn't affect the ABI.
+ */
+ CanVectorizeInner = LhsRowMajor && (!RhsRowMajor) && (LhsFlags & RhsFlags & ActualPacketAccessBit)
+ && (InnerSize % ei_packet_traits<Scalar>::size == 0)
+ };
+};
+
+template<typename LhsNested, typename RhsNested, int ProductMode> class Product : ei_no_assignment_operator,
+ public MatrixBase<Product<LhsNested, RhsNested, ProductMode> >
+{
+ public:
+
+ EIGEN_GENERIC_PUBLIC_INTERFACE(Product)
+
+ private:
+
+ typedef typename ei_traits<Product>::_LhsNested _LhsNested;
+ typedef typename ei_traits<Product>::_RhsNested _RhsNested;
+
+ enum {
+ PacketSize = ei_packet_traits<Scalar>::size,
+ InnerSize = ei_traits<Product>::InnerSize,
+ Unroll = CoeffReadCost <= EIGEN_UNROLLING_LIMIT,
+ CanVectorizeInner = ei_traits<Product>::CanVectorizeInner
+ };
+
+ typedef ei_product_coeff_impl<CanVectorizeInner ? InnerVectorization : NoVectorization,
+ Unroll ? InnerSize-1 : Dynamic,
+ _LhsNested, _RhsNested, Scalar> ScalarCoeffImpl;
+
+ public:
+
+ template<typename Lhs, typename Rhs>
+ inline Product(const Lhs& lhs, const Rhs& rhs)
+ : m_lhs(lhs), m_rhs(rhs)
+ {
+ // we don't allow taking products of matrices of different real types, as that wouldn't be vectorizable.
+ // We still allow to mix T and complex<T>.
+ EIGEN_STATIC_ASSERT((ei_is_same_type<typename Lhs::RealScalar, typename Rhs::RealScalar>::ret),
+ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
+ ei_assert(lhs.cols() == rhs.rows()
+ && "invalid matrix product"
+ && "if you wanted a coeff-wise or a dot product use the respective explicit functions");
+ }
+
+ /** \internal
+ * compute \a res += \c *this using the cache friendly product.
+ */
+ template<typename DestDerived>
+ void _cacheFriendlyEvalAndAdd(DestDerived& res) const;
+
+ /** \internal
+ * \returns whether it is worth it to use the cache friendly product.
+ */
+ EIGEN_STRONG_INLINE bool _useCacheFriendlyProduct() const
+ {
+ return m_lhs.cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
+ && ( rows()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
+ || cols()>=EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD);
+ }
+
+ EIGEN_STRONG_INLINE int rows() const { return m_lhs.rows(); }
+ EIGEN_STRONG_INLINE int cols() const { return m_rhs.cols(); }
+
+ EIGEN_STRONG_INLINE const Scalar coeff(int row, int col) const
+ {
+ Scalar res;
+ ScalarCoeffImpl::run(row, col, m_lhs, m_rhs, res);
+ return res;
+ }
+
+ /* Allow index-based non-packet access. It is impossible though to allow index-based packed access,
+ * which is why we don't set the LinearAccessBit.
+ */
+ EIGEN_STRONG_INLINE const Scalar coeff(int index) const
+ {
+ Scalar res;
+ const int row = RowsAtCompileTime == 1 ? 0 : index;
+ const int col = RowsAtCompileTime == 1 ? index : 0;
+ ScalarCoeffImpl::run(row, col, m_lhs, m_rhs, res);
+ return res;
+ }
+
+ template<int LoadMode>
+ EIGEN_STRONG_INLINE const PacketScalar packet(int row, int col) const
+ {
+ PacketScalar res;
+ ei_product_packet_impl<Flags&RowMajorBit ? RowMajor : ColMajor,
+ Unroll ? InnerSize-1 : Dynamic,
+ _LhsNested, _RhsNested, PacketScalar, LoadMode>
+ ::run(row, col, m_lhs, m_rhs, res);
+ return res;
+ }
+
+ EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
+ EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
+
+ protected:
+ const LhsNested m_lhs;
+ const RhsNested m_rhs;
+};
+
+/** \returns the matrix product of \c *this and \a other.
+ *
+ * \note If instead of the matrix product you want the coefficient-wise product, see Cwise::operator*().
+ *
+ * \sa lazy(), operator*=(const MatrixBase&), Cwise::operator*()
+ */
+template<typename Derived>
+template<typename OtherDerived>
+inline const typename ProductReturnType<Derived,OtherDerived>::Type
+MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
+{
+ enum {
+ ProductIsValid = Derived::ColsAtCompileTime==Dynamic
+ || OtherDerived::RowsAtCompileTime==Dynamic
+ || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime),
+ AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
+ SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived)
+ };
+ // note to the lost user:
+ // * for a dot product use: v1.dot(v2)
+ // * for a coeff-wise product use: v1.cwise()*v2
+ EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
+ INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
+ EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
+ INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
+ EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
+ return typename ProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
+}
+
+/** replaces \c *this by \c *this * \a other.
+ *
+ * \returns a reference to \c *this
+ */
+template<typename Derived>
+template<typename OtherDerived>
+inline Derived &
+MatrixBase<Derived>::operator*=(const MatrixBase<OtherDerived> &other)
+{
+ return derived() = derived() * other.derived();
+}
+
+/***************************************************************************
+* Normal product .coeff() implementation (with meta-unrolling)
+***************************************************************************/
+
+/**************************************
+*** Scalar path - no vectorization ***
+**************************************/
+
+template<int Index, typename Lhs, typename Rhs, typename RetScalar>
+struct ei_product_coeff_impl<NoVectorization, Index, Lhs, Rhs, RetScalar>
+{
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
+ {
+ ei_product_coeff_impl<NoVectorization, Index-1, Lhs, Rhs, RetScalar>::run(row, col, lhs, rhs, res);
+ res += lhs.coeff(row, Index) * rhs.coeff(Index, col);
+ }
+};
+
+template<typename Lhs, typename Rhs, typename RetScalar>
+struct ei_product_coeff_impl<NoVectorization, 0, Lhs, Rhs, RetScalar>
+{
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
+ {
+ res = lhs.coeff(row, 0) * rhs.coeff(0, col);
+ }
+};
+
+template<typename Lhs, typename Rhs, typename RetScalar>
+struct ei_product_coeff_impl<NoVectorization, Dynamic, Lhs, Rhs, RetScalar>
+{
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, RetScalar& res)
+ {
+ ei_assert(lhs.cols()>0 && "you are using a non initialized matrix");
+ res = lhs.coeff(row, 0) * rhs.coeff(0, col);
+ for(int i = 1; i < lhs.cols(); ++i)
+ res += lhs.coeff(row, i) * rhs.coeff(i, col);
+ }
+};
+
+// prevent buggy user code from causing an infinite recursion
+template<typename Lhs, typename Rhs, typename RetScalar>
+struct ei_product_coeff_impl<NoVectorization, -1, Lhs, Rhs, RetScalar>
+{
+ EIGEN_STRONG_INLINE static void run(int, int, const Lhs&, const Rhs&, RetScalar&) {}
+};
+
+/*******************************************
+*** Scalar path with inner vectorization ***
+*******************************************/
+
+template<int Index, typename Lhs, typename Rhs, typename PacketScalar>
+struct ei_product_coeff_vectorized_unroller
+{
+ enum { PacketSize = ei_packet_traits<typename Lhs::Scalar>::size };
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres)
+ {
+ ei_product_coeff_vectorized_unroller<Index-PacketSize, Lhs, Rhs, PacketScalar>::run(row, col, lhs, rhs, pres);
+ pres = ei_padd(pres, ei_pmul( lhs.template packet<Aligned>(row, Index) , rhs.template packet<Aligned>(Index, col) ));
+ }
+};
+
+template<typename Lhs, typename Rhs, typename PacketScalar>
+struct ei_product_coeff_vectorized_unroller<0, Lhs, Rhs, PacketScalar>
+{
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres)
+ {
+ pres = ei_pmul(lhs.template packet<Aligned>(row, 0) , rhs.template packet<Aligned>(0, col));
+ }
+};
+
+template<int Index, typename Lhs, typename Rhs, typename RetScalar>
+struct ei_product_coeff_impl<InnerVectorization, Index, Lhs, Rhs, RetScalar>
+{
+ typedef typename Lhs::PacketScalar PacketScalar;
+ enum { PacketSize = ei_packet_traits<typename Lhs::Scalar>::size };
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
+ {
+ PacketScalar pres;
+ ei_product_coeff_vectorized_unroller<Index+1-PacketSize, Lhs, Rhs, PacketScalar>::run(row, col, lhs, rhs, pres);
+ ei_product_coeff_impl<NoVectorization,Index,Lhs,Rhs,RetScalar>::run(row, col, lhs, rhs, res);
+ res = ei_predux(pres);
+ }
+};
+
+template<typename Lhs, typename Rhs, int LhsRows = Lhs::RowsAtCompileTime, int RhsCols = Rhs::ColsAtCompileTime>
+struct ei_product_coeff_vectorized_dyn_selector
+{
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
+ {
+ res = ei_dot_impl<
+ Block<Lhs, 1, ei_traits<Lhs>::ColsAtCompileTime>,
+ Block<Rhs, ei_traits<Rhs>::RowsAtCompileTime, 1>,
+ LinearVectorization, NoUnrolling>::run(lhs.row(row), rhs.col(col));
+ }
+};
+
+// NOTE the 3 following specializations are because taking .col(0) on a vector is a bit slower
+// NOTE maybe they are now useless since we have a specialization for Block<Matrix>
+template<typename Lhs, typename Rhs, int RhsCols>
+struct ei_product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,RhsCols>
+{
+ EIGEN_STRONG_INLINE static void run(int /*row*/, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
+ {
+ res = ei_dot_impl<
+ Lhs,
+ Block<Rhs, ei_traits<Rhs>::RowsAtCompileTime, 1>,
+ LinearVectorization, NoUnrolling>::run(lhs, rhs.col(col));
+ }
+};
+
+template<typename Lhs, typename Rhs, int LhsRows>
+struct ei_product_coeff_vectorized_dyn_selector<Lhs,Rhs,LhsRows,1>
+{
+ EIGEN_STRONG_INLINE static void run(int row, int /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
+ {
+ res = ei_dot_impl<
+ Block<Lhs, 1, ei_traits<Lhs>::ColsAtCompileTime>,
+ Rhs,
+ LinearVectorization, NoUnrolling>::run(lhs.row(row), rhs);
+ }
+};
+
+template<typename Lhs, typename Rhs>
+struct ei_product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,1>
+{
+ EIGEN_STRONG_INLINE static void run(int /*row*/, int /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
+ {
+ res = ei_dot_impl<
+ Lhs,
+ Rhs,
+ LinearVectorization, NoUnrolling>::run(lhs, rhs);
+ }
+};
+
+template<typename Lhs, typename Rhs, typename RetScalar>
+struct ei_product_coeff_impl<InnerVectorization, Dynamic, Lhs, Rhs, RetScalar>
+{
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
+ {
+ ei_product_coeff_vectorized_dyn_selector<Lhs,Rhs>::run(row, col, lhs, rhs, res);
+ }
+};
+
+/*******************
+*** Packet path ***
+*******************/
+
+template<int Index, typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
+struct ei_product_packet_impl<RowMajor, Index, Lhs, Rhs, PacketScalar, LoadMode>
+{
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar &res)
+ {
+ ei_product_packet_impl<RowMajor, Index-1, Lhs, Rhs, PacketScalar, LoadMode>::run(row, col, lhs, rhs, res);
+ res = ei_pmadd(ei_pset1(lhs.coeff(row, Index)), rhs.template packet<LoadMode>(Index, col), res);
+ }
+};
+
+template<int Index, typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
+struct ei_product_packet_impl<ColMajor, Index, Lhs, Rhs, PacketScalar, LoadMode>
+{
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar &res)
+ {
+ ei_product_packet_impl<ColMajor, Index-1, Lhs, Rhs, PacketScalar, LoadMode>::run(row, col, lhs, rhs, res);
+ res = ei_pmadd(lhs.template packet<LoadMode>(row, Index), ei_pset1(rhs.coeff(Index, col)), res);
+ }
+};
+
+template<typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
+struct ei_product_packet_impl<RowMajor, 0, Lhs, Rhs, PacketScalar, LoadMode>
+{
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar &res)
+ {
+ res = ei_pmul(ei_pset1(lhs.coeff(row, 0)),rhs.template packet<LoadMode>(0, col));
+ }
+};
+
+template<typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
+struct ei_product_packet_impl<ColMajor, 0, Lhs, Rhs, PacketScalar, LoadMode>
+{
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar &res)
+ {
+ res = ei_pmul(lhs.template packet<LoadMode>(row, 0), ei_pset1(rhs.coeff(0, col)));
+ }
+};
+
+template<typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
+struct ei_product_packet_impl<RowMajor, Dynamic, Lhs, Rhs, PacketScalar, LoadMode>
+{
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar& res)
+ {
+ ei_assert(lhs.cols()>0 && "you are using a non initialized matrix");
+ res = ei_pmul(ei_pset1(lhs.coeff(row, 0)),rhs.template packet<LoadMode>(0, col));
+ for(int i = 1; i < lhs.cols(); ++i)
+ res = ei_pmadd(ei_pset1(lhs.coeff(row, i)), rhs.template packet<LoadMode>(i, col), res);
+ }
+};
+
+template<typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
+struct ei_product_packet_impl<ColMajor, Dynamic, Lhs, Rhs, PacketScalar, LoadMode>
+{
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, PacketScalar& res)
+ {
+ ei_assert(lhs.cols()>0 && "you are using a non initialized matrix");
+ res = ei_pmul(lhs.template packet<LoadMode>(row, 0), ei_pset1(rhs.coeff(0, col)));
+ for(int i = 1; i < lhs.cols(); ++i)
+ res = ei_pmadd(lhs.template packet<LoadMode>(row, i), ei_pset1(rhs.coeff(i, col)), res);
+ }
+};
+
+/***************************************************************************
+* Cache friendly product callers and specific nested evaluation strategies
+***************************************************************************/
+
+template<typename Scalar, typename RhsType>
+static void ei_cache_friendly_product_colmajor_times_vector(
+ int size, const Scalar* lhs, int lhsStride, const RhsType& rhs, Scalar* res);
+
+template<typename Scalar, typename ResType>
+static void ei_cache_friendly_product_rowmajor_times_vector(
+ const Scalar* lhs, int lhsStride, const Scalar* rhs, int rhsSize, ResType& res);
+
+template<typename ProductType,
+ int LhsRows = ei_traits<ProductType>::RowsAtCompileTime,
+ int LhsOrder = int(ei_traits<ProductType>::LhsFlags)&RowMajorBit ? RowMajor : ColMajor,
+ int LhsHasDirectAccess = int(ei_traits<ProductType>::LhsFlags)&DirectAccessBit? HasDirectAccess : NoDirectAccess,
+ int RhsCols = ei_traits<ProductType>::ColsAtCompileTime,
+ int RhsOrder = int(ei_traits<ProductType>::RhsFlags)&RowMajorBit ? RowMajor : ColMajor,
+ int RhsHasDirectAccess = int(ei_traits<ProductType>::RhsFlags)&DirectAccessBit? HasDirectAccess : NoDirectAccess>
+struct ei_cache_friendly_product_selector
+{
+ template<typename DestDerived>
+ inline static void run(DestDerived& res, const ProductType& product)
+ {
+ product._cacheFriendlyEvalAndAdd(res);
+ }
+};
+
+// optimized colmajor * vector path
+template<typename ProductType, int LhsRows, int RhsOrder, int RhsAccess>
+struct ei_cache_friendly_product_selector<ProductType,LhsRows,ColMajor,NoDirectAccess,1,RhsOrder,RhsAccess>
+{
+ template<typename DestDerived>
+ inline static void run(DestDerived& res, const ProductType& product)
+ {
+ const int size = product.rhs().rows();
+ for (int k=0; k<size; ++k)
+ res += product.rhs().coeff(k) * product.lhs().col(k);
+ }
+};
+
+// optimized cache friendly colmajor * vector path for matrix with direct access flag
+// NOTE this path could also be enabled for expressions if we add runtime align queries
+template<typename ProductType, int LhsRows, int RhsOrder, int RhsAccess>
+struct ei_cache_friendly_product_selector<ProductType,LhsRows,ColMajor,HasDirectAccess,1,RhsOrder,RhsAccess>
+{
+ typedef typename ProductType::Scalar Scalar;
+
+ template<typename DestDerived>
+ inline static void run(DestDerived& res, const ProductType& product)
+ {
+ enum {
+ EvalToRes = (ei_packet_traits<Scalar>::size==1)
+ ||((DestDerived::Flags&ActualPacketAccessBit) && (!(DestDerived::Flags & RowMajorBit))) };
+ Scalar* EIGEN_RESTRICT _res;
+ if (EvalToRes)
+ _res = &res.coeffRef(0);
+ else
+ {
+ _res = ei_aligned_stack_new(Scalar,res.size());
+ Map<Matrix<Scalar,DestDerived::RowsAtCompileTime,1> >(_res, res.size()) = res;
+ }
+ ei_cache_friendly_product_colmajor_times_vector(res.size(),
+ &product.lhs().const_cast_derived().coeffRef(0,0), product.lhs().stride(),
+ product.rhs(), _res);
+
+ if (!EvalToRes)
+ {
+ res = Map<Matrix<Scalar,DestDerived::SizeAtCompileTime,1> >(_res, res.size());
+ ei_aligned_stack_delete(Scalar, _res, res.size());
+ }
+ }
+};
+
+// optimized vector * rowmajor path
+template<typename ProductType, int LhsOrder, int LhsAccess, int RhsCols>
+struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCols,RowMajor,NoDirectAccess>
+{
+ template<typename DestDerived>
+ inline static void run(DestDerived& res, const ProductType& product)
+ {
+ const int cols = product.lhs().cols();
+ for (int j=0; j<cols; ++j)
+ res += product.lhs().coeff(j) * product.rhs().row(j);
+ }
+};
+
+// optimized cache friendly vector * rowmajor path for matrix with direct access flag
+// NOTE this path coul also be enabled for expressions if we add runtime align queries
+template<typename ProductType, int LhsOrder, int LhsAccess, int RhsCols>
+struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCols,RowMajor,HasDirectAccess>
+{
+ typedef typename ProductType::Scalar Scalar;
+
+ template<typename DestDerived>
+ inline static void run(DestDerived& res, const ProductType& product)
+ {
+ enum {
+ EvalToRes = (ei_packet_traits<Scalar>::size==1)
+ ||((DestDerived::Flags & ActualPacketAccessBit) && (DestDerived::Flags & RowMajorBit)) };
+ Scalar* EIGEN_RESTRICT _res;
+ if (EvalToRes)
+ _res = &res.coeffRef(0);
+ else
+ {
+ _res = ei_aligned_stack_new(Scalar, res.size());
+ Map<Matrix<Scalar,DestDerived::SizeAtCompileTime,1> >(_res, res.size()) = res;
+ }
+ ei_cache_friendly_product_colmajor_times_vector(res.size(),
+ &product.rhs().const_cast_derived().coeffRef(0,0), product.rhs().stride(),
+ product.lhs().transpose(), _res);
+
+ if (!EvalToRes)
+ {
+ res = Map<Matrix<Scalar,DestDerived::SizeAtCompileTime,1> >(_res, res.size());
+ ei_aligned_stack_delete(Scalar, _res, res.size());
+ }
+ }
+};
+
+// optimized rowmajor - vector product
+template<typename ProductType, int LhsRows, int RhsOrder, int RhsAccess>
+struct ei_cache_friendly_product_selector<ProductType,LhsRows,RowMajor,HasDirectAccess,1,RhsOrder,RhsAccess>
+{
+ typedef typename ProductType::Scalar Scalar;
+ typedef typename ei_traits<ProductType>::_RhsNested Rhs;
+ enum {
+ UseRhsDirectly = ((ei_packet_traits<Scalar>::size==1) || (Rhs::Flags&ActualPacketAccessBit))
+ && (!(Rhs::Flags & RowMajorBit)) };
+
+ template<typename DestDerived>
+ inline static void run(DestDerived& res, const ProductType& product)
+ {
+ Scalar* EIGEN_RESTRICT _rhs;
+ if (UseRhsDirectly)
+ _rhs = &product.rhs().const_cast_derived().coeffRef(0);
+ else
+ {
+ _rhs = ei_aligned_stack_new(Scalar, product.rhs().size());
+ Map<Matrix<Scalar,Rhs::SizeAtCompileTime,1> >(_rhs, product.rhs().size()) = product.rhs();
+ }
+ ei_cache_friendly_product_rowmajor_times_vector(&product.lhs().const_cast_derived().coeffRef(0,0), product.lhs().stride(),
+ _rhs, product.rhs().size(), res);
+
+ if (!UseRhsDirectly) ei_aligned_stack_delete(Scalar, _rhs, product.rhs().size());
+ }
+};
+
+// optimized vector - colmajor product
+template<typename ProductType, int LhsOrder, int LhsAccess, int RhsCols>
+struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCols,ColMajor,HasDirectAccess>
+{
+ typedef typename ProductType::Scalar Scalar;
+ typedef typename ei_traits<ProductType>::_LhsNested Lhs;
+ enum {
+ UseLhsDirectly = ((ei_packet_traits<Scalar>::size==1) || (Lhs::Flags&ActualPacketAccessBit))
+ && (Lhs::Flags & RowMajorBit) };
+
+ template<typename DestDerived>
+ inline static void run(DestDerived& res, const ProductType& product)
+ {
+ Scalar* EIGEN_RESTRICT _lhs;
+ if (UseLhsDirectly)
+ _lhs = &product.lhs().const_cast_derived().coeffRef(0);
+ else
+ {
+ _lhs = ei_aligned_stack_new(Scalar, product.lhs().size());
+ Map<Matrix<Scalar,Lhs::SizeAtCompileTime,1> >(_lhs, product.lhs().size()) = product.lhs();
+ }
+ ei_cache_friendly_product_rowmajor_times_vector(&product.rhs().const_cast_derived().coeffRef(0,0), product.rhs().stride(),
+ _lhs, product.lhs().size(), res);
+
+ if(!UseLhsDirectly) ei_aligned_stack_delete(Scalar, _lhs, product.lhs().size());
+ }
+};
+
+// discard this case which has to be handled by the default path
+// (we keep it to be sure to hit a compilation error if this is not the case)
+template<typename ProductType, int LhsRows, int RhsOrder, int RhsAccess>
+struct ei_cache_friendly_product_selector<ProductType,LhsRows,RowMajor,NoDirectAccess,1,RhsOrder,RhsAccess>
+{};
+
+// discard this case which has to be handled by the default path
+// (we keep it to be sure to hit a compilation error if this is not the case)
+template<typename ProductType, int LhsOrder, int LhsAccess, int RhsCols>
+struct ei_cache_friendly_product_selector<ProductType,1,LhsOrder,LhsAccess,RhsCols,ColMajor,NoDirectAccess>
+{};
+
+
+/** \internal */
+template<typename Derived>
+template<typename Lhs,typename Rhs>
+inline Derived&
+MatrixBase<Derived>::operator+=(const Flagged<Product<Lhs,Rhs,CacheFriendlyProduct>, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other)
+{
+ if (other._expression()._useCacheFriendlyProduct())
+ ei_cache_friendly_product_selector<Product<Lhs,Rhs,CacheFriendlyProduct> >::run(const_cast_derived(), other._expression());
+ else
+ lazyAssign(derived() + other._expression());
+ return derived();
+}
+
+template<typename Derived>
+template<typename Lhs, typename Rhs>
+inline Derived& MatrixBase<Derived>::lazyAssign(const Product<Lhs,Rhs,CacheFriendlyProduct>& product)
+{
+ if (product._useCacheFriendlyProduct())
+ {
+ setZero();
+ ei_cache_friendly_product_selector<Product<Lhs,Rhs,CacheFriendlyProduct> >::run(const_cast_derived(), product);
+ }
+ else
+ {
+ lazyAssign<Product<Lhs,Rhs,CacheFriendlyProduct> >(product);
+ }
+ return derived();
+}
+
+template<typename T> struct ei_product_copy_rhs
+{
+ typedef typename ei_meta_if<
+ (ei_traits<T>::Flags & RowMajorBit)
+ || (!(ei_traits<T>::Flags & DirectAccessBit)),
+ typename ei_plain_matrix_type_column_major<T>::type,
+ const T&
+ >::ret type;
+};
+
+template<typename T> struct ei_product_copy_lhs
+{
+ typedef typename ei_meta_if<
+ (!(int(ei_traits<T>::Flags) & DirectAccessBit)),
+ typename ei_plain_matrix_type<T>::type,
+ const T&
+ >::ret type;
+};
+
+template<typename Lhs, typename Rhs, int ProductMode>
+template<typename DestDerived>
+inline void Product<Lhs,Rhs,ProductMode>::_cacheFriendlyEvalAndAdd(DestDerived& res) const
+{
+ typedef typename ei_product_copy_lhs<_LhsNested>::type LhsCopy;
+ typedef typename ei_unref<LhsCopy>::type _LhsCopy;
+ typedef typename ei_product_copy_rhs<_RhsNested>::type RhsCopy;
+ typedef typename ei_unref<RhsCopy>::type _RhsCopy;
+ LhsCopy lhs(m_lhs);
+ RhsCopy rhs(m_rhs);
+ ei_cache_friendly_product<Scalar>(
+ rows(), cols(), lhs.cols(),
+ _LhsCopy::Flags&RowMajorBit, (const Scalar*)&(lhs.const_cast_derived().coeffRef(0,0)), lhs.stride(),
+ _RhsCopy::Flags&RowMajorBit, (const Scalar*)&(rhs.const_cast_derived().coeffRef(0,0)), rhs.stride(),
+ DestDerived::Flags&RowMajorBit, (Scalar*)&(res.coeffRef(0,0)), res.stride()
+ );
+}
+
+#endif // EIGEN_PRODUCT_H
diff --git a/extern/Eigen2/Eigen/src/Core/Redux.h b/extern/Eigen2/Eigen/src/Core/Redux.h
new file mode 100644
index 00000000000..734ef1929a4
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/Redux.h
@@ -0,0 +1,117 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_REDUX_H
+#define EIGEN_REDUX_H
+
+template<typename BinaryOp, typename Derived, int Start, int Length>
+struct ei_redux_impl
+{
+ enum {
+ HalfLength = Length/2
+ };
+
+ typedef typename ei_result_of<BinaryOp(typename Derived::Scalar)>::type Scalar;
+
+ static Scalar run(const Derived &mat, const BinaryOp& func)
+ {
+ return func(
+ ei_redux_impl<BinaryOp, Derived, Start, HalfLength>::run(mat, func),
+ ei_redux_impl<BinaryOp, Derived, Start+HalfLength, Length - HalfLength>::run(mat, func));
+ }
+};
+
+template<typename BinaryOp, typename Derived, int Start>
+struct ei_redux_impl<BinaryOp, Derived, Start, 1>
+{
+ enum {
+ col = Start / Derived::RowsAtCompileTime,
+ row = Start % Derived::RowsAtCompileTime
+ };
+
+ typedef typename ei_result_of<BinaryOp(typename Derived::Scalar)>::type Scalar;
+
+ static Scalar run(const Derived &mat, const BinaryOp &)
+ {
+ return mat.coeff(row, col);
+ }
+};
+
+template<typename BinaryOp, typename Derived, int Start>
+struct ei_redux_impl<BinaryOp, Derived, Start, Dynamic>
+{
+ typedef typename ei_result_of<BinaryOp(typename Derived::Scalar)>::type Scalar;
+ static Scalar run(const Derived& mat, const BinaryOp& func)
+ {
+ ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using a non initialized matrix");
+ Scalar res;
+ res = mat.coeff(0,0);
+ for(int i = 1; i < mat.rows(); ++i)
+ res = func(res, mat.coeff(i, 0));
+ for(int j = 1; j < mat.cols(); ++j)
+ for(int i = 0; i < mat.rows(); ++i)
+ res = func(res, mat.coeff(i, j));
+ return res;
+ }
+};
+
+/** \returns the result of a full redux operation on the whole matrix or vector using \a func
+ *
+ * The template parameter \a BinaryOp is the type of the functor \a func which must be
+ * an assiociative operator. Both current STL and TR1 functor styles are handled.
+ *
+ * \sa MatrixBase::sum(), MatrixBase::minCoeff(), MatrixBase::maxCoeff(), MatrixBase::colwise(), MatrixBase::rowwise()
+ */
+template<typename Derived>
+template<typename BinaryOp>
+typename ei_result_of<BinaryOp(typename ei_traits<Derived>::Scalar)>::type
+MatrixBase<Derived>::redux(const BinaryOp& func) const
+{
+ const bool unroll = SizeAtCompileTime * CoeffReadCost
+ + (SizeAtCompileTime-1) * ei_functor_traits<BinaryOp>::Cost
+ <= EIGEN_UNROLLING_LIMIT;
+ return ei_redux_impl<BinaryOp, Derived, 0, unroll ? int(SizeAtCompileTime) : Dynamic>
+ ::run(derived(), func);
+}
+
+/** \returns the minimum of all coefficients of *this
+ */
+template<typename Derived>
+inline typename ei_traits<Derived>::Scalar
+MatrixBase<Derived>::minCoeff() const
+{
+ return this->redux(Eigen::ei_scalar_min_op<Scalar>());
+}
+
+/** \returns the maximum of all coefficients of *this
+ */
+template<typename Derived>
+inline typename ei_traits<Derived>::Scalar
+MatrixBase<Derived>::maxCoeff() const
+{
+ return this->redux(Eigen::ei_scalar_max_op<Scalar>());
+}
+
+#endif // EIGEN_REDUX_H
diff --git a/extern/Eigen2/Eigen/src/Core/SolveTriangular.h b/extern/Eigen2/Eigen/src/Core/SolveTriangular.h
new file mode 100644
index 00000000000..12fb0e1d159
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/SolveTriangular.h
@@ -0,0 +1,297 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SOLVETRIANGULAR_H
+#define EIGEN_SOLVETRIANGULAR_H
+
+template<typename XprType> struct ei_is_part { enum {value=false}; };
+template<typename XprType, unsigned int Mode> struct ei_is_part<Part<XprType,Mode> > { enum {value=true}; };
+
+template<typename Lhs, typename Rhs,
+ int TriangularPart = (int(Lhs::Flags) & LowerTriangularBit)
+ ? LowerTriangular
+ : (int(Lhs::Flags) & UpperTriangularBit)
+ ? UpperTriangular
+ : -1,
+ int StorageOrder = ei_is_part<Lhs>::value ? -1 // this is to solve ambiguous specializations
+ : int(Lhs::Flags) & (RowMajorBit|SparseBit)
+ >
+struct ei_solve_triangular_selector;
+
+// transform a Part xpr to a Flagged xpr
+template<typename Lhs, unsigned int LhsMode, typename Rhs, int UpLo, int StorageOrder>
+struct ei_solve_triangular_selector<Part<Lhs,LhsMode>,Rhs,UpLo,StorageOrder>
+{
+ static void run(const Part<Lhs,LhsMode>& lhs, Rhs& other)
+ {
+ ei_solve_triangular_selector<Flagged<Lhs,LhsMode,0>,Rhs>::run(lhs._expression(), other);
+ }
+};
+
+// forward substitution, row-major
+template<typename Lhs, typename Rhs, int UpLo>
+struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,RowMajor|IsDense>
+{
+ typedef typename Rhs::Scalar Scalar;
+ static void run(const Lhs& lhs, Rhs& other)
+ {
+ const bool IsLowerTriangular = (UpLo==LowerTriangular);
+ const int size = lhs.cols();
+ /* We perform the inverse product per block of 4 rows such that we perfectly match
+ * our optimized matrix * vector product. blockyStart represents the number of rows
+ * we have process first using the non-block version.
+ */
+ int blockyStart = (std::max(size-5,0)/4)*4;
+ if (IsLowerTriangular)
+ blockyStart = size - blockyStart;
+ else
+ blockyStart -= 1;
+ for(int c=0 ; c<other.cols() ; ++c)
+ {
+ // process first rows using the non block version
+ if(!(Lhs::Flags & UnitDiagBit))
+ {
+ if (IsLowerTriangular)
+ other.coeffRef(0,c) = other.coeff(0,c)/lhs.coeff(0, 0);
+ else
+ other.coeffRef(size-1,c) = other.coeff(size-1, c)/lhs.coeff(size-1, size-1);
+ }
+ for(int i=(IsLowerTriangular ? 1 : size-2); IsLowerTriangular ? i<blockyStart : i>blockyStart; i += (IsLowerTriangular ? 1 : -1) )
+ {
+ Scalar tmp = other.coeff(i,c)
+ - (IsLowerTriangular ? ((lhs.row(i).start(i)) * other.col(c).start(i)).coeff(0,0)
+ : ((lhs.row(i).end(size-i-1)) * other.col(c).end(size-i-1)).coeff(0,0));
+ if (Lhs::Flags & UnitDiagBit)
+ other.coeffRef(i,c) = tmp;
+ else
+ other.coeffRef(i,c) = tmp/lhs.coeff(i,i);
+ }
+
+ // now let's process the remaining rows 4 at once
+ for(int i=blockyStart; IsLowerTriangular ? i<size : i>0; )
+ {
+ int startBlock = i;
+ int endBlock = startBlock + (IsLowerTriangular ? 4 : -4);
+
+ /* Process the i cols times 4 rows block, and keep the result in a temporary vector */
+ // FIXME use fixed size block but take care to small fixed size matrices...
+ Matrix<Scalar,Dynamic,1> btmp(4);
+ if (IsLowerTriangular)
+ btmp = lhs.block(startBlock,0,4,i) * other.col(c).start(i);
+ else
+ btmp = lhs.block(i-3,i+1,4,size-1-i) * other.col(c).end(size-1-i);
+
+ /* Let's process the 4x4 sub-matrix as usual.
+ * btmp stores the diagonal coefficients used to update the remaining part of the result.
+ */
+ {
+ Scalar tmp = other.coeff(startBlock,c)-btmp.coeff(IsLowerTriangular?0:3);
+ if (Lhs::Flags & UnitDiagBit)
+ other.coeffRef(i,c) = tmp;
+ else
+ other.coeffRef(i,c) = tmp/lhs.coeff(i,i);
+ }
+
+ i += IsLowerTriangular ? 1 : -1;
+ for (;IsLowerTriangular ? i<endBlock : i>endBlock; i += IsLowerTriangular ? 1 : -1)
+ {
+ int remainingSize = IsLowerTriangular ? i-startBlock : startBlock-i;
+ Scalar tmp = other.coeff(i,c)
+ - btmp.coeff(IsLowerTriangular ? remainingSize : 3-remainingSize)
+ - ( lhs.row(i).segment(IsLowerTriangular ? startBlock : i+1, remainingSize)
+ * other.col(c).segment(IsLowerTriangular ? startBlock : i+1, remainingSize)).coeff(0,0);
+
+ if (Lhs::Flags & UnitDiagBit)
+ other.coeffRef(i,c) = tmp;
+ else
+ other.coeffRef(i,c) = tmp/lhs.coeff(i,i);
+ }
+ }
+ }
+ }
+};
+
+// Implements the following configurations:
+// - inv(LowerTriangular, ColMajor) * Column vector
+// - inv(LowerTriangular,UnitDiag,ColMajor) * Column vector
+// - inv(UpperTriangular, ColMajor) * Column vector
+// - inv(UpperTriangular,UnitDiag,ColMajor) * Column vector
+template<typename Lhs, typename Rhs, int UpLo>
+struct ei_solve_triangular_selector<Lhs,Rhs,UpLo,ColMajor|IsDense>
+{
+ typedef typename Rhs::Scalar Scalar;
+ typedef typename ei_packet_traits<Scalar>::type Packet;
+ enum { PacketSize = ei_packet_traits<Scalar>::size };
+
+ static void run(const Lhs& lhs, Rhs& other)
+ {
+ static const bool IsLowerTriangular = (UpLo==LowerTriangular);
+ const int size = lhs.cols();
+ for(int c=0 ; c<other.cols() ; ++c)
+ {
+ /* let's perform the inverse product per block of 4 columns such that we perfectly match
+ * our optimized matrix * vector product. blockyEnd represents the number of rows
+ * we can process using the block version.
+ */
+ int blockyEnd = (std::max(size-5,0)/4)*4;
+ if (!IsLowerTriangular)
+ blockyEnd = size-1 - blockyEnd;
+ for(int i=IsLowerTriangular ? 0 : size-1; IsLowerTriangular ? i<blockyEnd : i>blockyEnd;)
+ {
+ /* Let's process the 4x4 sub-matrix as usual.
+ * btmp stores the diagonal coefficients used to update the remaining part of the result.
+ */
+ int startBlock = i;
+ int endBlock = startBlock + (IsLowerTriangular ? 4 : -4);
+ Matrix<Scalar,4,1> btmp;
+ for (;IsLowerTriangular ? i<endBlock : i>endBlock;
+ i += IsLowerTriangular ? 1 : -1)
+ {
+ if(!(Lhs::Flags & UnitDiagBit))
+ other.coeffRef(i,c) /= lhs.coeff(i,i);
+ int remainingSize = IsLowerTriangular ? endBlock-i-1 : i-endBlock-1;
+ if (remainingSize>0)
+ other.col(c).segment((IsLowerTriangular ? i : endBlock) + 1, remainingSize) -=
+ other.coeffRef(i,c)
+ * Block<Lhs,Dynamic,1>(lhs, (IsLowerTriangular ? i : endBlock) + 1, i, remainingSize, 1);
+ btmp.coeffRef(IsLowerTriangular ? i-startBlock : remainingSize) = -other.coeffRef(i,c);
+ }
+
+ /* Now we can efficiently update the remaining part of the result as a matrix * vector product.
+ * NOTE in order to reduce both compilation time and binary size, let's directly call
+ * the fast product implementation. It is equivalent to the following code:
+ * other.col(c).end(size-endBlock) += (lhs.block(endBlock, startBlock, size-endBlock, endBlock-startBlock)
+ * * other.col(c).block(startBlock,endBlock-startBlock)).lazy();
+ */
+ // FIXME this is cool but what about conjugate/adjoint expressions ? do we want to evaluate them ?
+ // this is a more general problem though.
+ ei_cache_friendly_product_colmajor_times_vector(
+ IsLowerTriangular ? size-endBlock : endBlock+1,
+ &(lhs.const_cast_derived().coeffRef(IsLowerTriangular ? endBlock : 0, IsLowerTriangular ? startBlock : endBlock+1)),
+ lhs.stride(),
+ btmp, &(other.coeffRef(IsLowerTriangular ? endBlock : 0, c)));
+// if (IsLowerTriangular)
+// other.col(c).end(size-endBlock) += (lhs.block(endBlock, startBlock, size-endBlock, endBlock-startBlock)
+// * other.col(c).block(startBlock,endBlock-startBlock)).lazy();
+// else
+// other.col(c).end(size-endBlock) += (lhs.block(endBlock, startBlock, size-endBlock, endBlock-startBlock)
+// * other.col(c).block(startBlock,endBlock-startBlock)).lazy();
+ }
+
+ /* Now we have to process the remaining part as usual */
+ int i;
+ for(i=blockyEnd; IsLowerTriangular ? i<size-1 : i>0; i += (IsLowerTriangular ? 1 : -1) )
+ {
+ if(!(Lhs::Flags & UnitDiagBit))
+ other.coeffRef(i,c) /= lhs.coeff(i,i);
+
+ /* NOTE we cannot use lhs.col(i).end(size-i-1) because Part::coeffRef gets called by .col() to
+ * get the address of the start of the row
+ */
+ if(IsLowerTriangular)
+ other.col(c).end(size-i-1) -= other.coeffRef(i,c) * Block<Lhs,Dynamic,1>(lhs, i+1,i, size-i-1,1);
+ else
+ other.col(c).start(i) -= other.coeffRef(i,c) * Block<Lhs,Dynamic,1>(lhs, 0,i, i, 1);
+ }
+ if(!(Lhs::Flags & UnitDiagBit))
+ other.coeffRef(i,c) /= lhs.coeff(i,i);
+ }
+ }
+};
+
+/** "in-place" version of MatrixBase::solveTriangular() where the result is written in \a other
+ *
+ * \nonstableyet
+ *
+ * The parameter is only marked 'const' to make the C++ compiler accept a temporary expression here.
+ * This function will const_cast it, so constness isn't honored here.
+ *
+ * See MatrixBase:solveTriangular() for the details.
+ */
+template<typename Derived>
+template<typename OtherDerived>
+void MatrixBase<Derived>::solveTriangularInPlace(const MatrixBase<OtherDerived>& _other) const
+{
+ MatrixBase<OtherDerived>& other = _other.const_cast_derived();
+ ei_assert(derived().cols() == derived().rows());
+ ei_assert(derived().cols() == other.rows());
+ ei_assert(!(Flags & ZeroDiagBit));
+ ei_assert(Flags & (UpperTriangularBit|LowerTriangularBit));
+
+ enum { copy = ei_traits<OtherDerived>::Flags & RowMajorBit };
+
+ typedef typename ei_meta_if<copy,
+ typename ei_plain_matrix_type_column_major<OtherDerived>::type, OtherDerived&>::ret OtherCopy;
+ OtherCopy otherCopy(other.derived());
+
+ ei_solve_triangular_selector<Derived, typename ei_unref<OtherCopy>::type>::run(derived(), otherCopy);
+
+ if (copy)
+ other = otherCopy;
+}
+
+/** \returns the product of the inverse of \c *this with \a other, \a *this being triangular.
+ *
+ * \nonstableyet
+ *
+ * This function computes the inverse-matrix matrix product inverse(\c *this) * \a other.
+ * The matrix \c *this must be triangular and invertible (i.e., all the coefficients of the
+ * diagonal must be non zero). It works as a forward (resp. backward) substitution if \c *this
+ * is an upper (resp. lower) triangular matrix.
+ *
+ * It is required that \c *this be marked as either an upper or a lower triangular matrix, which
+ * can be done by marked(), and that is automatically the case with expressions such as those returned
+ * by extract().
+ *
+ * \addexample SolveTriangular \label How to solve a triangular system (aka. how to multiply the inverse of a triangular matrix by another one)
+ *
+ * Example: \include MatrixBase_marked.cpp
+ * Output: \verbinclude MatrixBase_marked.out
+ *
+ * This function is essentially a wrapper to the faster solveTriangularInPlace() function creating
+ * a temporary copy of \a other, calling solveTriangularInPlace() on the copy and returning it.
+ * Therefore, if \a other is not needed anymore, it is quite faster to call solveTriangularInPlace()
+ * instead of solveTriangular().
+ *
+ * For users coming from BLAS, this function (and more specifically solveTriangularInPlace()) offer
+ * all the operations supported by the \c *TRSV and \c *TRSM BLAS routines.
+ *
+ * \b Tips: to perform a \em "right-inverse-multiply" you can simply transpose the operation, e.g.:
+ * \code
+ * M * T^1 <=> T.transpose().solveTriangularInPlace(M.transpose());
+ * \endcode
+ *
+ * \sa solveTriangularInPlace(), marked(), extract()
+ */
+template<typename Derived>
+template<typename OtherDerived>
+typename ei_plain_matrix_type_column_major<OtherDerived>::type
+MatrixBase<Derived>::solveTriangular(const MatrixBase<OtherDerived>& other) const
+{
+ typename ei_plain_matrix_type_column_major<OtherDerived>::type res(other);
+ solveTriangularInPlace(res);
+ return res;
+}
+
+#endif // EIGEN_SOLVETRIANGULAR_H
diff --git a/extern/Eigen2/Eigen/src/Core/Sum.h b/extern/Eigen2/Eigen/src/Core/Sum.h
new file mode 100644
index 00000000000..6d7e9959fa5
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/Sum.h
@@ -0,0 +1,271 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SUM_H
+#define EIGEN_SUM_H
+
+/***************************************************************************
+* Part 1 : the logic deciding a strategy for vectorization and unrolling
+***************************************************************************/
+
+template<typename Derived>
+struct ei_sum_traits
+{
+private:
+ enum {
+ PacketSize = ei_packet_traits<typename Derived::Scalar>::size
+ };
+
+public:
+ enum {
+ Vectorization = (int(Derived::Flags)&ActualPacketAccessBit)
+ && (int(Derived::Flags)&LinearAccessBit)
+ ? LinearVectorization
+ : NoVectorization
+ };
+
+private:
+ enum {
+ Cost = Derived::SizeAtCompileTime * Derived::CoeffReadCost
+ + (Derived::SizeAtCompileTime-1) * NumTraits<typename Derived::Scalar>::AddCost,
+ UnrollingLimit = EIGEN_UNROLLING_LIMIT * (int(Vectorization) == int(NoVectorization) ? 1 : int(PacketSize))
+ };
+
+public:
+ enum {
+ Unrolling = Cost <= UnrollingLimit
+ ? CompleteUnrolling
+ : NoUnrolling
+ };
+};
+
+/***************************************************************************
+* Part 2 : unrollers
+***************************************************************************/
+
+/*** no vectorization ***/
+
+template<typename Derived, int Start, int Length>
+struct ei_sum_novec_unroller
+{
+ enum {
+ HalfLength = Length/2
+ };
+
+ typedef typename Derived::Scalar Scalar;
+
+ inline static Scalar run(const Derived &mat)
+ {
+ return ei_sum_novec_unroller<Derived, Start, HalfLength>::run(mat)
+ + ei_sum_novec_unroller<Derived, Start+HalfLength, Length-HalfLength>::run(mat);
+ }
+};
+
+template<typename Derived, int Start>
+struct ei_sum_novec_unroller<Derived, Start, 1>
+{
+ enum {
+ col = Start / Derived::RowsAtCompileTime,
+ row = Start % Derived::RowsAtCompileTime
+ };
+
+ typedef typename Derived::Scalar Scalar;
+
+ inline static Scalar run(const Derived &mat)
+ {
+ return mat.coeff(row, col);
+ }
+};
+
+/*** vectorization ***/
+
+template<typename Derived, int Start, int Length>
+struct ei_sum_vec_unroller
+{
+ enum {
+ PacketSize = ei_packet_traits<typename Derived::Scalar>::size,
+ HalfLength = Length/2
+ };
+
+ typedef typename Derived::Scalar Scalar;
+ typedef typename ei_packet_traits<Scalar>::type PacketScalar;
+
+ inline static PacketScalar run(const Derived &mat)
+ {
+ return ei_padd(
+ ei_sum_vec_unroller<Derived, Start, HalfLength>::run(mat),
+ ei_sum_vec_unroller<Derived, Start+HalfLength, Length-HalfLength>::run(mat) );
+ }
+};
+
+template<typename Derived, int Start>
+struct ei_sum_vec_unroller<Derived, Start, 1>
+{
+ enum {
+ index = Start * ei_packet_traits<typename Derived::Scalar>::size,
+ row = int(Derived::Flags)&RowMajorBit
+ ? index / int(Derived::ColsAtCompileTime)
+ : index % Derived::RowsAtCompileTime,
+ col = int(Derived::Flags)&RowMajorBit
+ ? index % int(Derived::ColsAtCompileTime)
+ : index / Derived::RowsAtCompileTime,
+ alignment = (Derived::Flags & AlignedBit) ? Aligned : Unaligned
+ };
+
+ typedef typename Derived::Scalar Scalar;
+ typedef typename ei_packet_traits<Scalar>::type PacketScalar;
+
+ inline static PacketScalar run(const Derived &mat)
+ {
+ return mat.template packet<alignment>(row, col);
+ }
+};
+
+/***************************************************************************
+* Part 3 : implementation of all cases
+***************************************************************************/
+
+template<typename Derived,
+ int Vectorization = ei_sum_traits<Derived>::Vectorization,
+ int Unrolling = ei_sum_traits<Derived>::Unrolling
+>
+struct ei_sum_impl;
+
+template<typename Derived>
+struct ei_sum_impl<Derived, NoVectorization, NoUnrolling>
+{
+ typedef typename Derived::Scalar Scalar;
+ static Scalar run(const Derived& mat)
+ {
+ ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using a non initialized matrix");
+ Scalar res;
+ res = mat.coeff(0, 0);
+ for(int i = 1; i < mat.rows(); ++i)
+ res += mat.coeff(i, 0);
+ for(int j = 1; j < mat.cols(); ++j)
+ for(int i = 0; i < mat.rows(); ++i)
+ res += mat.coeff(i, j);
+ return res;
+ }
+};
+
+template<typename Derived>
+struct ei_sum_impl<Derived, NoVectorization, CompleteUnrolling>
+ : public ei_sum_novec_unroller<Derived, 0, Derived::SizeAtCompileTime>
+{};
+
+template<typename Derived>
+struct ei_sum_impl<Derived, LinearVectorization, NoUnrolling>
+{
+ typedef typename Derived::Scalar Scalar;
+ typedef typename ei_packet_traits<Scalar>::type PacketScalar;
+
+ static Scalar run(const Derived& mat)
+ {
+ const int size = mat.size();
+ const int packetSize = ei_packet_traits<Scalar>::size;
+ const int alignedStart = (Derived::Flags & AlignedBit)
+ || !(Derived::Flags & DirectAccessBit)
+ ? 0
+ : ei_alignmentOffset(&mat.const_cast_derived().coeffRef(0), size);
+ enum {
+ alignment = (Derived::Flags & DirectAccessBit) || (Derived::Flags & AlignedBit)
+ ? Aligned : Unaligned
+ };
+ const int alignedSize = ((size-alignedStart)/packetSize)*packetSize;
+ const int alignedEnd = alignedStart + alignedSize;
+ Scalar res;
+
+ if(alignedSize)
+ {
+ PacketScalar packet_res = mat.template packet<alignment>(alignedStart);
+ for(int index = alignedStart + packetSize; index < alignedEnd; index += packetSize)
+ packet_res = ei_padd(packet_res, mat.template packet<alignment>(index));
+ res = ei_predux(packet_res);
+ }
+ else // too small to vectorize anything.
+ // since this is dynamic-size hence inefficient anyway for such small sizes, don't try to optimize.
+ {
+ res = Scalar(0);
+ }
+
+ for(int index = 0; index < alignedStart; ++index)
+ res += mat.coeff(index);
+
+ for(int index = alignedEnd; index < size; ++index)
+ res += mat.coeff(index);
+
+ return res;
+ }
+};
+
+template<typename Derived>
+struct ei_sum_impl<Derived, LinearVectorization, CompleteUnrolling>
+{
+ typedef typename Derived::Scalar Scalar;
+ typedef typename ei_packet_traits<Scalar>::type PacketScalar;
+ enum {
+ PacketSize = ei_packet_traits<Scalar>::size,
+ Size = Derived::SizeAtCompileTime,
+ VectorizationSize = (Size / PacketSize) * PacketSize
+ };
+ static Scalar run(const Derived& mat)
+ {
+ Scalar res = ei_predux(ei_sum_vec_unroller<Derived, 0, Size / PacketSize>::run(mat));
+ if (VectorizationSize != Size)
+ res += ei_sum_novec_unroller<Derived, VectorizationSize, Size-VectorizationSize>::run(mat);
+ return res;
+ }
+};
+
+/***************************************************************************
+* Part 4 : implementation of MatrixBase methods
+***************************************************************************/
+
+/** \returns the sum of all coefficients of *this
+ *
+ * \sa trace()
+ */
+template<typename Derived>
+inline typename ei_traits<Derived>::Scalar
+MatrixBase<Derived>::sum() const
+{
+ return ei_sum_impl<Derived>::run(derived());
+}
+
+/** \returns the trace of \c *this, i.e. the sum of the coefficients on the main diagonal.
+ *
+ * \c *this can be any matrix, not necessarily square.
+ *
+ * \sa diagonal(), sum()
+ */
+template<typename Derived>
+inline typename ei_traits<Derived>::Scalar
+MatrixBase<Derived>::trace() const
+{
+ return diagonal().sum();
+}
+
+#endif // EIGEN_SUM_H
diff --git a/extern/Eigen3/Eigen/src/Core/Swap.h b/extern/Eigen2/Eigen/src/Core/Swap.h
index 5fb03286675..9aaac652fd8 100644
--- a/extern/Eigen3/Eigen/src/Core/Swap.h
+++ b/extern/Eigen2/Eigen/src/Core/Swap.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
@@ -26,58 +26,54 @@
#define EIGEN_SWAP_H
/** \class SwapWrapper
- * \ingroup Core_Module
*
* \internal
*
* \brief Internal helper class for swapping two expressions
*/
-namespace internal {
template<typename ExpressionType>
-struct traits<SwapWrapper<ExpressionType> > : traits<ExpressionType> {};
-}
+struct ei_traits<SwapWrapper<ExpressionType> >
+{
+ typedef typename ExpressionType::Scalar Scalar;
+ enum {
+ RowsAtCompileTime = ExpressionType::RowsAtCompileTime,
+ ColsAtCompileTime = ExpressionType::ColsAtCompileTime,
+ MaxRowsAtCompileTime = ExpressionType::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = ExpressionType::MaxColsAtCompileTime,
+ Flags = ExpressionType::Flags,
+ CoeffReadCost = ExpressionType::CoeffReadCost
+ };
+};
template<typename ExpressionType> class SwapWrapper
- : public internal::dense_xpr_base<SwapWrapper<ExpressionType> >::type
+ : public MatrixBase<SwapWrapper<ExpressionType> >
{
public:
- typedef typename internal::dense_xpr_base<SwapWrapper>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(SwapWrapper)
- typedef typename internal::packet_traits<Scalar>::type Packet;
+ EIGEN_GENERIC_PUBLIC_INTERFACE(SwapWrapper)
+ typedef typename ei_packet_traits<Scalar>::type Packet;
inline SwapWrapper(ExpressionType& xpr) : m_expression(xpr) {}
- inline Index rows() const { return m_expression.rows(); }
- inline Index cols() const { return m_expression.cols(); }
- inline Index outerStride() const { return m_expression.outerStride(); }
- inline Index innerStride() const { return m_expression.innerStride(); }
+ inline int rows() const { return m_expression.rows(); }
+ inline int cols() const { return m_expression.cols(); }
+ inline int stride() const { return m_expression.stride(); }
- inline Scalar& coeffRef(Index row, Index col)
+ inline Scalar& coeffRef(int row, int col)
{
return m_expression.const_cast_derived().coeffRef(row, col);
}
- inline Scalar& coeffRef(Index index)
+ inline Scalar& coeffRef(int index)
{
return m_expression.const_cast_derived().coeffRef(index);
}
- inline Scalar& coeffRef(Index row, Index col) const
- {
- return m_expression.coeffRef(row, col);
- }
-
- inline Scalar& coeffRef(Index index) const
- {
- return m_expression.coeffRef(index);
- }
-
template<typename OtherDerived>
- void copyCoeff(Index row, Index col, const DenseBase<OtherDerived>& other)
+ void copyCoeff(int row, int col, const MatrixBase<OtherDerived>& other)
{
OtherDerived& _other = other.const_cast_derived();
- eigen_internal_assert(row >= 0 && row < rows()
+ ei_internal_assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
Scalar tmp = m_expression.coeff(row, col);
m_expression.coeffRef(row, col) = _other.coeff(row, col);
@@ -85,20 +81,20 @@ template<typename ExpressionType> class SwapWrapper
}
template<typename OtherDerived>
- void copyCoeff(Index index, const DenseBase<OtherDerived>& other)
+ void copyCoeff(int index, const MatrixBase<OtherDerived>& other)
{
OtherDerived& _other = other.const_cast_derived();
- eigen_internal_assert(index >= 0 && index < m_expression.size());
+ ei_internal_assert(index >= 0 && index < m_expression.size());
Scalar tmp = m_expression.coeff(index);
m_expression.coeffRef(index) = _other.coeff(index);
_other.coeffRef(index) = tmp;
}
template<typename OtherDerived, int StoreMode, int LoadMode>
- void copyPacket(Index row, Index col, const DenseBase<OtherDerived>& other)
+ void copyPacket(int row, int col, const MatrixBase<OtherDerived>& other)
{
OtherDerived& _other = other.const_cast_derived();
- eigen_internal_assert(row >= 0 && row < rows()
+ ei_internal_assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
Packet tmp = m_expression.template packet<StoreMode>(row, col);
m_expression.template writePacket<StoreMode>(row, col,
@@ -108,10 +104,10 @@ template<typename ExpressionType> class SwapWrapper
}
template<typename OtherDerived, int StoreMode, int LoadMode>
- void copyPacket(Index index, const DenseBase<OtherDerived>& other)
+ void copyPacket(int index, const MatrixBase<OtherDerived>& other)
{
OtherDerived& _other = other.const_cast_derived();
- eigen_internal_assert(index >= 0 && index < m_expression.size());
+ ei_internal_assert(index >= 0 && index < m_expression.size());
Packet tmp = m_expression.template packet<StoreMode>(index);
m_expression.template writePacket<StoreMode>(index,
_other.template packet<LoadMode>(index)
@@ -121,6 +117,29 @@ template<typename ExpressionType> class SwapWrapper
protected:
ExpressionType& m_expression;
+
+ private:
+ SwapWrapper& operator=(const SwapWrapper&);
};
+/** swaps *this with the expression \a other.
+ *
+ * \note \a other is only marked for internal reasons, but of course
+ * it gets const-casted. One reason is that one will often call swap
+ * on temporary objects (hence non-const references are forbidden).
+ * Another reason is that lazyAssign takes a const argument anyway.
+ */
+template<typename Derived>
+template<typename OtherDerived>
+void MatrixBase<Derived>::swap(const MatrixBase<OtherDerived>& other)
+{
+ (SwapWrapper<Derived>(derived())).lazyAssign(other);
+}
+
#endif // EIGEN_SWAP_H
+
+
+
+
+
+
diff --git a/extern/Eigen2/Eigen/src/Core/Transpose.h b/extern/Eigen2/Eigen/src/Core/Transpose.h
new file mode 100644
index 00000000000..870edfe320b
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/Transpose.h
@@ -0,0 +1,228 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_TRANSPOSE_H
+#define EIGEN_TRANSPOSE_H
+
+/** \class Transpose
+ *
+ * \brief Expression of the transpose of a matrix
+ *
+ * \param MatrixType the type of the object of which we are taking the transpose
+ *
+ * This class represents an expression of the transpose of a matrix.
+ * It is the return type of MatrixBase::transpose() and MatrixBase::adjoint()
+ * and most of the time this is the only way it is used.
+ *
+ * \sa MatrixBase::transpose(), MatrixBase::adjoint()
+ */
+template<typename MatrixType>
+struct ei_traits<Transpose<MatrixType> >
+{
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
+ typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
+ enum {
+ RowsAtCompileTime = MatrixType::ColsAtCompileTime,
+ ColsAtCompileTime = MatrixType::RowsAtCompileTime,
+ MaxRowsAtCompileTime = MatrixType::MaxColsAtCompileTime,
+ MaxColsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
+ Flags = ((int(_MatrixTypeNested::Flags) ^ RowMajorBit)
+ & ~(LowerTriangularBit | UpperTriangularBit))
+ | (int(_MatrixTypeNested::Flags)&UpperTriangularBit ? LowerTriangularBit : 0)
+ | (int(_MatrixTypeNested::Flags)&LowerTriangularBit ? UpperTriangularBit : 0),
+ CoeffReadCost = _MatrixTypeNested::CoeffReadCost
+ };
+};
+
+template<typename MatrixType> class Transpose
+ : public MatrixBase<Transpose<MatrixType> >
+{
+ public:
+
+ EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose)
+
+ inline Transpose(const MatrixType& matrix) : m_matrix(matrix) {}
+
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose)
+
+ inline int rows() const { return m_matrix.cols(); }
+ inline int cols() const { return m_matrix.rows(); }
+ inline int nonZeros() const { return m_matrix.nonZeros(); }
+ inline int stride(void) const { return m_matrix.stride(); }
+
+ inline Scalar& coeffRef(int row, int col)
+ {
+ return m_matrix.const_cast_derived().coeffRef(col, row);
+ }
+
+ inline const Scalar coeff(int row, int col) const
+ {
+ return m_matrix.coeff(col, row);
+ }
+
+ inline const Scalar coeff(int index) const
+ {
+ return m_matrix.coeff(index);
+ }
+
+ inline Scalar& coeffRef(int index)
+ {
+ return m_matrix.const_cast_derived().coeffRef(index);
+ }
+
+ template<int LoadMode>
+ inline const PacketScalar packet(int row, int col) const
+ {
+ return m_matrix.template packet<LoadMode>(col, row);
+ }
+
+ template<int LoadMode>
+ inline void writePacket(int row, int col, const PacketScalar& x)
+ {
+ m_matrix.const_cast_derived().template writePacket<LoadMode>(col, row, x);
+ }
+
+ template<int LoadMode>
+ inline const PacketScalar packet(int index) const
+ {
+ return m_matrix.template packet<LoadMode>(index);
+ }
+
+ template<int LoadMode>
+ inline void writePacket(int index, const PacketScalar& x)
+ {
+ m_matrix.const_cast_derived().template writePacket<LoadMode>(index, x);
+ }
+
+ protected:
+ const typename MatrixType::Nested m_matrix;
+};
+
+/** \returns an expression of the transpose of *this.
+ *
+ * Example: \include MatrixBase_transpose.cpp
+ * Output: \verbinclude MatrixBase_transpose.out
+ *
+ * \warning If you want to replace a matrix by its own transpose, do \b NOT do this:
+ * \code
+ * m = m.transpose(); // bug!!! caused by aliasing effect
+ * \endcode
+ * Instead, use the transposeInPlace() method:
+ * \code
+ * m.transposeInPlace();
+ * \endcode
+ * which gives Eigen good opportunities for optimization, or alternatively you can also do:
+ * \code
+ * m = m.transpose().eval();
+ * \endcode
+ *
+ * \sa transposeInPlace(), adjoint() */
+template<typename Derived>
+inline Transpose<Derived>
+MatrixBase<Derived>::transpose()
+{
+ return derived();
+}
+
+/** This is the const version of transpose().
+ *
+ * Make sure you read the warning for transpose() !
+ *
+ * \sa transposeInPlace(), adjoint() */
+template<typename Derived>
+inline const Transpose<Derived>
+MatrixBase<Derived>::transpose() const
+{
+ return derived();
+}
+
+/** \returns an expression of the adjoint (i.e. conjugate transpose) of *this.
+ *
+ * Example: \include MatrixBase_adjoint.cpp
+ * Output: \verbinclude MatrixBase_adjoint.out
+ *
+ * \warning If you want to replace a matrix by its own adjoint, do \b NOT do this:
+ * \code
+ * m = m.adjoint(); // bug!!! caused by aliasing effect
+ * \endcode
+ * Instead, do:
+ * \code
+ * m = m.adjoint().eval();
+ * \endcode
+ *
+ * \sa transpose(), conjugate(), class Transpose, class ei_scalar_conjugate_op */
+template<typename Derived>
+inline const typename MatrixBase<Derived>::AdjointReturnType
+MatrixBase<Derived>::adjoint() const
+{
+ return conjugate().nestByValue();
+}
+
+/***************************************************************************
+* "in place" transpose implementation
+***************************************************************************/
+
+template<typename MatrixType,
+ bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) && MatrixType::RowsAtCompileTime!=Dynamic>
+struct ei_inplace_transpose_selector;
+
+template<typename MatrixType>
+struct ei_inplace_transpose_selector<MatrixType,true> { // square matrix
+ static void run(MatrixType& m) {
+ m.template part<StrictlyUpperTriangular>().swap(m.transpose());
+ }
+};
+
+template<typename MatrixType>
+struct ei_inplace_transpose_selector<MatrixType,false> { // non square matrix
+ static void run(MatrixType& m) {
+ if (m.rows()==m.cols())
+ m.template part<StrictlyUpperTriangular>().swap(m.transpose());
+ else
+ m = m.transpose().eval();
+ }
+};
+
+/** This is the "in place" version of transpose: it transposes \c *this.
+ *
+ * In most cases it is probably better to simply use the transposed expression
+ * of a matrix. However, when transposing the matrix data itself is really needed,
+ * then this "in-place" version is probably the right choice because it provides
+ * the following additional features:
+ * - less error prone: doing the same operation with .transpose() requires special care:
+ * \code m = m.transpose().eval(); \endcode
+ * - no temporary object is created (currently only for squared matrices)
+ * - it allows future optimizations (cache friendliness, etc.)
+ *
+ * \note if the matrix is not square, then \c *this must be a resizable matrix.
+ *
+ * \sa transpose(), adjoint() */
+template<typename Derived>
+inline void MatrixBase<Derived>::transposeInPlace()
+{
+ ei_inplace_transpose_selector<Derived>::run(derived());
+}
+
+#endif // EIGEN_TRANSPOSE_H
diff --git a/extern/Eigen3/Eigen/src/Core/Visitor.h b/extern/Eigen2/Eigen/src/Core/Visitor.h
index 378ebcba174..7569114e90d 100644
--- a/extern/Eigen3/Eigen/src/Core/Visitor.h
+++ b/extern/Eigen2/Eigen/src/Core/Visitor.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -25,10 +25,8 @@
#ifndef EIGEN_VISITOR_H
#define EIGEN_VISITOR_H
-namespace internal {
-
template<typename Visitor, typename Derived, int UnrollCount>
-struct visitor_impl
+struct ei_visitor_impl
{
enum {
col = (UnrollCount-1) / Derived::RowsAtCompileTime,
@@ -37,13 +35,13 @@ struct visitor_impl
inline static void run(const Derived &mat, Visitor& visitor)
{
- visitor_impl<Visitor, Derived, UnrollCount-1>::run(mat, visitor);
+ ei_visitor_impl<Visitor, Derived, UnrollCount-1>::run(mat, visitor);
visitor(mat.coeff(row, col), row, col);
}
};
template<typename Visitor, typename Derived>
-struct visitor_impl<Visitor, Derived, 1>
+struct ei_visitor_impl<Visitor, Derived, 1>
{
inline static void run(const Derived &mat, Visitor& visitor)
{
@@ -52,21 +50,19 @@ struct visitor_impl<Visitor, Derived, 1>
};
template<typename Visitor, typename Derived>
-struct visitor_impl<Visitor, Derived, Dynamic>
+struct ei_visitor_impl<Visitor, Derived, Dynamic>
{
- typedef typename Derived::Index Index;
inline static void run(const Derived& mat, Visitor& visitor)
{
visitor.init(mat.coeff(0,0), 0, 0);
- for(Index i = 1; i < mat.rows(); ++i)
+ for(int i = 1; i < mat.rows(); ++i)
visitor(mat.coeff(i, 0), i, 0);
- for(Index j = 1; j < mat.cols(); ++j)
- for(Index i = 0; i < mat.rows(); ++i)
+ for(int j = 1; j < mat.cols(); ++j)
+ for(int i = 0; i < mat.rows(); ++i)
visitor(mat.coeff(i, j), i, j);
}
};
-} // end namespace internal
/** Applies the visitor \a visitor to the whole coefficients of the matrix or vector.
*
@@ -74,44 +70,38 @@ struct visitor_impl<Visitor, Derived, Dynamic>
* \code
* struct MyVisitor {
* // called for the first coefficient
- * void init(const Scalar& value, Index i, Index j);
+ * void init(const Scalar& value, int i, int j);
* // called for all other coefficients
- * void operator() (const Scalar& value, Index i, Index j);
+ * void operator() (const Scalar& value, int i, int j);
* };
* \endcode
*
* \note compared to one or two \em for \em loops, visitors offer automatic
* unrolling for small fixed size matrix.
*
- * \sa minCoeff(Index*,Index*), maxCoeff(Index*,Index*), DenseBase::redux()
+ * \sa minCoeff(int*,int*), maxCoeff(int*,int*), MatrixBase::redux()
*/
template<typename Derived>
template<typename Visitor>
-void DenseBase<Derived>::visit(Visitor& visitor) const
+void MatrixBase<Derived>::visit(Visitor& visitor) const
{
- enum { unroll = SizeAtCompileTime != Dynamic
- && CoeffReadCost != Dynamic
- && (SizeAtCompileTime == 1 || internal::functor_traits<Visitor>::Cost != Dynamic)
- && SizeAtCompileTime * CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits<Visitor>::Cost
- <= EIGEN_UNROLLING_LIMIT };
- return internal::visitor_impl<Visitor, Derived,
+ const bool unroll = SizeAtCompileTime * CoeffReadCost
+ + (SizeAtCompileTime-1) * ei_functor_traits<Visitor>::Cost
+ <= EIGEN_UNROLLING_LIMIT;
+ return ei_visitor_impl<Visitor, Derived,
unroll ? int(SizeAtCompileTime) : Dynamic
>::run(derived(), visitor);
}
-namespace internal {
-
/** \internal
* \brief Base class to implement min and max visitors
*/
-template <typename Derived>
-struct coeff_visitor
+template <typename Scalar>
+struct ei_coeff_visitor
{
- typedef typename Derived::Index Index;
- typedef typename Derived::Scalar Scalar;
- Index row, col;
+ int row, col;
Scalar res;
- inline void init(const Scalar& value, Index i, Index j)
+ inline void init(const Scalar& value, int i, int j)
{
res = value;
row = i;
@@ -122,14 +112,12 @@ struct coeff_visitor
/** \internal
* \brief Visitor computing the min coefficient with its value and coordinates
*
- * \sa DenseBase::minCoeff(Index*, Index*)
+ * \sa MatrixBase::minCoeff(int*, int*)
*/
-template <typename Derived>
-struct min_coeff_visitor : coeff_visitor<Derived>
+template <typename Scalar>
+struct ei_min_coeff_visitor : ei_coeff_visitor<Scalar>
{
- typedef typename Derived::Index Index;
- typedef typename Derived::Scalar Scalar;
- void operator() (const Scalar& value, Index i, Index j)
+ void operator() (const Scalar& value, int i, int j)
{
if(value < this->res)
{
@@ -141,7 +129,7 @@ struct min_coeff_visitor : coeff_visitor<Derived>
};
template<typename Scalar>
-struct functor_traits<min_coeff_visitor<Scalar> > {
+struct ei_functor_traits<ei_min_coeff_visitor<Scalar> > {
enum {
Cost = NumTraits<Scalar>::AddCost
};
@@ -150,14 +138,12 @@ struct functor_traits<min_coeff_visitor<Scalar> > {
/** \internal
* \brief Visitor computing the max coefficient with its value and coordinates
*
- * \sa DenseBase::maxCoeff(Index*, Index*)
+ * \sa MatrixBase::maxCoeff(int*, int*)
*/
-template <typename Derived>
-struct max_coeff_visitor : coeff_visitor<Derived>
+template <typename Scalar>
+struct ei_max_coeff_visitor : ei_coeff_visitor<Scalar>
{
- typedef typename Derived::Index Index;
- typedef typename Derived::Scalar Scalar;
- void operator() (const Scalar& value, Index i, Index j)
+ void operator() (const Scalar& value, int i, int j)
{
if(value > this->res)
{
@@ -169,25 +155,22 @@ struct max_coeff_visitor : coeff_visitor<Derived>
};
template<typename Scalar>
-struct functor_traits<max_coeff_visitor<Scalar> > {
+struct ei_functor_traits<ei_max_coeff_visitor<Scalar> > {
enum {
Cost = NumTraits<Scalar>::AddCost
};
};
-} // end namespace internal
-
/** \returns the minimum of all coefficients of *this
* and puts in *row and *col its location.
*
- * \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visitor(), DenseBase::minCoeff()
+ * \sa MatrixBase::minCoeff(int*), MatrixBase::maxCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::minCoeff()
*/
template<typename Derived>
-template<typename IndexType>
-typename internal::traits<Derived>::Scalar
-DenseBase<Derived>::minCoeff(IndexType* row, IndexType* col) const
+typename ei_traits<Derived>::Scalar
+MatrixBase<Derived>::minCoeff(int* row, int* col) const
{
- internal::min_coeff_visitor<Derived> minVisitor;
+ ei_min_coeff_visitor<Scalar> minVisitor;
this->visit(minVisitor);
*row = minVisitor.row;
if (col) *col = minVisitor.col;
@@ -197,15 +180,14 @@ DenseBase<Derived>::minCoeff(IndexType* row, IndexType* col) const
/** \returns the minimum of all coefficients of *this
* and puts in *index its location.
*
- * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::minCoeff()
+ * \sa MatrixBase::minCoeff(int*,int*), MatrixBase::maxCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::minCoeff()
*/
template<typename Derived>
-template<typename IndexType>
-typename internal::traits<Derived>::Scalar
-DenseBase<Derived>::minCoeff(IndexType* index) const
+typename ei_traits<Derived>::Scalar
+MatrixBase<Derived>::minCoeff(int* index) const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- internal::min_coeff_visitor<Derived> minVisitor;
+ ei_min_coeff_visitor<Scalar> minVisitor;
this->visit(minVisitor);
*index = (RowsAtCompileTime==1) ? minVisitor.col : minVisitor.row;
return minVisitor.res;
@@ -214,14 +196,13 @@ DenseBase<Derived>::minCoeff(IndexType* index) const
/** \returns the maximum of all coefficients of *this
* and puts in *row and *col its location.
*
- * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
+ * \sa MatrixBase::minCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::maxCoeff()
*/
template<typename Derived>
-template<typename IndexType>
-typename internal::traits<Derived>::Scalar
-DenseBase<Derived>::maxCoeff(IndexType* row, IndexType* col) const
+typename ei_traits<Derived>::Scalar
+MatrixBase<Derived>::maxCoeff(int* row, int* col) const
{
- internal::max_coeff_visitor<Derived> maxVisitor;
+ ei_max_coeff_visitor<Scalar> maxVisitor;
this->visit(maxVisitor);
*row = maxVisitor.row;
if (col) *col = maxVisitor.col;
@@ -231,15 +212,14 @@ DenseBase<Derived>::maxCoeff(IndexType* row, IndexType* col) const
/** \returns the maximum of all coefficients of *this
* and puts in *index its location.
*
- * \sa DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
+ * \sa MatrixBase::maxCoeff(int*,int*), MatrixBase::minCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::maxCoeff()
*/
template<typename Derived>
-template<typename IndexType>
-typename internal::traits<Derived>::Scalar
-DenseBase<Derived>::maxCoeff(IndexType* index) const
+typename ei_traits<Derived>::Scalar
+MatrixBase<Derived>::maxCoeff(int* index) const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- internal::max_coeff_visitor<Derived> maxVisitor;
+ ei_max_coeff_visitor<Scalar> maxVisitor;
this->visit(maxVisitor);
*index = (RowsAtCompileTime==1) ? maxVisitor.col : maxVisitor.row;
return maxVisitor.res;
diff --git a/extern/Eigen2/Eigen/src/Core/arch/AltiVec/PacketMath.h b/extern/Eigen2/Eigen/src/Core/arch/AltiVec/PacketMath.h
new file mode 100644
index 00000000000..4de3b5e2e0b
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/arch/AltiVec/PacketMath.h
@@ -0,0 +1,354 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Konstantinos Margaritis <markos@codex.gr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_PACKET_MATH_ALTIVEC_H
+#define EIGEN_PACKET_MATH_ALTIVEC_H
+
+#ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
+#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 4
+#endif
+
+typedef __vector float v4f;
+typedef __vector int v4i;
+typedef __vector unsigned int v4ui;
+typedef __vector __bool int v4bi;
+
+// We don't want to write the same code all the time, but we need to reuse the constants
+// and it doesn't really work to declare them global, so we define macros instead
+
+#define USE_CONST_v0i const v4i v0i = vec_splat_s32(0)
+#define USE_CONST_v1i const v4i v1i = vec_splat_s32(1)
+#define USE_CONST_v16i_ const v4i v16i_ = vec_splat_s32(-16)
+#define USE_CONST_v0f USE_CONST_v0i; const v4f v0f = (v4f) v0i
+#define USE_CONST_v1f USE_CONST_v1i; const v4f v1f = vec_ctf(v1i, 0)
+#define USE_CONST_v1i_ const v4ui v1i_ = vec_splat_u32(-1)
+#define USE_CONST_v0f_ USE_CONST_v1i_; const v4f v0f_ = (v4f) vec_sl(v1i_, v1i_)
+
+template<> struct ei_packet_traits<float> { typedef v4f type; enum {size=4}; };
+template<> struct ei_packet_traits<int> { typedef v4i type; enum {size=4}; };
+
+template<> struct ei_unpacket_traits<v4f> { typedef float type; enum {size=4}; };
+template<> struct ei_unpacket_traits<v4i> { typedef int type; enum {size=4}; };
+
+inline std::ostream & operator <<(std::ostream & s, const v4f & v)
+{
+ union {
+ v4f v;
+ float n[4];
+ } vt;
+ vt.v = v;
+ s << vt.n[0] << ", " << vt.n[1] << ", " << vt.n[2] << ", " << vt.n[3];
+ return s;
+}
+
+inline std::ostream & operator <<(std::ostream & s, const v4i & v)
+{
+ union {
+ v4i v;
+ int n[4];
+ } vt;
+ vt.v = v;
+ s << vt.n[0] << ", " << vt.n[1] << ", " << vt.n[2] << ", " << vt.n[3];
+ return s;
+}
+
+inline std::ostream & operator <<(std::ostream & s, const v4ui & v)
+{
+ union {
+ v4ui v;
+ unsigned int n[4];
+ } vt;
+ vt.v = v;
+ s << vt.n[0] << ", " << vt.n[1] << ", " << vt.n[2] << ", " << vt.n[3];
+ return s;
+}
+
+inline std::ostream & operator <<(std::ostream & s, const v4bi & v)
+{
+ union {
+ __vector __bool int v;
+ unsigned int n[4];
+ } vt;
+ vt.v = v;
+ s << vt.n[0] << ", " << vt.n[1] << ", " << vt.n[2] << ", " << vt.n[3];
+ return s;
+}
+
+template<> inline v4f ei_padd(const v4f& a, const v4f& b) { return vec_add(a,b); }
+template<> inline v4i ei_padd(const v4i& a, const v4i& b) { return vec_add(a,b); }
+
+template<> inline v4f ei_psub(const v4f& a, const v4f& b) { return vec_sub(a,b); }
+template<> inline v4i ei_psub(const v4i& a, const v4i& b) { return vec_sub(a,b); }
+
+template<> inline v4f ei_pmul(const v4f& a, const v4f& b) { USE_CONST_v0f; return vec_madd(a,b, v0f); }
+template<> inline v4i ei_pmul(const v4i& a, const v4i& b)
+{
+ // Detailed in: http://freevec.org/content/32bit_signed_integer_multiplication_altivec
+ //Set up constants, variables
+ v4i a1, b1, bswap, low_prod, high_prod, prod, prod_, v1sel;
+ USE_CONST_v0i;
+ USE_CONST_v1i;
+ USE_CONST_v16i_;
+
+ // Get the absolute values
+ a1 = vec_abs(a);
+ b1 = vec_abs(b);
+
+ // Get the signs using xor
+ v4bi sgn = (v4bi) vec_cmplt(vec_xor(a, b), v0i);
+
+ // Do the multiplication for the asbolute values.
+ bswap = (v4i) vec_rl((v4ui) b1, (v4ui) v16i_ );
+ low_prod = vec_mulo((__vector short)a1, (__vector short)b1);
+ high_prod = vec_msum((__vector short)a1, (__vector short)bswap, v0i);
+ high_prod = (v4i) vec_sl((v4ui) high_prod, (v4ui) v16i_);
+ prod = vec_add( low_prod, high_prod );
+
+ // NOR the product and select only the negative elements according to the sign mask
+ prod_ = vec_nor(prod, prod);
+ prod_ = vec_sel(v0i, prod_, sgn);
+
+ // Add 1 to the result to get the negative numbers
+ v1sel = vec_sel(v0i, v1i, sgn);
+ prod_ = vec_add(prod_, v1sel);
+
+ // Merge the results back to the final vector.
+ prod = vec_sel(prod, prod_, sgn);
+
+ return prod;
+}
+
+template<> inline v4f ei_pdiv(const v4f& a, const v4f& b) {
+ v4f t, y_0, y_1, res;
+ USE_CONST_v0f;
+ USE_CONST_v1f;
+
+ // Altivec does not offer a divide instruction, we have to do a reciprocal approximation
+ y_0 = vec_re(b);
+
+ // Do one Newton-Raphson iteration to get the needed accuracy
+ t = vec_nmsub(y_0, b, v1f);
+ y_1 = vec_madd(y_0, t, y_0);
+
+ res = vec_madd(a, y_1, v0f);
+ return res;
+}
+
+template<> inline v4f ei_pmadd(const v4f& a, const v4f& b, const v4f& c) { return vec_madd(a, b, c); }
+
+template<> inline v4f ei_pmin(const v4f& a, const v4f& b) { return vec_min(a,b); }
+template<> inline v4i ei_pmin(const v4i& a, const v4i& b) { return vec_min(a,b); }
+
+template<> inline v4f ei_pmax(const v4f& a, const v4f& b) { return vec_max(a,b); }
+template<> inline v4i ei_pmax(const v4i& a, const v4i& b) { return vec_max(a,b); }
+
+template<> inline v4f ei_pload(const float* from) { return vec_ld(0, from); }
+template<> inline v4i ei_pload(const int* from) { return vec_ld(0, from); }
+
+template<> inline v4f ei_ploadu(const float* from)
+{
+ // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html
+ __vector unsigned char MSQ, LSQ;
+ __vector unsigned char mask;
+ MSQ = vec_ld(0, (unsigned char *)from); // most significant quadword
+ LSQ = vec_ld(15, (unsigned char *)from); // least significant quadword
+ mask = vec_lvsl(0, from); // create the permute mask
+ return (v4f) vec_perm(MSQ, LSQ, mask); // align the data
+}
+
+template<> inline v4i ei_ploadu(const int* from)
+{
+ // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html
+ __vector unsigned char MSQ, LSQ;
+ __vector unsigned char mask;
+ MSQ = vec_ld(0, (unsigned char *)from); // most significant quadword
+ LSQ = vec_ld(15, (unsigned char *)from); // least significant quadword
+ mask = vec_lvsl(0, from); // create the permute mask
+ return (v4i) vec_perm(MSQ, LSQ, mask); // align the data
+}
+
+template<> inline v4f ei_pset1(const float& from)
+{
+ // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html
+ float __attribute__(aligned(16)) af[4];
+ af[0] = from;
+ v4f vc = vec_ld(0, af);
+ vc = vec_splat(vc, 0);
+ return vc;
+}
+
+template<> inline v4i ei_pset1(const int& from)
+{
+ int __attribute__(aligned(16)) ai[4];
+ ai[0] = from;
+ v4i vc = vec_ld(0, ai);
+ vc = vec_splat(vc, 0);
+ return vc;
+}
+
+template<> inline void ei_pstore(float* to, const v4f& from) { vec_st(from, 0, to); }
+template<> inline void ei_pstore(int* to, const v4i& from) { vec_st(from, 0, to); }
+
+template<> inline void ei_pstoreu(float* to, const v4f& from)
+{
+ // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html
+ // Warning: not thread safe!
+ __vector unsigned char MSQ, LSQ, edges;
+ __vector unsigned char edgeAlign, align;
+
+ MSQ = vec_ld(0, (unsigned char *)to); // most significant quadword
+ LSQ = vec_ld(15, (unsigned char *)to); // least significant quadword
+ edgeAlign = vec_lvsl(0, to); // permute map to extract edges
+ edges=vec_perm(LSQ,MSQ,edgeAlign); // extract the edges
+ align = vec_lvsr( 0, to ); // permute map to misalign data
+ MSQ = vec_perm(edges,(__vector unsigned char)from,align); // misalign the data (MSQ)
+ LSQ = vec_perm((__vector unsigned char)from,edges,align); // misalign the data (LSQ)
+ vec_st( LSQ, 15, (unsigned char *)to ); // Store the LSQ part first
+ vec_st( MSQ, 0, (unsigned char *)to ); // Store the MSQ part
+}
+
+template<> inline void ei_pstoreu(int* to , const v4i& from )
+{
+ // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html
+ // Warning: not thread safe!
+ __vector unsigned char MSQ, LSQ, edges;
+ __vector unsigned char edgeAlign, align;
+
+ MSQ = vec_ld(0, (unsigned char *)to); // most significant quadword
+ LSQ = vec_ld(15, (unsigned char *)to); // least significant quadword
+ edgeAlign = vec_lvsl(0, to); // permute map to extract edges
+ edges=vec_perm(LSQ,MSQ,edgeAlign); // extract the edges
+ align = vec_lvsr( 0, to ); // permute map to misalign data
+ MSQ = vec_perm(edges,(__vector unsigned char)from,align); // misalign the data (MSQ)
+ LSQ = vec_perm((__vector unsigned char)from,edges,align); // misalign the data (LSQ)
+ vec_st( LSQ, 15, (unsigned char *)to ); // Store the LSQ part first
+ vec_st( MSQ, 0, (unsigned char *)to ); // Store the MSQ part
+}
+
+template<> inline float ei_pfirst(const v4f& a)
+{
+ float __attribute__(aligned(16)) af[4];
+ vec_st(a, 0, af);
+ return af[0];
+}
+
+template<> inline int ei_pfirst(const v4i& a)
+{
+ int __attribute__(aligned(16)) ai[4];
+ vec_st(a, 0, ai);
+ return ai[0];
+}
+
+inline v4f ei_preduxp(const v4f* vecs)
+{
+ v4f v[4], sum[4];
+
+ // It's easier and faster to transpose then add as columns
+ // Check: http://www.freevec.org/function/matrix_4x4_transpose_floats for explanation
+ // Do the transpose, first set of moves
+ v[0] = vec_mergeh(vecs[0], vecs[2]);
+ v[1] = vec_mergel(vecs[0], vecs[2]);
+ v[2] = vec_mergeh(vecs[1], vecs[3]);
+ v[3] = vec_mergel(vecs[1], vecs[3]);
+ // Get the resulting vectors
+ sum[0] = vec_mergeh(v[0], v[2]);
+ sum[1] = vec_mergel(v[0], v[2]);
+ sum[2] = vec_mergeh(v[1], v[3]);
+ sum[3] = vec_mergel(v[1], v[3]);
+
+ // Now do the summation:
+ // Lines 0+1
+ sum[0] = vec_add(sum[0], sum[1]);
+ // Lines 2+3
+ sum[1] = vec_add(sum[2], sum[3]);
+ // Add the results
+ sum[0] = vec_add(sum[0], sum[1]);
+ return sum[0];
+}
+
+inline float ei_predux(const v4f& a)
+{
+ v4f b, sum;
+ b = (v4f)vec_sld(a, a, 8);
+ sum = vec_add(a, b);
+ b = (v4f)vec_sld(sum, sum, 4);
+ sum = vec_add(sum, b);
+ return ei_pfirst(sum);
+}
+
+inline v4i ei_preduxp(const v4i* vecs)
+{
+ v4i v[4], sum[4];
+
+ // It's easier and faster to transpose then add as columns
+ // Check: http://www.freevec.org/function/matrix_4x4_transpose_floats for explanation
+ // Do the transpose, first set of moves
+ v[0] = vec_mergeh(vecs[0], vecs[2]);
+ v[1] = vec_mergel(vecs[0], vecs[2]);
+ v[2] = vec_mergeh(vecs[1], vecs[3]);
+ v[3] = vec_mergel(vecs[1], vecs[3]);
+ // Get the resulting vectors
+ sum[0] = vec_mergeh(v[0], v[2]);
+ sum[1] = vec_mergel(v[0], v[2]);
+ sum[2] = vec_mergeh(v[1], v[3]);
+ sum[3] = vec_mergel(v[1], v[3]);
+
+ // Now do the summation:
+ // Lines 0+1
+ sum[0] = vec_add(sum[0], sum[1]);
+ // Lines 2+3
+ sum[1] = vec_add(sum[2], sum[3]);
+ // Add the results
+ sum[0] = vec_add(sum[0], sum[1]);
+ return sum[0];
+}
+
+inline int ei_predux(const v4i& a)
+{
+ USE_CONST_v0i;
+ v4i sum;
+ sum = vec_sums(a, v0i);
+ sum = vec_sld(sum, v0i, 12);
+ return ei_pfirst(sum);
+}
+
+template<int Offset>
+struct ei_palign_impl<Offset, v4f>
+{
+ inline static void run(v4f& first, const v4f& second)
+ {
+ first = vec_sld(first, second, Offset*4);
+ }
+};
+
+template<int Offset>
+struct ei_palign_impl<Offset, v4i>
+{
+ inline static void run(v4i& first, const v4i& second)
+ {
+ first = vec_sld(first, second, Offset*4);
+ }
+};
+
+#endif // EIGEN_PACKET_MATH_ALTIVEC_H
diff --git a/extern/Eigen2/Eigen/src/Core/arch/SSE/PacketMath.h b/extern/Eigen2/Eigen/src/Core/arch/SSE/PacketMath.h
new file mode 100644
index 00000000000..9ca65b9be5b
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/arch/SSE/PacketMath.h
@@ -0,0 +1,321 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_PACKET_MATH_SSE_H
+#define EIGEN_PACKET_MATH_SSE_H
+
+#ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
+#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 16
+#endif
+
+template<> struct ei_packet_traits<float> { typedef __m128 type; enum {size=4}; };
+template<> struct ei_packet_traits<double> { typedef __m128d type; enum {size=2}; };
+template<> struct ei_packet_traits<int> { typedef __m128i type; enum {size=4}; };
+
+template<> struct ei_unpacket_traits<__m128> { typedef float type; enum {size=4}; };
+template<> struct ei_unpacket_traits<__m128d> { typedef double type; enum {size=2}; };
+template<> struct ei_unpacket_traits<__m128i> { typedef int type; enum {size=4}; };
+
+template<> EIGEN_STRONG_INLINE __m128 ei_pset1<float>(const float& from) { return _mm_set1_ps(from); }
+template<> EIGEN_STRONG_INLINE __m128d ei_pset1<double>(const double& from) { return _mm_set1_pd(from); }
+template<> EIGEN_STRONG_INLINE __m128i ei_pset1<int>(const int& from) { return _mm_set1_epi32(from); }
+
+template<> EIGEN_STRONG_INLINE __m128 ei_padd<__m128>(const __m128& a, const __m128& b) { return _mm_add_ps(a,b); }
+template<> EIGEN_STRONG_INLINE __m128d ei_padd<__m128d>(const __m128d& a, const __m128d& b) { return _mm_add_pd(a,b); }
+template<> EIGEN_STRONG_INLINE __m128i ei_padd<__m128i>(const __m128i& a, const __m128i& b) { return _mm_add_epi32(a,b); }
+
+template<> EIGEN_STRONG_INLINE __m128 ei_psub<__m128>(const __m128& a, const __m128& b) { return _mm_sub_ps(a,b); }
+template<> EIGEN_STRONG_INLINE __m128d ei_psub<__m128d>(const __m128d& a, const __m128d& b) { return _mm_sub_pd(a,b); }
+template<> EIGEN_STRONG_INLINE __m128i ei_psub<__m128i>(const __m128i& a, const __m128i& b) { return _mm_sub_epi32(a,b); }
+
+template<> EIGEN_STRONG_INLINE __m128 ei_pmul<__m128>(const __m128& a, const __m128& b) { return _mm_mul_ps(a,b); }
+template<> EIGEN_STRONG_INLINE __m128d ei_pmul<__m128d>(const __m128d& a, const __m128d& b) { return _mm_mul_pd(a,b); }
+template<> EIGEN_STRONG_INLINE __m128i ei_pmul<__m128i>(const __m128i& a, const __m128i& b)
+{
+ return _mm_or_si128(
+ _mm_and_si128(
+ _mm_mul_epu32(a,b),
+ _mm_setr_epi32(0xffffffff,0,0xffffffff,0)),
+ _mm_slli_si128(
+ _mm_and_si128(
+ _mm_mul_epu32(_mm_srli_si128(a,4),_mm_srli_si128(b,4)),
+ _mm_setr_epi32(0xffffffff,0,0xffffffff,0)), 4));
+}
+
+template<> EIGEN_STRONG_INLINE __m128 ei_pdiv<__m128>(const __m128& a, const __m128& b) { return _mm_div_ps(a,b); }
+template<> EIGEN_STRONG_INLINE __m128d ei_pdiv<__m128d>(const __m128d& a, const __m128d& b) { return _mm_div_pd(a,b); }
+template<> EIGEN_STRONG_INLINE __m128i ei_pdiv<__m128i>(const __m128i& /*a*/, const __m128i& /*b*/)
+{ ei_assert(false && "packet integer division are not supported by SSE");
+ __m128i dummy = ei_pset1<int>(0);
+ return dummy;
+}
+
+// for some weird raisons, it has to be overloaded for packet integer
+template<> EIGEN_STRONG_INLINE __m128i ei_pmadd(const __m128i& a, const __m128i& b, const __m128i& c) { return ei_padd(ei_pmul(a,b), c); }
+
+template<> EIGEN_STRONG_INLINE __m128 ei_pmin<__m128>(const __m128& a, const __m128& b) { return _mm_min_ps(a,b); }
+template<> EIGEN_STRONG_INLINE __m128d ei_pmin<__m128d>(const __m128d& a, const __m128d& b) { return _mm_min_pd(a,b); }
+// FIXME this vectorized min operator is likely to be slower than the standard one
+template<> EIGEN_STRONG_INLINE __m128i ei_pmin<__m128i>(const __m128i& a, const __m128i& b)
+{
+ __m128i mask = _mm_cmplt_epi32(a,b);
+ return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b));
+}
+
+template<> EIGEN_STRONG_INLINE __m128 ei_pmax<__m128>(const __m128& a, const __m128& b) { return _mm_max_ps(a,b); }
+template<> EIGEN_STRONG_INLINE __m128d ei_pmax<__m128d>(const __m128d& a, const __m128d& b) { return _mm_max_pd(a,b); }
+// FIXME this vectorized max operator is likely to be slower than the standard one
+template<> EIGEN_STRONG_INLINE __m128i ei_pmax<__m128i>(const __m128i& a, const __m128i& b)
+{
+ __m128i mask = _mm_cmpgt_epi32(a,b);
+ return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b));
+}
+
+template<> EIGEN_STRONG_INLINE __m128 ei_pload<float>(const float* from) { return _mm_load_ps(from); }
+template<> EIGEN_STRONG_INLINE __m128d ei_pload<double>(const double* from) { return _mm_load_pd(from); }
+template<> EIGEN_STRONG_INLINE __m128i ei_pload<int>(const int* from) { return _mm_load_si128(reinterpret_cast<const __m128i*>(from)); }
+
+template<> EIGEN_STRONG_INLINE __m128 ei_ploadu<float>(const float* from) { return _mm_loadu_ps(from); }
+// template<> EIGEN_STRONG_INLINE __m128 ei_ploadu(const float* from) {
+// if (size_t(from)&0xF)
+// return _mm_loadu_ps(from);
+// else
+// return _mm_loadu_ps(from);
+// }
+template<> EIGEN_STRONG_INLINE __m128d ei_ploadu<double>(const double* from) { return _mm_loadu_pd(from); }
+template<> EIGEN_STRONG_INLINE __m128i ei_ploadu<int>(const int* from) { return _mm_loadu_si128(reinterpret_cast<const __m128i*>(from)); }
+
+template<> EIGEN_STRONG_INLINE void ei_pstore<float>(float* to, const __m128& from) { _mm_store_ps(to, from); }
+template<> EIGEN_STRONG_INLINE void ei_pstore<double>(double* to, const __m128d& from) { _mm_store_pd(to, from); }
+template<> EIGEN_STRONG_INLINE void ei_pstore<int>(int* to, const __m128i& from) { _mm_store_si128(reinterpret_cast<__m128i*>(to), from); }
+
+template<> EIGEN_STRONG_INLINE void ei_pstoreu<float>(float* to, const __m128& from) { _mm_storeu_ps(to, from); }
+template<> EIGEN_STRONG_INLINE void ei_pstoreu<double>(double* to, const __m128d& from) { _mm_storeu_pd(to, from); }
+template<> EIGEN_STRONG_INLINE void ei_pstoreu<int>(int* to, const __m128i& from) { _mm_storeu_si128(reinterpret_cast<__m128i*>(to), from); }
+
+#ifdef _MSC_VER
+// this fix internal compilation error
+template<> EIGEN_STRONG_INLINE float ei_pfirst<__m128>(const __m128& a) { float x = _mm_cvtss_f32(a); return x; }
+template<> EIGEN_STRONG_INLINE double ei_pfirst<__m128d>(const __m128d& a) { double x = _mm_cvtsd_f64(a); return x; }
+template<> EIGEN_STRONG_INLINE int ei_pfirst<__m128i>(const __m128i& a) { int x = _mm_cvtsi128_si32(a); return x; }
+#else
+template<> EIGEN_STRONG_INLINE float ei_pfirst<__m128>(const __m128& a) { return _mm_cvtss_f32(a); }
+template<> EIGEN_STRONG_INLINE double ei_pfirst<__m128d>(const __m128d& a) { return _mm_cvtsd_f64(a); }
+template<> EIGEN_STRONG_INLINE int ei_pfirst<__m128i>(const __m128i& a) { return _mm_cvtsi128_si32(a); }
+#endif
+
+#ifdef __SSE3__
+// TODO implement SSE2 versions as well as integer versions
+template<> EIGEN_STRONG_INLINE __m128 ei_preduxp<__m128>(const __m128* vecs)
+{
+ return _mm_hadd_ps(_mm_hadd_ps(vecs[0], vecs[1]),_mm_hadd_ps(vecs[2], vecs[3]));
+}
+template<> EIGEN_STRONG_INLINE __m128d ei_preduxp<__m128d>(const __m128d* vecs)
+{
+ return _mm_hadd_pd(vecs[0], vecs[1]);
+}
+// SSSE3 version:
+// EIGEN_STRONG_INLINE __m128i ei_preduxp(const __m128i* vecs)
+// {
+// return _mm_hadd_epi32(_mm_hadd_epi32(vecs[0], vecs[1]),_mm_hadd_epi32(vecs[2], vecs[3]));
+// }
+
+template<> EIGEN_STRONG_INLINE float ei_predux<__m128>(const __m128& a)
+{
+ __m128 tmp0 = _mm_hadd_ps(a,a);
+ return ei_pfirst(_mm_hadd_ps(tmp0, tmp0));
+}
+
+template<> EIGEN_STRONG_INLINE double ei_predux<__m128d>(const __m128d& a) { return ei_pfirst(_mm_hadd_pd(a, a)); }
+
+// SSSE3 version:
+// EIGEN_STRONG_INLINE float ei_predux(const __m128i& a)
+// {
+// __m128i tmp0 = _mm_hadd_epi32(a,a);
+// return ei_pfirst(_mm_hadd_epi32(tmp0, tmp0));
+// }
+#else
+// SSE2 versions
+template<> EIGEN_STRONG_INLINE float ei_predux<__m128>(const __m128& a)
+{
+ __m128 tmp = _mm_add_ps(a, _mm_movehl_ps(a,a));
+ return ei_pfirst(_mm_add_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1)));
+}
+template<> EIGEN_STRONG_INLINE double ei_predux<__m128d>(const __m128d& a)
+{
+ return ei_pfirst(_mm_add_sd(a, _mm_unpackhi_pd(a,a)));
+}
+
+template<> EIGEN_STRONG_INLINE __m128 ei_preduxp<__m128>(const __m128* vecs)
+{
+ __m128 tmp0, tmp1, tmp2;
+ tmp0 = _mm_unpacklo_ps(vecs[0], vecs[1]);
+ tmp1 = _mm_unpackhi_ps(vecs[0], vecs[1]);
+ tmp2 = _mm_unpackhi_ps(vecs[2], vecs[3]);
+ tmp0 = _mm_add_ps(tmp0, tmp1);
+ tmp1 = _mm_unpacklo_ps(vecs[2], vecs[3]);
+ tmp1 = _mm_add_ps(tmp1, tmp2);
+ tmp2 = _mm_movehl_ps(tmp1, tmp0);
+ tmp0 = _mm_movelh_ps(tmp0, tmp1);
+ return _mm_add_ps(tmp0, tmp2);
+}
+
+template<> EIGEN_STRONG_INLINE __m128d ei_preduxp<__m128d>(const __m128d* vecs)
+{
+ return _mm_add_pd(_mm_unpacklo_pd(vecs[0], vecs[1]), _mm_unpackhi_pd(vecs[0], vecs[1]));
+}
+#endif // SSE3
+
+template<> EIGEN_STRONG_INLINE int ei_predux<__m128i>(const __m128i& a)
+{
+ __m128i tmp = _mm_add_epi32(a, _mm_unpackhi_epi64(a,a));
+ return ei_pfirst(tmp) + ei_pfirst(_mm_shuffle_epi32(tmp, 1));
+}
+
+template<> EIGEN_STRONG_INLINE __m128i ei_preduxp<__m128i>(const __m128i* vecs)
+{
+ __m128i tmp0, tmp1, tmp2;
+ tmp0 = _mm_unpacklo_epi32(vecs[0], vecs[1]);
+ tmp1 = _mm_unpackhi_epi32(vecs[0], vecs[1]);
+ tmp2 = _mm_unpackhi_epi32(vecs[2], vecs[3]);
+ tmp0 = _mm_add_epi32(tmp0, tmp1);
+ tmp1 = _mm_unpacklo_epi32(vecs[2], vecs[3]);
+ tmp1 = _mm_add_epi32(tmp1, tmp2);
+ tmp2 = _mm_unpacklo_epi64(tmp0, tmp1);
+ tmp0 = _mm_unpackhi_epi64(tmp0, tmp1);
+ return _mm_add_epi32(tmp0, tmp2);
+}
+
+#if (defined __GNUC__)
+// template <> EIGEN_STRONG_INLINE __m128 ei_pmadd(const __m128& a, const __m128& b, const __m128& c)
+// {
+// __m128 res = b;
+// asm("mulps %[a], %[b] \n\taddps %[c], %[b]" : [b] "+x" (res) : [a] "x" (a), [c] "x" (c));
+// return res;
+// }
+// EIGEN_STRONG_INLINE __m128i _mm_alignr_epi8(const __m128i& a, const __m128i& b, const int i)
+// {
+// __m128i res = a;
+// asm("palignr %[i], %[a], %[b] " : [b] "+x" (res) : [a] "x" (a), [i] "i" (i));
+// return res;
+// }
+#endif
+
+#ifdef __SSSE3__
+// SSSE3 versions
+template<int Offset>
+struct ei_palign_impl<Offset,__m128>
+{
+ EIGEN_STRONG_INLINE static void run(__m128& first, const __m128& second)
+ {
+ if (Offset!=0)
+ first = _mm_castsi128_ps(_mm_alignr_epi8(_mm_castps_si128(second), _mm_castps_si128(first), Offset*4));
+ }
+};
+
+template<int Offset>
+struct ei_palign_impl<Offset,__m128i>
+{
+ EIGEN_STRONG_INLINE static void run(__m128i& first, const __m128i& second)
+ {
+ if (Offset!=0)
+ first = _mm_alignr_epi8(second,first, Offset*4);
+ }
+};
+
+template<int Offset>
+struct ei_palign_impl<Offset,__m128d>
+{
+ EIGEN_STRONG_INLINE static void run(__m128d& first, const __m128d& second)
+ {
+ if (Offset==1)
+ first = _mm_castsi128_pd(_mm_alignr_epi8(_mm_castpd_si128(second), _mm_castpd_si128(first), 8));
+ }
+};
+#else
+// SSE2 versions
+template<int Offset>
+struct ei_palign_impl<Offset,__m128>
+{
+ EIGEN_STRONG_INLINE static void run(__m128& first, const __m128& second)
+ {
+ if (Offset==1)
+ {
+ first = _mm_move_ss(first,second);
+ first = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(first),0x39));
+ }
+ else if (Offset==2)
+ {
+ first = _mm_movehl_ps(first,first);
+ first = _mm_movelh_ps(first,second);
+ }
+ else if (Offset==3)
+ {
+ first = _mm_move_ss(first,second);
+ first = _mm_shuffle_ps(first,second,0x93);
+ }
+ }
+};
+
+template<int Offset>
+struct ei_palign_impl<Offset,__m128i>
+{
+ EIGEN_STRONG_INLINE static void run(__m128i& first, const __m128i& second)
+ {
+ if (Offset==1)
+ {
+ first = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(first),_mm_castsi128_ps(second)));
+ first = _mm_shuffle_epi32(first,0x39);
+ }
+ else if (Offset==2)
+ {
+ first = _mm_castps_si128(_mm_movehl_ps(_mm_castsi128_ps(first),_mm_castsi128_ps(first)));
+ first = _mm_castps_si128(_mm_movelh_ps(_mm_castsi128_ps(first),_mm_castsi128_ps(second)));
+ }
+ else if (Offset==3)
+ {
+ first = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(first),_mm_castsi128_ps(second)));
+ first = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(first),_mm_castsi128_ps(second),0x93));
+ }
+ }
+};
+
+template<int Offset>
+struct ei_palign_impl<Offset,__m128d>
+{
+ EIGEN_STRONG_INLINE static void run(__m128d& first, const __m128d& second)
+ {
+ if (Offset==1)
+ {
+ first = _mm_castps_pd(_mm_movehl_ps(_mm_castpd_ps(first),_mm_castpd_ps(first)));
+ first = _mm_castps_pd(_mm_movelh_ps(_mm_castpd_ps(first),_mm_castpd_ps(second)));
+ }
+ }
+};
+#endif
+
+#define ei_vec4f_swizzle1(v,p,q,r,s) \
+ (_mm_castsi128_ps(_mm_shuffle_epi32( _mm_castps_si128(v), ((s)<<6|(r)<<4|(q)<<2|(p)))))
+
+#endif // EIGEN_PACKET_MATH_SSE_H
diff --git a/extern/Eigen2/Eigen/src/Core/util/Constants.h b/extern/Eigen2/Eigen/src/Core/util/Constants.h
new file mode 100644
index 00000000000..296c3caa5f6
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/util/Constants.h
@@ -0,0 +1,254 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_CONSTANTS_H
+#define EIGEN_CONSTANTS_H
+
+/** This value means that a quantity is not known at compile-time, and that instead the value is
+ * stored in some runtime variable.
+ *
+ * Explanation for the choice of this value:
+ * - It should be positive and larger than any reasonable compile-time-fixed number of rows or columns.
+ * This allows to simplify many compile-time conditions throughout Eigen.
+ * - It should be smaller than the sqrt of INT_MAX. Indeed, we often multiply a number of rows with a number
+ * of columns in order to compute a number of coefficients. Even if we guard that with an "if" checking whether
+ * the values are Dynamic, we still get a compiler warning "integer overflow". So the only way to get around
+ * it would be a meta-selector. Doing this everywhere would reduce code readability and lenghten compilation times.
+ * Also, disabling compiler warnings for integer overflow, sounds like a bad idea.
+ *
+ * If you wish to port Eigen to a platform where sizeof(int)==2, it is perfectly possible to set Dynamic to, say, 100.
+ */
+const int Dynamic = 10000;
+
+/** This value means +Infinity; it is currently used only as the p parameter to MatrixBase::lpNorm<int>().
+ * The value Infinity there means the L-infinity norm.
+ */
+const int Infinity = -1;
+
+/** \defgroup flags flags
+ * \ingroup Core_Module
+ *
+ * These are the possible bits which can be OR'ed to constitute the flags of a matrix or
+ * expression.
+ *
+ * It is important to note that these flags are a purely compile-time notion. They are a compile-time property of
+ * an expression type, implemented as enum's. They are not stored in memory at runtime, and they do not incur any
+ * runtime overhead.
+ *
+ * \sa MatrixBase::Flags
+ */
+
+/** \ingroup flags
+ *
+ * for a matrix, this means that the storage order is row-major.
+ * If this bit is not set, the storage order is column-major.
+ * For an expression, this determines the storage order of
+ * the matrix created by evaluation of that expression. */
+const unsigned int RowMajorBit = 0x1;
+
+/** \ingroup flags
+ *
+ * means the expression should be evaluated by the calling expression */
+const unsigned int EvalBeforeNestingBit = 0x2;
+
+/** \ingroup flags
+ *
+ * means the expression should be evaluated before any assignement */
+const unsigned int EvalBeforeAssigningBit = 0x4;
+
+/** \ingroup flags
+ *
+ * Short version: means the expression might be vectorized
+ *
+ * Long version: means that the coefficients can be handled by packets
+ * and start at a memory location whose alignment meets the requirements
+ * of the present CPU architecture for optimized packet access. In the fixed-size
+ * case, there is the additional condition that the total size of the coefficients
+ * array is a multiple of the packet size, so that it is possible to access all the
+ * coefficients by packets. In the dynamic-size case, there is no such condition
+ * on the total size, so it might not be possible to access the few last coeffs
+ * by packets.
+ *
+ * \note This bit can be set regardless of whether vectorization is actually enabled.
+ * To check for actual vectorizability, see \a ActualPacketAccessBit.
+ */
+const unsigned int PacketAccessBit = 0x8;
+
+#ifdef EIGEN_VECTORIZE
+/** \ingroup flags
+ *
+ * If vectorization is enabled (EIGEN_VECTORIZE is defined) this constant
+ * is set to the value \a PacketAccessBit.
+ *
+ * If vectorization is not enabled (EIGEN_VECTORIZE is not defined) this constant
+ * is set to the value 0.
+ */
+const unsigned int ActualPacketAccessBit = PacketAccessBit;
+#else
+const unsigned int ActualPacketAccessBit = 0x0;
+#endif
+
+/** \ingroup flags
+ *
+ * Short version: means the expression can be seen as 1D vector.
+ *
+ * Long version: means that one can access the coefficients
+ * of this expression by coeff(int), and coeffRef(int) in the case of a lvalue expression. These
+ * index-based access methods are guaranteed
+ * to not have to do any runtime computation of a (row, col)-pair from the index, so that it
+ * is guaranteed that whenever it is available, index-based access is at least as fast as
+ * (row,col)-based access. Expressions for which that isn't possible don't have the LinearAccessBit.
+ *
+ * If both PacketAccessBit and LinearAccessBit are set, then the
+ * packets of this expression can be accessed by packet(int), and writePacket(int) in the case of a
+ * lvalue expression.
+ *
+ * Typically, all vector expressions have the LinearAccessBit, but there is one exception:
+ * Product expressions don't have it, because it would be troublesome for vectorization, even when the
+ * Product is a vector expression. Thus, vector Product expressions allow index-based coefficient access but
+ * not index-based packet access, so they don't have the LinearAccessBit.
+ */
+const unsigned int LinearAccessBit = 0x10;
+
+/** \ingroup flags
+ *
+ * Means that the underlying array of coefficients can be directly accessed. This means two things.
+ * First, references to the coefficients must be available through coeffRef(int, int). This rules out read-only
+ * expressions whose coefficients are computed on demand by coeff(int, int). Second, the memory layout of the
+ * array of coefficients must be exactly the natural one suggested by rows(), cols(), stride(), and the RowMajorBit.
+ * This rules out expressions such as DiagonalCoeffs, whose coefficients, though referencable, do not have
+ * such a regular memory layout.
+ */
+const unsigned int DirectAccessBit = 0x20;
+
+/** \ingroup flags
+ *
+ * means the first coefficient packet is guaranteed to be aligned */
+const unsigned int AlignedBit = 0x40;
+
+/** \ingroup flags
+ *
+ * means all diagonal coefficients are equal to 0 */
+const unsigned int ZeroDiagBit = 0x80;
+
+/** \ingroup flags
+ *
+ * means all diagonal coefficients are equal to 1 */
+const unsigned int UnitDiagBit = 0x100;
+
+/** \ingroup flags
+ *
+ * means the matrix is selfadjoint (M=M*). */
+const unsigned int SelfAdjointBit = 0x200;
+
+/** \ingroup flags
+ *
+ * means the strictly lower triangular part is 0 */
+const unsigned int UpperTriangularBit = 0x400;
+
+/** \ingroup flags
+ *
+ * means the strictly upper triangular part is 0 */
+const unsigned int LowerTriangularBit = 0x800;
+
+/** \ingroup flags
+ *
+ * means the expression includes sparse matrices and the sparse path has to be taken. */
+const unsigned int SparseBit = 0x1000;
+
+// list of flags that are inherited by default
+const unsigned int HereditaryBits = RowMajorBit
+ | EvalBeforeNestingBit
+ | EvalBeforeAssigningBit
+ | SparseBit;
+
+// Possible values for the Mode parameter of part() and of extract()
+const unsigned int UpperTriangular = UpperTriangularBit;
+const unsigned int StrictlyUpperTriangular = UpperTriangularBit | ZeroDiagBit;
+const unsigned int LowerTriangular = LowerTriangularBit;
+const unsigned int StrictlyLowerTriangular = LowerTriangularBit | ZeroDiagBit;
+const unsigned int SelfAdjoint = SelfAdjointBit;
+
+// additional possible values for the Mode parameter of extract()
+const unsigned int UnitUpperTriangular = UpperTriangularBit | UnitDiagBit;
+const unsigned int UnitLowerTriangular = LowerTriangularBit | UnitDiagBit;
+const unsigned int Diagonal = UpperTriangular | LowerTriangular;
+
+enum { Aligned, Unaligned };
+enum { ForceAligned, AsRequested };
+enum { ConditionalJumpCost = 5 };
+enum CornerType { TopLeft, TopRight, BottomLeft, BottomRight };
+enum DirectionType { Vertical, Horizontal };
+enum ProductEvaluationMode { NormalProduct, CacheFriendlyProduct, DiagonalProduct, SparseTimeSparseProduct, SparseTimeDenseProduct, DenseTimeSparseProduct };
+
+enum {
+ /** \internal Equivalent to a slice vectorization for fixed-size matrices having good alignment
+ * and good size */
+ InnerVectorization,
+ /** \internal Vectorization path using a single loop plus scalar loops for the
+ * unaligned boundaries */
+ LinearVectorization,
+ /** \internal Generic vectorization path using one vectorized loop per row/column with some
+ * scalar loops to handle the unaligned boundaries */
+ SliceVectorization,
+ NoVectorization
+};
+
+enum {
+ NoUnrolling,
+ InnerUnrolling,
+ CompleteUnrolling
+};
+
+enum {
+ ColMajor = 0,
+ RowMajor = 0x1, // it is only a coincidence that this is equal to RowMajorBit -- don't rely on that
+ /** \internal Don't require alignment for the matrix itself (the array of coefficients, if dynamically allocated, may still be
+ requested to be aligned) */
+ DontAlign = 0,
+ /** \internal Align the matrix itself if it is vectorizable fixed-size */
+ AutoAlign = 0x2
+};
+
+enum {
+ IsDense = 0,
+ IsSparse = SparseBit,
+ NoDirectAccess = 0,
+ HasDirectAccess = DirectAccessBit
+};
+
+const int EiArch_Generic = 0x0;
+const int EiArch_SSE = 0x1;
+const int EiArch_AltiVec = 0x2;
+
+#if defined EIGEN_VECTORIZE_SSE
+ const int EiArch = EiArch_SSE;
+#elif defined EIGEN_VECTORIZE_ALTIVEC
+ const int EiArch = EiArch_AltiVec;
+#else
+ const int EiArch = EiArch_Generic;
+#endif
+
+#endif // EIGEN_CONSTANTS_H
diff --git a/extern/Eigen2/Eigen/src/Core/util/DisableMSVCWarnings.h b/extern/Eigen2/Eigen/src/Core/util/DisableMSVCWarnings.h
new file mode 100644
index 00000000000..765ddecc53c
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/util/DisableMSVCWarnings.h
@@ -0,0 +1,5 @@
+
+#ifdef _MSC_VER
+ #pragma warning( push )
+ #pragma warning( disable : 4181 4244 4127 4211 4717 )
+#endif
diff --git a/extern/Eigen2/Eigen/src/Core/util/EnableMSVCWarnings.h b/extern/Eigen2/Eigen/src/Core/util/EnableMSVCWarnings.h
new file mode 100644
index 00000000000..8bd61601ebb
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/util/EnableMSVCWarnings.h
@@ -0,0 +1,4 @@
+
+#ifdef _MSC_VER
+ #pragma warning( pop )
+#endif
diff --git a/extern/Eigen2/Eigen/src/Core/util/ForwardDeclarations.h b/extern/Eigen2/Eigen/src/Core/util/ForwardDeclarations.h
new file mode 100644
index 00000000000..a72a40b1bfc
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/util/ForwardDeclarations.h
@@ -0,0 +1,125 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_FORWARDDECLARATIONS_H
+#define EIGEN_FORWARDDECLARATIONS_H
+
+template<typename T> struct ei_traits;
+template<typename T> struct NumTraits;
+
+template<typename _Scalar, int _Rows, int _Cols,
+ int _Options = EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION | AutoAlign,
+ int _MaxRows = _Rows, int _MaxCols = _Cols> class Matrix;
+
+template<typename ExpressionType, unsigned int Added, unsigned int Removed> class Flagged;
+template<typename ExpressionType> class NestByValue;
+template<typename ExpressionType> class SwapWrapper;
+template<typename MatrixType> class Minor;
+template<typename MatrixType, int BlockRows=Dynamic, int BlockCols=Dynamic, int PacketAccess=AsRequested,
+ int _DirectAccessStatus = ei_traits<MatrixType>::Flags&DirectAccessBit ? DirectAccessBit
+ : ei_traits<MatrixType>::Flags&SparseBit> class Block;
+template<typename MatrixType> class Transpose;
+template<typename MatrixType> class Conjugate;
+template<typename NullaryOp, typename MatrixType> class CwiseNullaryOp;
+template<typename UnaryOp, typename MatrixType> class CwiseUnaryOp;
+template<typename BinaryOp, typename Lhs, typename Rhs> class CwiseBinaryOp;
+template<typename Lhs, typename Rhs, int ProductMode> class Product;
+template<typename CoeffsVectorType> class DiagonalMatrix;
+template<typename MatrixType> class DiagonalCoeffs;
+template<typename MatrixType, int PacketAccess = AsRequested> class Map;
+template<typename MatrixType, unsigned int Mode> class Part;
+template<typename MatrixType, unsigned int Mode> class Extract;
+template<typename ExpressionType> class Cwise;
+template<typename ExpressionType> class WithFormat;
+template<typename MatrixType> struct CommaInitializer;
+
+
+template<typename Lhs, typename Rhs> struct ei_product_mode;
+template<typename Lhs, typename Rhs, int ProductMode = ei_product_mode<Lhs,Rhs>::value> struct ProductReturnType;
+
+template<typename Scalar> struct ei_scalar_sum_op;
+template<typename Scalar> struct ei_scalar_difference_op;
+template<typename Scalar> struct ei_scalar_product_op;
+template<typename Scalar> struct ei_scalar_quotient_op;
+template<typename Scalar> struct ei_scalar_opposite_op;
+template<typename Scalar> struct ei_scalar_conjugate_op;
+template<typename Scalar> struct ei_scalar_real_op;
+template<typename Scalar> struct ei_scalar_imag_op;
+template<typename Scalar> struct ei_scalar_abs_op;
+template<typename Scalar> struct ei_scalar_abs2_op;
+template<typename Scalar> struct ei_scalar_sqrt_op;
+template<typename Scalar> struct ei_scalar_exp_op;
+template<typename Scalar> struct ei_scalar_log_op;
+template<typename Scalar> struct ei_scalar_cos_op;
+template<typename Scalar> struct ei_scalar_sin_op;
+template<typename Scalar> struct ei_scalar_pow_op;
+template<typename Scalar> struct ei_scalar_inverse_op;
+template<typename Scalar> struct ei_scalar_square_op;
+template<typename Scalar> struct ei_scalar_cube_op;
+template<typename Scalar, typename NewType> struct ei_scalar_cast_op;
+template<typename Scalar> struct ei_scalar_multiple_op;
+template<typename Scalar> struct ei_scalar_quotient1_op;
+template<typename Scalar> struct ei_scalar_min_op;
+template<typename Scalar> struct ei_scalar_max_op;
+template<typename Scalar> struct ei_scalar_random_op;
+template<typename Scalar> struct ei_scalar_add_op;
+template<typename Scalar> struct ei_scalar_constant_op;
+template<typename Scalar> struct ei_scalar_identity_op;
+
+struct IOFormat;
+
+template<typename Scalar>
+void ei_cache_friendly_product(
+ int _rows, int _cols, int depth,
+ bool _lhsRowMajor, const Scalar* _lhs, int _lhsStride,
+ bool _rhsRowMajor, const Scalar* _rhs, int _rhsStride,
+ bool resRowMajor, Scalar* res, int resStride);
+
+// Array module
+template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType> class Select;
+template<typename MatrixType, typename BinaryOp, int Direction> class PartialReduxExpr;
+template<typename ExpressionType, int Direction> class PartialRedux;
+
+template<typename MatrixType> class LU;
+template<typename MatrixType> class QR;
+template<typename MatrixType> class SVD;
+template<typename MatrixType> class LLT;
+template<typename MatrixType> class LDLT;
+
+// Geometry module:
+template<typename Derived, int _Dim> class RotationBase;
+template<typename Lhs, typename Rhs> class Cross;
+template<typename Scalar> class Quaternion;
+template<typename Scalar> class Rotation2D;
+template<typename Scalar> class AngleAxis;
+template<typename Scalar,int Dim> class Transform;
+template <typename _Scalar, int _AmbientDim> class ParametrizedLine;
+template <typename _Scalar, int _AmbientDim> class Hyperplane;
+template<typename Scalar,int Dim> class Translation;
+template<typename Scalar,int Dim> class Scaling;
+
+// Sparse module:
+template<typename Lhs, typename Rhs, int ProductMode> class SparseProduct;
+
+#endif // EIGEN_FORWARDDECLARATIONS_H
diff --git a/extern/Eigen2/Eigen/src/Core/util/Macros.h b/extern/Eigen2/Eigen/src/Core/util/Macros.h
new file mode 100644
index 00000000000..89b20312a52
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/util/Macros.h
@@ -0,0 +1,273 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_MACROS_H
+#define EIGEN_MACROS_H
+
+#undef minor
+
+#define EIGEN_WORLD_VERSION 2
+#define EIGEN_MAJOR_VERSION 0
+#define EIGEN_MINOR_VERSION 6
+
+#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
+ (EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
+ EIGEN_MINOR_VERSION>=z))))
+
+// 16 byte alignment is only useful for vectorization. Since it affects the ABI, we need to enable 16 byte alignment on all
+// platforms where vectorization might be enabled. In theory we could always enable alignment, but it can be a cause of problems
+// on some platforms, so we just disable it in certain common platform (compiler+architecture combinations) to avoid these problems.
+#if defined(__GNUC__) && !(defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__ia64__) || defined(__ppc__))
+#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 1
+#else
+#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 0
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ <= 3)
+#define EIGEN_GCC3_OR_OLDER 1
+#else
+#define EIGEN_GCC3_OR_OLDER 0
+#endif
+
+// FIXME vectorization + alignment is completely disabled with sun studio
+#if !EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT && !EIGEN_GCC3_OR_OLDER && !defined(__SUNPRO_CC)
+ #define EIGEN_ARCH_WANTS_ALIGNMENT 1
+#else
+ #define EIGEN_ARCH_WANTS_ALIGNMENT 0
+#endif
+
+// EIGEN_ALIGN is the true test whether we want to align or not. It takes into account both the user choice to explicitly disable
+// alignment (EIGEN_DONT_ALIGN) and the architecture config (EIGEN_ARCH_WANTS_ALIGNMENT). Henceforth, only EIGEN_ALIGN should be used.
+#if EIGEN_ARCH_WANTS_ALIGNMENT && !defined(EIGEN_DONT_ALIGN)
+ #define EIGEN_ALIGN 1
+#else
+ #define EIGEN_ALIGN 0
+ #ifdef EIGEN_VECTORIZE
+ #error "Vectorization enabled, but our platform checks say that we don't do 16 byte alignment on this platform. If you added vectorization for another architecture, you also need to edit this platform check."
+ #endif
+ #ifndef EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
+ #define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
+ #endif
+#endif
+
+#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
+#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION RowMajor
+#else
+#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ColMajor
+#endif
+
+/** \internal Defines the maximal loop size to enable meta unrolling of loops.
+ * Note that the value here is expressed in Eigen's own notion of "number of FLOPS",
+ * it does not correspond to the number of iterations or the number of instructions
+ */
+#ifndef EIGEN_UNROLLING_LIMIT
+#define EIGEN_UNROLLING_LIMIT 100
+#endif
+
+/** \internal Define the maximal size in Bytes of blocks fitting in CPU cache.
+ * The current value is set to generate blocks of 256x256 for float
+ *
+ * Typically for a single-threaded application you would set that to 25% of the size of your CPU caches in bytes
+ */
+#ifndef EIGEN_TUNE_FOR_CPU_CACHE_SIZE
+#define EIGEN_TUNE_FOR_CPU_CACHE_SIZE (sizeof(float)*256*256)
+#endif
+
+// FIXME this should go away quickly
+#ifdef EIGEN_TUNE_FOR_L2_CACHE_SIZE
+#error EIGEN_TUNE_FOR_L2_CACHE_SIZE is now called EIGEN_TUNE_FOR_CPU_CACHE_SIZE.
+#endif
+
+#define USING_PART_OF_NAMESPACE_EIGEN \
+EIGEN_USING_MATRIX_TYPEDEFS \
+using Eigen::Matrix; \
+using Eigen::MatrixBase; \
+using Eigen::ei_random; \
+using Eigen::ei_real; \
+using Eigen::ei_imag; \
+using Eigen::ei_conj; \
+using Eigen::ei_abs; \
+using Eigen::ei_abs2; \
+using Eigen::ei_sqrt; \
+using Eigen::ei_exp; \
+using Eigen::ei_log; \
+using Eigen::ei_sin; \
+using Eigen::ei_cos;
+
+#ifdef NDEBUG
+# ifndef EIGEN_NO_DEBUG
+# define EIGEN_NO_DEBUG
+# endif
+#endif
+
+#ifndef ei_assert
+#ifdef EIGEN_NO_DEBUG
+#define ei_assert(x)
+#else
+#define ei_assert(x) assert(x)
+#endif
+#endif
+
+#ifdef EIGEN_INTERNAL_DEBUGGING
+#define ei_internal_assert(x) ei_assert(x)
+#else
+#define ei_internal_assert(x)
+#endif
+
+#ifdef EIGEN_NO_DEBUG
+#define EIGEN_ONLY_USED_FOR_DEBUG(x) (void)x
+#else
+#define EIGEN_ONLY_USED_FOR_DEBUG(x)
+#endif
+
+// EIGEN_ALWAYS_INLINE_ATTRIB should be use in the declaration of function
+// which should be inlined even in debug mode.
+// FIXME with the always_inline attribute,
+// gcc 3.4.x reports the following compilation error:
+// Eval.h:91: sorry, unimplemented: inlining failed in call to 'const Eigen::Eval<Derived> Eigen::MatrixBase<Scalar, Derived>::eval() const'
+// : function body not available
+#if EIGEN_GNUC_AT_LEAST(4,0)
+#define EIGEN_ALWAYS_INLINE_ATTRIB __attribute__((always_inline))
+#else
+#define EIGEN_ALWAYS_INLINE_ATTRIB
+#endif
+
+// EIGEN_FORCE_INLINE means "inline as much as possible"
+#if (defined _MSC_VER)
+#define EIGEN_STRONG_INLINE __forceinline
+#else
+#define EIGEN_STRONG_INLINE inline
+#endif
+
+#if (defined __GNUC__)
+#define EIGEN_DONT_INLINE __attribute__((noinline))
+#elif (defined _MSC_VER)
+#define EIGEN_DONT_INLINE __declspec(noinline)
+#else
+#define EIGEN_DONT_INLINE
+#endif
+
+#if (defined __GNUC__)
+#define EIGEN_DEPRECATED __attribute__((deprecated))
+#elif (defined _MSC_VER)
+#define EIGEN_DEPRECATED __declspec(deprecated)
+#else
+#define EIGEN_DEPRECATED
+#endif
+
+/* EIGEN_ALIGN_128 forces data to be 16-byte aligned, EVEN if vectorization (EIGEN_VECTORIZE) is disabled,
+ * so that vectorization doesn't affect binary compatibility.
+ *
+ * If we made alignment depend on whether or not EIGEN_VECTORIZE is defined, it would be impossible to link
+ * vectorized and non-vectorized code.
+ */
+#if !EIGEN_ALIGN
+#define EIGEN_ALIGN_128
+#elif (defined __GNUC__)
+#define EIGEN_ALIGN_128 __attribute__((aligned(16)))
+#elif (defined _MSC_VER)
+#define EIGEN_ALIGN_128 __declspec(align(16))
+#else
+#error Please tell me what is the equivalent of __attribute__((aligned(16))) for your compiler
+#endif
+
+#ifdef EIGEN_DONT_USE_RESTRICT_KEYWORD
+ #define EIGEN_RESTRICT
+#endif
+#ifndef EIGEN_RESTRICT
+ #define EIGEN_RESTRICT __restrict
+#endif
+
+#ifndef EIGEN_STACK_ALLOCATION_LIMIT
+#define EIGEN_STACK_ALLOCATION_LIMIT 1000000
+#endif
+
+#ifndef EIGEN_DEFAULT_IO_FORMAT
+#define EIGEN_DEFAULT_IO_FORMAT Eigen::IOFormat()
+#endif
+
+// format used in Eigen's documentation
+// needed to define it here as escaping characters in CMake add_definition's argument seems very problematic.
+#define EIGEN_DOCS_IO_FORMAT IOFormat(3, AlignCols, " ", "\n", "", "")
+
+#define EIGEN_INHERIT_ASSIGNMENT_OPERATOR(Derived, Op) \
+template<typename OtherDerived> \
+EIGEN_STRONG_INLINE Derived& operator Op(const Eigen::MatrixBase<OtherDerived>& other) \
+{ \
+ return Base::operator Op(other.derived()); \
+} \
+EIGEN_STRONG_INLINE Derived& operator Op(const Derived& other) \
+{ \
+ return Base::operator Op(other); \
+}
+
+#define EIGEN_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, Op) \
+template<typename Other> \
+EIGEN_STRONG_INLINE Derived& operator Op(const Other& scalar) \
+{ \
+ return Base::operator Op(scalar); \
+}
+
+#define EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Derived) \
+EIGEN_INHERIT_ASSIGNMENT_OPERATOR(Derived, =) \
+EIGEN_INHERIT_ASSIGNMENT_OPERATOR(Derived, +=) \
+EIGEN_INHERIT_ASSIGNMENT_OPERATOR(Derived, -=) \
+EIGEN_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, *=) \
+EIGEN_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, /=)
+
+#define _EIGEN_GENERIC_PUBLIC_INTERFACE(Derived, BaseClass) \
+typedef BaseClass Base; \
+typedef typename Eigen::ei_traits<Derived>::Scalar Scalar; \
+typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; \
+typedef typename Base::PacketScalar PacketScalar; \
+typedef typename Eigen::ei_nested<Derived>::type Nested; \
+enum { RowsAtCompileTime = Eigen::ei_traits<Derived>::RowsAtCompileTime, \
+ ColsAtCompileTime = Eigen::ei_traits<Derived>::ColsAtCompileTime, \
+ MaxRowsAtCompileTime = Eigen::ei_traits<Derived>::MaxRowsAtCompileTime, \
+ MaxColsAtCompileTime = Eigen::ei_traits<Derived>::MaxColsAtCompileTime, \
+ Flags = Eigen::ei_traits<Derived>::Flags, \
+ CoeffReadCost = Eigen::ei_traits<Derived>::CoeffReadCost, \
+ SizeAtCompileTime = Base::SizeAtCompileTime, \
+ MaxSizeAtCompileTime = Base::MaxSizeAtCompileTime, \
+ IsVectorAtCompileTime = Base::IsVectorAtCompileTime };
+
+#define EIGEN_GENERIC_PUBLIC_INTERFACE(Derived) \
+_EIGEN_GENERIC_PUBLIC_INTERFACE(Derived, Eigen::MatrixBase<Derived>)
+
+#define EIGEN_ENUM_MIN(a,b) (((int)a <= (int)b) ? (int)a : (int)b)
+#define EIGEN_ENUM_MAX(a,b) (((int)a >= (int)b) ? (int)a : (int)b)
+
+// just an empty macro !
+#define EIGEN_EMPTY
+
+// concatenate two tokens
+#define EIGEN_CAT2(a,b) a ## b
+#define EIGEN_CAT(a,b) EIGEN_CAT2(a,b)
+
+// convert a token to a string
+#define EIGEN_MAKESTRING2(a) #a
+#define EIGEN_MAKESTRING(a) EIGEN_MAKESTRING2(a)
+
+#endif // EIGEN_MACROS_H
diff --git a/extern/Eigen2/Eigen/src/Core/util/Memory.h b/extern/Eigen2/Eigen/src/Core/util/Memory.h
new file mode 100644
index 00000000000..0a43e7f7bf2
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/util/Memory.h
@@ -0,0 +1,387 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2009 Kenneth Riddile <kfriddile@yahoo.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_MEMORY_H
+#define EIGEN_MEMORY_H
+
+// FreeBSD 6 seems to have 16-byte aligned malloc
+// See http://svn.freebsd.org/viewvc/base/stable/6/lib/libc/stdlib/malloc.c?view=markup
+// FreeBSD 7 seems to have 16-byte aligned malloc except on ARM and MIPS architectures
+// See http://svn.freebsd.org/viewvc/base/stable/7/lib/libc/stdlib/malloc.c?view=markup
+#if defined(__FreeBSD__) && !defined(__arm__) && !defined(__mips__)
+#define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 1
+#else
+#define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 0
+#endif
+
+#if defined(__APPLE__) || defined(_WIN64) || EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED
+ #define EIGEN_MALLOC_ALREADY_ALIGNED 1
+#else
+ #define EIGEN_MALLOC_ALREADY_ALIGNED 0
+#endif
+
+#if ((defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
+ #define EIGEN_HAS_POSIX_MEMALIGN 1
+#else
+ #define EIGEN_HAS_POSIX_MEMALIGN 0
+#endif
+
+#ifdef EIGEN_VECTORIZE_SSE
+ #define EIGEN_HAS_MM_MALLOC 1
+#else
+ #define EIGEN_HAS_MM_MALLOC 0
+#endif
+
+/** \internal like malloc, but the returned pointer is guaranteed to be 16-byte aligned.
+ * Fast, but wastes 16 additional bytes of memory.
+ * Does not throw any exception.
+ */
+inline void* ei_handmade_aligned_malloc(size_t size)
+{
+ void *original = malloc(size+16);
+ void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
+ *(reinterpret_cast<void**>(aligned) - 1) = original;
+ return aligned;
+}
+
+/** \internal frees memory allocated with ei_handmade_aligned_malloc */
+inline void ei_handmade_aligned_free(void *ptr)
+{
+ if(ptr)
+ free(*(reinterpret_cast<void**>(ptr) - 1));
+}
+
+/** \internal allocates \a size bytes. The returned pointer is guaranteed to have 16 bytes alignment.
+ * On allocation error, the returned pointer is null, and if exceptions are enabled then a std::bad_alloc is thrown.
+ */
+inline void* ei_aligned_malloc(size_t size)
+{
+ #ifdef EIGEN_NO_MALLOC
+ ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
+ #endif
+
+ void *result;
+ #if !EIGEN_ALIGN
+ result = malloc(size);
+ #elif EIGEN_MALLOC_ALREADY_ALIGNED
+ result = malloc(size);
+ #elif EIGEN_HAS_POSIX_MEMALIGN
+ if(posix_memalign(&result, 16, size)) result = 0;
+ #elif EIGEN_HAS_MM_MALLOC
+ result = _mm_malloc(size, 16);
+ #elif (defined _MSC_VER)
+ result = _aligned_malloc(size, 16);
+ #else
+ result = ei_handmade_aligned_malloc(size);
+ #endif
+
+ #ifdef EIGEN_EXCEPTIONS
+ if(result == 0)
+ throw std::bad_alloc();
+ #endif
+ return result;
+}
+
+/** allocates \a size bytes. If Align is true, then the returned ptr is 16-byte-aligned.
+ * On allocation error, the returned pointer is null, and if exceptions are enabled then a std::bad_alloc is thrown.
+ */
+template<bool Align> inline void* ei_conditional_aligned_malloc(size_t size)
+{
+ return ei_aligned_malloc(size);
+}
+
+template<> inline void* ei_conditional_aligned_malloc<false>(size_t size)
+{
+ #ifdef EIGEN_NO_MALLOC
+ ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
+ #endif
+
+ void *result = malloc(size);
+ #ifdef EIGEN_EXCEPTIONS
+ if(!result) throw std::bad_alloc();
+ #endif
+ return result;
+}
+
+/** \internal construct the elements of an array.
+ * The \a size parameter tells on how many objects to call the constructor of T.
+ */
+template<typename T> inline T* ei_construct_elements_of_array(T *ptr, size_t size)
+{
+ for (size_t i=0; i < size; ++i) ::new (ptr + i) T;
+ return ptr;
+}
+
+/** allocates \a size objects of type T. The returned pointer is guaranteed to have 16 bytes alignment.
+ * On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
+ * The default constructor of T is called.
+ */
+template<typename T> inline T* ei_aligned_new(size_t size)
+{
+ T *result = reinterpret_cast<T*>(ei_aligned_malloc(sizeof(T)*size));
+ return ei_construct_elements_of_array(result, size);
+}
+
+template<typename T, bool Align> inline T* ei_conditional_aligned_new(size_t size)
+{
+ T *result = reinterpret_cast<T*>(ei_conditional_aligned_malloc<Align>(sizeof(T)*size));
+ return ei_construct_elements_of_array(result, size);
+}
+
+/** \internal free memory allocated with ei_aligned_malloc
+ */
+inline void ei_aligned_free(void *ptr)
+{
+ #if !EIGEN_ALIGN
+ free(ptr);
+ #elif EIGEN_MALLOC_ALREADY_ALIGNED
+ free(ptr);
+ #elif EIGEN_HAS_POSIX_MEMALIGN
+ free(ptr);
+ #elif EIGEN_HAS_MM_MALLOC
+ _mm_free(ptr);
+ #elif defined(_MSC_VER)
+ _aligned_free(ptr);
+ #else
+ ei_handmade_aligned_free(ptr);
+ #endif
+}
+
+/** \internal free memory allocated with ei_conditional_aligned_malloc
+ */
+template<bool Align> inline void ei_conditional_aligned_free(void *ptr)
+{
+ ei_aligned_free(ptr);
+}
+
+template<> inline void ei_conditional_aligned_free<false>(void *ptr)
+{
+ free(ptr);
+}
+
+/** \internal destruct the elements of an array.
+ * The \a size parameters tells on how many objects to call the destructor of T.
+ */
+template<typename T> inline void ei_destruct_elements_of_array(T *ptr, size_t size)
+{
+ // always destruct an array starting from the end.
+ while(size) ptr[--size].~T();
+}
+
+/** \internal delete objects constructed with ei_aligned_new
+ * The \a size parameters tells on how many objects to call the destructor of T.
+ */
+template<typename T> inline void ei_aligned_delete(T *ptr, size_t size)
+{
+ ei_destruct_elements_of_array<T>(ptr, size);
+ ei_aligned_free(ptr);
+}
+
+/** \internal delete objects constructed with ei_conditional_aligned_new
+ * The \a size parameters tells on how many objects to call the destructor of T.
+ */
+template<typename T, bool Align> inline void ei_conditional_aligned_delete(T *ptr, size_t size)
+{
+ ei_destruct_elements_of_array<T>(ptr, size);
+ ei_conditional_aligned_free<Align>(ptr);
+}
+
+/** \internal \returns the number of elements which have to be skipped such that data are 16 bytes aligned */
+template<typename Scalar>
+inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
+{
+ typedef typename ei_packet_traits<Scalar>::type Packet;
+ const int PacketSize = ei_packet_traits<Scalar>::size;
+ const int PacketAlignedMask = PacketSize-1;
+ const bool Vectorized = PacketSize>1;
+ return Vectorized
+ ? std::min<int>( (PacketSize - (int((size_t(ptr)/sizeof(Scalar))) & PacketAlignedMask))
+ & PacketAlignedMask, maxOffset)
+ : 0;
+}
+
+/** \internal
+ * ei_aligned_stack_alloc(SIZE) allocates an aligned buffer of SIZE bytes
+ * on the stack if SIZE is smaller than EIGEN_STACK_ALLOCATION_LIMIT.
+ * Otherwise the memory is allocated on the heap.
+ * Data allocated with ei_aligned_stack_alloc \b must be freed by calling ei_aligned_stack_free(PTR,SIZE).
+ * \code
+ * float * data = ei_aligned_stack_alloc(float,array.size());
+ * // ...
+ * ei_aligned_stack_free(data,float,array.size());
+ * \endcode
+ */
+#ifdef __linux__
+ #define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \
+ ? alloca(SIZE) \
+ : ei_aligned_malloc(SIZE)
+ #define ei_aligned_stack_free(PTR,SIZE) if(SIZE>EIGEN_STACK_ALLOCATION_LIMIT) ei_aligned_free(PTR)
+#else
+ #define ei_aligned_stack_alloc(SIZE) ei_aligned_malloc(SIZE)
+ #define ei_aligned_stack_free(PTR,SIZE) ei_aligned_free(PTR)
+#endif
+
+#define ei_aligned_stack_new(TYPE,SIZE) ei_construct_elements_of_array(reinterpret_cast<TYPE*>(ei_aligned_stack_alloc(sizeof(TYPE)*SIZE)), SIZE)
+#define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {ei_destruct_elements_of_array<TYPE>(PTR, SIZE); \
+ ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0)
+
+
+#if EIGEN_ALIGN
+ #ifdef EIGEN_EXCEPTIONS
+ #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
+ void* operator new(size_t size, const std::nothrow_t&) throw() { \
+ try { return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); } \
+ catch (...) { return 0; } \
+ return 0; \
+ }
+ #else
+ #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
+ void* operator new(size_t size, const std::nothrow_t&) throw() { \
+ return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
+ }
+ #endif
+
+ #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
+ void *operator new(size_t size) { \
+ return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
+ } \
+ void *operator new[](size_t size) { \
+ return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
+ } \
+ void operator delete(void * ptr) throw() { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
+ void operator delete[](void * ptr) throw() { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
+ /* in-place new and delete. since (at least afaik) there is no actual */ \
+ /* memory allocated we can safely let the default implementation handle */ \
+ /* this particular case. */ \
+ static void *operator new(size_t size, void *ptr) { return ::operator new(size,ptr); } \
+ void operator delete(void * memory, void *ptr) throw() { return ::operator delete(memory,ptr); } \
+ /* nothrow-new (returns zero instead of std::bad_alloc) */ \
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
+ void operator delete(void *ptr, const std::nothrow_t&) throw() { \
+ Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); \
+ } \
+ typedef void ei_operator_new_marker_type;
+#else
+ #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
+#endif
+
+#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(true)
+#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar,Size) \
+ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0))
+
+
+/** \class aligned_allocator
+*
+* \brief stl compatible allocator to use with with 16 byte aligned types
+*
+* Example:
+* \code
+* // Matrix4f requires 16 bytes alignment:
+* std::map< int, Matrix4f, std::less<int>, aligned_allocator<Matrix4f> > my_map_mat4;
+* // Vector3f does not require 16 bytes alignment, no need to use Eigen's allocator:
+* std::map< int, Vector3f > my_map_vec3;
+* \endcode
+*
+*/
+template<class T>
+class aligned_allocator
+{
+public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T value_type;
+
+ template<class U>
+ struct rebind
+ {
+ typedef aligned_allocator<U> other;
+ };
+
+ pointer address( reference value ) const
+ {
+ return &value;
+ }
+
+ const_pointer address( const_reference value ) const
+ {
+ return &value;
+ }
+
+ aligned_allocator() throw()
+ {
+ }
+
+ aligned_allocator( const aligned_allocator& ) throw()
+ {
+ }
+
+ template<class U>
+ aligned_allocator( const aligned_allocator<U>& ) throw()
+ {
+ }
+
+ ~aligned_allocator() throw()
+ {
+ }
+
+ size_type max_size() const throw()
+ {
+ return std::numeric_limits<size_type>::max();
+ }
+
+ pointer allocate( size_type num, const_pointer* hint = 0 )
+ {
+ static_cast<void>( hint ); // suppress unused variable warning
+ return static_cast<pointer>( ei_aligned_malloc( num * sizeof(T) ) );
+ }
+
+ void construct( pointer p, const T& value )
+ {
+ ::new( p ) T( value );
+ }
+
+ void destroy( pointer p )
+ {
+ p->~T();
+ }
+
+ void deallocate( pointer p, size_type /*num*/ )
+ {
+ ei_aligned_free( p );
+ }
+
+ bool operator!=(const aligned_allocator<T>& other) const
+ { return false; }
+
+ bool operator==(const aligned_allocator<T>& other) const
+ { return true; }
+};
+
+#endif // EIGEN_MEMORY_H
diff --git a/extern/Eigen2/Eigen/src/Core/util/Meta.h b/extern/Eigen2/Eigen/src/Core/util/Meta.h
new file mode 100644
index 00000000000..c65c52ef42f
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/util/Meta.h
@@ -0,0 +1,183 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_META_H
+#define EIGEN_META_H
+
+/** \internal
+ * \file Meta.h
+ * This file contains generic metaprogramming classes which are not specifically related to Eigen.
+ * \note In case you wonder, yes we're aware that Boost already provides all these features,
+ * we however don't want to add a dependency to Boost.
+ */
+
+struct ei_meta_true { enum { ret = 1 }; };
+struct ei_meta_false { enum { ret = 0 }; };
+
+template<bool Condition, typename Then, typename Else>
+struct ei_meta_if { typedef Then ret; };
+
+template<typename Then, typename Else>
+struct ei_meta_if <false, Then, Else> { typedef Else ret; };
+
+template<typename T, typename U> struct ei_is_same_type { enum { ret = 0 }; };
+template<typename T> struct ei_is_same_type<T,T> { enum { ret = 1 }; };
+
+template<typename T> struct ei_unref { typedef T type; };
+template<typename T> struct ei_unref<T&> { typedef T type; };
+
+template<typename T> struct ei_unpointer { typedef T type; };
+template<typename T> struct ei_unpointer<T*> { typedef T type; };
+template<typename T> struct ei_unpointer<T*const> { typedef T type; };
+
+template<typename T> struct ei_unconst { typedef T type; };
+template<typename T> struct ei_unconst<const T> { typedef T type; };
+template<typename T> struct ei_unconst<T const &> { typedef T & type; };
+template<typename T> struct ei_unconst<T const *> { typedef T * type; };
+
+template<typename T> struct ei_cleantype { typedef T type; };
+template<typename T> struct ei_cleantype<const T> { typedef typename ei_cleantype<T>::type type; };
+template<typename T> struct ei_cleantype<const T&> { typedef typename ei_cleantype<T>::type type; };
+template<typename T> struct ei_cleantype<T&> { typedef typename ei_cleantype<T>::type type; };
+template<typename T> struct ei_cleantype<const T*> { typedef typename ei_cleantype<T>::type type; };
+template<typename T> struct ei_cleantype<T*> { typedef typename ei_cleantype<T>::type type; };
+
+/** \internal
+ * Convenient struct to get the result type of a unary or binary functor.
+ *
+ * It supports both the current STL mechanism (using the result_type member) as well as
+ * upcoming next STL generation (using a templated result member).
+ * If none of these members is provided, then the type of the first argument is returned. FIXME, that behavior is a pretty bad hack.
+ */
+template<typename T> struct ei_result_of {};
+
+struct ei_has_none {int a[1];};
+struct ei_has_std_result_type {int a[2];};
+struct ei_has_tr1_result {int a[3];};
+
+template<typename Func, typename ArgType, int SizeOf=sizeof(ei_has_none)>
+struct ei_unary_result_of_select {typedef ArgType type;};
+
+template<typename Func, typename ArgType>
+struct ei_unary_result_of_select<Func, ArgType, sizeof(ei_has_std_result_type)> {typedef typename Func::result_type type;};
+
+template<typename Func, typename ArgType>
+struct ei_unary_result_of_select<Func, ArgType, sizeof(ei_has_tr1_result)> {typedef typename Func::template result<Func(ArgType)>::type type;};
+
+template<typename Func, typename ArgType>
+struct ei_result_of<Func(ArgType)> {
+ template<typename T>
+ static ei_has_std_result_type testFunctor(T const *, typename T::result_type const * = 0);
+ template<typename T>
+ static ei_has_tr1_result testFunctor(T const *, typename T::template result<T(ArgType)>::type const * = 0);
+ static ei_has_none testFunctor(...);
+
+ // note that the following indirection is needed for gcc-3.3
+ enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
+ typedef typename ei_unary_result_of_select<Func, ArgType, FunctorType>::type type;
+};
+
+template<typename Func, typename ArgType0, typename ArgType1, int SizeOf=sizeof(ei_has_none)>
+struct ei_binary_result_of_select {typedef ArgType0 type;};
+
+template<typename Func, typename ArgType0, typename ArgType1>
+struct ei_binary_result_of_select<Func, ArgType0, ArgType1, sizeof(ei_has_std_result_type)>
+{typedef typename Func::result_type type;};
+
+template<typename Func, typename ArgType0, typename ArgType1>
+struct ei_binary_result_of_select<Func, ArgType0, ArgType1, sizeof(ei_has_tr1_result)>
+{typedef typename Func::template result<Func(ArgType0,ArgType1)>::type type;};
+
+template<typename Func, typename ArgType0, typename ArgType1>
+struct ei_result_of<Func(ArgType0,ArgType1)> {
+ template<typename T>
+ static ei_has_std_result_type testFunctor(T const *, typename T::result_type const * = 0);
+ template<typename T>
+ static ei_has_tr1_result testFunctor(T const *, typename T::template result<T(ArgType0,ArgType1)>::type const * = 0);
+ static ei_has_none testFunctor(...);
+
+ // note that the following indirection is needed for gcc-3.3
+ enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
+ typedef typename ei_binary_result_of_select<Func, ArgType0, ArgType1, FunctorType>::type type;
+};
+
+/** \internal In short, it computes int(sqrt(\a Y)) with \a Y an integer.
+ * Usage example: \code ei_meta_sqrt<1023>::ret \endcode
+ */
+template<int Y,
+ int InfX = 0,
+ int SupX = ((Y==1) ? 1 : Y/2),
+ bool Done = ((SupX-InfX)<=1 ? true : ((SupX*SupX <= Y) && ((SupX+1)*(SupX+1) > Y))) >
+ // use ?: instead of || just to shut up a stupid gcc 4.3 warning
+class ei_meta_sqrt
+{
+ enum {
+ MidX = (InfX+SupX)/2,
+ TakeInf = MidX*MidX > Y ? 1 : 0,
+ NewInf = int(TakeInf) ? InfX : int(MidX),
+ NewSup = int(TakeInf) ? int(MidX) : SupX
+ };
+ public:
+ enum { ret = ei_meta_sqrt<Y,NewInf,NewSup>::ret };
+};
+
+template<int Y, int InfX, int SupX>
+class ei_meta_sqrt<Y, InfX, SupX, true> { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
+
+/** \internal determines whether the product of two numeric types is allowed and what the return type is */
+template<typename T, typename U> struct ei_scalar_product_traits
+{
+ // dummy general case where T and U aren't compatible -- not allowed anyway but we catch it elsewhere
+ //enum { Cost = NumTraits<T>::MulCost };
+ typedef T ReturnType;
+};
+
+template<typename T> struct ei_scalar_product_traits<T,T>
+{
+ //enum { Cost = NumTraits<T>::MulCost };
+ typedef T ReturnType;
+};
+
+template<typename T> struct ei_scalar_product_traits<T,std::complex<T> >
+{
+ //enum { Cost = 2*NumTraits<T>::MulCost };
+ typedef std::complex<T> ReturnType;
+};
+
+template<typename T> struct ei_scalar_product_traits<std::complex<T>, T>
+{
+ //enum { Cost = 2*NumTraits<T>::MulCost };
+ typedef std::complex<T> ReturnType;
+};
+
+// FIXME quick workaround around current limitation of ei_result_of
+template<typename Scalar, typename ArgType0, typename ArgType1>
+struct ei_result_of<ei_scalar_product_op<Scalar>(ArgType0,ArgType1)> {
+typedef typename ei_scalar_product_traits<typename ei_cleantype<ArgType0>::type, typename ei_cleantype<ArgType1>::type>::ReturnType type;
+};
+
+
+
+#endif // EIGEN_META_H
diff --git a/extern/Eigen3/Eigen/src/Core/util/StaticAssert.h b/extern/Eigen2/Eigen/src/Core/util/StaticAssert.h
index 99c7c9972f0..2c13098a20f 100644
--- a/extern/Eigen3/Eigen/src/Core/util/StaticAssert.h
+++ b/extern/Eigen2/Eigen/src/Core/util/StaticAssert.h
@@ -1,8 +1,8 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -29,11 +29,11 @@
/* Some notes on Eigen's static assertion mechanism:
*
* - in EIGEN_STATIC_ASSERT(CONDITION,MSG) the parameter CONDITION must be a compile time boolean
- * expression, and MSG an enum listed in struct internal::static_assertion<true>
+ * expression, and MSG an enum listed in struct ei_static_assert<true>
*
* - define EIGEN_NO_STATIC_ASSERT to disable them (and save compilation time)
* in that case, the static assertion is converted to the following runtime assert:
- * eigen_assert(CONDITION && "MSG")
+ * ei_assert(CONDITION && "MSG")
*
* - currently EIGEN_STATIC_ASSERT can only be used in function scope
*
@@ -41,20 +41,18 @@
#ifndef EIGEN_NO_STATIC_ASSERT
- #if defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(_MSC_VER) && (_MSC_VER >= 1600))
+ #ifdef __GXX_EXPERIMENTAL_CXX0X__
// if native static_assert is enabled, let's use it
#define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG);
- #else // not CXX0X
-
- namespace internal {
+ #else // CXX0X
template<bool condition>
- struct static_assertion {};
+ struct ei_static_assert {};
template<>
- struct static_assertion<true>
+ struct ei_static_assert<true>
{
enum {
YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX,
@@ -62,15 +60,10 @@
YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES,
THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE,
THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE,
- THIS_METHOD_IS_ONLY_FOR_OBJECTS_OF_A_SPECIFIC_SIZE,
YOU_MADE_A_PROGRAMMING_MISTAKE,
- EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT,
- EIGEN_INTERNAL_COMPILATION_ERROR_OR_YOU_MADE_A_PROGRAMMING_MISTAKE,
YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR,
- YOU_CALLED_A_DYNAMIC_SIZE_METHOD_ON_A_FIXED_SIZE_MATRIX_OR_VECTOR,
UNALIGNED_LOAD_AND_STORE_OPERATIONS_UNIMPLEMENTED_ON_ALTIVEC,
- THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES,
- NUMERIC_TYPE_MUST_BE_REAL,
+ NUMERIC_TYPE_MUST_BE_FLOATING_POINT,
COEFFICIENT_WRITE_ACCESS_TO_SELFADJOINT_NOT_SUPPORTED,
WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED,
THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE,
@@ -81,38 +74,23 @@
THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES,
THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES,
INVALID_MATRIX_TEMPLATE_PARAMETERS,
- INVALID_MATRIXBASE_TEMPLATE_PARAMETERS,
BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER,
- THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX,
- THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE,
- THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES,
- YOU_ALREADY_SPECIFIED_THIS_STRIDE,
- INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION,
- THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD,
- PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1,
- THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS,
- YOU_CANNOT_MIX_ARRAYS_AND_MATRICES,
- YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION,
- THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY,
- YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT,
- THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS
+ THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX
};
};
- } // end namespace internal
-
// Specialized implementation for MSVC to avoid "conditional
// expression is constant" warnings. This implementation doesn't
// appear to work under GCC, hence the multiple implementations.
#ifdef _MSC_VER
#define EIGEN_STATIC_ASSERT(CONDITION,MSG) \
- {Eigen::internal::static_assertion<bool(CONDITION)>::MSG;}
+ {Eigen::ei_static_assert<CONDITION ? true : false>::MSG;}
#else
#define EIGEN_STATIC_ASSERT(CONDITION,MSG) \
- if (Eigen::internal::static_assertion<bool(CONDITION)>::MSG) {}
+ if (Eigen::ei_static_assert<CONDITION ? true : false>::MSG) {}
#endif
@@ -120,7 +98,7 @@
#else // EIGEN_NO_STATIC_ASSERT
- #define EIGEN_STATIC_ASSERT(CONDITION,MSG) eigen_assert((CONDITION) && #MSG);
+ #define EIGEN_STATIC_ASSERT(CONDITION,MSG) ei_assert((CONDITION) && #MSG);
#endif // EIGEN_NO_STATIC_ASSERT
@@ -135,11 +113,6 @@
EIGEN_STATIC_ASSERT(TYPE::SizeAtCompileTime!=Eigen::Dynamic, \
YOU_CALLED_A_FIXED_SIZE_METHOD_ON_A_DYNAMIC_SIZE_MATRIX_OR_VECTOR)
-// static assertion failing if the type \a TYPE is not dynamic-size
-#define EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(TYPE) \
- EIGEN_STATIC_ASSERT(TYPE::SizeAtCompileTime==Eigen::Dynamic, \
- YOU_CALLED_A_DYNAMIC_SIZE_METHOD_ON_A_FIXED_SIZE_MATRIX_OR_VECTOR)
-
// static assertion failing if the type \a TYPE is not a vector type of the given size
#define EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(TYPE, SIZE) \
EIGEN_STATIC_ASSERT(TYPE::IsVectorAtCompileTime && TYPE::SizeAtCompileTime==SIZE, \
@@ -159,26 +132,12 @@
YOU_MIXED_VECTORS_OF_DIFFERENT_SIZES)
#define EIGEN_PREDICATE_SAME_MATRIX_SIZE(TYPE0,TYPE1) \
- ( \
- (int(TYPE0::SizeAtCompileTime)==0 && int(TYPE1::SizeAtCompileTime)==0) \
- || (\
- (int(TYPE0::RowsAtCompileTime)==Eigen::Dynamic \
- || int(TYPE1::RowsAtCompileTime)==Eigen::Dynamic \
- || int(TYPE0::RowsAtCompileTime)==int(TYPE1::RowsAtCompileTime)) \
- && (int(TYPE0::ColsAtCompileTime)==Eigen::Dynamic \
- || int(TYPE1::ColsAtCompileTime)==Eigen::Dynamic \
- || int(TYPE0::ColsAtCompileTime)==int(TYPE1::ColsAtCompileTime))\
- ) \
- )
-
-#ifdef EIGEN2_SUPPORT
- #define EIGEN_STATIC_ASSERT_NON_INTEGER(TYPE) \
- eigen_assert(!NumTraits<Scalar>::IsInteger);
-#else
- #define EIGEN_STATIC_ASSERT_NON_INTEGER(TYPE) \
- EIGEN_STATIC_ASSERT(!NumTraits<TYPE>::IsInteger, THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES)
-#endif
-
+ ((int(TYPE0::RowsAtCompileTime)==Eigen::Dynamic \
+ || int(TYPE1::RowsAtCompileTime)==Eigen::Dynamic \
+ || int(TYPE0::RowsAtCompileTime)==int(TYPE1::RowsAtCompileTime)) \
+ && (int(TYPE0::ColsAtCompileTime)==Eigen::Dynamic \
+ || int(TYPE1::ColsAtCompileTime)==Eigen::Dynamic \
+ || int(TYPE0::ColsAtCompileTime)==int(TYPE1::ColsAtCompileTime)))
// static assertion failing if it is guaranteed at compile-time that the two matrix expression types have different sizes
#define EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(TYPE0,TYPE1) \
@@ -186,13 +145,4 @@
EIGEN_PREDICATE_SAME_MATRIX_SIZE(TYPE0,TYPE1),\
YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES)
-#define EIGEN_STATIC_ASSERT_SIZE_1x1(TYPE) \
- EIGEN_STATIC_ASSERT((TYPE::RowsAtCompileTime == 1 || TYPE::RowsAtCompileTime == Dynamic) && \
- (TYPE::ColsAtCompileTime == 1 || TYPE::ColsAtCompileTime == Dynamic), \
- THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS)
-
-#define EIGEN_STATIC_ASSERT_LVALUE(Derived) \
- EIGEN_STATIC_ASSERT(internal::is_lvalue<Derived>::value, \
- THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY)
-
#endif // EIGEN_STATIC_ASSERT_H
diff --git a/extern/Eigen2/Eigen/src/Core/util/XprHelper.h b/extern/Eigen2/Eigen/src/Core/util/XprHelper.h
new file mode 100644
index 00000000000..12d6f9a3a3e
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Core/util/XprHelper.h
@@ -0,0 +1,219 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_XPRHELPER_H
+#define EIGEN_XPRHELPER_H
+
+// just a workaround because GCC seems to not really like empty structs
+#ifdef __GNUG__
+ struct ei_empty_struct{char _ei_dummy_;};
+ #define EIGEN_EMPTY_STRUCT : Eigen::ei_empty_struct
+#else
+ #define EIGEN_EMPTY_STRUCT
+#endif
+
+//classes inheriting ei_no_assignment_operator don't generate a default operator=.
+class ei_no_assignment_operator
+{
+ private:
+ ei_no_assignment_operator& operator=(const ei_no_assignment_operator&);
+};
+
+/** \internal If the template parameter Value is Dynamic, this class is just a wrapper around an int variable that
+ * can be accessed using value() and setValue().
+ * Otherwise, this class is an empty structure and value() just returns the template parameter Value.
+ */
+template<int Value> class ei_int_if_dynamic EIGEN_EMPTY_STRUCT
+{
+ public:
+ ei_int_if_dynamic() {}
+ explicit ei_int_if_dynamic(int) {}
+ static int value() { return Value; }
+ void setValue(int) {}
+};
+
+template<> class ei_int_if_dynamic<Dynamic>
+{
+ int m_value;
+ ei_int_if_dynamic() {}
+ public:
+ explicit ei_int_if_dynamic(int value) : m_value(value) {}
+ int value() const { return m_value; }
+ void setValue(int value) { m_value = value; }
+};
+
+template<typename T> struct ei_functor_traits
+{
+ enum
+ {
+ Cost = 10,
+ PacketAccess = false
+ };
+};
+
+template<typename T> struct ei_packet_traits
+{
+ typedef T type;
+ enum {size=1};
+};
+
+template<typename T> struct ei_unpacket_traits
+{
+ typedef T type;
+ enum {size=1};
+};
+
+template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
+class ei_compute_matrix_flags
+{
+ enum {
+ row_major_bit = Options&RowMajor ? RowMajorBit : 0,
+ inner_max_size = row_major_bit ? MaxCols : MaxRows,
+ is_big = inner_max_size == Dynamic,
+ is_packet_size_multiple = (Cols*Rows) % ei_packet_traits<Scalar>::size == 0,
+ aligned_bit = ((Options&AutoAlign) && (is_big || is_packet_size_multiple)) ? AlignedBit : 0,
+ packet_access_bit = ei_packet_traits<Scalar>::size > 1 && aligned_bit ? PacketAccessBit : 0
+ };
+
+ public:
+ enum { ret = LinearAccessBit | DirectAccessBit | packet_access_bit | row_major_bit | aligned_bit };
+};
+
+template<int _Rows, int _Cols> struct ei_size_at_compile_time
+{
+ enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols };
+};
+
+/* ei_eval : the return type of eval(). For matrices, this is just a const reference
+ * in order to avoid a useless copy
+ */
+
+template<typename T, int Sparseness = ei_traits<T>::Flags&SparseBit> class ei_eval;
+
+template<typename T> struct ei_eval<T,IsDense>
+{
+ typedef Matrix<typename ei_traits<T>::Scalar,
+ ei_traits<T>::RowsAtCompileTime,
+ ei_traits<T>::ColsAtCompileTime,
+ AutoAlign | (ei_traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
+ ei_traits<T>::MaxRowsAtCompileTime,
+ ei_traits<T>::MaxColsAtCompileTime
+ > type;
+};
+
+// for matrices, no need to evaluate, just use a const reference to avoid a useless copy
+template<typename _Scalar, int _Rows, int _Cols, int _StorageOrder, int _MaxRows, int _MaxCols>
+struct ei_eval<Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols>, IsDense>
+{
+ typedef const Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols>& type;
+};
+
+/* ei_plain_matrix_type : the difference from ei_eval is that ei_plain_matrix_type is always a plain matrix type,
+ * whereas ei_eval is a const reference in the case of a matrix
+ */
+template<typename T> struct ei_plain_matrix_type
+{
+ typedef Matrix<typename ei_traits<T>::Scalar,
+ ei_traits<T>::RowsAtCompileTime,
+ ei_traits<T>::ColsAtCompileTime,
+ AutoAlign | (ei_traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
+ ei_traits<T>::MaxRowsAtCompileTime,
+ ei_traits<T>::MaxColsAtCompileTime
+ > type;
+};
+
+/* ei_plain_matrix_type_column_major : same as ei_plain_matrix_type but guaranteed to be column-major
+ */
+template<typename T> struct ei_plain_matrix_type_column_major
+{
+ typedef Matrix<typename ei_traits<T>::Scalar,
+ ei_traits<T>::RowsAtCompileTime,
+ ei_traits<T>::ColsAtCompileTime,
+ AutoAlign | ColMajor,
+ ei_traits<T>::MaxRowsAtCompileTime,
+ ei_traits<T>::MaxColsAtCompileTime
+ > type;
+};
+
+template<typename T> struct ei_must_nest_by_value { enum { ret = false }; };
+template<typename T> struct ei_must_nest_by_value<NestByValue<T> > { enum { ret = true }; };
+
+/** \internal Determines how a given expression should be nested into another one.
+ * For example, when you do a * (b+c), Eigen will determine how the expression b+c should be
+ * nested into the bigger product expression. The choice is between nesting the expression b+c as-is, or
+ * evaluating that expression b+c into a temporary variable d, and nest d so that the resulting expression is
+ * a*d. Evaluating can be beneficial for example if every coefficient access in the resulting expression causes
+ * many coefficient accesses in the nested expressions -- as is the case with matrix product for example.
+ *
+ * \param T the type of the expression being nested
+ * \param n the number of coefficient accesses in the nested expression for each coefficient access in the bigger expression.
+ *
+ * Example. Suppose that a, b, and c are of type Matrix3d. The user forms the expression a*(b+c).
+ * b+c is an expression "sum of matrices", which we will denote by S. In order to determine how to nest it,
+ * the Product expression uses: ei_nested<S, 3>::ret, which turns out to be Matrix3d because the internal logic of
+ * ei_nested determined that in this case it was better to evaluate the expression b+c into a temporary. On the other hand,
+ * since a is of type Matrix3d, the Product expression nests it as ei_nested<Matrix3d, 3>::ret, which turns out to be
+ * const Matrix3d&, because the internal logic of ei_nested determined that since a was already a matrix, there was no point
+ * in copying it into another matrix.
+ */
+template<typename T, int n=1, typename PlainMatrixType = typename ei_eval<T>::type> struct ei_nested
+{
+ enum {
+ CostEval = (n+1) * int(NumTraits<typename ei_traits<T>::Scalar>::ReadCost),
+ CostNoEval = (n-1) * int(ei_traits<T>::CoeffReadCost)
+ };
+ typedef typename ei_meta_if<
+ ei_must_nest_by_value<T>::ret,
+ T,
+ typename ei_meta_if<
+ (int(ei_traits<T>::Flags) & EvalBeforeNestingBit)
+ || ( int(CostEval) <= int(CostNoEval) ),
+ PlainMatrixType,
+ const T&
+ >::ret
+ >::ret type;
+};
+
+template<unsigned int Flags> struct ei_are_flags_consistent
+{
+ enum { ret = !( (Flags&UnitDiagBit && Flags&ZeroDiagBit) )
+ };
+};
+
+/** \internal Gives the type of a sub-matrix or sub-vector of a matrix of type \a ExpressionType and size \a Size
+ * TODO: could be a good idea to define a big ReturnType struct ??
+ */
+template<typename ExpressionType, int RowsOrSize=Dynamic, int Cols=Dynamic> struct BlockReturnType {
+ typedef Block<ExpressionType, (ei_traits<ExpressionType>::RowsAtCompileTime == 1 ? 1 : RowsOrSize),
+ (ei_traits<ExpressionType>::ColsAtCompileTime == 1 ? 1 : RowsOrSize)> SubVectorType;
+ typedef Block<ExpressionType, RowsOrSize, Cols> Type;
+};
+
+template<typename CurrentType, typename NewType> struct ei_cast_return_type
+{
+ typedef typename ei_meta_if<ei_is_same_type<CurrentType,NewType>::ret,const CurrentType&,NewType>::ret type;
+};
+
+#endif // EIGEN_XPRHELPER_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h b/extern/Eigen2/Eigen/src/Geometry/AlignedBox.h
index 78df29d408a..14ec9261e3a 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h
+++ b/extern/Eigen2/Eigen/src/Geometry/AlignedBox.h
@@ -22,7 +22,8 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
+#ifndef EIGEN_ALIGNEDBOX_H
+#define EIGEN_ALIGNEDBOX_H
/** \geometry_module \ingroup Geometry_Module
* \nonstableyet
@@ -63,7 +64,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==
~AlignedBox() {}
/** \returns the dimension in which the box holds */
- inline int dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size()-1 : int(AmbientDimAtCompileTime); }
+ inline int dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size()-1 : AmbientDimAtCompileTime; }
/** \returns true if the box is null, i.e, empty. */
inline bool isNull() const { return (m_min.cwise() > m_max).any(); }
@@ -71,18 +72,18 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==
/** Makes \c *this a null/empty box. */
inline void setNull()
{
- m_min.setConstant( (std::numeric_limits<Scalar>::max)());
- m_max.setConstant(-(std::numeric_limits<Scalar>::max)());
+ m_min.setConstant( std::numeric_limits<Scalar>::max());
+ m_max.setConstant(-std::numeric_limits<Scalar>::max());
}
/** \returns the minimal corner */
- inline const VectorType& (min)() const { return m_min; }
+ inline const VectorType& min() const { return m_min; }
/** \returns a non const reference to the minimal corner */
- inline VectorType& (min)() { return m_min; }
+ inline VectorType& min() { return m_min; }
/** \returns the maximal corner */
- inline const VectorType& (max)() const { return m_max; }
+ inline const VectorType& max() const { return m_max; }
/** \returns a non const reference to the maximal corner */
- inline VectorType& (max)() { return m_max; }
+ inline VectorType& max() { return m_max; }
/** \returns true if the point \a p is inside the box \c *this. */
inline bool contains(const VectorType& p) const
@@ -90,19 +91,19 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==
/** \returns true if the box \a b is entirely inside the box \c *this. */
inline bool contains(const AlignedBox& b) const
- { return (m_min.cwise()<=(b.min)()).all() && ((b.max)().cwise()<=m_max).all(); }
+ { return (m_min.cwise()<=b.min()).all() && (b.max().cwise()<=m_max).all(); }
/** Extends \c *this such that it contains the point \a p and returns a reference to \c *this. */
inline AlignedBox& extend(const VectorType& p)
- { m_min = (m_min.cwise().min)(p); m_max = (m_max.cwise().max)(p); return *this; }
+ { m_min = m_min.cwise().min(p); m_max = m_max.cwise().max(p); return *this; }
/** Extends \c *this such that it contains the box \a b and returns a reference to \c *this. */
inline AlignedBox& extend(const AlignedBox& b)
- { m_min = (m_min.cwise().min)(b.m_min); m_max = (m_max.cwise().max)(b.m_max); return *this; }
+ { m_min = m_min.cwise().min(b.m_min); m_max = m_max.cwise().max(b.m_max); return *this; }
/** Clamps \c *this by the box \a b and returns a reference to \c *this. */
inline AlignedBox& clamp(const AlignedBox& b)
- { m_min = (m_min.cwise().max)(b.m_min); m_max = (m_max.cwise().min)(b.m_max); return *this; }
+ { m_min = m_min.cwise().max(b.m_min); m_max = m_max.cwise().min(b.m_max); return *this; }
/** Translate \c *this by the vector \a t and returns a reference to \c *this. */
inline AlignedBox& translate(const VectorType& t)
@@ -127,10 +128,10 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==
* then this function smartly returns a const reference to \c *this.
*/
template<typename NewScalarType>
- inline typename internal::cast_return_type<AlignedBox,
+ inline typename ei_cast_return_type<AlignedBox,
AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
{
- return typename internal::cast_return_type<AlignedBox,
+ return typename ei_cast_return_type<AlignedBox,
AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
}
@@ -138,8 +139,8 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==
template<typename OtherScalarType>
inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime>& other)
{
- m_min = (other.min)().template cast<Scalar>();
- m_max = (other.max)().template cast<Scalar>();
+ m_min = other.min().template cast<Scalar>();
+ m_max = other.max().template cast<Scalar>();
}
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
@@ -168,3 +169,5 @@ inline Scalar AlignedBox<Scalar,AmbiantDim>::squaredExteriorDistance(const Vecto
}
return dist2;
}
+
+#endif // EIGEN_ALIGNEDBOX_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AngleAxis.h b/extern/Eigen2/Eigen/src/Geometry/AngleAxis.h
index f7b2d51e3e2..91e3d0d61ec 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AngleAxis.h
+++ b/extern/Eigen2/Eigen/src/Geometry/AngleAxis.h
@@ -22,8 +22,8 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
-
+#ifndef EIGEN_ANGLEAXIS_H
+#define EIGEN_ANGLEAXIS_H
/** \geometry_module \ingroup Geometry_Module
*
@@ -139,8 +139,8 @@ public:
* then this function smartly returns a const reference to \c *this.
*/
template<typename NewScalarType>
- inline typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type cast() const
- { return typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type(*this); }
+ inline typename ei_cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type cast() const
+ { return typename ei_cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type(*this); }
/** Copy constructor with scalar type conversion */
template<typename OtherScalarType>
@@ -224,3 +224,5 @@ AngleAxis<Scalar>::toRotationMatrix(void) const
return res;
}
+
+#endif // EIGEN_ANGLEAXIS_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/EulerAngles.h b/extern/Eigen2/Eigen/src/Geometry/EulerAngles.h
index d246a6ebf4a..204118ac94d 100644
--- a/extern/Eigen3/Eigen/src/Geometry/EulerAngles.h
+++ b/extern/Eigen2/Eigen/src/Geometry/EulerAngles.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -26,7 +26,7 @@
#define EIGEN_EULERANGLES_H
/** \geometry_module \ingroup Geometry_Module
- *
+ * \nonstableyet
*
* \returns the Euler-angles of the rotation matrix \c *this using the convention defined by the triplet (\a a0,\a a1,\a a2)
*
@@ -43,48 +43,48 @@
*/
template<typename Derived>
inline Matrix<typename MatrixBase<Derived>::Scalar,3,1>
-MatrixBase<Derived>::eulerAngles(Index a0, Index a1, Index a2) const
+MatrixBase<Derived>::eulerAngles(int a0, int a1, int a2) const
{
/* Implemented from Graphics Gems IV */
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Derived,3,3)
Matrix<Scalar,3,1> res;
typedef Matrix<typename Derived::Scalar,2,1> Vector2;
- const Scalar epsilon = NumTraits<Scalar>::dummy_precision();
+ const Scalar epsilon = precision<Scalar>();
- const Index odd = ((a0+1)%3 == a1) ? 0 : 1;
- const Index i = a0;
- const Index j = (a0 + 1 + odd)%3;
- const Index k = (a0 + 2 - odd)%3;
+ const int odd = ((a0+1)%3 == a1) ? 0 : 1;
+ const int i = a0;
+ const int j = (a0 + 1 + odd)%3;
+ const int k = (a0 + 2 - odd)%3;
if (a0==a2)
{
Scalar s = Vector2(coeff(j,i) , coeff(k,i)).norm();
- res[1] = internal::atan2(s, coeff(i,i));
+ res[1] = ei_atan2(s, coeff(i,i));
if (s > epsilon)
{
- res[0] = internal::atan2(coeff(j,i), coeff(k,i));
- res[2] = internal::atan2(coeff(i,j),-coeff(i,k));
+ res[0] = ei_atan2(coeff(j,i), coeff(k,i));
+ res[2] = ei_atan2(coeff(i,j),-coeff(i,k));
}
else
{
res[0] = Scalar(0);
- res[2] = (coeff(i,i)>0?1:-1)*internal::atan2(-coeff(k,j), coeff(j,j));
+ res[2] = (coeff(i,i)>0?1:-1)*ei_atan2(-coeff(k,j), coeff(j,j));
}
}
else
{
Scalar c = Vector2(coeff(i,i) , coeff(i,j)).norm();
- res[1] = internal::atan2(-coeff(i,k), c);
+ res[1] = ei_atan2(-coeff(i,k), c);
if (c > epsilon)
{
- res[0] = internal::atan2(coeff(j,k), coeff(k,k));
- res[2] = internal::atan2(coeff(i,j), coeff(i,i));
+ res[0] = ei_atan2(coeff(j,k), coeff(k,k));
+ res[2] = ei_atan2(coeff(i,j), coeff(i,i));
}
else
{
res[0] = Scalar(0);
- res[2] = (coeff(i,k)>0?1:-1)*internal::atan2(-coeff(k,j), coeff(j,j));
+ res[2] = (coeff(i,k)>0?1:-1)*ei_atan2(-coeff(k,j), coeff(j,j));
}
}
if (!odd)
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h b/extern/Eigen2/Eigen/src/Geometry/Hyperplane.h
index 81c4f55b173..22c530d4be0 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h
+++ b/extern/Eigen2/Eigen/src/Geometry/Hyperplane.h
@@ -23,7 +23,8 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
+#ifndef EIGEN_HYPERPLANE_H
+#define EIGEN_HYPERPLANE_H
/** \geometry_module \ingroup Geometry_Module
*
@@ -51,9 +52,9 @@ public:
typedef _Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
- typedef Matrix<Scalar,int(AmbientDimAtCompileTime)==Dynamic
+ typedef Matrix<Scalar,AmbientDimAtCompileTime==Dynamic
? Dynamic
- : int(AmbientDimAtCompileTime)+1,1> Coefficients;
+ : AmbientDimAtCompileTime+1,1> Coefficients;
typedef Block<Coefficients,AmbientDimAtCompileTime,1> NormalReturnType;
/** Default constructor without initialization */
@@ -70,7 +71,7 @@ public:
: m_coeffs(n.size()+1)
{
normal() = n;
- offset() = -e.eigen2_dot(n);
+ offset() = -e.dot(n);
}
/** Constructs a plane from its normal \a n and distance to the origin \a d
@@ -91,7 +92,7 @@ public:
{
Hyperplane result(p0.size());
result.normal() = (p1 - p0).unitOrthogonal();
- result.offset() = -result.normal().eigen2_dot(p0);
+ result.offset() = -result.normal().dot(p0);
return result;
}
@@ -103,7 +104,7 @@ public:
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 3)
Hyperplane result(p0.size());
result.normal() = (p2 - p0).cross(p1 - p0).normalized();
- result.offset() = -result.normal().eigen2_dot(p0);
+ result.offset() = -result.normal().dot(p0);
return result;
}
@@ -115,13 +116,13 @@ public:
explicit Hyperplane(const ParametrizedLine<Scalar, AmbientDimAtCompileTime>& parametrized)
{
normal() = parametrized.direction().unitOrthogonal();
- offset() = -normal().eigen2_dot(parametrized.origin());
+ offset() = -normal().dot(parametrized.origin());
}
~Hyperplane() {}
/** \returns the dimension in which the plane holds */
- inline int dim() const { return int(AmbientDimAtCompileTime)==Dynamic ? m_coeffs.size()-1 : int(AmbientDimAtCompileTime); }
+ inline int dim() const { return AmbientDimAtCompileTime==Dynamic ? m_coeffs.size()-1 : AmbientDimAtCompileTime; }
/** normalizes \c *this */
void normalize(void)
@@ -132,7 +133,7 @@ public:
/** \returns the signed distance between the plane \c *this and a point \a p.
* \sa absDistance()
*/
- inline Scalar signedDistance(const VectorType& p) const { return p.eigen2_dot(normal()) + offset(); }
+ inline Scalar signedDistance(const VectorType& p) const { return p.dot(normal()) + offset(); }
/** \returns the absolute distance between the plane \c *this and a point \a p.
* \sa signedDistance()
@@ -146,7 +147,7 @@ public:
/** \returns a constant reference to the unit normal vector of the plane, which corresponds
* to the linear part of the implicit equation.
*/
- inline const NormalReturnType normal() const { return NormalReturnType(*const_cast<Coefficients*>(&m_coeffs),0,0,dim(),1); }
+ inline const NormalReturnType normal() const { return NormalReturnType(m_coeffs,0,0,dim(),1); }
/** \returns a non-constant reference to the unit normal vector of the plane, which corresponds
* to the linear part of the implicit equation.
@@ -230,7 +231,7 @@ public:
TransformTraits traits = Affine)
{
transform(t.linear(), traits);
- offset() -= t.translation().eigen2_dot(normal());
+ offset() -= t.translation().dot(normal());
return *this;
}
@@ -240,10 +241,10 @@ public:
* then this function smartly returns a const reference to \c *this.
*/
template<typename NewScalarType>
- inline typename internal::cast_return_type<Hyperplane,
+ inline typename ei_cast_return_type<Hyperplane,
Hyperplane<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
{
- return typename internal::cast_return_type<Hyperplane,
+ return typename ei_cast_return_type<Hyperplane,
Hyperplane<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
}
@@ -263,3 +264,5 @@ protected:
Coefficients m_coeffs;
};
+
+#endif // EIGEN_HYPERPLANE_H
diff --git a/extern/Eigen2/Eigen/src/Geometry/OrthoMethods.h b/extern/Eigen2/Eigen/src/Geometry/OrthoMethods.h
new file mode 100644
index 00000000000..047152d0b99
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Geometry/OrthoMethods.h
@@ -0,0 +1,119 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_ORTHOMETHODS_H
+#define EIGEN_ORTHOMETHODS_H
+
+/** \geometry_module
+ *
+ * \returns the cross product of \c *this and \a other
+ *
+ * Here is a very good explanation of cross-product: http://xkcd.com/199/
+ */
+template<typename Derived>
+template<typename OtherDerived>
+inline typename MatrixBase<Derived>::PlainMatrixType
+MatrixBase<Derived>::cross(const MatrixBase<OtherDerived>& other) const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,3)
+
+ // Note that there is no need for an expression here since the compiler
+ // optimize such a small temporary very well (even within a complex expression)
+ const typename ei_nested<Derived,2>::type lhs(derived());
+ const typename ei_nested<OtherDerived,2>::type rhs(other.derived());
+ return typename ei_plain_matrix_type<Derived>::type(
+ lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1),
+ lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2),
+ lhs.coeff(0) * rhs.coeff(1) - lhs.coeff(1) * rhs.coeff(0)
+ );
+}
+
+template<typename Derived, int Size = Derived::SizeAtCompileTime>
+struct ei_unitOrthogonal_selector
+{
+ typedef typename ei_plain_matrix_type<Derived>::type VectorType;
+ typedef typename ei_traits<Derived>::Scalar Scalar;
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ inline static VectorType run(const Derived& src)
+ {
+ VectorType perp(src.size());
+ /* Let us compute the crossed product of *this with a vector
+ * that is not too close to being colinear to *this.
+ */
+
+ /* unless the x and y coords are both close to zero, we can
+ * simply take ( -y, x, 0 ) and normalize it.
+ */
+ if((!ei_isMuchSmallerThan(src.x(), src.z()))
+ || (!ei_isMuchSmallerThan(src.y(), src.z())))
+ {
+ RealScalar invnm = RealScalar(1)/src.template start<2>().norm();
+ perp.coeffRef(0) = -ei_conj(src.y())*invnm;
+ perp.coeffRef(1) = ei_conj(src.x())*invnm;
+ perp.coeffRef(2) = 0;
+ }
+ /* if both x and y are close to zero, then the vector is close
+ * to the z-axis, so it's far from colinear to the x-axis for instance.
+ * So we take the crossed product with (1,0,0) and normalize it.
+ */
+ else
+ {
+ RealScalar invnm = RealScalar(1)/src.template end<2>().norm();
+ perp.coeffRef(0) = 0;
+ perp.coeffRef(1) = -ei_conj(src.z())*invnm;
+ perp.coeffRef(2) = ei_conj(src.y())*invnm;
+ }
+ if( (Derived::SizeAtCompileTime!=Dynamic && Derived::SizeAtCompileTime>3)
+ || (Derived::SizeAtCompileTime==Dynamic && src.size()>3) )
+ perp.end(src.size()-3).setZero();
+
+ return perp;
+ }
+};
+
+template<typename Derived>
+struct ei_unitOrthogonal_selector<Derived,2>
+{
+ typedef typename ei_plain_matrix_type<Derived>::type VectorType;
+ inline static VectorType run(const Derived& src)
+ { return VectorType(-ei_conj(src.y()), ei_conj(src.x())).normalized(); }
+};
+
+/** \returns a unit vector which is orthogonal to \c *this
+ *
+ * The size of \c *this must be at least 2. If the size is exactly 2,
+ * then the returned vector is a counter clock wise rotation of \c *this, i.e., (-y,x).normalized().
+ *
+ * \sa cross()
+ */
+template<typename Derived>
+typename MatrixBase<Derived>::PlainMatrixType
+MatrixBase<Derived>::unitOrthogonal() const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
+ return ei_unitOrthogonal_selector<Derived>::run(derived());
+}
+
+#endif // EIGEN_ORTHOMETHODS_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h b/extern/Eigen2/Eigen/src/Geometry/ParametrizedLine.h
index 411c4b57079..2b990d084f0 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h
+++ b/extern/Eigen2/Eigen/src/Geometry/ParametrizedLine.h
@@ -23,8 +23,8 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
-
+#ifndef EIGEN_PARAMETRIZEDLINE_H
+#define EIGEN_PARAMETRIZEDLINE_H
/** \geometry_module \ingroup Geometry_Module
*
@@ -85,7 +85,7 @@ public:
RealScalar squaredDistance(const VectorType& p) const
{
VectorType diff = p-origin();
- return (diff - diff.eigen2_dot(direction())* direction()).squaredNorm();
+ return (diff - diff.dot(direction())* direction()).squaredNorm();
}
/** \returns the distance of a point \a p to its projection onto the line \c *this.
* \sa squaredDistance()
@@ -94,7 +94,7 @@ public:
/** \returns the projection of a point \a p onto the line \c *this. */
VectorType projection(const VectorType& p) const
- { return origin() + (p-origin()).eigen2_dot(direction()) * direction(); }
+ { return origin() + (p-origin()).dot(direction()) * direction(); }
Scalar intersection(const Hyperplane<_Scalar, _AmbientDim>& hyperplane);
@@ -104,10 +104,10 @@ public:
* then this function smartly returns a const reference to \c *this.
*/
template<typename NewScalarType>
- inline typename internal::cast_return_type<ParametrizedLine,
+ inline typename ei_cast_return_type<ParametrizedLine,
ParametrizedLine<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
{
- return typename internal::cast_return_type<ParametrizedLine,
+ return typename ei_cast_return_type<ParametrizedLine,
ParametrizedLine<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
}
@@ -148,6 +148,8 @@ inline ParametrizedLine<_Scalar, _AmbientDim>::ParametrizedLine(const Hyperplane
template <typename _Scalar, int _AmbientDim>
inline _Scalar ParametrizedLine<_Scalar, _AmbientDim>::intersection(const Hyperplane<_Scalar, _AmbientDim>& hyperplane)
{
- return -(hyperplane.offset()+origin().eigen2_dot(hyperplane.normal()))
- /(direction().eigen2_dot(hyperplane.normal()));
+ return -(hyperplane.offset()+origin().dot(hyperplane.normal()))
+ /(direction().dot(hyperplane.normal()));
}
+
+#endif // EIGEN_PARAMETRIZEDLINE_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h b/extern/Eigen2/Eigen/src/Geometry/Quaternion.h
index a75fa42aeac..3fcbff4e71d 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h
+++ b/extern/Eigen2/Eigen/src/Geometry/Quaternion.h
@@ -22,7 +22,8 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
+#ifndef EIGEN_QUATERNION_H
+#define EIGEN_QUATERNION_H
template<typename Other,
int OtherRows=Other::RowsAtCompileTime,
@@ -97,7 +98,7 @@ public:
inline Scalar& w() { return m_coeffs.coeffRef(3); }
/** \returns a read-only vector expression of the imaginary part (x,y,z) */
- inline const Block<const Coefficients,3,1> vec() const { return m_coeffs.template start<3>(); }
+ inline const Block<Coefficients,3,1> vec() const { return m_coeffs.template start<3>(); }
/** \returns a vector expression of the imaginary part (x,y,z) */
inline Block<Coefficients,3,1> vec() { return m_coeffs.template start<3>(); }
@@ -171,7 +172,7 @@ public:
* corresponds to the cosine of half the angle between the two rotations.
* \sa angularDistance()
*/
- inline Scalar eigen2_dot(const Quaternion& other) const { return m_coeffs.eigen2_dot(other.m_coeffs); }
+ inline Scalar dot(const Quaternion& other) const { return m_coeffs.dot(other.m_coeffs); }
inline Scalar angularDistance(const Quaternion& other) const;
@@ -197,8 +198,8 @@ public:
* then this function smartly returns a const reference to \c *this.
*/
template<typename NewScalarType>
- inline typename internal::cast_return_type<Quaternion,Quaternion<NewScalarType> >::type cast() const
- { return typename internal::cast_return_type<Quaternion,Quaternion<NewScalarType> >::type(*this); }
+ inline typename ei_cast_return_type<Quaternion,Quaternion<NewScalarType> >::type cast() const
+ { return typename ei_cast_return_type<Quaternion,Quaternion<NewScalarType> >::type(*this); }
/** Copy constructor with scalar type conversion */
template<typename OtherScalarType>
@@ -224,7 +225,7 @@ typedef Quaternion<float> Quaternionf;
typedef Quaternion<double> Quaterniond;
// Generic Quaternion * Quaternion product
-template<typename Scalar> inline Quaternion<Scalar>
+template<int Arch,typename Scalar> inline Quaternion<Scalar>
ei_quaternion_product(const Quaternion<Scalar>& a, const Quaternion<Scalar>& b)
{
return Quaternion<Scalar>
@@ -236,11 +237,32 @@ ei_quaternion_product(const Quaternion<Scalar>& a, const Quaternion<Scalar>& b)
);
}
+#ifdef EIGEN_VECTORIZE_SSE
+template<> inline Quaternion<float>
+ei_quaternion_product<EiArch_SSE,float>(const Quaternion<float>& _a, const Quaternion<float>& _b)
+{
+ const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0,0,0,0x80000000));
+ Quaternion<float> res;
+ __m128 a = _a.coeffs().packet<Aligned>(0);
+ __m128 b = _b.coeffs().packet<Aligned>(0);
+ __m128 flip1 = _mm_xor_ps(_mm_mul_ps(ei_vec4f_swizzle1(a,1,2,0,2),
+ ei_vec4f_swizzle1(b,2,0,1,2)),mask);
+ __m128 flip2 = _mm_xor_ps(_mm_mul_ps(ei_vec4f_swizzle1(a,3,3,3,1),
+ ei_vec4f_swizzle1(b,0,1,2,1)),mask);
+ ei_pstore(&res.x(),
+ _mm_add_ps(_mm_sub_ps(_mm_mul_ps(a,ei_vec4f_swizzle1(b,3,3,3,3)),
+ _mm_mul_ps(ei_vec4f_swizzle1(a,2,0,1,0),
+ ei_vec4f_swizzle1(b,1,2,0,0))),
+ _mm_add_ps(flip1,flip2)));
+ return res;
+}
+#endif
+
/** \returns the concatenation of two rotations as a quaternion-quaternion product */
template <typename Scalar>
inline Quaternion<Scalar> Quaternion<Scalar>::operator* (const Quaternion& other) const
{
- return ei_quaternion_product(*this,other);
+ return ei_quaternion_product<EiArch>(*this,other);
}
/** \sa operator*(Quaternion) */
@@ -352,7 +374,7 @@ inline Quaternion<Scalar>& Quaternion<Scalar>::setFromTwoVectors(const MatrixBas
{
Vector3 v0 = a.normalized();
Vector3 v1 = b.normalized();
- Scalar c = v0.eigen2_dot(v1);
+ Scalar c = v0.dot(v1);
// if dot == 1, vectors are the same
if (ei_isApprox(c,Scalar(1)))
@@ -411,12 +433,12 @@ inline Quaternion<Scalar> Quaternion<Scalar>::conjugate() const
}
/** \returns the angle (in radian) between two rotations
- * \sa eigen2_dot()
+ * \sa dot()
*/
template <typename Scalar>
inline Scalar Quaternion<Scalar>::angularDistance(const Quaternion& other) const
{
- double d = ei_abs(this->eigen2_dot(other));
+ double d = ei_abs(this->dot(other));
if (d>=1.0)
return 0;
return Scalar(2) * std::acos(d);
@@ -428,31 +450,22 @@ inline Scalar Quaternion<Scalar>::angularDistance(const Quaternion& other) const
template <typename Scalar>
Quaternion<Scalar> Quaternion<Scalar>::slerp(Scalar t, const Quaternion& other) const
{
- static const Scalar one = Scalar(1) - machine_epsilon<Scalar>();
- Scalar d = this->eigen2_dot(other);
+ static const Scalar one = Scalar(1) - precision<Scalar>();
+ Scalar d = this->dot(other);
Scalar absD = ei_abs(d);
+ if (absD>=one)
+ return *this;
- Scalar scale0;
- Scalar scale1;
+ // theta is the angle between the 2 quaternions
+ Scalar theta = std::acos(absD);
+ Scalar sinTheta = ei_sin(theta);
- if (absD>=one)
- {
- scale0 = Scalar(1) - t;
- scale1 = t;
- }
- else
- {
- // theta is the angle between the 2 quaternions
- Scalar theta = std::acos(absD);
- Scalar sinTheta = ei_sin(theta);
-
- scale0 = ei_sin( ( Scalar(1) - t ) * theta) / sinTheta;
- scale1 = ei_sin( ( t * theta) ) / sinTheta;
- if (d<0)
- scale1 = -scale1;
- }
+ Scalar scale0 = ei_sin( ( Scalar(1) - t ) * theta) / sinTheta;
+ Scalar scale1 = ei_sin( ( t * theta) ) / sinTheta;
+ if (d<0)
+ scale1 = -scale1;
- return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
+ return Quaternion(scale0 * m_coeffs + scale1 * other.m_coeffs);
}
// set from a rotation matrix
@@ -504,3 +517,5 @@ struct ei_quaternion_assign_impl<Other,4,1>
q.coeffs() = vec;
}
};
+
+#endif // EIGEN_QUATERNION_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h b/extern/Eigen2/Eigen/src/Geometry/Rotation2D.h
index ee7c80e7eaa..dca7f06bf5d 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h
+++ b/extern/Eigen2/Eigen/src/Geometry/Rotation2D.h
@@ -22,8 +22,8 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
-
+#ifndef EIGEN_ROTATION2D_H
+#define EIGEN_ROTATION2D_H
/** \geometry_module \ingroup Geometry_Module
*
@@ -107,8 +107,8 @@ public:
* then this function smartly returns a const reference to \c *this.
*/
template<typename NewScalarType>
- inline typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type cast() const
- { return typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type(*this); }
+ inline typename ei_cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type cast() const
+ { return typename ei_cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type(*this); }
/** Copy constructor with scalar type conversion */
template<typename OtherScalarType>
@@ -155,3 +155,5 @@ Rotation2D<Scalar>::toRotationMatrix(void) const
Scalar cosA = ei_cos(m_angle);
return (Matrix2() << cosA, -sinA, sinA, cosA).finished();
}
+
+#endif // EIGEN_ROTATION2D_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h b/extern/Eigen2/Eigen/src/Geometry/RotationBase.h
index 2f494f198bd..5fec0f18d72 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h
+++ b/extern/Eigen2/Eigen/src/Geometry/RotationBase.h
@@ -22,7 +22,8 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
+#ifndef EIGEN_ROTATIONBASE_H
+#define EIGEN_ROTATIONBASE_H
// this file aims to contains the various representations of rotation/orientation
// in 2D and 3D space excepted Matrix and Quaternion.
@@ -132,3 +133,5 @@ inline static const MatrixBase<OtherDerived>& ei_toRotationMatrix(const MatrixBa
YOU_MADE_A_PROGRAMMING_MISTAKE)
return mat;
}
+
+#endif // EIGEN_ROTATIONBASE_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h b/extern/Eigen2/Eigen/src/Geometry/Scaling.h
index 108e6d7d58f..5daf0a49961 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h
+++ b/extern/Eigen2/Eigen/src/Geometry/Scaling.h
@@ -22,8 +22,8 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
-
+#ifndef EIGEN_SCALING_H
+#define EIGEN_SCALING_H
/** \geometry_module \ingroup Geometry_Module
*
@@ -132,8 +132,8 @@ public:
* then this function smartly returns a const reference to \c *this.
*/
template<typename NewScalarType>
- inline typename internal::cast_return_type<Scaling,Scaling<NewScalarType,Dim> >::type cast() const
- { return typename internal::cast_return_type<Scaling,Scaling<NewScalarType,Dim> >::type(*this); }
+ inline typename ei_cast_return_type<Scaling,Scaling<NewScalarType,Dim> >::type cast() const
+ { return typename ei_cast_return_type<Scaling,Scaling<NewScalarType,Dim> >::type(*this); }
/** Copy constructor with scalar type conversion */
template<typename OtherScalarType>
@@ -177,3 +177,5 @@ Scaling<Scalar,Dim>::operator* (const TransformType& t) const
res.prescale(m_coeffs);
return res;
}
+
+#endif // EIGEN_SCALING_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h b/extern/Eigen2/Eigen/src/Geometry/Transform.h
index 88956c86c73..8425a1cd963 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h
+++ b/extern/Eigen2/Eigen/src/Geometry/Transform.h
@@ -23,8 +23,15 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
-
+#ifndef EIGEN_TRANSFORM_H
+#define EIGEN_TRANSFORM_H
+
+/** Represents some traits of a transformation */
+enum TransformTraits {
+ Isometry, ///< the transformation is a concatenation of translations and rotations
+ Affine, ///< the transformation is affine (linear transformation + translation)
+ Projective ///< the transformation might not be affine
+};
// Note that we have to pass Dim and HDim because it is not allowed to use a template
// parameter to define a template specialization. To be more precise, in the following
@@ -70,14 +77,10 @@ public:
typedef Matrix<Scalar,Dim,Dim> LinearMatrixType;
/** type of read/write reference to the linear part of the transformation */
typedef Block<MatrixType,Dim,Dim> LinearPart;
- /** type of read/write reference to the linear part of the transformation */
- typedef const Block<const MatrixType,Dim,Dim> ConstLinearPart;
/** type of a vector */
typedef Matrix<Scalar,Dim,1> VectorType;
/** type of a read/write reference to the translation part of the rotation */
typedef Block<MatrixType,Dim,1> TranslationPart;
- /** type of a read/write reference to the translation part of the rotation */
- typedef const Block<const MatrixType,Dim,1> ConstTranslationPart;
/** corresponding translation type */
typedef Translation<Scalar,Dim> TranslationType;
/** corresponding scaling transformation type */
@@ -159,12 +162,12 @@ public:
inline MatrixType& matrix() { return m_matrix; }
/** \returns a read-only expression of the linear (linear) part of the transformation */
- inline ConstLinearPart linear() const { return m_matrix.template block<Dim,Dim>(0,0); }
+ inline const LinearPart linear() const { return m_matrix.template block<Dim,Dim>(0,0); }
/** \returns a writable expression of the linear (linear) part of the transformation */
inline LinearPart linear() { return m_matrix.template block<Dim,Dim>(0,0); }
/** \returns a read-only expression of the translation vector of the transformation */
- inline ConstTranslationPart translation() const { return m_matrix.template block<Dim,1>(0,Dim); }
+ inline const TranslationPart translation() const { return m_matrix.template block<Dim,1>(0,Dim); }
/** \returns a writable expression of the translation vector of the transformation */
inline TranslationPart translation() { return m_matrix.template block<Dim,1>(0,Dim); }
@@ -269,8 +272,8 @@ public:
* then this function smartly returns a const reference to \c *this.
*/
template<typename NewScalarType>
- inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim> >::type cast() const
- { return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim> >::type(*this); }
+ inline typename ei_cast_return_type<Transform,Transform<NewScalarType,Dim> >::type cast() const
+ { return typename ei_cast_return_type<Transform,Transform<NewScalarType,Dim> >::type(*this); }
/** Copy constructor with scalar type conversion */
template<typename OtherScalarType>
@@ -632,20 +635,7 @@ template<typename Scalar, int Dim>
template<typename RotationMatrixType, typename ScalingMatrixType>
void Transform<Scalar,Dim>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
{
- JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU|ComputeFullV);
- Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
- Matrix<Scalar, Dim, 1> sv(svd.singularValues());
- sv.coeffRef(0) *= x;
- if(scaling)
- {
- scaling->noalias() = svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint();
- }
- if(rotation)
- {
- LinearMatrixType m(svd.matrixU());
- m.col(0) /= x;
- rotation->noalias() = m * svd.matrixV().adjoint();
- }
+ linear().svd().computeRotationScaling(rotation, scaling);
}
/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
@@ -663,20 +653,7 @@ template<typename Scalar, int Dim>
template<typename ScalingMatrixType, typename RotationMatrixType>
void Transform<Scalar,Dim>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
{
- JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU|ComputeFullV);
- Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
- Matrix<Scalar, Dim, 1> sv(svd.singularValues());
- sv.coeffRef(0) *= x;
- if(scaling)
- {
- scaling->noalias() = svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint();
- }
- if(rotation)
- {
- LinearMatrixType m(svd.matrixU());
- m.col(0) /= x;
- rotation->noalias() = m * svd.matrixV().adjoint();
- }
+ linear().svd().computeScalingRotation(scaling, rotation);
}
/** Convenient method to set \c *this from a position, orientation and scale
@@ -791,8 +768,18 @@ struct ei_transform_product_impl<Other,Dim,HDim, Dim,1>
{
typedef typename Other::Scalar Scalar;
typedef Transform<Scalar,Dim> TransformType;
- typedef Matrix<Scalar,Dim,1> ResultType;
+ typedef typename TransformType::LinearPart MatrixType;
+ typedef const CwiseUnaryOp<
+ ei_scalar_multiple_op<Scalar>,
+ NestByValue<CwiseBinaryOp<
+ ei_scalar_sum_op<Scalar>,
+ NestByValue<typename ProductReturnType<NestByValue<MatrixType>,Other>::Type >,
+ NestByValue<typename TransformType::TranslationPart> > >
+ > ResultType;
+ // FIXME should we offer an optimized version when the last row is known to be 0,0...,0,1 ?
static ResultType run(const TransformType& tr, const Other& other)
- { return ((tr.linear() * other) + tr.translation())
+ { return ((tr.linear().nestByValue() * other).nestByValue() + tr.translation().nestByValue()).nestByValue()
* (Scalar(1) / ( (tr.matrix().template block<1,Dim>(Dim,0) * other).coeff(0) + tr.matrix().coeff(Dim,Dim))); }
};
+
+#endif // EIGEN_TRANSFORM_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h b/extern/Eigen2/Eigen/src/Geometry/Translation.h
index e651e310212..4b2fc7a56fc 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h
+++ b/extern/Eigen2/Eigen/src/Geometry/Translation.h
@@ -22,8 +22,8 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
-
+#ifndef EIGEN_TRANSLATION_H
+#define EIGEN_TRANSLATION_H
/** \geometry_module \ingroup Geometry_Module
*
@@ -135,8 +135,8 @@ public:
* then this function smartly returns a const reference to \c *this.
*/
template<typename NewScalarType>
- inline typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type cast() const
- { return typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type(*this); }
+ inline typename ei_cast_return_type<Translation,Translation<NewScalarType,Dim> >::type cast() const
+ { return typename ei_cast_return_type<Translation,Translation<NewScalarType,Dim> >::type(*this); }
/** Copy constructor with scalar type conversion */
template<typename OtherScalarType>
@@ -194,3 +194,5 @@ Translation<Scalar,Dim>::operator* (const TransformType& t) const
res.pretranslate(m_coeffs);
return res;
}
+
+#endif // EIGEN_TRANSLATION_H
diff --git a/extern/Eigen3/Eigen/src/LU/Determinant.h b/extern/Eigen2/Eigen/src/LU/Determinant.h
index b4fe36eb061..4f435054ac6 100644
--- a/extern/Eigen3/Eigen/src/LU/Determinant.h
+++ b/extern/Eigen2/Eigen/src/LU/Determinant.h
@@ -1,5 +1,5 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
@@ -25,10 +25,8 @@
#ifndef EIGEN_DETERMINANT_H
#define EIGEN_DETERMINANT_H
-namespace internal {
-
template<typename Derived>
-inline const typename Derived::Scalar bruteforce_det3_helper
+inline const typename Derived::Scalar ei_bruteforce_det3_helper
(const MatrixBase<Derived>& matrix, int a, int b, int c)
{
return matrix.coeff(0,a)
@@ -36,77 +34,89 @@ inline const typename Derived::Scalar bruteforce_det3_helper
}
template<typename Derived>
-const typename Derived::Scalar bruteforce_det4_helper
+const typename Derived::Scalar ei_bruteforce_det4_helper
(const MatrixBase<Derived>& matrix, int j, int k, int m, int n)
{
return (matrix.coeff(j,0) * matrix.coeff(k,1) - matrix.coeff(k,0) * matrix.coeff(j,1))
* (matrix.coeff(m,2) * matrix.coeff(n,3) - matrix.coeff(n,2) * matrix.coeff(m,3));
}
+const int TriangularDeterminant = 0;
+
template<typename Derived,
- int DeterminantType = Derived::RowsAtCompileTime
-> struct determinant_impl
+ int DeterminantType =
+ (Derived::Flags & (UpperTriangularBit | LowerTriangularBit))
+ ? TriangularDeterminant : Derived::RowsAtCompileTime
+> struct ei_determinant_impl
+{
+ static inline typename ei_traits<Derived>::Scalar run(const Derived& m)
+ {
+ return m.lu().determinant();
+ }
+};
+
+template<typename Derived> struct ei_determinant_impl<Derived, TriangularDeterminant>
{
- static inline typename traits<Derived>::Scalar run(const Derived& m)
+ static inline typename ei_traits<Derived>::Scalar run(const Derived& m)
{
- if(Derived::ColsAtCompileTime==Dynamic && m.rows()==0)
- return typename traits<Derived>::Scalar(1);
- return m.partialPivLu().determinant();
+ if (Derived::Flags & UnitDiagBit)
+ return 1;
+ else if (Derived::Flags & ZeroDiagBit)
+ return 0;
+ else
+ return m.diagonal().redux(ei_scalar_product_op<typename ei_traits<Derived>::Scalar>());
}
};
-template<typename Derived> struct determinant_impl<Derived, 1>
+template<typename Derived> struct ei_determinant_impl<Derived, 1>
{
- static inline typename traits<Derived>::Scalar run(const Derived& m)
+ static inline typename ei_traits<Derived>::Scalar run(const Derived& m)
{
return m.coeff(0,0);
}
};
-template<typename Derived> struct determinant_impl<Derived, 2>
+template<typename Derived> struct ei_determinant_impl<Derived, 2>
{
- static inline typename traits<Derived>::Scalar run(const Derived& m)
+ static inline typename ei_traits<Derived>::Scalar run(const Derived& m)
{
return m.coeff(0,0) * m.coeff(1,1) - m.coeff(1,0) * m.coeff(0,1);
}
};
-template<typename Derived> struct determinant_impl<Derived, 3>
+template<typename Derived> struct ei_determinant_impl<Derived, 3>
{
- static inline typename traits<Derived>::Scalar run(const Derived& m)
+ static typename ei_traits<Derived>::Scalar run(const Derived& m)
{
- return bruteforce_det3_helper(m,0,1,2)
- - bruteforce_det3_helper(m,1,0,2)
- + bruteforce_det3_helper(m,2,0,1);
+ return ei_bruteforce_det3_helper(m,0,1,2)
+ - ei_bruteforce_det3_helper(m,1,0,2)
+ + ei_bruteforce_det3_helper(m,2,0,1);
}
};
-template<typename Derived> struct determinant_impl<Derived, 4>
+template<typename Derived> struct ei_determinant_impl<Derived, 4>
{
- static typename traits<Derived>::Scalar run(const Derived& m)
+ static typename ei_traits<Derived>::Scalar run(const Derived& m)
{
// trick by Martin Costabel to compute 4x4 det with only 30 muls
- return bruteforce_det4_helper(m,0,1,2,3)
- - bruteforce_det4_helper(m,0,2,1,3)
- + bruteforce_det4_helper(m,0,3,1,2)
- + bruteforce_det4_helper(m,1,2,0,3)
- - bruteforce_det4_helper(m,1,3,0,2)
- + bruteforce_det4_helper(m,2,3,0,1);
+ return ei_bruteforce_det4_helper(m,0,1,2,3)
+ - ei_bruteforce_det4_helper(m,0,2,1,3)
+ + ei_bruteforce_det4_helper(m,0,3,1,2)
+ + ei_bruteforce_det4_helper(m,1,2,0,3)
+ - ei_bruteforce_det4_helper(m,1,3,0,2)
+ + ei_bruteforce_det4_helper(m,2,3,0,1);
}
};
-} // end namespace internal
-
/** \lu_module
*
* \returns the determinant of this matrix
*/
template<typename Derived>
-inline typename internal::traits<Derived>::Scalar MatrixBase<Derived>::determinant() const
+inline typename ei_traits<Derived>::Scalar MatrixBase<Derived>::determinant() const
{
assert(rows() == cols());
- typedef typename internal::nested<Derived,Base::RowsAtCompileTime>::type Nested;
- return internal::determinant_impl<typename internal::remove_all<Nested>::type>::run(derived());
+ return ei_determinant_impl<Derived>::run(derived());
}
#endif // EIGEN_DETERMINANT_H
diff --git a/extern/Eigen2/Eigen/src/LU/Inverse.h b/extern/Eigen2/Eigen/src/LU/Inverse.h
new file mode 100644
index 00000000000..3d4d6348949
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/LU/Inverse.h
@@ -0,0 +1,258 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_INVERSE_H
+#define EIGEN_INVERSE_H
+
+/********************************************************************
+*** Part 1 : optimized implementations for fixed-size 2,3,4 cases ***
+********************************************************************/
+
+template<typename MatrixType>
+void ei_compute_inverse_in_size2_case(const MatrixType& matrix, MatrixType* result)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ const Scalar invdet = Scalar(1) / matrix.determinant();
+ result->coeffRef(0,0) = matrix.coeff(1,1) * invdet;
+ result->coeffRef(1,0) = -matrix.coeff(1,0) * invdet;
+ result->coeffRef(0,1) = -matrix.coeff(0,1) * invdet;
+ result->coeffRef(1,1) = matrix.coeff(0,0) * invdet;
+}
+
+template<typename XprType, typename MatrixType>
+bool ei_compute_inverse_in_size2_case_with_check(const XprType& matrix, MatrixType* result)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ const Scalar det = matrix.determinant();
+ if(ei_isMuchSmallerThan(det, matrix.cwise().abs().maxCoeff())) return false;
+ const Scalar invdet = Scalar(1) / det;
+ result->coeffRef(0,0) = matrix.coeff(1,1) * invdet;
+ result->coeffRef(1,0) = -matrix.coeff(1,0) * invdet;
+ result->coeffRef(0,1) = -matrix.coeff(0,1) * invdet;
+ result->coeffRef(1,1) = matrix.coeff(0,0) * invdet;
+ return true;
+}
+
+template<typename MatrixType>
+void ei_compute_inverse_in_size3_case(const MatrixType& matrix, MatrixType* result)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ const Scalar det_minor00 = matrix.minor(0,0).determinant();
+ const Scalar det_minor10 = matrix.minor(1,0).determinant();
+ const Scalar det_minor20 = matrix.minor(2,0).determinant();
+ const Scalar invdet = Scalar(1) / ( det_minor00 * matrix.coeff(0,0)
+ - det_minor10 * matrix.coeff(1,0)
+ + det_minor20 * matrix.coeff(2,0) );
+ result->coeffRef(0, 0) = det_minor00 * invdet;
+ result->coeffRef(0, 1) = -det_minor10 * invdet;
+ result->coeffRef(0, 2) = det_minor20 * invdet;
+ result->coeffRef(1, 0) = -matrix.minor(0,1).determinant() * invdet;
+ result->coeffRef(1, 1) = matrix.minor(1,1).determinant() * invdet;
+ result->coeffRef(1, 2) = -matrix.minor(2,1).determinant() * invdet;
+ result->coeffRef(2, 0) = matrix.minor(0,2).determinant() * invdet;
+ result->coeffRef(2, 1) = -matrix.minor(1,2).determinant() * invdet;
+ result->coeffRef(2, 2) = matrix.minor(2,2).determinant() * invdet;
+}
+
+template<typename MatrixType>
+bool ei_compute_inverse_in_size4_case_helper(const MatrixType& matrix, MatrixType* result)
+{
+ /* Let's split M into four 2x2 blocks:
+ * (P Q)
+ * (R S)
+ * If P is invertible, with inverse denoted by P_inverse, and if
+ * (S - R*P_inverse*Q) is also invertible, then the inverse of M is
+ * (P' Q')
+ * (R' S')
+ * where
+ * S' = (S - R*P_inverse*Q)^(-1)
+ * P' = P1 + (P1*Q) * S' *(R*P_inverse)
+ * Q' = -(P_inverse*Q) * S'
+ * R' = -S' * (R*P_inverse)
+ */
+ typedef Block<MatrixType,2,2> XprBlock22;
+ typedef typename MatrixBase<XprBlock22>::PlainMatrixType Block22;
+ Block22 P_inverse;
+ if(ei_compute_inverse_in_size2_case_with_check(matrix.template block<2,2>(0,0), &P_inverse))
+ {
+ const Block22 Q = matrix.template block<2,2>(0,2);
+ const Block22 P_inverse_times_Q = P_inverse * Q;
+ const XprBlock22 R = matrix.template block<2,2>(2,0);
+ const Block22 R_times_P_inverse = R * P_inverse;
+ const Block22 R_times_P_inverse_times_Q = R_times_P_inverse * Q;
+ const XprBlock22 S = matrix.template block<2,2>(2,2);
+ const Block22 X = S - R_times_P_inverse_times_Q;
+ Block22 Y;
+ ei_compute_inverse_in_size2_case(X, &Y);
+ result->template block<2,2>(2,2) = Y;
+ result->template block<2,2>(2,0) = - Y * R_times_P_inverse;
+ const Block22 Z = P_inverse_times_Q * Y;
+ result->template block<2,2>(0,2) = - Z;
+ result->template block<2,2>(0,0) = P_inverse + Z * R_times_P_inverse;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+template<typename MatrixType>
+void ei_compute_inverse_in_size4_case(const MatrixType& matrix, MatrixType* result)
+{
+ if(ei_compute_inverse_in_size4_case_helper(matrix, result))
+ {
+ // good ! The topleft 2x2 block was invertible, so the 2x2 blocks approach is successful.
+ return;
+ }
+ else
+ {
+ // rare case: the topleft 2x2 block is not invertible (but the matrix itself is assumed to be).
+ // since this is a rare case, we don't need to optimize it. We just want to handle it with little
+ // additional code.
+ MatrixType m(matrix);
+ m.row(0).swap(m.row(2));
+ m.row(1).swap(m.row(3));
+ if(ei_compute_inverse_in_size4_case_helper(m, result))
+ {
+ // good, the topleft 2x2 block of m is invertible. Since m is different from matrix in that some
+ // rows were permuted, the actual inverse of matrix is derived from the inverse of m by permuting
+ // the corresponding columns.
+ result->col(0).swap(result->col(2));
+ result->col(1).swap(result->col(3));
+ }
+ else
+ {
+ // last possible case. Since matrix is assumed to be invertible, this last case has to work.
+ // first, undo the swaps previously made
+ m.row(0).swap(m.row(2));
+ m.row(1).swap(m.row(3));
+ // swap row 0 with the the row among 0 and 1 that has the biggest 2 first coeffs
+ int swap0with = ei_abs(m.coeff(0,0))+ei_abs(m.coeff(0,1))>ei_abs(m.coeff(1,0))+ei_abs(m.coeff(1,1)) ? 0 : 1;
+ m.row(0).swap(m.row(swap0with));
+ // swap row 1 with the the row among 2 and 3 that has the biggest 2 first coeffs
+ int swap1with = ei_abs(m.coeff(2,0))+ei_abs(m.coeff(2,1))>ei_abs(m.coeff(3,0))+ei_abs(m.coeff(3,1)) ? 2 : 3;
+ m.row(1).swap(m.row(swap1with));
+ ei_compute_inverse_in_size4_case_helper(m, result);
+ result->col(1).swap(result->col(swap1with));
+ result->col(0).swap(result->col(swap0with));
+ }
+ }
+}
+
+/***********************************************
+*** Part 2 : selector and MatrixBase methods ***
+***********************************************/
+
+template<typename MatrixType, int Size = MatrixType::RowsAtCompileTime>
+struct ei_compute_inverse
+{
+ static inline void run(const MatrixType& matrix, MatrixType* result)
+ {
+ LU<MatrixType> lu(matrix);
+ lu.computeInverse(result);
+ }
+};
+
+template<typename MatrixType>
+struct ei_compute_inverse<MatrixType, 1>
+{
+ static inline void run(const MatrixType& matrix, MatrixType* result)
+ {
+ typedef typename MatrixType::Scalar Scalar;
+ result->coeffRef(0,0) = Scalar(1) / matrix.coeff(0,0);
+ }
+};
+
+template<typename MatrixType>
+struct ei_compute_inverse<MatrixType, 2>
+{
+ static inline void run(const MatrixType& matrix, MatrixType* result)
+ {
+ ei_compute_inverse_in_size2_case(matrix, result);
+ }
+};
+
+template<typename MatrixType>
+struct ei_compute_inverse<MatrixType, 3>
+{
+ static inline void run(const MatrixType& matrix, MatrixType* result)
+ {
+ ei_compute_inverse_in_size3_case(matrix, result);
+ }
+};
+
+template<typename MatrixType>
+struct ei_compute_inverse<MatrixType, 4>
+{
+ static inline void run(const MatrixType& matrix, MatrixType* result)
+ {
+ ei_compute_inverse_in_size4_case(matrix, result);
+ }
+};
+
+/** \lu_module
+ *
+ * Computes the matrix inverse of this matrix.
+ *
+ * \note This matrix must be invertible, otherwise the result is undefined.
+ *
+ * \param result Pointer to the matrix in which to store the result.
+ *
+ * Example: \include MatrixBase_computeInverse.cpp
+ * Output: \verbinclude MatrixBase_computeInverse.out
+ *
+ * \sa inverse()
+ */
+template<typename Derived>
+inline void MatrixBase<Derived>::computeInverse(PlainMatrixType *result) const
+{
+ ei_assert(rows() == cols());
+ EIGEN_STATIC_ASSERT(NumTraits<Scalar>::HasFloatingPoint,NUMERIC_TYPE_MUST_BE_FLOATING_POINT)
+ ei_compute_inverse<PlainMatrixType>::run(eval(), result);
+}
+
+/** \lu_module
+ *
+ * \returns the matrix inverse of this matrix.
+ *
+ * \note This matrix must be invertible, otherwise the result is undefined.
+ *
+ * \note This method returns a matrix by value, which can be inefficient. To avoid that overhead,
+ * use computeInverse() instead.
+ *
+ * Example: \include MatrixBase_inverse.cpp
+ * Output: \verbinclude MatrixBase_inverse.out
+ *
+ * \sa computeInverse()
+ */
+template<typename Derived>
+inline const typename MatrixBase<Derived>::PlainMatrixType MatrixBase<Derived>::inverse() const
+{
+ PlainMatrixType result(rows(), cols());
+ computeInverse(&result);
+ return result;
+}
+
+#endif // EIGEN_INVERSE_H
diff --git a/extern/Eigen2/Eigen/src/LU/LU.h b/extern/Eigen2/Eigen/src/LU/LU.h
new file mode 100644
index 00000000000..176e76a91a3
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/LU/LU.h
@@ -0,0 +1,541 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_LU_H
+#define EIGEN_LU_H
+
+/** \ingroup LU_Module
+ *
+ * \class LU
+ *
+ * \brief LU decomposition of a matrix with complete pivoting, and related features
+ *
+ * \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, so that the rank
+ * of A is the index of the first zero on the diagonal of U (with indices starting at 0) if any.
+ *
+ * This decomposition provides the generic approach to solving systems of linear equations, computing
+ * the rank, invertibility, inverse, kernel, and determinant.
+ *
+ * This LU decomposition is very stable and well tested with large matrices. Even exact rank computation
+ * works at sizes larger than 1000x1000. However there are use cases where the SVD decomposition is inherently
+ * more stable when dealing with numerically damaged input. For example, computing the kernel is more stable with
+ * SVD because the SVD can determine which singular values are negligible while LU has to work at the level of matrix
+ * coefficients that are less meaningful in this respect.
+ *
+ * The data of the LU decomposition can be directly accessed through the methods matrixLU(),
+ * permutationP(), permutationQ().
+ *
+ * As an exemple, here is how the original matrix can be retrieved:
+ * \include class_LU.cpp
+ * Output: \verbinclude class_LU.out
+ *
+ * \sa MatrixBase::lu(), MatrixBase::determinant(), MatrixBase::inverse(), MatrixBase::computeInverse()
+ */
+template<typename MatrixType> class LU
+{
+ public:
+
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+ typedef Matrix<int, 1, MatrixType::ColsAtCompileTime> IntRowVectorType;
+ typedef Matrix<int, MatrixType::RowsAtCompileTime, 1> IntColVectorType;
+ typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
+ typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVectorType;
+
+ enum { MaxSmallDimAtCompileTime = EIGEN_ENUM_MIN(
+ MatrixType::MaxColsAtCompileTime,
+ MatrixType::MaxRowsAtCompileTime)
+ };
+
+ typedef Matrix<typename MatrixType::Scalar,
+ MatrixType::ColsAtCompileTime, // the number of rows in the "kernel matrix" is the number of cols of the original matrix
+ // so that the product "matrix * kernel = zero" makes sense
+ Dynamic, // we don't know at compile-time the dimension of the kernel
+ MatrixType::Options,
+ MatrixType::MaxColsAtCompileTime, // see explanation for 2nd template parameter
+ MatrixType::MaxColsAtCompileTime // the kernel is a subspace of the domain space, whose dimension is the number
+ // of columns of the original matrix
+ > KernelResultType;
+
+ typedef Matrix<typename MatrixType::Scalar,
+ MatrixType::RowsAtCompileTime, // the image is a subspace of the destination space, whose dimension is the number
+ // of rows of the original matrix
+ Dynamic, // we don't know at compile time the dimension of the image (the rank)
+ MatrixType::Options,
+ MatrixType::MaxRowsAtCompileTime, // the image matrix will consist of columns from the original matrix,
+ MatrixType::MaxColsAtCompileTime // so it has the same number of rows and at most as many columns.
+ > ImageResultType;
+
+ /** Constructor.
+ *
+ * \param matrix the matrix of which to compute the LU decomposition.
+ */
+ LU(const MatrixType& matrix);
+
+ /** \returns the LU decomposition matrix: the upper-triangular part is U, the
+ * unit-lower-triangular part is L (at least for square matrices; in the non-square
+ * case, special care is needed, see the documentation of class LU).
+ *
+ * \sa matrixL(), matrixU()
+ */
+ inline const MatrixType& matrixLU() const
+ {
+ return m_lu;
+ }
+
+ /** \returns a vector of integers, whose size is the number of rows of the matrix being decomposed,
+ * representing the P permutation i.e. the permutation of the rows. For its precise meaning,
+ * see the examples given in the documentation of class LU.
+ *
+ * \sa permutationQ()
+ */
+ inline const IntColVectorType& permutationP() const
+ {
+ return m_p;
+ }
+
+ /** \returns a vector of integers, whose size is the number of columns of the matrix being
+ * decomposed, representing the Q permutation i.e. the permutation of the columns.
+ * For its precise meaning, see the examples given in the documentation of class LU.
+ *
+ * \sa permutationP()
+ */
+ inline const IntRowVectorType& permutationQ() const
+ {
+ return m_q;
+ }
+
+ /** Computes a basis of the kernel of the matrix, also called the null-space of the matrix.
+ *
+ * \note This method is only allowed on non-invertible matrices, as determined by
+ * isInvertible(). Calling it on an invertible matrix will make an assertion fail.
+ *
+ * \param result a pointer to the matrix in which to store the kernel. The columns of this
+ * matrix will be set to form a basis of the kernel (it will be resized
+ * if necessary).
+ *
+ * Example: \include LU_computeKernel.cpp
+ * Output: \verbinclude LU_computeKernel.out
+ *
+ * \sa kernel(), computeImage(), image()
+ */
+ template<typename KernelMatrixType>
+ void computeKernel(KernelMatrixType *result) const;
+
+ /** Computes a basis of the image of the matrix, also called the column-space or range of he matrix.
+ *
+ * \note Calling this method on the zero matrix will make an assertion fail.
+ *
+ * \param result a pointer to the matrix in which to store the image. The columns of this
+ * matrix will be set to form a basis of the image (it will be resized
+ * if necessary).
+ *
+ * Example: \include LU_computeImage.cpp
+ * Output: \verbinclude LU_computeImage.out
+ *
+ * \sa image(), computeKernel(), kernel()
+ */
+ template<typename ImageMatrixType>
+ void computeImage(ImageMatrixType *result) const;
+
+ /** \returns the kernel of the matrix, also called its null-space. The columns of the returned matrix
+ * will form a basis of the kernel.
+ *
+ * \note: this method is only allowed on non-invertible matrices, as determined by
+ * isInvertible(). Calling it on an invertible matrix will make an assertion fail.
+ *
+ * \note: this method returns a matrix by value, which induces some inefficiency.
+ * If you prefer to avoid this overhead, use computeKernel() instead.
+ *
+ * Example: \include LU_kernel.cpp
+ * Output: \verbinclude LU_kernel.out
+ *
+ * \sa computeKernel(), image()
+ */
+ const KernelResultType kernel() const;
+
+ /** \returns the image of the matrix, also called its column-space. The columns of the returned matrix
+ * will form a basis of the kernel.
+ *
+ * \note: Calling this method on the zero matrix will make an assertion fail.
+ *
+ * \note: this method returns a matrix by value, which induces some inefficiency.
+ * If you prefer to avoid this overhead, use computeImage() instead.
+ *
+ * Example: \include LU_image.cpp
+ * Output: \verbinclude LU_image.out
+ *
+ * \sa computeImage(), kernel()
+ */
+ const ImageResultType image() const;
+
+ /** This method finds a solution x to the equation Ax=b, where A is the matrix of which
+ * *this is the LU decomposition, if any exists.
+ *
+ * \param b the right-hand-side of the equation to solve. Can be a vector or a matrix,
+ * the only requirement in order for the equation to make sense is that
+ * b.rows()==A.rows(), where A is the matrix of which *this is the LU decomposition.
+ * \param result a pointer to the vector or matrix in which to store the solution, if any exists.
+ * Resized if necessary, so that result->rows()==A.cols() and result->cols()==b.cols().
+ * If no solution exists, *result is left with undefined coefficients.
+ *
+ * \returns true if any solution exists, false if no solution exists.
+ *
+ * \note If there exist more than one solution, this method will arbitrarily choose one.
+ * If you need a complete analysis of the space of solutions, take the one solution obtained
+ * by this method and add to it elements of the kernel, as determined by kernel().
+ *
+ * Example: \include LU_solve.cpp
+ * Output: \verbinclude LU_solve.out
+ *
+ * \sa MatrixBase::solveTriangular(), kernel(), computeKernel(), inverse(), computeInverse()
+ */
+ template<typename OtherDerived, typename ResultType>
+ bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const;
+
+ /** \returns the determinant of the matrix of which
+ * *this is the LU decomposition. It has only linear complexity
+ * (that is, O(n) where n is the dimension of the square matrix)
+ * as the LU decomposition has already been computed.
+ *
+ * \note This is only for square matrices.
+ *
+ * \note For fixed-size matrices of size up to 4, MatrixBase::determinant() offers
+ * optimized paths.
+ *
+ * \warning a determinant can be very big or small, so for matrices
+ * of large enough dimension, there is a risk of overflow/underflow.
+ *
+ * \sa MatrixBase::determinant()
+ */
+ typename ei_traits<MatrixType>::Scalar determinant() const;
+
+ /** \returns the rank of the matrix of which *this is the LU decomposition.
+ *
+ * \note This is computed at the time of the construction of the LU decomposition. This
+ * method does not perform any further computation.
+ */
+ inline int rank() const
+ {
+ return m_rank;
+ }
+
+ /** \returns the dimension of the kernel of the matrix of which *this is the LU decomposition.
+ *
+ * \note Since the rank is computed at the time of the construction of the LU decomposition, this
+ * method almost does not perform any further computation.
+ */
+ inline int dimensionOfKernel() const
+ {
+ return m_lu.cols() - m_rank;
+ }
+
+ /** \returns true if the matrix of which *this is the LU decomposition represents an injective
+ * linear map, i.e. has trivial kernel; false otherwise.
+ *
+ * \note Since the rank is computed at the time of the construction of the LU decomposition, this
+ * method almost does not perform any further computation.
+ */
+ inline bool isInjective() const
+ {
+ return m_rank == m_lu.cols();
+ }
+
+ /** \returns true if the matrix of which *this is the LU decomposition represents a surjective
+ * linear map; false otherwise.
+ *
+ * \note Since the rank is computed at the time of the construction of the LU decomposition, this
+ * method almost does not perform any further computation.
+ */
+ inline bool isSurjective() const
+ {
+ return m_rank == m_lu.rows();
+ }
+
+ /** \returns true if the matrix of which *this is the LU decomposition is invertible.
+ *
+ * \note Since the rank is computed at the time of the construction of the LU decomposition, this
+ * method almost does not perform any further computation.
+ */
+ inline bool isInvertible() const
+ {
+ return isInjective() && isSurjective();
+ }
+
+ /** Computes the inverse of the matrix of which *this is the LU decomposition.
+ *
+ * \param result a pointer to the matrix into which to store the inverse. Resized if needed.
+ *
+ * \note If this matrix is not invertible, *result is left with undefined coefficients.
+ * Use isInvertible() to first determine whether this matrix is invertible.
+ *
+ * \sa MatrixBase::computeInverse(), inverse()
+ */
+ inline void computeInverse(MatrixType *result) const
+ {
+ solve(MatrixType::Identity(m_lu.rows(), m_lu.cols()), result);
+ }
+
+ /** \returns the inverse of the matrix of which *this is the LU decomposition.
+ *
+ * \note If this matrix is not invertible, the returned matrix has undefined coefficients.
+ * Use isInvertible() to first determine whether this matrix is invertible.
+ *
+ * \sa computeInverse(), MatrixBase::inverse()
+ */
+ inline MatrixType inverse() const
+ {
+ MatrixType result;
+ computeInverse(&result);
+ return result;
+ }
+
+ protected:
+ const MatrixType& m_originalMatrix;
+ MatrixType m_lu;
+ IntColVectorType m_p;
+ IntRowVectorType m_q;
+ int m_det_pq;
+ int m_rank;
+ RealScalar m_precision;
+};
+
+template<typename MatrixType>
+LU<MatrixType>::LU(const MatrixType& matrix)
+ : m_originalMatrix(matrix),
+ m_lu(matrix),
+ m_p(matrix.rows()),
+ m_q(matrix.cols())
+{
+ const int size = matrix.diagonal().size();
+ const int rows = matrix.rows();
+ const int cols = matrix.cols();
+
+ // this formula comes from experimenting (see "LU precision tuning" thread on the list)
+ // and turns out to be identical to Higham's formula used already in LDLt.
+ m_precision = machine_epsilon<Scalar>() * size;
+
+ IntColVectorType rows_transpositions(matrix.rows());
+ IntRowVectorType cols_transpositions(matrix.cols());
+ int number_of_transpositions = 0;
+
+ RealScalar biggest = RealScalar(0);
+ m_rank = size;
+ for(int k = 0; k < size; ++k)
+ {
+ int row_of_biggest_in_corner, col_of_biggest_in_corner;
+ RealScalar biggest_in_corner;
+
+ biggest_in_corner = m_lu.corner(Eigen::BottomRight, rows-k, cols-k)
+ .cwise().abs()
+ .maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
+ row_of_biggest_in_corner += k;
+ col_of_biggest_in_corner += k;
+ if(k==0) biggest = biggest_in_corner;
+
+ // if the corner is negligible, then we have less than full rank, and we can finish early
+ if(ei_isMuchSmallerThan(biggest_in_corner, biggest, m_precision))
+ {
+ m_rank = k;
+ for(int i = k; i < size; i++)
+ {
+ rows_transpositions.coeffRef(i) = i;
+ cols_transpositions.coeffRef(i) = i;
+ }
+ break;
+ }
+
+ rows_transpositions.coeffRef(k) = row_of_biggest_in_corner;
+ cols_transpositions.coeffRef(k) = col_of_biggest_in_corner;
+ if(k != row_of_biggest_in_corner) {
+ m_lu.row(k).swap(m_lu.row(row_of_biggest_in_corner));
+ ++number_of_transpositions;
+ }
+ if(k != col_of_biggest_in_corner) {
+ m_lu.col(k).swap(m_lu.col(col_of_biggest_in_corner));
+ ++number_of_transpositions;
+ }
+ if(k<rows-1)
+ m_lu.col(k).end(rows-k-1) /= m_lu.coeff(k,k);
+ if(k<size-1)
+ for(int col = k + 1; col < cols; ++col)
+ m_lu.col(col).end(rows-k-1) -= m_lu.col(k).end(rows-k-1) * m_lu.coeff(k,col);
+ }
+
+ for(int k = 0; k < matrix.rows(); ++k) m_p.coeffRef(k) = k;
+ for(int k = size-1; k >= 0; --k)
+ std::swap(m_p.coeffRef(k), m_p.coeffRef(rows_transpositions.coeff(k)));
+
+ for(int k = 0; k < matrix.cols(); ++k) m_q.coeffRef(k) = k;
+ for(int k = 0; k < size; ++k)
+ std::swap(m_q.coeffRef(k), m_q.coeffRef(cols_transpositions.coeff(k)));
+
+ m_det_pq = (number_of_transpositions%2) ? -1 : 1;
+}
+
+template<typename MatrixType>
+typename ei_traits<MatrixType>::Scalar LU<MatrixType>::determinant() const
+{
+ return Scalar(m_det_pq) * m_lu.diagonal().redux(ei_scalar_product_op<Scalar>());
+}
+
+template<typename MatrixType>
+template<typename KernelMatrixType>
+void LU<MatrixType>::computeKernel(KernelMatrixType *result) const
+{
+ ei_assert(!isInvertible());
+ const int dimker = dimensionOfKernel(), cols = m_lu.cols();
+ result->resize(cols, dimker);
+
+ /* Let us use the following lemma:
+ *
+ * Lemma: If the matrix A has the LU decomposition PAQ = LU,
+ * then Ker A = Q(Ker U).
+ *
+ * Proof: trivial: just keep in mind that P, Q, L are invertible.
+ */
+
+ /* Thus, all we need to do is to compute Ker U, and then apply Q.
+ *
+ * U is upper triangular, with eigenvalues sorted so that any zeros appear at the end.
+ * Thus, the diagonal of U ends with exactly
+ * m_dimKer zero's. Let us use that to construct m_dimKer linearly
+ * independent vectors in Ker U.
+ */
+
+ Matrix<Scalar, Dynamic, Dynamic, MatrixType::Options,
+ MatrixType::MaxColsAtCompileTime, MatrixType::MaxColsAtCompileTime>
+ y(-m_lu.corner(TopRight, m_rank, dimker));
+
+ m_lu.corner(TopLeft, m_rank, m_rank)
+ .template marked<UpperTriangular>()
+ .solveTriangularInPlace(y);
+
+ for(int i = 0; i < m_rank; ++i) result->row(m_q.coeff(i)) = y.row(i);
+ for(int i = m_rank; i < cols; ++i) result->row(m_q.coeff(i)).setZero();
+ for(int k = 0; k < dimker; ++k) result->coeffRef(m_q.coeff(m_rank+k), k) = Scalar(1);
+}
+
+template<typename MatrixType>
+const typename LU<MatrixType>::KernelResultType
+LU<MatrixType>::kernel() const
+{
+ KernelResultType result(m_lu.cols(), dimensionOfKernel());
+ computeKernel(&result);
+ return result;
+}
+
+template<typename MatrixType>
+template<typename ImageMatrixType>
+void LU<MatrixType>::computeImage(ImageMatrixType *result) const
+{
+ ei_assert(m_rank > 0);
+ result->resize(m_originalMatrix.rows(), m_rank);
+ for(int i = 0; i < m_rank; ++i)
+ result->col(i) = m_originalMatrix.col(m_q.coeff(i));
+}
+
+template<typename MatrixType>
+const typename LU<MatrixType>::ImageResultType
+LU<MatrixType>::image() const
+{
+ ImageResultType result(m_originalMatrix.rows(), m_rank);
+ computeImage(&result);
+ return result;
+}
+
+template<typename MatrixType>
+template<typename OtherDerived, typename ResultType>
+bool LU<MatrixType>::solve(
+ const MatrixBase<OtherDerived>& b,
+ ResultType *result
+) const
+{
+ /* The decomposition PAQ = LU can be rewritten as A = P^{-1} L U Q^{-1}.
+ * So we proceed as follows:
+ * Step 1: compute c = Pb.
+ * Step 2: replace c by the solution x to Lx = c. Exists because L is invertible.
+ * Step 3: replace c by the solution x to Ux = c. Check if a solution really exists.
+ * Step 4: result = Qc;
+ */
+
+ const int rows = m_lu.rows(), cols = m_lu.cols();
+ ei_assert(b.rows() == rows);
+ const int smalldim = std::min(rows, cols);
+
+ typename OtherDerived::PlainMatrixType c(b.rows(), b.cols());
+
+ // Step 1
+ for(int i = 0; i < rows; ++i) c.row(m_p.coeff(i)) = b.row(i);
+
+ // Step 2
+ m_lu.corner(Eigen::TopLeft,smalldim,smalldim).template marked<UnitLowerTriangular>()
+ .solveTriangularInPlace(
+ c.corner(Eigen::TopLeft, smalldim, c.cols()));
+ if(rows>cols)
+ {
+ c.corner(Eigen::BottomLeft, rows-cols, c.cols())
+ -= m_lu.corner(Eigen::BottomLeft, rows-cols, cols) * c.corner(Eigen::TopLeft, cols, c.cols());
+ }
+
+ // Step 3
+ if(!isSurjective())
+ {
+ // is c is in the image of U ?
+ RealScalar biggest_in_c = m_rank>0 ? c.corner(TopLeft, m_rank, c.cols()).cwise().abs().maxCoeff() : 0;
+ for(int col = 0; col < c.cols(); ++col)
+ for(int row = m_rank; row < c.rows(); ++row)
+ if(!ei_isMuchSmallerThan(c.coeff(row,col), biggest_in_c, m_precision))
+ return false;
+ }
+ m_lu.corner(TopLeft, m_rank, m_rank)
+ .template marked<UpperTriangular>()
+ .solveTriangularInPlace(c.corner(TopLeft, m_rank, c.cols()));
+
+ // Step 4
+ result->resize(m_lu.cols(), b.cols());
+ for(int i = 0; i < m_rank; ++i) result->row(m_q.coeff(i)) = c.row(i);
+ for(int i = m_rank; i < m_lu.cols(); ++i) result->row(m_q.coeff(i)).setZero();
+ return true;
+}
+
+/** \lu_module
+ *
+ * \return the LU decomposition of \c *this.
+ *
+ * \sa class LU
+ */
+template<typename Derived>
+inline const LU<typename MatrixBase<Derived>::PlainMatrixType>
+MatrixBase<Derived>::lu() const
+{
+ return LU<PlainMatrixType>(eval());
+}
+
+#endif // EIGEN_LU_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h b/extern/Eigen2/Eigen/src/LeastSquares/LeastSquares.h
index 4b62ffa92c7..b2595ede1fe 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h
+++ b/extern/Eigen2/Eigen/src/LeastSquares/LeastSquares.h
@@ -22,8 +22,8 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-#ifndef EIGEN2_LEASTSQUARES_H
-#define EIGEN2_LEASTSQUARES_H
+#ifndef EIGEN_LEASTSQUARES_H
+#define EIGEN_LEASTSQUARES_H
/** \ingroup LeastSquares_Module
*
@@ -179,4 +179,4 @@ void fitHyperplane(int numPoints,
}
-#endif // EIGEN2_LEASTSQUARES_H
+#endif // EIGEN_LEASTSQUARES_H
diff --git a/extern/Eigen2/Eigen/src/QR/EigenSolver.h b/extern/Eigen2/Eigen/src/QR/EigenSolver.h
new file mode 100644
index 00000000000..70f21cebcdb
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/QR/EigenSolver.h
@@ -0,0 +1,722 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_EIGENSOLVER_H
+#define EIGEN_EIGENSOLVER_H
+
+/** \ingroup QR_Module
+ * \nonstableyet
+ *
+ * \class EigenSolver
+ *
+ * \brief Eigen values/vectors solver for non selfadjoint matrices
+ *
+ * \param MatrixType the type of the matrix of which we are computing the eigen decomposition
+ *
+ * Currently it only support real matrices.
+ *
+ * \note this code was adapted from JAMA (public domain)
+ *
+ * \sa MatrixBase::eigenvalues(), SelfAdjointEigenSolver
+ */
+template<typename _MatrixType> class EigenSolver
+{
+ public:
+
+ typedef _MatrixType MatrixType;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ typedef std::complex<RealScalar> Complex;
+ typedef Matrix<Complex, MatrixType::ColsAtCompileTime, 1> EigenvalueType;
+ typedef Matrix<Complex, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime> EigenvectorType;
+ typedef Matrix<RealScalar, MatrixType::ColsAtCompileTime, 1> RealVectorType;
+ typedef Matrix<RealScalar, Dynamic, 1> RealVectorTypeX;
+
+ /**
+ * \brief Default Constructor.
+ *
+ * The default constructor is useful in cases in which the user intends to
+ * perform decompositions via EigenSolver::compute(const MatrixType&).
+ */
+ EigenSolver() : m_eivec(), m_eivalues(), m_isInitialized(false) {}
+
+ EigenSolver(const MatrixType& matrix)
+ : m_eivec(matrix.rows(), matrix.cols()),
+ m_eivalues(matrix.cols()),
+ m_isInitialized(false)
+ {
+ compute(matrix);
+ }
+
+
+ EigenvectorType eigenvectors(void) const;
+
+ /** \returns a real matrix V of pseudo eigenvectors.
+ *
+ * Let D be the block diagonal matrix with the real eigenvalues in 1x1 blocks,
+ * and any complex values u+iv in 2x2 blocks [u v ; -v u]. Then, the matrices D
+ * and V satisfy A*V = V*D.
+ *
+ * More precisely, if the diagonal matrix of the eigen values is:\n
+ * \f$
+ * \left[ \begin{array}{cccccc}
+ * u+iv & & & & & \\
+ * & u-iv & & & & \\
+ * & & a+ib & & & \\
+ * & & & a-ib & & \\
+ * & & & & x & \\
+ * & & & & & y \\
+ * \end{array} \right]
+ * \f$ \n
+ * then, we have:\n
+ * \f$
+ * D =\left[ \begin{array}{cccccc}
+ * u & v & & & & \\
+ * -v & u & & & & \\
+ * & & a & b & & \\
+ * & & -b & a & & \\
+ * & & & & x & \\
+ * & & & & & y \\
+ * \end{array} \right]
+ * \f$
+ *
+ * \sa pseudoEigenvalueMatrix()
+ */
+ const MatrixType& pseudoEigenvectors() const
+ {
+ ei_assert(m_isInitialized && "EigenSolver is not initialized.");
+ return m_eivec;
+ }
+
+ MatrixType pseudoEigenvalueMatrix() const;
+
+ /** \returns the eigenvalues as a column vector */
+ EigenvalueType eigenvalues() const
+ {
+ ei_assert(m_isInitialized && "EigenSolver is not initialized.");
+ return m_eivalues;
+ }
+
+ void compute(const MatrixType& matrix);
+
+ private:
+
+ void orthes(MatrixType& matH, RealVectorType& ort);
+ void hqr2(MatrixType& matH);
+
+ protected:
+ MatrixType m_eivec;
+ EigenvalueType m_eivalues;
+ bool m_isInitialized;
+};
+
+/** \returns the real block diagonal matrix D of the eigenvalues.
+ *
+ * See pseudoEigenvectors() for the details.
+ */
+template<typename MatrixType>
+MatrixType EigenSolver<MatrixType>::pseudoEigenvalueMatrix() const
+{
+ ei_assert(m_isInitialized && "EigenSolver is not initialized.");
+ int n = m_eivec.cols();
+ MatrixType matD = MatrixType::Zero(n,n);
+ for (int i=0; i<n; ++i)
+ {
+ if (ei_isMuchSmallerThan(ei_imag(m_eivalues.coeff(i)), ei_real(m_eivalues.coeff(i))))
+ matD.coeffRef(i,i) = ei_real(m_eivalues.coeff(i));
+ else
+ {
+ matD.template block<2,2>(i,i) << ei_real(m_eivalues.coeff(i)), ei_imag(m_eivalues.coeff(i)),
+ -ei_imag(m_eivalues.coeff(i)), ei_real(m_eivalues.coeff(i));
+ ++i;
+ }
+ }
+ return matD;
+}
+
+/** \returns the normalized complex eigenvectors as a matrix of column vectors.
+ *
+ * \sa eigenvalues(), pseudoEigenvectors()
+ */
+template<typename MatrixType>
+typename EigenSolver<MatrixType>::EigenvectorType EigenSolver<MatrixType>::eigenvectors(void) const
+{
+ ei_assert(m_isInitialized && "EigenSolver is not initialized.");
+ int n = m_eivec.cols();
+ EigenvectorType matV(n,n);
+ for (int j=0; j<n; ++j)
+ {
+ if (ei_isMuchSmallerThan(ei_abs(ei_imag(m_eivalues.coeff(j))), ei_abs(ei_real(m_eivalues.coeff(j)))))
+ {
+ // we have a real eigen value
+ matV.col(j) = m_eivec.col(j).template cast<Complex>();
+ }
+ else
+ {
+ // we have a pair of complex eigen values
+ for (int i=0; i<n; ++i)
+ {
+ matV.coeffRef(i,j) = Complex(m_eivec.coeff(i,j), m_eivec.coeff(i,j+1));
+ matV.coeffRef(i,j+1) = Complex(m_eivec.coeff(i,j), -m_eivec.coeff(i,j+1));
+ }
+ matV.col(j).normalize();
+ matV.col(j+1).normalize();
+ ++j;
+ }
+ }
+ return matV;
+}
+
+template<typename MatrixType>
+void EigenSolver<MatrixType>::compute(const MatrixType& matrix)
+{
+ assert(matrix.cols() == matrix.rows());
+ int n = matrix.cols();
+ m_eivalues.resize(n,1);
+
+ MatrixType matH = matrix;
+ RealVectorType ort(n);
+
+ // Reduce to Hessenberg form.
+ orthes(matH, ort);
+
+ // Reduce Hessenberg to real Schur form.
+ hqr2(matH);
+
+ m_isInitialized = true;
+}
+
+// Nonsymmetric reduction to Hessenberg form.
+template<typename MatrixType>
+void EigenSolver<MatrixType>::orthes(MatrixType& matH, RealVectorType& ort)
+{
+ // This is derived from the Algol procedures orthes and ortran,
+ // by Martin and Wilkinson, Handbook for Auto. Comp.,
+ // Vol.ii-Linear Algebra, and the corresponding
+ // Fortran subroutines in EISPACK.
+
+ int n = m_eivec.cols();
+ int low = 0;
+ int high = n-1;
+
+ for (int m = low+1; m <= high-1; ++m)
+ {
+ // Scale column.
+ RealScalar scale = matH.block(m, m-1, high-m+1, 1).cwise().abs().sum();
+ if (scale != 0.0)
+ {
+ // Compute Householder transformation.
+ RealScalar h = 0.0;
+ // FIXME could be rewritten, but this one looks better wrt cache
+ for (int i = high; i >= m; i--)
+ {
+ ort.coeffRef(i) = matH.coeff(i,m-1)/scale;
+ h += ort.coeff(i) * ort.coeff(i);
+ }
+ RealScalar g = ei_sqrt(h);
+ if (ort.coeff(m) > 0)
+ g = -g;
+ h = h - ort.coeff(m) * g;
+ ort.coeffRef(m) = ort.coeff(m) - g;
+
+ // Apply Householder similarity transformation
+ // H = (I-u*u'/h)*H*(I-u*u')/h)
+ int bSize = high-m+1;
+ matH.block(m, m, bSize, n-m) -= ((ort.segment(m, bSize)/h)
+ * (ort.segment(m, bSize).transpose() * matH.block(m, m, bSize, n-m)).lazy()).lazy();
+
+ matH.block(0, m, high+1, bSize) -= ((matH.block(0, m, high+1, bSize) * ort.segment(m, bSize)).lazy()
+ * (ort.segment(m, bSize)/h).transpose()).lazy();
+
+ ort.coeffRef(m) = scale*ort.coeff(m);
+ matH.coeffRef(m,m-1) = scale*g;
+ }
+ }
+
+ // Accumulate transformations (Algol's ortran).
+ m_eivec.setIdentity();
+
+ for (int m = high-1; m >= low+1; m--)
+ {
+ if (matH.coeff(m,m-1) != 0.0)
+ {
+ ort.segment(m+1, high-m) = matH.col(m-1).segment(m+1, high-m);
+
+ int bSize = high-m+1;
+ m_eivec.block(m, m, bSize, bSize) += ( (ort.segment(m, bSize) / (matH.coeff(m,m-1) * ort.coeff(m) ) )
+ * (ort.segment(m, bSize).transpose() * m_eivec.block(m, m, bSize, bSize)).lazy());
+ }
+ }
+}
+
+// Complex scalar division.
+template<typename Scalar>
+std::complex<Scalar> cdiv(Scalar xr, Scalar xi, Scalar yr, Scalar yi)
+{
+ Scalar r,d;
+ if (ei_abs(yr) > ei_abs(yi))
+ {
+ r = yi/yr;
+ d = yr + r*yi;
+ return std::complex<Scalar>((xr + r*xi)/d, (xi - r*xr)/d);
+ }
+ else
+ {
+ r = yr/yi;
+ d = yi + r*yr;
+ return std::complex<Scalar>((r*xr + xi)/d, (r*xi - xr)/d);
+ }
+}
+
+
+// Nonsymmetric reduction from Hessenberg to real Schur form.
+template<typename MatrixType>
+void EigenSolver<MatrixType>::hqr2(MatrixType& matH)
+{
+ // This is derived from the Algol procedure hqr2,
+ // by Martin and Wilkinson, Handbook for Auto. Comp.,
+ // Vol.ii-Linear Algebra, and the corresponding
+ // Fortran subroutine in EISPACK.
+
+ // Initialize
+ int nn = m_eivec.cols();
+ int n = nn-1;
+ int low = 0;
+ int high = nn-1;
+ Scalar eps = ei_pow(Scalar(2),ei_is_same_type<Scalar,float>::ret ? Scalar(-23) : Scalar(-52));
+ Scalar exshift = 0.0;
+ Scalar p=0,q=0,r=0,s=0,z=0,t,w,x,y;
+
+ // Store roots isolated by balanc and compute matrix norm
+ // FIXME to be efficient the following would requires a triangular reduxion code
+ // Scalar norm = matH.upper().cwise().abs().sum() + matH.corner(BottomLeft,n,n).diagonal().cwise().abs().sum();
+ Scalar norm = 0.0;
+ for (int j = 0; j < nn; ++j)
+ {
+ // FIXME what's the purpose of the following since the condition is always false
+ if ((j < low) || (j > high))
+ {
+ m_eivalues.coeffRef(j) = Complex(matH.coeff(j,j), 0.0);
+ }
+ norm += matH.row(j).segment(std::max(j-1,0), nn-std::max(j-1,0)).cwise().abs().sum();
+ }
+
+ // Outer loop over eigenvalue index
+ int iter = 0;
+ while (n >= low)
+ {
+ // Look for single small sub-diagonal element
+ int l = n;
+ while (l > low)
+ {
+ s = ei_abs(matH.coeff(l-1,l-1)) + ei_abs(matH.coeff(l,l));
+ if (s == 0.0)
+ s = norm;
+ if (ei_abs(matH.coeff(l,l-1)) < eps * s)
+ break;
+ l--;
+ }
+
+ // Check for convergence
+ // One root found
+ if (l == n)
+ {
+ matH.coeffRef(n,n) = matH.coeff(n,n) + exshift;
+ m_eivalues.coeffRef(n) = Complex(matH.coeff(n,n), 0.0);
+ n--;
+ iter = 0;
+ }
+ else if (l == n-1) // Two roots found
+ {
+ w = matH.coeff(n,n-1) * matH.coeff(n-1,n);
+ p = (matH.coeff(n-1,n-1) - matH.coeff(n,n)) * Scalar(0.5);
+ q = p * p + w;
+ z = ei_sqrt(ei_abs(q));
+ matH.coeffRef(n,n) = matH.coeff(n,n) + exshift;
+ matH.coeffRef(n-1,n-1) = matH.coeff(n-1,n-1) + exshift;
+ x = matH.coeff(n,n);
+
+ // Scalar pair
+ if (q >= 0)
+ {
+ if (p >= 0)
+ z = p + z;
+ else
+ z = p - z;
+
+ m_eivalues.coeffRef(n-1) = Complex(x + z, 0.0);
+ m_eivalues.coeffRef(n) = Complex(z!=0.0 ? x - w / z : m_eivalues.coeff(n-1).real(), 0.0);
+
+ x = matH.coeff(n,n-1);
+ s = ei_abs(x) + ei_abs(z);
+ p = x / s;
+ q = z / s;
+ r = ei_sqrt(p * p+q * q);
+ p = p / r;
+ q = q / r;
+
+ // Row modification
+ for (int j = n-1; j < nn; ++j)
+ {
+ z = matH.coeff(n-1,j);
+ matH.coeffRef(n-1,j) = q * z + p * matH.coeff(n,j);
+ matH.coeffRef(n,j) = q * matH.coeff(n,j) - p * z;
+ }
+
+ // Column modification
+ for (int i = 0; i <= n; ++i)
+ {
+ z = matH.coeff(i,n-1);
+ matH.coeffRef(i,n-1) = q * z + p * matH.coeff(i,n);
+ matH.coeffRef(i,n) = q * matH.coeff(i,n) - p * z;
+ }
+
+ // Accumulate transformations
+ for (int i = low; i <= high; ++i)
+ {
+ z = m_eivec.coeff(i,n-1);
+ m_eivec.coeffRef(i,n-1) = q * z + p * m_eivec.coeff(i,n);
+ m_eivec.coeffRef(i,n) = q * m_eivec.coeff(i,n) - p * z;
+ }
+ }
+ else // Complex pair
+ {
+ m_eivalues.coeffRef(n-1) = Complex(x + p, z);
+ m_eivalues.coeffRef(n) = Complex(x + p, -z);
+ }
+ n = n - 2;
+ iter = 0;
+ }
+ else // No convergence yet
+ {
+ // Form shift
+ x = matH.coeff(n,n);
+ y = 0.0;
+ w = 0.0;
+ if (l < n)
+ {
+ y = matH.coeff(n-1,n-1);
+ w = matH.coeff(n,n-1) * matH.coeff(n-1,n);
+ }
+
+ // Wilkinson's original ad hoc shift
+ if (iter == 10)
+ {
+ exshift += x;
+ for (int i = low; i <= n; ++i)
+ matH.coeffRef(i,i) -= x;
+ s = ei_abs(matH.coeff(n,n-1)) + ei_abs(matH.coeff(n-1,n-2));
+ x = y = Scalar(0.75) * s;
+ w = Scalar(-0.4375) * s * s;
+ }
+
+ // MATLAB's new ad hoc shift
+ if (iter == 30)
+ {
+ s = Scalar((y - x) / 2.0);
+ s = s * s + w;
+ if (s > 0)
+ {
+ s = ei_sqrt(s);
+ if (y < x)
+ s = -s;
+ s = Scalar(x - w / ((y - x) / 2.0 + s));
+ for (int i = low; i <= n; ++i)
+ matH.coeffRef(i,i) -= s;
+ exshift += s;
+ x = y = w = Scalar(0.964);
+ }
+ }
+
+ iter = iter + 1; // (Could check iteration count here.)
+
+ // Look for two consecutive small sub-diagonal elements
+ int m = n-2;
+ while (m >= l)
+ {
+ z = matH.coeff(m,m);
+ r = x - z;
+ s = y - z;
+ p = (r * s - w) / matH.coeff(m+1,m) + matH.coeff(m,m+1);
+ q = matH.coeff(m+1,m+1) - z - r - s;
+ r = matH.coeff(m+2,m+1);
+ s = ei_abs(p) + ei_abs(q) + ei_abs(r);
+ p = p / s;
+ q = q / s;
+ r = r / s;
+ if (m == l) {
+ break;
+ }
+ if (ei_abs(matH.coeff(m,m-1)) * (ei_abs(q) + ei_abs(r)) <
+ eps * (ei_abs(p) * (ei_abs(matH.coeff(m-1,m-1)) + ei_abs(z) +
+ ei_abs(matH.coeff(m+1,m+1)))))
+ {
+ break;
+ }
+ m--;
+ }
+
+ for (int i = m+2; i <= n; ++i)
+ {
+ matH.coeffRef(i,i-2) = 0.0;
+ if (i > m+2)
+ matH.coeffRef(i,i-3) = 0.0;
+ }
+
+ // Double QR step involving rows l:n and columns m:n
+ for (int k = m; k <= n-1; ++k)
+ {
+ int notlast = (k != n-1);
+ if (k != m) {
+ p = matH.coeff(k,k-1);
+ q = matH.coeff(k+1,k-1);
+ r = notlast ? matH.coeff(k+2,k-1) : Scalar(0);
+ x = ei_abs(p) + ei_abs(q) + ei_abs(r);
+ if (x != 0.0)
+ {
+ p = p / x;
+ q = q / x;
+ r = r / x;
+ }
+ }
+
+ if (x == 0.0)
+ break;
+
+ s = ei_sqrt(p * p + q * q + r * r);
+
+ if (p < 0)
+ s = -s;
+
+ if (s != 0)
+ {
+ if (k != m)
+ matH.coeffRef(k,k-1) = -s * x;
+ else if (l != m)
+ matH.coeffRef(k,k-1) = -matH.coeff(k,k-1);
+
+ p = p + s;
+ x = p / s;
+ y = q / s;
+ z = r / s;
+ q = q / p;
+ r = r / p;
+
+ // Row modification
+ for (int j = k; j < nn; ++j)
+ {
+ p = matH.coeff(k,j) + q * matH.coeff(k+1,j);
+ if (notlast)
+ {
+ p = p + r * matH.coeff(k+2,j);
+ matH.coeffRef(k+2,j) = matH.coeff(k+2,j) - p * z;
+ }
+ matH.coeffRef(k,j) = matH.coeff(k,j) - p * x;
+ matH.coeffRef(k+1,j) = matH.coeff(k+1,j) - p * y;
+ }
+
+ // Column modification
+ for (int i = 0; i <= std::min(n,k+3); ++i)
+ {
+ p = x * matH.coeff(i,k) + y * matH.coeff(i,k+1);
+ if (notlast)
+ {
+ p = p + z * matH.coeff(i,k+2);
+ matH.coeffRef(i,k+2) = matH.coeff(i,k+2) - p * r;
+ }
+ matH.coeffRef(i,k) = matH.coeff(i,k) - p;
+ matH.coeffRef(i,k+1) = matH.coeff(i,k+1) - p * q;
+ }
+
+ // Accumulate transformations
+ for (int i = low; i <= high; ++i)
+ {
+ p = x * m_eivec.coeff(i,k) + y * m_eivec.coeff(i,k+1);
+ if (notlast)
+ {
+ p = p + z * m_eivec.coeff(i,k+2);
+ m_eivec.coeffRef(i,k+2) = m_eivec.coeff(i,k+2) - p * r;
+ }
+ m_eivec.coeffRef(i,k) = m_eivec.coeff(i,k) - p;
+ m_eivec.coeffRef(i,k+1) = m_eivec.coeff(i,k+1) - p * q;
+ }
+ } // (s != 0)
+ } // k loop
+ } // check convergence
+ } // while (n >= low)
+
+ // Backsubstitute to find vectors of upper triangular form
+ if (norm == 0.0)
+ {
+ return;
+ }
+
+ for (n = nn-1; n >= 0; n--)
+ {
+ p = m_eivalues.coeff(n).real();
+ q = m_eivalues.coeff(n).imag();
+
+ // Scalar vector
+ if (q == 0)
+ {
+ int l = n;
+ matH.coeffRef(n,n) = 1.0;
+ for (int i = n-1; i >= 0; i--)
+ {
+ w = matH.coeff(i,i) - p;
+ r = (matH.row(i).segment(l,n-l+1) * matH.col(n).segment(l, n-l+1))(0,0);
+
+ if (m_eivalues.coeff(i).imag() < 0.0)
+ {
+ z = w;
+ s = r;
+ }
+ else
+ {
+ l = i;
+ if (m_eivalues.coeff(i).imag() == 0.0)
+ {
+ if (w != 0.0)
+ matH.coeffRef(i,n) = -r / w;
+ else
+ matH.coeffRef(i,n) = -r / (eps * norm);
+ }
+ else // Solve real equations
+ {
+ x = matH.coeff(i,i+1);
+ y = matH.coeff(i+1,i);
+ q = (m_eivalues.coeff(i).real() - p) * (m_eivalues.coeff(i).real() - p) + m_eivalues.coeff(i).imag() * m_eivalues.coeff(i).imag();
+ t = (x * s - z * r) / q;
+ matH.coeffRef(i,n) = t;
+ if (ei_abs(x) > ei_abs(z))
+ matH.coeffRef(i+1,n) = (-r - w * t) / x;
+ else
+ matH.coeffRef(i+1,n) = (-s - y * t) / z;
+ }
+
+ // Overflow control
+ t = ei_abs(matH.coeff(i,n));
+ if ((eps * t) * t > 1)
+ matH.col(n).end(nn-i) /= t;
+ }
+ }
+ }
+ else if (q < 0) // Complex vector
+ {
+ std::complex<Scalar> cc;
+ int l = n-1;
+
+ // Last vector component imaginary so matrix is triangular
+ if (ei_abs(matH.coeff(n,n-1)) > ei_abs(matH.coeff(n-1,n)))
+ {
+ matH.coeffRef(n-1,n-1) = q / matH.coeff(n,n-1);
+ matH.coeffRef(n-1,n) = -(matH.coeff(n,n) - p) / matH.coeff(n,n-1);
+ }
+ else
+ {
+ cc = cdiv<Scalar>(0.0,-matH.coeff(n-1,n),matH.coeff(n-1,n-1)-p,q);
+ matH.coeffRef(n-1,n-1) = ei_real(cc);
+ matH.coeffRef(n-1,n) = ei_imag(cc);
+ }
+ matH.coeffRef(n,n-1) = 0.0;
+ matH.coeffRef(n,n) = 1.0;
+ for (int i = n-2; i >= 0; i--)
+ {
+ Scalar ra,sa,vr,vi;
+ ra = (matH.block(i,l, 1, n-l+1) * matH.block(l,n-1, n-l+1, 1)).lazy()(0,0);
+ sa = (matH.block(i,l, 1, n-l+1) * matH.block(l,n, n-l+1, 1)).lazy()(0,0);
+ w = matH.coeff(i,i) - p;
+
+ if (m_eivalues.coeff(i).imag() < 0.0)
+ {
+ z = w;
+ r = ra;
+ s = sa;
+ }
+ else
+ {
+ l = i;
+ if (m_eivalues.coeff(i).imag() == 0)
+ {
+ cc = cdiv(-ra,-sa,w,q);
+ matH.coeffRef(i,n-1) = ei_real(cc);
+ matH.coeffRef(i,n) = ei_imag(cc);
+ }
+ else
+ {
+ // Solve complex equations
+ x = matH.coeff(i,i+1);
+ y = matH.coeff(i+1,i);
+ vr = (m_eivalues.coeff(i).real() - p) * (m_eivalues.coeff(i).real() - p) + m_eivalues.coeff(i).imag() * m_eivalues.coeff(i).imag() - q * q;
+ vi = (m_eivalues.coeff(i).real() - p) * Scalar(2) * q;
+ if ((vr == 0.0) && (vi == 0.0))
+ vr = eps * norm * (ei_abs(w) + ei_abs(q) + ei_abs(x) + ei_abs(y) + ei_abs(z));
+
+ cc= cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
+ matH.coeffRef(i,n-1) = ei_real(cc);
+ matH.coeffRef(i,n) = ei_imag(cc);
+ if (ei_abs(x) > (ei_abs(z) + ei_abs(q)))
+ {
+ matH.coeffRef(i+1,n-1) = (-ra - w * matH.coeff(i,n-1) + q * matH.coeff(i,n)) / x;
+ matH.coeffRef(i+1,n) = (-sa - w * matH.coeff(i,n) - q * matH.coeff(i,n-1)) / x;
+ }
+ else
+ {
+ cc = cdiv(-r-y*matH.coeff(i,n-1),-s-y*matH.coeff(i,n),z,q);
+ matH.coeffRef(i+1,n-1) = ei_real(cc);
+ matH.coeffRef(i+1,n) = ei_imag(cc);
+ }
+ }
+
+ // Overflow control
+ t = std::max(ei_abs(matH.coeff(i,n-1)),ei_abs(matH.coeff(i,n)));
+ if ((eps * t) * t > 1)
+ matH.block(i, n-1, nn-i, 2) /= t;
+
+ }
+ }
+ }
+ }
+
+ // Vectors of isolated roots
+ for (int i = 0; i < nn; ++i)
+ {
+ // FIXME again what's the purpose of this test ?
+ // in this algo low==0 and high==nn-1 !!
+ if (i < low || i > high)
+ {
+ m_eivec.row(i).end(nn-i) = matH.row(i).end(nn-i);
+ }
+ }
+
+ // Back transformation to get eigenvectors of original matrix
+ int bRows = high-low+1;
+ for (int j = nn-1; j >= low; j--)
+ {
+ int bSize = std::min(j,high)-low+1;
+ m_eivec.col(j).segment(low, bRows) = (m_eivec.block(low, low, bRows, bSize) * matH.col(j).segment(low, bSize));
+ }
+}
+
+#endif // EIGEN_EIGENSOLVER_H
diff --git a/extern/Eigen2/Eigen/src/QR/HessenbergDecomposition.h b/extern/Eigen2/Eigen/src/QR/HessenbergDecomposition.h
new file mode 100644
index 00000000000..6d0ff794ec2
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/QR/HessenbergDecomposition.h
@@ -0,0 +1,250 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_HESSENBERGDECOMPOSITION_H
+#define EIGEN_HESSENBERGDECOMPOSITION_H
+
+/** \ingroup QR_Module
+ * \nonstableyet
+ *
+ * \class HessenbergDecomposition
+ *
+ * \brief Reduces a squared matrix to an Hessemberg form
+ *
+ * \param MatrixType the type of the matrix of which we are computing the Hessenberg decomposition
+ *
+ * This class performs an Hessenberg decomposition of a matrix \f$ A \f$ such that:
+ * \f$ A = Q H Q^* \f$ where \f$ Q \f$ is unitary and \f$ H \f$ a Hessenberg matrix.
+ *
+ * \sa class Tridiagonalization, class Qr
+ */
+template<typename _MatrixType> class HessenbergDecomposition
+{
+ public:
+
+ typedef _MatrixType MatrixType;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+
+ enum {
+ Size = MatrixType::RowsAtCompileTime,
+ SizeMinusOne = MatrixType::RowsAtCompileTime==Dynamic
+ ? Dynamic
+ : MatrixType::RowsAtCompileTime-1
+ };
+
+ typedef Matrix<Scalar, SizeMinusOne, 1> CoeffVectorType;
+ typedef Matrix<RealScalar, Size, 1> DiagonalType;
+ typedef Matrix<RealScalar, SizeMinusOne, 1> SubDiagonalType;
+
+ typedef typename NestByValue<DiagonalCoeffs<MatrixType> >::RealReturnType DiagonalReturnType;
+
+ typedef typename NestByValue<DiagonalCoeffs<
+ NestByValue<Block<MatrixType,SizeMinusOne,SizeMinusOne> > > >::RealReturnType SubDiagonalReturnType;
+
+ /** This constructor initializes a HessenbergDecomposition object for
+ * further use with HessenbergDecomposition::compute()
+ */
+ HessenbergDecomposition(int size = Size==Dynamic ? 2 : Size)
+ : m_matrix(size,size), m_hCoeffs(size-1)
+ {}
+
+ HessenbergDecomposition(const MatrixType& matrix)
+ : m_matrix(matrix),
+ m_hCoeffs(matrix.cols()-1)
+ {
+ _compute(m_matrix, m_hCoeffs);
+ }
+
+ /** Computes or re-compute the Hessenberg decomposition for the matrix \a matrix.
+ *
+ * This method allows to re-use the allocated data.
+ */
+ void compute(const MatrixType& matrix)
+ {
+ m_matrix = matrix;
+ m_hCoeffs.resize(matrix.rows()-1,1);
+ _compute(m_matrix, m_hCoeffs);
+ }
+
+ /** \returns the householder coefficients allowing to
+ * reconstruct the matrix Q from the packed data.
+ *
+ * \sa packedMatrix()
+ */
+ CoeffVectorType householderCoefficients(void) const { return m_hCoeffs; }
+
+ /** \returns the internal result of the decomposition.
+ *
+ * The returned matrix contains the following information:
+ * - the upper part and lower sub-diagonal represent the Hessenberg matrix H
+ * - the rest of the lower part contains the Householder vectors that, combined with
+ * Householder coefficients returned by householderCoefficients(),
+ * allows to reconstruct the matrix Q as follow:
+ * Q = H_{N-1} ... H_1 H_0
+ * where the matrices H are the Householder transformation:
+ * H_i = (I - h_i * v_i * v_i')
+ * where h_i == householderCoefficients()[i] and v_i is a Householder vector:
+ * v_i = [ 0, ..., 0, 1, M(i+2,i), ..., M(N-1,i) ]
+ *
+ * See LAPACK for further details on this packed storage.
+ */
+ const MatrixType& packedMatrix(void) const { return m_matrix; }
+
+ MatrixType matrixQ(void) const;
+ MatrixType matrixH(void) const;
+
+ private:
+
+ static void _compute(MatrixType& matA, CoeffVectorType& hCoeffs);
+
+ protected:
+ MatrixType m_matrix;
+ CoeffVectorType m_hCoeffs;
+};
+
+#ifndef EIGEN_HIDE_HEAVY_CODE
+
+/** \internal
+ * Performs a tridiagonal decomposition of \a matA in place.
+ *
+ * \param matA the input selfadjoint matrix
+ * \param hCoeffs returned Householder coefficients
+ *
+ * The result is written in the lower triangular part of \a matA.
+ *
+ * Implemented from Golub's "Matrix Computations", algorithm 8.3.1.
+ *
+ * \sa packedMatrix()
+ */
+template<typename MatrixType>
+void HessenbergDecomposition<MatrixType>::_compute(MatrixType& matA, CoeffVectorType& hCoeffs)
+{
+ assert(matA.rows()==matA.cols());
+ int n = matA.rows();
+ for (int i = 0; i<n-2; ++i)
+ {
+ // let's consider the vector v = i-th column starting at position i+1
+
+ // start of the householder transformation
+ // squared norm of the vector v skipping the first element
+ RealScalar v1norm2 = matA.col(i).end(n-(i+2)).squaredNorm();
+
+ if (ei_isMuchSmallerThan(v1norm2,static_cast<Scalar>(1)))
+ {
+ hCoeffs.coeffRef(i) = 0.;
+ }
+ else
+ {
+ Scalar v0 = matA.col(i).coeff(i+1);
+ RealScalar beta = ei_sqrt(ei_abs2(v0)+v1norm2);
+ if (ei_real(v0)>=0.)
+ beta = -beta;
+ matA.col(i).end(n-(i+2)) *= (Scalar(1)/(v0-beta));
+ matA.col(i).coeffRef(i+1) = beta;
+ Scalar h = (beta - v0) / beta;
+ // end of the householder transformation
+
+ // Apply similarity transformation to remaining columns,
+ // i.e., A = H' A H where H = I - h v v' and v = matA.col(i).end(n-i-1)
+ matA.col(i).coeffRef(i+1) = 1;
+
+ // first let's do A = H A
+ matA.corner(BottomRight,n-i-1,n-i-1) -= ((ei_conj(h) * matA.col(i).end(n-i-1)) *
+ (matA.col(i).end(n-i-1).adjoint() * matA.corner(BottomRight,n-i-1,n-i-1))).lazy();
+
+ // now let's do A = A H
+ matA.corner(BottomRight,n,n-i-1) -= ((matA.corner(BottomRight,n,n-i-1) * matA.col(i).end(n-i-1))
+ * (h * matA.col(i).end(n-i-1).adjoint())).lazy();
+
+ matA.col(i).coeffRef(i+1) = beta;
+ hCoeffs.coeffRef(i) = h;
+ }
+ }
+ if (NumTraits<Scalar>::IsComplex)
+ {
+ // Householder transformation on the remaining single scalar
+ int i = n-2;
+ Scalar v0 = matA.coeff(i+1,i);
+
+ RealScalar beta = ei_sqrt(ei_abs2(v0));
+ if (ei_real(v0)>=0.)
+ beta = -beta;
+ Scalar h = (beta - v0) / beta;
+ hCoeffs.coeffRef(i) = h;
+
+ // A = H* A
+ matA.corner(BottomRight,n-i-1,n-i) -= ei_conj(h) * matA.corner(BottomRight,n-i-1,n-i);
+
+ // A = A H
+ matA.col(n-1) -= h * matA.col(n-1);
+ }
+ else
+ {
+ hCoeffs.coeffRef(n-2) = 0;
+ }
+}
+
+/** reconstructs and returns the matrix Q */
+template<typename MatrixType>
+typename HessenbergDecomposition<MatrixType>::MatrixType
+HessenbergDecomposition<MatrixType>::matrixQ(void) const
+{
+ int n = m_matrix.rows();
+ MatrixType matQ = MatrixType::Identity(n,n);
+ for (int i = n-2; i>=0; i--)
+ {
+ Scalar tmp = m_matrix.coeff(i+1,i);
+ m_matrix.const_cast_derived().coeffRef(i+1,i) = 1;
+
+ matQ.corner(BottomRight,n-i-1,n-i-1) -=
+ ((m_hCoeffs.coeff(i) * m_matrix.col(i).end(n-i-1)) *
+ (m_matrix.col(i).end(n-i-1).adjoint() * matQ.corner(BottomRight,n-i-1,n-i-1)).lazy()).lazy();
+
+ m_matrix.const_cast_derived().coeffRef(i+1,i) = tmp;
+ }
+ return matQ;
+}
+
+#endif // EIGEN_HIDE_HEAVY_CODE
+
+/** constructs and returns the matrix H.
+ * Note that the matrix H is equivalent to the upper part of the packed matrix
+ * (including the lower sub-diagonal). Therefore, it might be often sufficient
+ * to directly use the packed matrix instead of creating a new one.
+ */
+template<typename MatrixType>
+typename HessenbergDecomposition<MatrixType>::MatrixType
+HessenbergDecomposition<MatrixType>::matrixH(void) const
+{
+ // FIXME should this function (and other similar) rather take a matrix as argument
+ // and fill it (to avoid temporaries)
+ int n = m_matrix.rows();
+ MatrixType matH = m_matrix;
+ if (n>2)
+ matH.corner(BottomLeft,n-2, n-2).template part<LowerTriangular>().setZero();
+ return matH;
+}
+
+#endif // EIGEN_HESSENBERGDECOMPOSITION_H
diff --git a/extern/Eigen2/Eigen/src/QR/QR.h b/extern/Eigen2/Eigen/src/QR/QR.h
new file mode 100644
index 00000000000..90751dd428d
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/QR/QR.h
@@ -0,0 +1,334 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_QR_H
+#define EIGEN_QR_H
+
+/** \ingroup QR_Module
+ * \nonstableyet
+ *
+ * \class QR
+ *
+ * \brief QR decomposition of a matrix
+ *
+ * \param MatrixType the type of the matrix of which we are computing the QR decomposition
+ *
+ * This class performs a QR decomposition using Householder transformations. The result is
+ * stored in a compact way compatible with LAPACK.
+ *
+ * \sa MatrixBase::qr()
+ */
+template<typename MatrixType> class QR
+{
+ public:
+
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename MatrixType::RealScalar RealScalar;
+ typedef Block<MatrixType, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> MatrixRBlockType;
+ typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> MatrixTypeR;
+ typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
+
+ /**
+ * \brief Default Constructor.
+ *
+ * The default constructor is useful in cases in which the user intends to
+ * perform decompositions via QR::compute(const MatrixType&).
+ */
+ QR() : m_qr(), m_hCoeffs(), m_isInitialized(false) {}
+
+ QR(const MatrixType& matrix)
+ : m_qr(matrix.rows(), matrix.cols()),
+ m_hCoeffs(matrix.cols()),
+ m_isInitialized(false)
+ {
+ compute(matrix);
+ }
+
+ /** \deprecated use isInjective()
+ * \returns whether or not the matrix is of full rank
+ *
+ * \note Since the rank is computed only once, i.e. the first time it is needed, this
+ * method almost does not perform any further computation.
+ */
+ EIGEN_DEPRECATED bool isFullRank() const
+ {
+ ei_assert(m_isInitialized && "QR is not initialized.");
+ return rank() == m_qr.cols();
+ }
+
+ /** \returns the rank of the matrix of which *this is the QR decomposition.
+ *
+ * \note Since the rank is computed only once, i.e. the first time it is needed, this
+ * method almost does not perform any further computation.
+ */
+ int rank() const;
+
+ /** \returns the dimension of the kernel of the matrix of which *this is the QR decomposition.
+ *
+ * \note Since the rank is computed only once, i.e. the first time it is needed, this
+ * method almost does not perform any further computation.
+ */
+ inline int dimensionOfKernel() const
+ {
+ ei_assert(m_isInitialized && "QR is not initialized.");
+ return m_qr.cols() - rank();
+ }
+
+ /** \returns true if the matrix of which *this is the QR decomposition represents an injective
+ * linear map, i.e. has trivial kernel; false otherwise.
+ *
+ * \note Since the rank is computed only once, i.e. the first time it is needed, this
+ * method almost does not perform any further computation.
+ */
+ inline bool isInjective() const
+ {
+ ei_assert(m_isInitialized && "QR is not initialized.");
+ return rank() == m_qr.cols();
+ }
+
+ /** \returns true if the matrix of which *this is the QR decomposition represents a surjective
+ * linear map; false otherwise.
+ *
+ * \note Since the rank is computed only once, i.e. the first time it is needed, this
+ * method almost does not perform any further computation.
+ */
+ inline bool isSurjective() const
+ {
+ ei_assert(m_isInitialized && "QR is not initialized.");
+ return rank() == m_qr.rows();
+ }
+
+ /** \returns true if the matrix of which *this is the QR decomposition is invertible.
+ *
+ * \note Since the rank is computed only once, i.e. the first time it is needed, this
+ * method almost does not perform any further computation.
+ */
+ inline bool isInvertible() const
+ {
+ ei_assert(m_isInitialized && "QR is not initialized.");
+ return isInjective() && isSurjective();
+ }
+
+ /** \returns a read-only expression of the matrix R of the actual the QR decomposition */
+ const Part<NestByValue<MatrixRBlockType>, UpperTriangular>
+ matrixR(void) const
+ {
+ ei_assert(m_isInitialized && "QR is not initialized.");
+ int cols = m_qr.cols();
+ return MatrixRBlockType(m_qr, 0, 0, cols, cols).nestByValue().template part<UpperTriangular>();
+ }
+
+ /** This method finds a solution x to the equation Ax=b, where A is the matrix of which
+ * *this is the QR decomposition, if any exists.
+ *
+ * \param b the right-hand-side of the equation to solve.
+ *
+ * \param result a pointer to the vector/matrix in which to store the solution, if any exists.
+ * Resized if necessary, so that result->rows()==A.cols() and result->cols()==b.cols().
+ * If no solution exists, *result is left with undefined coefficients.
+ *
+ * \returns true if any solution exists, false if no solution exists.
+ *
+ * \note If there exist more than one solution, this method will arbitrarily choose one.
+ * If you need a complete analysis of the space of solutions, take the one solution obtained
+ * by this method and add to it elements of the kernel, as determined by kernel().
+ *
+ * \note The case where b is a matrix is not yet implemented. Also, this
+ * code is space inefficient.
+ *
+ * Example: \include QR_solve.cpp
+ * Output: \verbinclude QR_solve.out
+ *
+ * \sa MatrixBase::solveTriangular(), kernel(), computeKernel(), inverse(), computeInverse()
+ */
+ template<typename OtherDerived, typename ResultType>
+ bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const;
+
+ MatrixType matrixQ(void) const;
+
+ void compute(const MatrixType& matrix);
+
+ protected:
+ MatrixType m_qr;
+ VectorType m_hCoeffs;
+ mutable int m_rank;
+ mutable bool m_rankIsUptodate;
+ bool m_isInitialized;
+};
+
+/** \returns the rank of the matrix of which *this is the QR decomposition. */
+template<typename MatrixType>
+int QR<MatrixType>::rank() const
+{
+ ei_assert(m_isInitialized && "QR is not initialized.");
+ if (!m_rankIsUptodate)
+ {
+ RealScalar maxCoeff = m_qr.diagonal().cwise().abs().maxCoeff();
+ int n = m_qr.cols();
+ m_rank = 0;
+ while(m_rank<n && !ei_isMuchSmallerThan(m_qr.diagonal().coeff(m_rank), maxCoeff))
+ ++m_rank;
+ m_rankIsUptodate = true;
+ }
+ return m_rank;
+}
+
+#ifndef EIGEN_HIDE_HEAVY_CODE
+
+template<typename MatrixType>
+void QR<MatrixType>::compute(const MatrixType& matrix)
+{
+ m_rankIsUptodate = false;
+ m_qr = matrix;
+ m_hCoeffs.resize(matrix.cols());
+
+ int rows = matrix.rows();
+ int cols = matrix.cols();
+ RealScalar eps2 = precision<RealScalar>()*precision<RealScalar>();
+
+ for (int k = 0; k < cols; ++k)
+ {
+ int remainingSize = rows-k;
+
+ RealScalar beta;
+ Scalar v0 = m_qr.col(k).coeff(k);
+
+ if (remainingSize==1)
+ {
+ if (NumTraits<Scalar>::IsComplex)
+ {
+ // Householder transformation on the remaining single scalar
+ beta = ei_abs(v0);
+ if (ei_real(v0)>0)
+ beta = -beta;
+ m_qr.coeffRef(k,k) = beta;
+ m_hCoeffs.coeffRef(k) = (beta - v0) / beta;
+ }
+ else
+ {
+ m_hCoeffs.coeffRef(k) = 0;
+ }
+ }
+ else if ((beta=m_qr.col(k).end(remainingSize-1).squaredNorm())>eps2)
+ // FIXME what about ei_imag(v0) ??
+ {
+ // form k-th Householder vector
+ beta = ei_sqrt(ei_abs2(v0)+beta);
+ if (ei_real(v0)>=0.)
+ beta = -beta;
+ m_qr.col(k).end(remainingSize-1) /= v0-beta;
+ m_qr.coeffRef(k,k) = beta;
+ Scalar h = m_hCoeffs.coeffRef(k) = (beta - v0) / beta;
+
+ // apply the Householder transformation (I - h v v') to remaining columns, i.e.,
+ // R <- (I - h v v') * R where v = [1,m_qr(k+1,k), m_qr(k+2,k), ...]
+ int remainingCols = cols - k -1;
+ if (remainingCols>0)
+ {
+ m_qr.coeffRef(k,k) = Scalar(1);
+ m_qr.corner(BottomRight, remainingSize, remainingCols) -= ei_conj(h) * m_qr.col(k).end(remainingSize)
+ * (m_qr.col(k).end(remainingSize).adjoint() * m_qr.corner(BottomRight, remainingSize, remainingCols));
+ m_qr.coeffRef(k,k) = beta;
+ }
+ }
+ else
+ {
+ m_hCoeffs.coeffRef(k) = 0;
+ }
+ }
+ m_isInitialized = true;
+}
+
+template<typename MatrixType>
+template<typename OtherDerived, typename ResultType>
+bool QR<MatrixType>::solve(
+ const MatrixBase<OtherDerived>& b,
+ ResultType *result
+) const
+{
+ ei_assert(m_isInitialized && "QR is not initialized.");
+ const int rows = m_qr.rows();
+ ei_assert(b.rows() == rows);
+ result->resize(rows, b.cols());
+
+ // TODO(keir): There is almost certainly a faster way to multiply by
+ // Q^T without explicitly forming matrixQ(). Investigate.
+ *result = matrixQ().transpose()*b;
+
+ if(!isSurjective())
+ {
+ // is result is in the image of R ?
+ RealScalar biggest_in_res = result->corner(TopLeft, m_rank, result->cols()).cwise().abs().maxCoeff();
+ for(int col = 0; col < result->cols(); ++col)
+ for(int row = m_rank; row < result->rows(); ++row)
+ if(!ei_isMuchSmallerThan(result->coeff(row,col), biggest_in_res))
+ return false;
+ }
+ m_qr.corner(TopLeft, m_rank, m_rank)
+ .template marked<UpperTriangular>()
+ .solveTriangularInPlace(result->corner(TopLeft, m_rank, result->cols()));
+
+ return true;
+}
+
+/** \returns the matrix Q */
+template<typename MatrixType>
+MatrixType QR<MatrixType>::matrixQ() const
+{
+ ei_assert(m_isInitialized && "QR is not initialized.");
+ // compute the product Q_0 Q_1 ... Q_n-1,
+ // where Q_k is the k-th Householder transformation I - h_k v_k v_k'
+ // and v_k is the k-th Householder vector [1,m_qr(k+1,k), m_qr(k+2,k), ...]
+ int rows = m_qr.rows();
+ int cols = m_qr.cols();
+ MatrixType res = MatrixType::Identity(rows, cols);
+ for (int k = cols-1; k >= 0; k--)
+ {
+ // to make easier the computation of the transformation, let's temporarily
+ // overwrite m_qr(k,k) such that the end of m_qr.col(k) is exactly our Householder vector.
+ Scalar beta = m_qr.coeff(k,k);
+ m_qr.const_cast_derived().coeffRef(k,k) = 1;
+ int endLength = rows-k;
+ res.corner(BottomRight,endLength, cols-k) -= ((m_hCoeffs.coeff(k) * m_qr.col(k).end(endLength))
+ * (m_qr.col(k).end(endLength).adjoint() * res.corner(BottomRight,endLength, cols-k)).lazy()).lazy();
+ m_qr.const_cast_derived().coeffRef(k,k) = beta;
+ }
+ return res;
+}
+
+#endif // EIGEN_HIDE_HEAVY_CODE
+
+/** \return the QR decomposition of \c *this.
+ *
+ * \sa class QR
+ */
+template<typename Derived>
+const QR<typename MatrixBase<Derived>::PlainMatrixType>
+MatrixBase<Derived>::qr() const
+{
+ return QR<PlainMatrixType>(eval());
+}
+
+
+#endif // EIGEN_QR_H
diff --git a/extern/Eigen3/Eigen/StdVector b/extern/Eigen2/Eigen/src/QR/QrInstantiations.cpp
index 3d8995e5aae..dacb05d3d1f 100644
--- a/extern/Eigen3/Eigen/StdVector
+++ b/extern/Eigen2/Eigen/src/QR/QrInstantiations.cpp
@@ -1,8 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -23,20 +22,22 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-#ifndef EIGEN_STDVECTOR_MODULE_H
-#define EIGEN_STDVECTOR_MODULE_H
-
-#include "Core"
-#include <vector>
-
-#if (defined(_MSC_VER) && defined(_WIN64)) /* MSVC auto aligns in 64 bit builds */
+#ifndef EIGEN_EXTERN_INSTANTIATIONS
+#define EIGEN_EXTERN_INSTANTIATIONS
+#endif
+#include "../../Core"
+#undef EIGEN_EXTERN_INSTANTIATIONS
-#define EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(...)
+#include "../../QR"
-#else
+namespace Eigen
+{
-#include "src/StlSupport/StdVector.h"
+template static void ei_tridiagonal_qr_step(float* , float* , int, int, float* , int);
+template static void ei_tridiagonal_qr_step(double* , double* , int, int, double* , int);
+template static void ei_tridiagonal_qr_step(float* , float* , int, int, std::complex<float>* , int);
+template static void ei_tridiagonal_qr_step(double* , double* , int, int, std::complex<double>* , int);
-#endif
+EIGEN_QR_MODULE_INSTANTIATE();
-#endif // EIGEN_STDVECTOR_MODULE_H
+}
diff --git a/extern/Eigen2/Eigen/src/QR/SelfAdjointEigenSolver.h b/extern/Eigen2/Eigen/src/QR/SelfAdjointEigenSolver.h
new file mode 100644
index 00000000000..70984efab9d
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/QR/SelfAdjointEigenSolver.h
@@ -0,0 +1,402 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SELFADJOINTEIGENSOLVER_H
+#define EIGEN_SELFADJOINTEIGENSOLVER_H
+
+/** \qr_module \ingroup QR_Module
+ * \nonstableyet
+ *
+ * \class SelfAdjointEigenSolver
+ *
+ * \brief Eigen values/vectors solver for selfadjoint matrix
+ *
+ * \param MatrixType the type of the matrix of which we are computing the eigen decomposition
+ *
+ * \note MatrixType must be an actual Matrix type, it can't be an expression type.
+ *
+ * \sa MatrixBase::eigenvalues(), class EigenSolver
+ */
+template<typename _MatrixType> class SelfAdjointEigenSolver
+{
+ public:
+
+ enum {Size = _MatrixType::RowsAtCompileTime };
+ typedef _MatrixType MatrixType;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ typedef std::complex<RealScalar> Complex;
+ typedef Matrix<RealScalar, MatrixType::ColsAtCompileTime, 1> RealVectorType;
+ typedef Matrix<RealScalar, Dynamic, 1> RealVectorTypeX;
+ typedef Tridiagonalization<MatrixType> TridiagonalizationType;
+
+ SelfAdjointEigenSolver()
+ : m_eivec(int(Size), int(Size)),
+ m_eivalues(int(Size))
+ {
+ ei_assert(Size!=Dynamic);
+ }
+
+ SelfAdjointEigenSolver(int size)
+ : m_eivec(size, size),
+ m_eivalues(size)
+ {}
+
+ /** Constructors computing the eigenvalues of the selfadjoint matrix \a matrix,
+ * as well as the eigenvectors if \a computeEigenvectors is true.
+ *
+ * \sa compute(MatrixType,bool), SelfAdjointEigenSolver(MatrixType,MatrixType,bool)
+ */
+ SelfAdjointEigenSolver(const MatrixType& matrix, bool computeEigenvectors = true)
+ : m_eivec(matrix.rows(), matrix.cols()),
+ m_eivalues(matrix.cols())
+ {
+ compute(matrix, computeEigenvectors);
+ }
+
+ /** Constructors computing the eigenvalues of the generalized eigen problem
+ * \f$ Ax = lambda B x \f$ with \a matA the selfadjoint matrix \f$ A \f$
+ * and \a matB the positive definite matrix \f$ B \f$ . The eigenvectors
+ * are computed if \a computeEigenvectors is true.
+ *
+ * \sa compute(MatrixType,MatrixType,bool), SelfAdjointEigenSolver(MatrixType,bool)
+ */
+ SelfAdjointEigenSolver(const MatrixType& matA, const MatrixType& matB, bool computeEigenvectors = true)
+ : m_eivec(matA.rows(), matA.cols()),
+ m_eivalues(matA.cols())
+ {
+ compute(matA, matB, computeEigenvectors);
+ }
+
+ void compute(const MatrixType& matrix, bool computeEigenvectors = true);
+
+ void compute(const MatrixType& matA, const MatrixType& matB, bool computeEigenvectors = true);
+
+ /** \returns the computed eigen vectors as a matrix of column vectors */
+ MatrixType eigenvectors(void) const
+ {
+ #ifndef NDEBUG
+ ei_assert(m_eigenvectorsOk);
+ #endif
+ return m_eivec;
+ }
+
+ /** \returns the computed eigen values */
+ RealVectorType eigenvalues(void) const { return m_eivalues; }
+
+ /** \returns the positive square root of the matrix
+ *
+ * \note the matrix itself must be positive in order for this to make sense.
+ */
+ MatrixType operatorSqrt() const
+ {
+ return m_eivec * m_eivalues.cwise().sqrt().asDiagonal() * m_eivec.adjoint();
+ }
+
+ /** \returns the positive inverse square root of the matrix
+ *
+ * \note the matrix itself must be positive definite in order for this to make sense.
+ */
+ MatrixType operatorInverseSqrt() const
+ {
+ return m_eivec * m_eivalues.cwise().inverse().cwise().sqrt().asDiagonal() * m_eivec.adjoint();
+ }
+
+
+ protected:
+ MatrixType m_eivec;
+ RealVectorType m_eivalues;
+ #ifndef NDEBUG
+ bool m_eigenvectorsOk;
+ #endif
+};
+
+#ifndef EIGEN_HIDE_HEAVY_CODE
+
+// from Golub's "Matrix Computations", algorithm 5.1.3
+template<typename Scalar>
+static void ei_givens_rotation(Scalar a, Scalar b, Scalar& c, Scalar& s)
+{
+ if (b==0)
+ {
+ c = 1; s = 0;
+ }
+ else if (ei_abs(b)>ei_abs(a))
+ {
+ Scalar t = -a/b;
+ s = Scalar(1)/ei_sqrt(1+t*t);
+ c = s * t;
+ }
+ else
+ {
+ Scalar t = -b/a;
+ c = Scalar(1)/ei_sqrt(1+t*t);
+ s = c * t;
+ }
+}
+
+/** \internal
+ *
+ * \qr_module
+ *
+ * Performs a QR step on a tridiagonal symmetric matrix represented as a
+ * pair of two vectors \a diag and \a subdiag.
+ *
+ * \param matA the input selfadjoint matrix
+ * \param hCoeffs returned Householder coefficients
+ *
+ * For compilation efficiency reasons, this procedure does not use eigen expression
+ * for its arguments.
+ *
+ * Implemented from Golub's "Matrix Computations", algorithm 8.3.2:
+ * "implicit symmetric QR step with Wilkinson shift"
+ */
+template<typename RealScalar, typename Scalar>
+static void ei_tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, int start, int end, Scalar* matrixQ, int n);
+
+/** Computes the eigenvalues of the selfadjoint matrix \a matrix,
+ * as well as the eigenvectors if \a computeEigenvectors is true.
+ *
+ * \sa SelfAdjointEigenSolver(MatrixType,bool), compute(MatrixType,MatrixType,bool)
+ */
+template<typename MatrixType>
+void SelfAdjointEigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvectors)
+{
+ #ifndef NDEBUG
+ m_eigenvectorsOk = computeEigenvectors;
+ #endif
+ assert(matrix.cols() == matrix.rows());
+ int n = matrix.cols();
+ m_eivalues.resize(n,1);
+
+ if(n==1)
+ {
+ m_eivalues.coeffRef(0,0) = ei_real(matrix.coeff(0,0));
+ m_eivec.setOnes();
+ return;
+ }
+
+ m_eivec = matrix;
+
+ // FIXME, should tridiag be a local variable of this function or an attribute of SelfAdjointEigenSolver ?
+ // the latter avoids multiple memory allocation when the same SelfAdjointEigenSolver is used multiple times...
+ // (same for diag and subdiag)
+ RealVectorType& diag = m_eivalues;
+ typename TridiagonalizationType::SubDiagonalType subdiag(n-1);
+ TridiagonalizationType::decomposeInPlace(m_eivec, diag, subdiag, computeEigenvectors);
+
+ int end = n-1;
+ int start = 0;
+ while (end>0)
+ {
+ for (int i = start; i<end; ++i)
+ if (ei_isMuchSmallerThan(ei_abs(subdiag[i]),(ei_abs(diag[i])+ei_abs(diag[i+1]))))
+ subdiag[i] = 0;
+
+ // find the largest unreduced block
+ while (end>0 && subdiag[end-1]==0)
+ end--;
+ if (end<=0)
+ break;
+ start = end - 1;
+ while (start>0 && subdiag[start-1]!=0)
+ start--;
+
+ ei_tridiagonal_qr_step(diag.data(), subdiag.data(), start, end, computeEigenvectors ? m_eivec.data() : (Scalar*)0, n);
+ }
+
+ // Sort eigenvalues and corresponding vectors.
+ // TODO make the sort optional ?
+ // TODO use a better sort algorithm !!
+ for (int i = 0; i < n-1; ++i)
+ {
+ int k;
+ m_eivalues.segment(i,n-i).minCoeff(&k);
+ if (k > 0)
+ {
+ std::swap(m_eivalues[i], m_eivalues[k+i]);
+ m_eivec.col(i).swap(m_eivec.col(k+i));
+ }
+ }
+}
+
+/** Computes the eigenvalues of the generalized eigen problem
+ * \f$ Ax = lambda B x \f$ with \a matA the selfadjoint matrix \f$ A \f$
+ * and \a matB the positive definite matrix \f$ B \f$ . The eigenvectors
+ * are computed if \a computeEigenvectors is true.
+ *
+ * \sa SelfAdjointEigenSolver(MatrixType,MatrixType,bool), compute(MatrixType,bool)
+ */
+template<typename MatrixType>
+void SelfAdjointEigenSolver<MatrixType>::
+compute(const MatrixType& matA, const MatrixType& matB, bool computeEigenvectors)
+{
+ ei_assert(matA.cols()==matA.rows() && matB.rows()==matA.rows() && matB.cols()==matB.rows());
+
+ // Compute the cholesky decomposition of matB = L L'
+ LLT<MatrixType> cholB(matB);
+
+ // compute C = inv(L) A inv(L')
+ MatrixType matC = matA;
+ cholB.matrixL().solveTriangularInPlace(matC);
+ // FIXME since we currently do not support A * inv(L'), let's do (inv(L) A')' :
+ matC = matC.adjoint().eval();
+ cholB.matrixL().template marked<LowerTriangular>().solveTriangularInPlace(matC);
+ matC = matC.adjoint().eval();
+ // this version works too:
+// matC = matC.transpose();
+// cholB.matrixL().conjugate().template marked<LowerTriangular>().solveTriangularInPlace(matC);
+// matC = matC.transpose();
+ // FIXME: this should work: (currently it only does for small matrices)
+// Transpose<MatrixType> trMatC(matC);
+// cholB.matrixL().conjugate().eval().template marked<LowerTriangular>().solveTriangularInPlace(trMatC);
+
+ compute(matC, computeEigenvectors);
+
+ if (computeEigenvectors)
+ {
+ // transform back the eigen vectors: evecs = inv(U) * evecs
+ cholB.matrixL().adjoint().template marked<UpperTriangular>().solveTriangularInPlace(m_eivec);
+ for (int i=0; i<m_eivec.cols(); ++i)
+ m_eivec.col(i) = m_eivec.col(i).normalized();
+ }
+}
+
+#endif // EIGEN_HIDE_HEAVY_CODE
+
+/** \qr_module
+ *
+ * \returns a vector listing the eigenvalues of this matrix.
+ */
+template<typename Derived>
+inline Matrix<typename NumTraits<typename ei_traits<Derived>::Scalar>::Real, ei_traits<Derived>::ColsAtCompileTime, 1>
+MatrixBase<Derived>::eigenvalues() const
+{
+ ei_assert(Flags&SelfAdjointBit);
+ return SelfAdjointEigenSolver<typename Derived::PlainMatrixType>(eval(),false).eigenvalues();
+}
+
+template<typename Derived, bool IsSelfAdjoint>
+struct ei_operatorNorm_selector
+{
+ static inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real
+ operatorNorm(const MatrixBase<Derived>& m)
+ {
+ // FIXME if it is really guaranteed that the eigenvalues are already sorted,
+ // then we don't need to compute a maxCoeff() here, comparing the 1st and last ones is enough.
+ return m.eigenvalues().cwise().abs().maxCoeff();
+ }
+};
+
+template<typename Derived> struct ei_operatorNorm_selector<Derived, false>
+{
+ static inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real
+ operatorNorm(const MatrixBase<Derived>& m)
+ {
+ typename Derived::PlainMatrixType m_eval(m);
+ // FIXME if it is really guaranteed that the eigenvalues are already sorted,
+ // then we don't need to compute a maxCoeff() here, comparing the 1st and last ones is enough.
+ return ei_sqrt(
+ (m_eval*m_eval.adjoint())
+ .template marked<SelfAdjoint>()
+ .eigenvalues()
+ .maxCoeff()
+ );
+ }
+};
+
+/** \qr_module
+ *
+ * \returns the matrix norm of this matrix.
+ */
+template<typename Derived>
+inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real
+MatrixBase<Derived>::operatorNorm() const
+{
+ return ei_operatorNorm_selector<Derived, Flags&SelfAdjointBit>
+ ::operatorNorm(derived());
+}
+
+#ifndef EIGEN_EXTERN_INSTANTIATIONS
+template<typename RealScalar, typename Scalar>
+static void ei_tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, int start, int end, Scalar* matrixQ, int n)
+{
+ RealScalar td = (diag[end-1] - diag[end])*RealScalar(0.5);
+ RealScalar e2 = ei_abs2(subdiag[end-1]);
+ RealScalar mu = diag[end] - e2 / (td + (td>0 ? 1 : -1) * ei_sqrt(td*td + e2));
+ RealScalar x = diag[start] - mu;
+ RealScalar z = subdiag[start];
+
+ for (int k = start; k < end; ++k)
+ {
+ RealScalar c, s;
+ ei_givens_rotation(x, z, c, s);
+
+ // do T = G' T G
+ RealScalar sdk = s * diag[k] + c * subdiag[k];
+ RealScalar dkp1 = s * subdiag[k] + c * diag[k+1];
+
+ diag[k] = c * (c * diag[k] - s * subdiag[k]) - s * (c * subdiag[k] - s * diag[k+1]);
+ diag[k+1] = s * sdk + c * dkp1;
+ subdiag[k] = c * sdk - s * dkp1;
+
+ if (k > start)
+ subdiag[k - 1] = c * subdiag[k-1] - s * z;
+
+ x = subdiag[k];
+
+ if (k < end - 1)
+ {
+ z = -s * subdiag[k+1];
+ subdiag[k + 1] = c * subdiag[k+1];
+ }
+
+ // apply the givens rotation to the unit matrix Q = Q * G
+ // G only modifies the two columns k and k+1
+ if (matrixQ)
+ {
+ #ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
+ #else
+ int kn = k*n;
+ int kn1 = (k+1)*n;
+ #endif
+ // let's do the product manually to avoid the need of temporaries...
+ for (int i=0; i<n; ++i)
+ {
+ #ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
+ Scalar matrixQ_i_k = matrixQ[i*n+k];
+ matrixQ[i*n+k] = c * matrixQ_i_k - s * matrixQ[i*n+k+1];
+ matrixQ[i*n+k+1] = s * matrixQ_i_k + c * matrixQ[i*n+k+1];
+ #else
+ Scalar matrixQ_i_k = matrixQ[i+kn];
+ matrixQ[i+kn] = c * matrixQ_i_k - s * matrixQ[i+kn1];
+ matrixQ[i+kn1] = s * matrixQ_i_k + c * matrixQ[i+kn1];
+ #endif
+ }
+ }
+ }
+}
+#endif
+
+#endif // EIGEN_SELFADJOINTEIGENSOLVER_H
diff --git a/extern/Eigen2/Eigen/src/QR/Tridiagonalization.h b/extern/Eigen2/Eigen/src/QR/Tridiagonalization.h
new file mode 100644
index 00000000000..9ea39be717c
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/QR/Tridiagonalization.h
@@ -0,0 +1,431 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_TRIDIAGONALIZATION_H
+#define EIGEN_TRIDIAGONALIZATION_H
+
+/** \ingroup QR_Module
+ * \nonstableyet
+ *
+ * \class Tridiagonalization
+ *
+ * \brief Trigiagonal decomposition of a selfadjoint matrix
+ *
+ * \param MatrixType the type of the matrix of which we are performing the tridiagonalization
+ *
+ * This class performs a tridiagonal decomposition of a selfadjoint matrix \f$ A \f$ such that:
+ * \f$ A = Q T Q^* \f$ where \f$ Q \f$ is unitary and \f$ T \f$ a real symmetric tridiagonal matrix.
+ *
+ * \sa MatrixBase::tridiagonalize()
+ */
+template<typename _MatrixType> class Tridiagonalization
+{
+ public:
+
+ typedef _MatrixType MatrixType;
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<Scalar>::Real RealScalar;
+ typedef typename ei_packet_traits<Scalar>::type Packet;
+
+ enum {
+ Size = MatrixType::RowsAtCompileTime,
+ SizeMinusOne = MatrixType::RowsAtCompileTime==Dynamic
+ ? Dynamic
+ : MatrixType::RowsAtCompileTime-1,
+ PacketSize = ei_packet_traits<Scalar>::size
+ };
+
+ typedef Matrix<Scalar, SizeMinusOne, 1> CoeffVectorType;
+ typedef Matrix<RealScalar, Size, 1> DiagonalType;
+ typedef Matrix<RealScalar, SizeMinusOne, 1> SubDiagonalType;
+
+ typedef typename NestByValue<DiagonalCoeffs<MatrixType> >::RealReturnType DiagonalReturnType;
+
+ typedef typename NestByValue<DiagonalCoeffs<
+ NestByValue<Block<MatrixType,SizeMinusOne,SizeMinusOne> > > >::RealReturnType SubDiagonalReturnType;
+
+ /** This constructor initializes a Tridiagonalization object for
+ * further use with Tridiagonalization::compute()
+ */
+ Tridiagonalization(int size = Size==Dynamic ? 2 : Size)
+ : m_matrix(size,size), m_hCoeffs(size-1)
+ {}
+
+ Tridiagonalization(const MatrixType& matrix)
+ : m_matrix(matrix),
+ m_hCoeffs(matrix.cols()-1)
+ {
+ _compute(m_matrix, m_hCoeffs);
+ }
+
+ /** Computes or re-compute the tridiagonalization for the matrix \a matrix.
+ *
+ * This method allows to re-use the allocated data.
+ */
+ void compute(const MatrixType& matrix)
+ {
+ m_matrix = matrix;
+ m_hCoeffs.resize(matrix.rows()-1, 1);
+ _compute(m_matrix, m_hCoeffs);
+ }
+
+ /** \returns the householder coefficients allowing to
+ * reconstruct the matrix Q from the packed data.
+ *
+ * \sa packedMatrix()
+ */
+ inline CoeffVectorType householderCoefficients(void) const { return m_hCoeffs; }
+
+ /** \returns the internal result of the decomposition.
+ *
+ * The returned matrix contains the following information:
+ * - the strict upper part is equal to the input matrix A
+ * - the diagonal and lower sub-diagonal represent the tridiagonal symmetric matrix (real).
+ * - the rest of the lower part contains the Householder vectors that, combined with
+ * Householder coefficients returned by householderCoefficients(),
+ * allows to reconstruct the matrix Q as follow:
+ * Q = H_{N-1} ... H_1 H_0
+ * where the matrices H are the Householder transformations:
+ * H_i = (I - h_i * v_i * v_i')
+ * where h_i == householderCoefficients()[i] and v_i is a Householder vector:
+ * v_i = [ 0, ..., 0, 1, M(i+2,i), ..., M(N-1,i) ]
+ *
+ * See LAPACK for further details on this packed storage.
+ */
+ inline const MatrixType& packedMatrix(void) const { return m_matrix; }
+
+ MatrixType matrixQ(void) const;
+ MatrixType matrixT(void) const;
+ const DiagonalReturnType diagonal(void) const;
+ const SubDiagonalReturnType subDiagonal(void) const;
+
+ static void decomposeInPlace(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, bool extractQ = true);
+
+ private:
+
+ static void _compute(MatrixType& matA, CoeffVectorType& hCoeffs);
+
+ static void _decomposeInPlace3x3(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, bool extractQ = true);
+
+ protected:
+ MatrixType m_matrix;
+ CoeffVectorType m_hCoeffs;
+};
+
+/** \returns an expression of the diagonal vector */
+template<typename MatrixType>
+const typename Tridiagonalization<MatrixType>::DiagonalReturnType
+Tridiagonalization<MatrixType>::diagonal(void) const
+{
+ return m_matrix.diagonal().nestByValue().real();
+}
+
+/** \returns an expression of the sub-diagonal vector */
+template<typename MatrixType>
+const typename Tridiagonalization<MatrixType>::SubDiagonalReturnType
+Tridiagonalization<MatrixType>::subDiagonal(void) const
+{
+ int n = m_matrix.rows();
+ return Block<MatrixType,SizeMinusOne,SizeMinusOne>(m_matrix, 1, 0, n-1,n-1)
+ .nestByValue().diagonal().nestByValue().real();
+}
+
+/** constructs and returns the tridiagonal matrix T.
+ * Note that the matrix T is equivalent to the diagonal and sub-diagonal of the packed matrix.
+ * Therefore, it might be often sufficient to directly use the packed matrix, or the vector
+ * expressions returned by diagonal() and subDiagonal() instead of creating a new matrix.
+ */
+template<typename MatrixType>
+typename Tridiagonalization<MatrixType>::MatrixType
+Tridiagonalization<MatrixType>::matrixT(void) const
+{
+ // FIXME should this function (and other similar ones) rather take a matrix as argument
+ // and fill it ? (to avoid temporaries)
+ int n = m_matrix.rows();
+ MatrixType matT = m_matrix;
+ matT.corner(TopRight,n-1, n-1).diagonal() = subDiagonal().template cast<Scalar>().conjugate();
+ if (n>2)
+ {
+ matT.corner(TopRight,n-2, n-2).template part<UpperTriangular>().setZero();
+ matT.corner(BottomLeft,n-2, n-2).template part<LowerTriangular>().setZero();
+ }
+ return matT;
+}
+
+#ifndef EIGEN_HIDE_HEAVY_CODE
+
+/** \internal
+ * Performs a tridiagonal decomposition of \a matA in place.
+ *
+ * \param matA the input selfadjoint matrix
+ * \param hCoeffs returned Householder coefficients
+ *
+ * The result is written in the lower triangular part of \a matA.
+ *
+ * Implemented from Golub's "Matrix Computations", algorithm 8.3.1.
+ *
+ * \sa packedMatrix()
+ */
+template<typename MatrixType>
+void Tridiagonalization<MatrixType>::_compute(MatrixType& matA, CoeffVectorType& hCoeffs)
+{
+ assert(matA.rows()==matA.cols());
+ int n = matA.rows();
+// std::cerr << matA << "\n\n";
+ for (int i = 0; i<n-2; ++i)
+ {
+ // let's consider the vector v = i-th column starting at position i+1
+
+ // start of the householder transformation
+ // squared norm of the vector v skipping the first element
+ RealScalar v1norm2 = matA.col(i).end(n-(i+2)).squaredNorm();
+
+ // FIXME comparing against 1
+ if (ei_isMuchSmallerThan(v1norm2,static_cast<Scalar>(1)))
+ {
+ hCoeffs.coeffRef(i) = 0.;
+ }
+ else
+ {
+ Scalar v0 = matA.col(i).coeff(i+1);
+ RealScalar beta = ei_sqrt(ei_abs2(v0)+v1norm2);
+ if (ei_real(v0)>=0.)
+ beta = -beta;
+ matA.col(i).end(n-(i+2)) *= (Scalar(1)/(v0-beta));
+ matA.col(i).coeffRef(i+1) = beta;
+ Scalar h = (beta - v0) / beta;
+ // end of the householder transformation
+
+ // Apply similarity transformation to remaining columns,
+ // i.e., A = H' A H where H = I - h v v' and v = matA.col(i).end(n-i-1)
+
+ matA.col(i).coeffRef(i+1) = 1;
+
+ /* This is the initial algorithm which minimize operation counts and maximize
+ * the use of Eigen's expression. Unfortunately, the first matrix-vector product
+ * using Part<LowerTriangular|Selfadjoint> is very very slow */
+ #ifdef EIGEN_NEVER_DEFINED
+ // matrix - vector product
+ hCoeffs.end(n-i-1) = (matA.corner(BottomRight,n-i-1,n-i-1).template part<LowerTriangular|SelfAdjoint>()
+ * (h * matA.col(i).end(n-i-1))).lazy();
+ // simple axpy
+ hCoeffs.end(n-i-1) += (h * Scalar(-0.5) * matA.col(i).end(n-i-1).dot(hCoeffs.end(n-i-1)))
+ * matA.col(i).end(n-i-1);
+ // rank-2 update
+ //Block<MatrixType,Dynamic,1> B(matA,i+1,i,n-i-1,1);
+ matA.corner(BottomRight,n-i-1,n-i-1).template part<LowerTriangular>() -=
+ (matA.col(i).end(n-i-1) * hCoeffs.end(n-i-1).adjoint()).lazy()
+ + (hCoeffs.end(n-i-1) * matA.col(i).end(n-i-1).adjoint()).lazy();
+ #endif
+ /* end initial algorithm */
+
+ /* If we still want to minimize operation count (i.e., perform operation on the lower part only)
+ * then we could provide the following algorithm for selfadjoint - vector product. However, a full
+ * matrix-vector product is still faster (at least for dynamic size, and not too small, did not check
+ * small matrices). The algo performs block matrix-vector and transposed matrix vector products. */
+ #ifdef EIGEN_NEVER_DEFINED
+ int n4 = (std::max(0,n-4)/4)*4;
+ hCoeffs.end(n-i-1).setZero();
+ for (int b=i+1; b<n4; b+=4)
+ {
+ // the ?x4 part:
+ hCoeffs.end(b-4) +=
+ Block<MatrixType,Dynamic,4>(matA,b+4,b,n-b-4,4) * matA.template block<4,1>(b,i);
+ // the respective transposed part:
+ Block<CoeffVectorType,4,1>(hCoeffs, b, 0, 4,1) +=
+ Block<MatrixType,Dynamic,4>(matA,b+4,b,n-b-4,4).adjoint() * Block<MatrixType,Dynamic,1>(matA,b+4,i,n-b-4,1);
+ // the 4x4 block diagonal:
+ Block<CoeffVectorType,4,1>(hCoeffs, b, 0, 4,1) +=
+ (Block<MatrixType,4,4>(matA,b,b,4,4).template part<LowerTriangular|SelfAdjoint>()
+ * (h * Block<MatrixType,4,1>(matA,b,i,4,1))).lazy();
+ }
+ #endif
+ // todo: handle the remaining part
+ /* end optimized selfadjoint - vector product */
+
+ /* Another interesting note: the above rank-2 update is much slower than the following hand written loop.
+ * After an analyze of the ASM, it seems GCC (4.2) generate poor code because of the Block. Moreover,
+ * if we remove the specialization of Block for Matrix then it is even worse, much worse ! */
+ #ifdef EIGEN_NEVER_DEFINED
+ for (int j1=i+1; j1<n; ++j1)
+ for (int i1=j1; i1<n; ++i1)
+ matA.coeffRef(i1,j1) -= matA.coeff(i1,i)*ei_conj(hCoeffs.coeff(j1-1))
+ + hCoeffs.coeff(i1-1)*ei_conj(matA.coeff(j1,i));
+ #endif
+ /* end hand writen partial rank-2 update */
+
+ /* The current fastest implementation: the full matrix is used, no "optimization" to use/compute
+ * only half of the matrix. Custom vectorization of the inner col -= alpha X + beta Y such that access
+ * to col are always aligned. Once we support that in Assign, then the algorithm could be rewriten as
+ * a single compact expression. This code is therefore a good benchmark when will do that. */
+
+ // let's use the end of hCoeffs to store temporary values:
+ hCoeffs.end(n-i-1) = (matA.corner(BottomRight,n-i-1,n-i-1) * (h * matA.col(i).end(n-i-1))).lazy();
+ // FIXME in the above expr a temporary is created because of the scalar multiple by h
+
+ hCoeffs.end(n-i-1) += (h * Scalar(-0.5) * matA.col(i).end(n-i-1).dot(hCoeffs.end(n-i-1)))
+ * matA.col(i).end(n-i-1);
+
+ const Scalar* EIGEN_RESTRICT pb = &matA.coeffRef(0,i);
+ const Scalar* EIGEN_RESTRICT pa = (&hCoeffs.coeffRef(0)) - 1;
+ for (int j1=i+1; j1<n; ++j1)
+ {
+ int starti = i+1;
+ int alignedEnd = starti;
+ if (PacketSize>1)
+ {
+ int alignedStart = (starti) + ei_alignmentOffset(&matA.coeffRef(starti,j1), n-starti);
+ alignedEnd = alignedStart + ((n-alignedStart)/PacketSize)*PacketSize;
+
+ for (int i1=starti; i1<alignedStart; ++i1)
+ matA.coeffRef(i1,j1) -= matA.coeff(i1,i)*ei_conj(hCoeffs.coeff(j1-1))
+ + hCoeffs.coeff(i1-1)*ei_conj(matA.coeff(j1,i));
+
+ Packet tmp0 = ei_pset1(hCoeffs.coeff(j1-1));
+ Packet tmp1 = ei_pset1(matA.coeff(j1,i));
+ Scalar* pc = &matA.coeffRef(0,j1);
+ for (int i1=alignedStart ; i1<alignedEnd; i1+=PacketSize)
+ ei_pstore(pc+i1,ei_psub(ei_pload(pc+i1),
+ ei_padd(ei_pmul(tmp0, ei_ploadu(pb+i1)),
+ ei_pmul(tmp1, ei_ploadu(pa+i1)))));
+ }
+ for (int i1=alignedEnd; i1<n; ++i1)
+ matA.coeffRef(i1,j1) -= matA.coeff(i1,i)*ei_conj(hCoeffs.coeff(j1-1))
+ + hCoeffs.coeff(i1-1)*ei_conj(matA.coeff(j1,i));
+ }
+ /* end optimized implementation */
+
+ // note: at that point matA(i+1,i+1) is the (i+1)-th element of the final diagonal
+ // note: the sequence of the beta values leads to the subdiagonal entries
+ matA.col(i).coeffRef(i+1) = beta;
+
+ hCoeffs.coeffRef(i) = h;
+ }
+ }
+ if (NumTraits<Scalar>::IsComplex)
+ {
+ // Householder transformation on the remaining single scalar
+ int i = n-2;
+ Scalar v0 = matA.col(i).coeff(i+1);
+ RealScalar beta = ei_abs(v0);
+ if (ei_real(v0)>=0.)
+ beta = -beta;
+ matA.col(i).coeffRef(i+1) = beta;
+ if(ei_isMuchSmallerThan(beta, Scalar(1))) hCoeffs.coeffRef(i) = Scalar(0);
+ else hCoeffs.coeffRef(i) = (beta - v0) / beta;
+ }
+ else
+ {
+ hCoeffs.coeffRef(n-2) = 0;
+ }
+}
+
+/** reconstructs and returns the matrix Q */
+template<typename MatrixType>
+typename Tridiagonalization<MatrixType>::MatrixType
+Tridiagonalization<MatrixType>::matrixQ(void) const
+{
+ int n = m_matrix.rows();
+ MatrixType matQ = MatrixType::Identity(n,n);
+ for (int i = n-2; i>=0; i--)
+ {
+ Scalar tmp = m_matrix.coeff(i+1,i);
+ m_matrix.const_cast_derived().coeffRef(i+1,i) = 1;
+
+ matQ.corner(BottomRight,n-i-1,n-i-1) -=
+ ((m_hCoeffs.coeff(i) * m_matrix.col(i).end(n-i-1)) *
+ (m_matrix.col(i).end(n-i-1).adjoint() * matQ.corner(BottomRight,n-i-1,n-i-1)).lazy()).lazy();
+
+ m_matrix.const_cast_derived().coeffRef(i+1,i) = tmp;
+ }
+ return matQ;
+}
+
+/** Performs a full decomposition in place */
+template<typename MatrixType>
+void Tridiagonalization<MatrixType>::decomposeInPlace(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, bool extractQ)
+{
+ int n = mat.rows();
+ ei_assert(mat.cols()==n && diag.size()==n && subdiag.size()==n-1);
+ if (n==3 && (!NumTraits<Scalar>::IsComplex) )
+ {
+ _decomposeInPlace3x3(mat, diag, subdiag, extractQ);
+ }
+ else
+ {
+ Tridiagonalization tridiag(mat);
+ diag = tridiag.diagonal();
+ subdiag = tridiag.subDiagonal();
+ if (extractQ)
+ mat = tridiag.matrixQ();
+ }
+}
+
+/** \internal
+ * Optimized path for 3x3 matrices.
+ * Especially useful for plane fitting.
+ */
+template<typename MatrixType>
+void Tridiagonalization<MatrixType>::_decomposeInPlace3x3(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, bool extractQ)
+{
+ diag[0] = ei_real(mat(0,0));
+ RealScalar v1norm2 = ei_abs2(mat(0,2));
+ if (ei_isMuchSmallerThan(v1norm2, RealScalar(1)))
+ {
+ diag[1] = ei_real(mat(1,1));
+ diag[2] = ei_real(mat(2,2));
+ subdiag[0] = ei_real(mat(0,1));
+ subdiag[1] = ei_real(mat(1,2));
+ if (extractQ)
+ mat.setIdentity();
+ }
+ else
+ {
+ RealScalar beta = ei_sqrt(ei_abs2(mat(0,1))+v1norm2);
+ RealScalar invBeta = RealScalar(1)/beta;
+ Scalar m01 = mat(0,1) * invBeta;
+ Scalar m02 = mat(0,2) * invBeta;
+ Scalar q = RealScalar(2)*m01*mat(1,2) + m02*(mat(2,2) - mat(1,1));
+ diag[1] = ei_real(mat(1,1) + m02*q);
+ diag[2] = ei_real(mat(2,2) - m02*q);
+ subdiag[0] = beta;
+ subdiag[1] = ei_real(mat(1,2) - m01 * q);
+ if (extractQ)
+ {
+ mat(0,0) = 1;
+ mat(0,1) = 0;
+ mat(0,2) = 0;
+ mat(1,0) = 0;
+ mat(1,1) = m01;
+ mat(1,2) = m02;
+ mat(2,0) = 0;
+ mat(2,1) = m02;
+ mat(2,2) = -m01;
+ }
+ }
+}
+
+#endif // EIGEN_HIDE_HEAVY_CODE
+
+#endif // EIGEN_TRIDIAGONALIZATION_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/SVD.h b/extern/Eigen2/Eigen/src/SVD/SVD.h
index 16b4b488f0c..d117c158397 100644
--- a/extern/Eigen3/Eigen/src/Eigen2Support/SVD.h
+++ b/extern/Eigen2/Eigen/src/SVD/SVD.h
@@ -22,8 +22,8 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-#ifndef EIGEN2_SVD_H
-#define EIGEN2_SVD_H
+#ifndef EIGEN_SVD_H
+#define EIGEN_SVD_H
/** \ingroup SVD_Module
* \nonstableyet
@@ -47,9 +47,9 @@ template<typename MatrixType> class SVD
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
enum {
- PacketSize = internal::packet_traits<Scalar>::size,
+ PacketSize = ei_packet_traits<Scalar>::size,
AlignmentMask = int(PacketSize)-1,
- MinSize = EIGEN_SIZE_MIN_PREFER_DYNAMIC(MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime)
+ MinSize = EIGEN_ENUM_MIN(MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime)
};
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVector;
@@ -61,12 +61,10 @@ template<typename MatrixType> class SVD
public:
- SVD() {} // a user who relied on compiler-generated default compiler reported problems with MSVC in 2.0.7
-
SVD(const MatrixType& matrix)
- : m_matU(matrix.rows(), (std::min)(matrix.rows(), matrix.cols())),
+ : m_matU(matrix.rows(), std::min(matrix.rows(), matrix.cols())),
m_matV(matrix.cols(),matrix.cols()),
- m_sigma((std::min)(matrix.rows(),matrix.cols()))
+ m_sigma(std::min(matrix.rows(),matrix.cols()))
{
compute(matrix);
}
@@ -108,13 +106,12 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
{
const int m = matrix.rows();
const int n = matrix.cols();
- const int nu = (std::min)(m,n);
+ const int nu = std::min(m,n);
ei_assert(m>=n && "In Eigen 2.0, SVD only works for MxN matrices with M>=N. Sorry!");
- ei_assert(m>1 && "In Eigen 2.0, SVD doesn't work on 1x1 matrices");
m_matU.resize(m, nu);
m_matU.setZero();
- m_sigma.resize((std::min)(m,n));
+ m_sigma.resize(std::min(m,n));
m_matV.resize(n,n);
RowVector e(n);
@@ -126,9 +123,9 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
// Reduce A to bidiagonal form, storing the diagonal elements
// in s and the super-diagonal elements in e.
- int nct = (std::min)(m-1,n);
- int nrt = (std::max)(0,(std::min)(n-2,m));
- for (k = 0; k < (std::max)(nct,nrt); ++k)
+ int nct = std::min(m-1,n);
+ int nrt = std::max(0,std::min(n-2,m));
+ for (k = 0; k < std::max(nct,nrt); ++k)
{
if (k < nct)
{
@@ -150,7 +147,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
if ((k < nct) && (m_sigma[k] != 0.0))
{
// Apply the transformation.
- Scalar t = matA.col(k).end(m-k).eigen2_dot(matA.col(j).end(m-k)); // FIXME dot product or cwise prod + .sum() ??
+ Scalar t = matA.col(k).end(m-k).dot(matA.col(j).end(m-k)); // FIXME dot product or cwise prod + .sum() ??
t = -t/matA(k,k);
matA.col(j).end(m-k) += t * matA.col(k).end(m-k);
}
@@ -193,7 +190,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
// Set up the final bidiagonal matrix or order p.
- int p = (std::min)(n,m+1);
+ int p = std::min(n,m+1);
if (nct < n)
m_sigma[nct] = matA(nct,nct);
if (m < p)
@@ -216,7 +213,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
{
for (j = k+1; j < nu; ++j)
{
- Scalar t = m_matU.col(k).end(m-k).eigen2_dot(m_matU.col(j).end(m-k)); // FIXME is it really a dot product we want ?
+ Scalar t = m_matU.col(k).end(m-k).dot(m_matU.col(j).end(m-k)); // FIXME is it really a dot product we want ?
t = -t/m_matU(k,k);
m_matU.col(j).end(m-k) += t * m_matU.col(k).end(m-k);
}
@@ -242,7 +239,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
{
for (j = k+1; j < nu; ++j)
{
- Scalar t = m_matV.col(k).end(n-k-1).eigen2_dot(m_matV.col(j).end(n-k-1)); // FIXME is it really a dot product we want ?
+ Scalar t = m_matV.col(k).end(n-k-1).dot(m_matV.col(j).end(n-k-1)); // FIXME is it really a dot product we want ?
t = -t/m_matV(k+1,k);
m_matV.col(j).end(n-k-1) += t * m_matV.col(k).end(n-k-1);
}
@@ -328,7 +325,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
e[p-2] = 0.0;
for (j = p-2; j >= k; --j)
{
- Scalar t(internal::hypot(m_sigma[j],f));
+ Scalar t(ei_hypot(m_sigma[j],f));
Scalar cs(m_sigma[j]/t);
Scalar sn(f/t);
m_sigma[j] = t;
@@ -357,7 +354,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
e[k-1] = 0.0;
for (j = k; j < p; ++j)
{
- Scalar t(internal::hypot(m_sigma[j],f));
+ Scalar t(ei_hypot(m_sigma[j],f));
Scalar cs( m_sigma[j]/t);
Scalar sn(f/t);
m_sigma[j] = t;
@@ -380,7 +377,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
case 3:
{
// Calculate the shift.
- Scalar scale = (std::max)((std::max)((std::max)((std::max)(
+ Scalar scale = std::max(std::max(std::max(std::max(
ei_abs(m_sigma[p-1]),ei_abs(m_sigma[p-2])),ei_abs(e[p-2])),
ei_abs(m_sigma[k])),ei_abs(e[k]));
Scalar sp = m_sigma[p-1]/scale;
@@ -405,7 +402,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
for (j = k; j < p-1; ++j)
{
- Scalar t = internal::hypot(f,g);
+ Scalar t = ei_hypot(f,g);
Scalar cs = f/t;
Scalar sn = g/t;
if (j != k)
@@ -423,7 +420,7 @@ void SVD<MatrixType>::compute(const MatrixType& matrix)
m_matV(i,j) = t;
}
}
- t = internal::hypot(f,g);
+ t = ei_hypot(f,g);
cs = f/t;
sn = g/t;
m_sigma[j] = t;
@@ -640,10 +637,10 @@ void SVD<MatrixType>::computeScalingRotation(ScalingType *scaling, RotationType
* \returns the SVD decomposition of \c *this
*/
template<typename Derived>
-inline SVD<typename MatrixBase<Derived>::PlainObject>
+inline SVD<typename MatrixBase<Derived>::PlainMatrixType>
MatrixBase<Derived>::svd() const
{
- return SVD<PlainObject>(derived());
+ return SVD<PlainMatrixType>(derived());
}
-#endif // EIGEN2_SVD_H
+#endif // EIGEN_SVD_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/AmbiVector.h b/extern/Eigen2/Eigen/src/Sparse/AmbiVector.h
index 2ea8ba3096b..f279e80f00a 100644
--- a/extern/Eigen3/Eigen/src/Sparse/AmbiVector.h
+++ b/extern/Eigen2/Eigen/src/Sparse/AmbiVector.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -30,57 +30,54 @@
*
* See BasicSparseLLT and SparseProduct for usage examples.
*/
-template<typename _Scalar, typename _Index>
-class AmbiVector
+template<typename _Scalar> class AmbiVector
{
public:
typedef _Scalar Scalar;
- typedef _Index Index;
typedef typename NumTraits<Scalar>::Real RealScalar;
-
- AmbiVector(Index size)
- : m_buffer(0), m_zero(0), m_size(0), m_allocatedSize(0), m_allocatedElements(0), m_mode(-1)
+ AmbiVector(int size)
+ : m_buffer(0), m_size(0), m_allocatedSize(0), m_allocatedElements(0), m_mode(-1)
{
resize(size);
}
- void init(double estimatedDensity);
+ void init(RealScalar estimatedDensity);
void init(int mode);
- Index nonZeros() const;
+ void nonZeros() const;
/** Specifies a sub-vector to work on */
- void setBounds(Index start, Index end) { m_start = start; m_end = end; }
+ void setBounds(int start, int end) { m_start = start; m_end = end; }
void setZero();
void restart();
- Scalar& coeffRef(Index i);
- Scalar& coeff(Index i);
+ Scalar& coeffRef(int i);
+ Scalar coeff(int i);
class Iterator;
~AmbiVector() { delete[] m_buffer; }
- void resize(Index size)
+ void resize(int size)
{
if (m_allocatedSize < size)
reallocate(size);
m_size = size;
}
- Index size() const { return m_size; }
+ int size() const { return m_size; }
protected:
- void reallocate(Index size)
+ void reallocate(int size)
{
// if the size of the matrix is not too large, let's allocate a bit more than needed such
// that we can handle dense vector even in sparse mode.
delete[] m_buffer;
if (size<1000)
{
- Index allocSize = (size * sizeof(ListEl))/sizeof(Scalar);
+ int allocSize = (size * sizeof(ListEl))/sizeof(Scalar);
m_allocatedElements = (allocSize*sizeof(Scalar))/sizeof(ListEl);
m_buffer = new Scalar[allocSize];
}
@@ -96,9 +93,9 @@ class AmbiVector
void reallocateSparse()
{
- Index copyElements = m_allocatedElements;
- m_allocatedElements = (std::min)(Index(m_allocatedElements*1.5),m_size);
- Index allocSize = m_allocatedElements * sizeof(ListEl);
+ int copyElements = m_allocatedElements;
+ m_allocatedElements = std::min(int(m_allocatedElements*1.5),m_size);
+ int allocSize = m_allocatedElements * sizeof(ListEl);
allocSize = allocSize/sizeof(Scalar) + (allocSize%sizeof(Scalar)>0?1:0);
Scalar* newBuffer = new Scalar[allocSize];
memcpy(newBuffer, m_buffer, copyElements * sizeof(ListEl));
@@ -110,30 +107,33 @@ class AmbiVector
// element type of the linked list
struct ListEl
{
- Index next;
- Index index;
+ int next;
+ int index;
Scalar value;
};
// used to store data in both mode
Scalar* m_buffer;
- Scalar m_zero;
- Index m_size;
- Index m_start;
- Index m_end;
- Index m_allocatedSize;
- Index m_allocatedElements;
- Index m_mode;
+ int m_size;
+ int m_start;
+ int m_end;
+ int m_allocatedSize;
+ int m_allocatedElements;
+ int m_mode;
// linked list mode
- Index m_llStart;
- Index m_llCurrent;
- Index m_llSize;
+ int m_llStart;
+ int m_llCurrent;
+ int m_llSize;
+
+ private:
+ AmbiVector(const AmbiVector&);
+
};
/** \returns the number of non zeros in the current sub vector */
-template<typename _Scalar,typename _Index>
-_Index AmbiVector<_Scalar,_Index>::nonZeros() const
+template<typename Scalar>
+void AmbiVector<Scalar>::nonZeros() const
{
if (m_mode==IsSparse)
return m_llSize;
@@ -141,8 +141,8 @@ _Index AmbiVector<_Scalar,_Index>::nonZeros() const
return m_end - m_start;
}
-template<typename _Scalar,typename _Index>
-void AmbiVector<_Scalar,_Index>::init(double estimatedDensity)
+template<typename Scalar>
+void AmbiVector<Scalar>::init(RealScalar estimatedDensity)
{
if (estimatedDensity>0.1)
init(IsDense);
@@ -150,8 +150,8 @@ void AmbiVector<_Scalar,_Index>::init(double estimatedDensity)
init(IsSparse);
}
-template<typename _Scalar,typename _Index>
-void AmbiVector<_Scalar,_Index>::init(int mode)
+template<typename Scalar>
+void AmbiVector<Scalar>::init(int mode)
{
m_mode = mode;
if (m_mode==IsSparse)
@@ -166,31 +166,31 @@ void AmbiVector<_Scalar,_Index>::init(int mode)
*
* Don't worry, this function is extremely cheap.
*/
-template<typename _Scalar,typename _Index>
-void AmbiVector<_Scalar,_Index>::restart()
+template<typename Scalar>
+void AmbiVector<Scalar>::restart()
{
m_llCurrent = m_llStart;
}
/** Set all coefficients of current subvector to zero */
-template<typename _Scalar,typename _Index>
-void AmbiVector<_Scalar,_Index>::setZero()
+template<typename Scalar>
+void AmbiVector<Scalar>::setZero()
{
if (m_mode==IsDense)
{
- for (Index i=m_start; i<m_end; ++i)
+ for (int i=m_start; i<m_end; ++i)
m_buffer[i] = Scalar(0);
}
else
{
- eigen_assert(m_mode==IsSparse);
+ ei_assert(m_mode==IsSparse);
m_llSize = 0;
m_llStart = -1;
}
}
-template<typename _Scalar,typename _Index>
-_Scalar& AmbiVector<_Scalar,_Index>::coeffRef(_Index i)
+template<typename Scalar>
+Scalar& AmbiVector<Scalar>::coeffRef(int i)
{
if (m_mode==IsDense)
return m_buffer[i];
@@ -198,7 +198,7 @@ _Scalar& AmbiVector<_Scalar,_Index>::coeffRef(_Index i)
{
ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_buffer);
// TODO factorize the following code to reduce code generation
- eigen_assert(m_mode==IsSparse);
+ ei_assert(m_mode==IsSparse);
if (m_llSize==0)
{
// this is the first element
@@ -224,8 +224,8 @@ _Scalar& AmbiVector<_Scalar,_Index>::coeffRef(_Index i)
}
else
{
- Index nextel = llElements[m_llCurrent].next;
- eigen_assert(i>=llElements[m_llCurrent].index && "you must call restart() before inserting an element with lower or equal index");
+ int nextel = llElements[m_llCurrent].next;
+ ei_assert(i>=llElements[m_llCurrent].index && "you must call restart() before inserting an element with lower or equal index");
while (nextel >= 0 && llElements[nextel].index<=i)
{
m_llCurrent = nextel;
@@ -244,7 +244,7 @@ _Scalar& AmbiVector<_Scalar,_Index>::coeffRef(_Index i)
reallocateSparse();
llElements = reinterpret_cast<ListEl*>(m_buffer);
}
- eigen_internal_assert(m_llSize<m_allocatedElements && "internal error: overflow in sparse mode");
+ ei_internal_assert(m_llSize<m_allocatedElements && "internal error: overflow in sparse mode");
// let's insert a new coefficient
ListEl& el = llElements[m_llSize];
el.value = Scalar(0);
@@ -258,36 +258,36 @@ _Scalar& AmbiVector<_Scalar,_Index>::coeffRef(_Index i)
}
}
-template<typename _Scalar,typename _Index>
-_Scalar& AmbiVector<_Scalar,_Index>::coeff(_Index i)
+template<typename Scalar>
+Scalar AmbiVector<Scalar>::coeff(int i)
{
if (m_mode==IsDense)
return m_buffer[i];
else
{
ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_buffer);
- eigen_assert(m_mode==IsSparse);
+ ei_assert(m_mode==IsSparse);
if ((m_llSize==0) || (i<llElements[m_llStart].index))
{
- return m_zero;
+ return Scalar(0);
}
else
{
- Index elid = m_llStart;
+ int elid = m_llStart;
while (elid >= 0 && llElements[elid].index<i)
elid = llElements[elid].next;
if (llElements[elid].index==i)
return llElements[m_llCurrent].value;
else
- return m_zero;
+ return Scalar(0);
}
}
}
/** Iterator over the nonzero coefficients */
-template<typename _Scalar,typename _Index>
-class AmbiVector<_Scalar,_Index>::Iterator
+template<typename _Scalar>
+class AmbiVector<_Scalar>::Iterator
{
public:
typedef _Scalar Scalar;
@@ -299,15 +299,13 @@ class AmbiVector<_Scalar,_Index>::Iterator
* In practice, all coefficients having a magnitude smaller than \a epsilon
* are skipped.
*/
- Iterator(const AmbiVector& vec, RealScalar epsilon = RealScalar(0.1)*NumTraits<RealScalar>::dummy_precision())
+ Iterator(const AmbiVector& vec, RealScalar epsilon = RealScalar(0.1)*precision<RealScalar>())
: m_vector(vec)
{
m_epsilon = epsilon;
m_isDense = m_vector.m_mode==IsDense;
if (m_isDense)
{
- m_currentEl = 0; // this is to avoid a compilation warning
- m_cachedValue = 0; // this is to avoid a compilation warning
m_cachedIndex = m_vector.m_start-1;
++(*this);
}
@@ -315,11 +313,10 @@ class AmbiVector<_Scalar,_Index>::Iterator
{
ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_vector.m_buffer);
m_currentEl = m_vector.m_llStart;
- while (m_currentEl>=0 && internal::abs(llElements[m_currentEl].value)<m_epsilon)
+ while (m_currentEl>=0 && ei_abs(llElements[m_currentEl].value)<m_epsilon)
m_currentEl = llElements[m_currentEl].next;
if (m_currentEl<0)
{
- m_cachedValue = 0; // this is to avoid a compilation warning
m_cachedIndex = -1;
}
else
@@ -330,7 +327,7 @@ class AmbiVector<_Scalar,_Index>::Iterator
}
}
- Index index() const { return m_cachedIndex; }
+ int index() const { return m_cachedIndex; }
Scalar value() const { return m_cachedValue; }
operator bool() const { return m_cachedIndex>=0; }
@@ -341,7 +338,7 @@ class AmbiVector<_Scalar,_Index>::Iterator
{
do {
++m_cachedIndex;
- } while (m_cachedIndex<m_vector.m_end && internal::abs(m_vector.m_buffer[m_cachedIndex])<m_epsilon);
+ } while (m_cachedIndex<m_vector.m_end && ei_abs(m_vector.m_buffer[m_cachedIndex])<m_epsilon);
if (m_cachedIndex<m_vector.m_end)
m_cachedValue = m_vector.m_buffer[m_cachedIndex];
else
@@ -352,7 +349,7 @@ class AmbiVector<_Scalar,_Index>::Iterator
ListEl* EIGEN_RESTRICT llElements = reinterpret_cast<ListEl*>(m_vector.m_buffer);
do {
m_currentEl = llElements[m_currentEl].next;
- } while (m_currentEl>=0 && internal::abs(llElements[m_currentEl].value)<m_epsilon);
+ } while (m_currentEl>=0 && ei_abs(llElements[m_currentEl].value)<m_epsilon);
if (m_currentEl<0)
{
m_cachedIndex = -1;
@@ -368,11 +365,14 @@ class AmbiVector<_Scalar,_Index>::Iterator
protected:
const AmbiVector& m_vector; // the target vector
- Index m_currentEl; // the current element in sparse/linked-list mode
+ int m_currentEl; // the current element in sparse/linked-list mode
RealScalar m_epsilon; // epsilon used to prune zero coefficients
- Index m_cachedIndex; // current coordinate
+ int m_cachedIndex; // current coordinate
Scalar m_cachedValue; // current value
bool m_isDense; // mode of the vector
+
+ private:
+ Iterator& operator=(const Iterator&);
};
diff --git a/extern/Eigen2/Eigen/src/Sparse/CholmodSupport.h b/extern/Eigen2/Eigen/src/Sparse/CholmodSupport.h
new file mode 100644
index 00000000000..dfd9c787ae9
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/CholmodSupport.h
@@ -0,0 +1,236 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_CHOLMODSUPPORT_H
+#define EIGEN_CHOLMODSUPPORT_H
+
+template<typename Scalar, typename CholmodType>
+void ei_cholmod_configure_matrix(CholmodType& mat)
+{
+ if (ei_is_same_type<Scalar,float>::ret)
+ {
+ mat.xtype = CHOLMOD_REAL;
+ mat.dtype = 1;
+ }
+ else if (ei_is_same_type<Scalar,double>::ret)
+ {
+ mat.xtype = CHOLMOD_REAL;
+ mat.dtype = 0;
+ }
+ else if (ei_is_same_type<Scalar,std::complex<float> >::ret)
+ {
+ mat.xtype = CHOLMOD_COMPLEX;
+ mat.dtype = 1;
+ }
+ else if (ei_is_same_type<Scalar,std::complex<double> >::ret)
+ {
+ mat.xtype = CHOLMOD_COMPLEX;
+ mat.dtype = 0;
+ }
+ else
+ {
+ ei_assert(false && "Scalar type not supported by CHOLMOD");
+ }
+}
+
+template<typename Derived>
+cholmod_sparse SparseMatrixBase<Derived>::asCholmodMatrix()
+{
+ typedef typename Derived::Scalar Scalar;
+ cholmod_sparse res;
+ res.nzmax = nonZeros();
+ res.nrow = rows();;
+ res.ncol = cols();
+ res.p = derived()._outerIndexPtr();
+ res.i = derived()._innerIndexPtr();
+ res.x = derived()._valuePtr();
+ res.xtype = CHOLMOD_REAL;
+ res.itype = CHOLMOD_INT;
+ res.sorted = 1;
+ res.packed = 1;
+ res.dtype = 0;
+ res.stype = -1;
+
+ ei_cholmod_configure_matrix<Scalar>(res);
+
+ if (Derived::Flags & SelfAdjoint)
+ {
+ if (Derived::Flags & UpperTriangular)
+ res.stype = 1;
+ else if (Derived::Flags & LowerTriangular)
+ res.stype = -1;
+ else
+ res.stype = 0;
+ }
+ else
+ res.stype = 0;
+
+ return res;
+}
+
+template<typename Derived>
+cholmod_dense ei_cholmod_map_eigen_to_dense(MatrixBase<Derived>& mat)
+{
+ EIGEN_STATIC_ASSERT((ei_traits<Derived>::Flags&RowMajorBit)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
+ typedef typename Derived::Scalar Scalar;
+
+ cholmod_dense res;
+ res.nrow = mat.rows();
+ res.ncol = mat.cols();
+ res.nzmax = res.nrow * res.ncol;
+ res.d = mat.derived().stride();
+ res.x = mat.derived().data();
+ res.z = 0;
+
+ ei_cholmod_configure_matrix<Scalar>(res);
+
+ return res;
+}
+
+template<typename Scalar, int Flags>
+MappedSparseMatrix<Scalar,Flags>::MappedSparseMatrix(cholmod_sparse& cm)
+{
+ m_innerSize = cm.nrow;
+ m_outerSize = cm.ncol;
+ m_outerIndex = reinterpret_cast<int*>(cm.p);
+ m_innerIndices = reinterpret_cast<int*>(cm.i);
+ m_values = reinterpret_cast<Scalar*>(cm.x);
+ m_nnz = m_outerIndex[cm.ncol];
+}
+
+template<typename MatrixType>
+class SparseLLT<MatrixType,Cholmod> : public SparseLLT<MatrixType>
+{
+ protected:
+ typedef SparseLLT<MatrixType> Base;
+ typedef typename Base::Scalar Scalar;
+ typedef typename Base::RealScalar RealScalar;
+ using Base::MatrixLIsDirty;
+ using Base::SupernodalFactorIsDirty;
+ using Base::m_flags;
+ using Base::m_matrix;
+ using Base::m_status;
+
+ public:
+
+ SparseLLT(int flags = 0)
+ : Base(flags), m_cholmodFactor(0)
+ {
+ cholmod_start(&m_cholmod);
+ }
+
+ SparseLLT(const MatrixType& matrix, int flags = 0)
+ : Base(flags), m_cholmodFactor(0)
+ {
+ cholmod_start(&m_cholmod);
+ compute(matrix);
+ }
+
+ ~SparseLLT()
+ {
+ if (m_cholmodFactor)
+ cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
+ cholmod_finish(&m_cholmod);
+ }
+
+ inline const typename Base::CholMatrixType& matrixL(void) const;
+
+ template<typename Derived>
+ void solveInPlace(MatrixBase<Derived> &b) const;
+
+ void compute(const MatrixType& matrix);
+
+ protected:
+ mutable cholmod_common m_cholmod;
+ cholmod_factor* m_cholmodFactor;
+};
+
+template<typename MatrixType>
+void SparseLLT<MatrixType,Cholmod>::compute(const MatrixType& a)
+{
+ if (m_cholmodFactor)
+ {
+ cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
+ m_cholmodFactor = 0;
+ }
+
+ cholmod_sparse A = const_cast<MatrixType&>(a).asCholmodMatrix();
+ m_cholmod.supernodal = CHOLMOD_AUTO;
+ // TODO
+ if (m_flags&IncompleteFactorization)
+ {
+ m_cholmod.nmethods = 1;
+ m_cholmod.method[0].ordering = CHOLMOD_NATURAL;
+ m_cholmod.postorder = 0;
+ }
+ else
+ {
+ m_cholmod.nmethods = 1;
+ m_cholmod.method[0].ordering = CHOLMOD_NATURAL;
+ m_cholmod.postorder = 0;
+ }
+ m_cholmod.final_ll = 1;
+ m_cholmodFactor = cholmod_analyze(&A, &m_cholmod);
+ cholmod_factorize(&A, m_cholmodFactor, &m_cholmod);
+
+ m_status = (m_status & ~SupernodalFactorIsDirty) | MatrixLIsDirty;
+}
+
+template<typename MatrixType>
+inline const typename SparseLLT<MatrixType>::CholMatrixType&
+SparseLLT<MatrixType,Cholmod>::matrixL() const
+{
+ if (m_status & MatrixLIsDirty)
+ {
+ ei_assert(!(m_status & SupernodalFactorIsDirty));
+
+ cholmod_sparse* cmRes = cholmod_factor_to_sparse(m_cholmodFactor, &m_cholmod);
+ const_cast<typename Base::CholMatrixType&>(m_matrix) = MappedSparseMatrix<Scalar>(*cmRes);
+ free(cmRes);
+
+ m_status = (m_status & ~MatrixLIsDirty);
+ }
+ return m_matrix;
+}
+
+template<typename MatrixType>
+template<typename Derived>
+void SparseLLT<MatrixType,Cholmod>::solveInPlace(MatrixBase<Derived> &b) const
+{
+ const int size = m_cholmodFactor->n;
+ ei_assert(size==b.rows());
+
+ // this uses Eigen's triangular sparse solver
+// if (m_status & MatrixLIsDirty)
+// matrixL();
+// Base::solveInPlace(b);
+ // as long as our own triangular sparse solver is not fully optimal,
+ // let's use CHOLMOD's one:
+ cholmod_dense cdb = ei_cholmod_map_eigen_to_dense(b);
+ cholmod_dense* x = cholmod_solve(CHOLMOD_LDLt, m_cholmodFactor, &cdb, &m_cholmod);
+ b = Matrix<typename Base::Scalar,Dynamic,1>::Map(reinterpret_cast<typename Base::Scalar*>(x->x),b.rows());
+ cholmod_free_dense(&x, &m_cholmod);
+}
+
+#endif // EIGEN_CHOLMODSUPPORT_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/CompressedStorage.h b/extern/Eigen2/Eigen/src/Sparse/CompressedStorage.h
index b3bde272ec2..4dbd3230985 100644
--- a/extern/Eigen3/Eigen/src/Sparse/CompressedStorage.h
+++ b/extern/Eigen2/Eigen/src/Sparse/CompressedStorage.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -28,20 +28,11 @@
/** Stores a sparse set of values as a list of values and a list of indices.
*
*/
-template<typename _Scalar,typename _Index>
+template<typename Scalar>
class CompressedStorage
{
- public:
-
- typedef _Scalar Scalar;
- typedef _Index Index;
-
- protected:
-
typedef typename NumTraits<Scalar>::Real RealScalar;
-
public:
-
CompressedStorage()
: m_values(0), m_indices(0), m_size(0), m_allocatedSize(0)
{}
@@ -62,7 +53,7 @@ class CompressedStorage
{
resize(other.size());
memcpy(m_values, other.m_values, m_size * sizeof(Scalar));
- memcpy(m_indices, other.m_indices, m_size * sizeof(Index));
+ memcpy(m_indices, other.m_indices, m_size * sizeof(int));
return *this;
}
@@ -100,9 +91,9 @@ class CompressedStorage
m_size = size;
}
- void append(const Scalar& v, Index i)
+ void append(const Scalar& v, int i)
{
- Index id = static_cast<Index>(m_size);
+ int id = m_size;
resize(m_size+1, 1);
m_values[id] = v;
m_indices[id] = i;
@@ -115,10 +106,10 @@ class CompressedStorage
inline Scalar& value(size_t i) { return m_values[i]; }
inline const Scalar& value(size_t i) const { return m_values[i]; }
- inline Index& index(size_t i) { return m_indices[i]; }
- inline const Index& index(size_t i) const { return m_indices[i]; }
+ inline int& index(size_t i) { return m_indices[i]; }
+ inline const int& index(size_t i) const { return m_indices[i]; }
- static CompressedStorage Map(Index* indices, Scalar* values, size_t size)
+ static CompressedStorage Map(int* indices, Scalar* values, size_t size)
{
CompressedStorage res;
res.m_indices = indices;
@@ -126,15 +117,15 @@ class CompressedStorage
res.m_allocatedSize = res.m_size = size;
return res;
}
-
+
/** \returns the largest \c k such that for all \c j in [0,k) index[\c j]\<\a key */
- inline Index searchLowerIndex(Index key) const
+ inline int searchLowerIndex(int key) const
{
return searchLowerIndex(0, m_size, key);
}
-
+
/** \returns the largest \c k in [start,end) such that for all \c j in [start,k) index[\c j]\<\a key */
- inline Index searchLowerIndex(size_t start, size_t end, Index key) const
+ inline int searchLowerIndex(size_t start, size_t end, int key) const
{
while(end>start)
{
@@ -144,12 +135,12 @@ class CompressedStorage
else
end = mid;
}
- return static_cast<Index>(start);
+ return start;
}
-
+
/** \returns the stored value at index \a key
* If the value does not exist, then the value \a defaultValue is returned without any insertion. */
- inline Scalar at(Index key, Scalar defaultValue = Scalar(0)) const
+ inline Scalar at(int key, Scalar defaultValue = Scalar(0)) const
{
if (m_size==0)
return defaultValue;
@@ -160,11 +151,11 @@ class CompressedStorage
const size_t id = searchLowerIndex(0,m_size-1,key);
return ((id<m_size) && (m_indices[id]==key)) ? m_values[id] : defaultValue;
}
-
+
/** Like at(), but the search is performed in the range [start,end) */
- inline Scalar atInRange(size_t start, size_t end, Index key, Scalar defaultValue = Scalar(0)) const
+ inline Scalar atInRange(size_t start, size_t end, int key, Scalar defaultValue = Scalar(0)) const
{
- if (start>=end)
+ if (start==end)
return Scalar(0);
else if (end>start && key==m_indices[end-1])
return m_values[end-1];
@@ -173,11 +164,11 @@ class CompressedStorage
const size_t id = searchLowerIndex(start,end-1,key);
return ((id<end) && (m_indices[id]==key)) ? m_values[id] : defaultValue;
}
-
+
/** \returns a reference to the value at index \a key
* If the value does not exist, then the value \a defaultValue is inserted
* such that the keys are sorted. */
- inline Scalar& atWithInsertion(Index key, Scalar defaultValue = Scalar(0))
+ inline Scalar& atWithInsertion(int key, Scalar defaultValue = Scalar(0))
{
size_t id = searchLowerIndex(0,m_size,key);
if (id>=m_size || m_indices[id]!=key)
@@ -193,14 +184,14 @@ class CompressedStorage
}
return m_values[id];
}
-
- void prune(Scalar reference, RealScalar epsilon = NumTraits<RealScalar>::dummy_precision())
+
+ void prune(Scalar reference, RealScalar epsilon = precision<RealScalar>())
{
size_t k = 0;
size_t n = size();
for (size_t i=0; i<n; ++i)
{
- if (!internal::isMuchSmallerThan(value(i), reference, epsilon))
+ if (!ei_isMuchSmallerThan(value(i), reference, epsilon))
{
value(k) = value(i);
index(k) = index(i);
@@ -215,11 +206,11 @@ class CompressedStorage
inline void reallocate(size_t size)
{
Scalar* newValues = new Scalar[size];
- Index* newIndices = new Index[size];
- size_t copySize = (std::min)(size, m_size);
+ int* newIndices = new int[size];
+ size_t copySize = std::min(size, m_size);
// copy
memcpy(newValues, m_values, copySize * sizeof(Scalar));
- memcpy(newIndices, m_indices, copySize * sizeof(Index));
+ memcpy(newIndices, m_indices, copySize * sizeof(int));
// delete old stuff
delete[] m_values;
delete[] m_indices;
@@ -230,7 +221,7 @@ class CompressedStorage
protected:
Scalar* m_values;
- Index* m_indices;
+ int* m_indices;
size_t m_size;
size_t m_allocatedSize;
diff --git a/extern/Eigen3/Eigen/src/Sparse/CoreIterators.h b/extern/Eigen2/Eigen/src/Sparse/CoreIterators.h
index b4beaeee69e..f1520a585ca 100644
--- a/extern/Eigen3/Eigen/src/Sparse/CoreIterators.h
+++ b/extern/Eigen2/Eigen/src/Sparse/CoreIterators.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -35,16 +35,13 @@
*/
// generic version for dense matrix and expressions
-template<typename Derived> class DenseBase<Derived>::InnerIterator
+template<typename Derived> class MatrixBase<Derived>::InnerIterator
{
- protected:
typedef typename Derived::Scalar Scalar;
- typedef typename Derived::Index Index;
-
enum { IsRowMajor = (Derived::Flags&RowMajorBit)==RowMajorBit };
public:
- EIGEN_STRONG_INLINE InnerIterator(const Derived& expr, Index outer)
- : m_expression(expr), m_inner(0), m_outer(outer), m_end(expr.innerSize())
+ EIGEN_STRONG_INLINE InnerIterator(const Derived& expr, int outer)
+ : m_expression(expr), m_inner(0), m_outer(outer), m_end(expr.rows())
{}
EIGEN_STRONG_INLINE Scalar value() const
@@ -55,17 +52,17 @@ template<typename Derived> class DenseBase<Derived>::InnerIterator
EIGEN_STRONG_INLINE InnerIterator& operator++() { m_inner++; return *this; }
- EIGEN_STRONG_INLINE Index index() const { return m_inner; }
- inline Index row() const { return IsRowMajor ? m_outer : index(); }
- inline Index col() const { return IsRowMajor ? index() : m_outer; }
+ EIGEN_STRONG_INLINE int index() const { return m_inner; }
+ inline int row() const { return IsRowMajor ? m_outer : index(); }
+ inline int col() const { return IsRowMajor ? index() : m_outer; }
EIGEN_STRONG_INLINE operator bool() const { return m_inner < m_end && m_inner>=0; }
protected:
const Derived& m_expression;
- Index m_inner;
- const Index m_outer;
- const Index m_end;
+ int m_inner;
+ const int m_outer;
+ const int m_end;
};
#endif // EIGEN_COREITERATORS_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/DynamicSparseMatrix.h b/extern/Eigen2/Eigen/src/Sparse/DynamicSparseMatrix.h
index 93e75f4c601..01f97cd6d94 100644
--- a/extern/Eigen3/Eigen/src/Sparse/DynamicSparseMatrix.h
+++ b/extern/Eigen2/Eigen/src/Sparse/DynamicSparseMatrix.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -35,75 +35,65 @@
* random read/write accesses in log(rho*outer_size) where \c rho is the probability that a coefficient is
* nonzero and outer_size is the number of columns if the matrix is column-major and the number of rows
* otherwise.
- *
+ *
* Internally, the data are stored as a std::vector of compressed vector. The performances of random writes might
* decrease as the number of nonzeros per inner-vector increase. In practice, we observed very good performance
* till about 100 nonzeros/vector, and the performance remains relatively good till 500 nonzeros/vectors.
*
* \see SparseMatrix
*/
-
-namespace internal {
-template<typename _Scalar, int _Options, typename _Index>
-struct traits<DynamicSparseMatrix<_Scalar, _Options, _Index> >
+template<typename _Scalar, int _Flags>
+struct ei_traits<DynamicSparseMatrix<_Scalar, _Flags> >
{
typedef _Scalar Scalar;
- typedef _Index Index;
- typedef Sparse StorageKind;
- typedef MatrixXpr XprKind;
enum {
RowsAtCompileTime = Dynamic,
ColsAtCompileTime = Dynamic,
MaxRowsAtCompileTime = Dynamic,
MaxColsAtCompileTime = Dynamic,
- Flags = _Options | NestByRefBit | LvalueBit,
+ Flags = SparseBit | _Flags,
CoeffReadCost = NumTraits<Scalar>::ReadCost,
SupportedAccessPatterns = OuterRandomAccessPattern
};
};
-}
-template<typename _Scalar, int _Options, typename _Index>
+template<typename _Scalar, int _Flags>
class DynamicSparseMatrix
- : public SparseMatrixBase<DynamicSparseMatrix<_Scalar, _Options, _Index> >
+ : public SparseMatrixBase<DynamicSparseMatrix<_Scalar, _Flags> >
{
public:
- EIGEN_SPARSE_PUBLIC_INTERFACE(DynamicSparseMatrix)
+ EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(DynamicSparseMatrix)
// FIXME: why are these operator already alvailable ???
// EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(DynamicSparseMatrix, +=)
// EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(DynamicSparseMatrix, -=)
typedef MappedSparseMatrix<Scalar,Flags> Map;
- using Base::IsRowMajor;
- using Base::operator=;
- enum {
- Options = _Options
- };
protected:
+ enum { IsRowMajor = Base::IsRowMajor };
typedef DynamicSparseMatrix<Scalar,(Flags&~RowMajorBit)|(IsRowMajor?RowMajorBit:0)> TransposedSparseMatrix;
- Index m_innerSize;
- std::vector<CompressedStorage<Scalar,Index> > m_data;
+ int m_innerSize;
+ std::vector<CompressedStorage<Scalar> > m_data;
public:
-
- inline Index rows() const { return IsRowMajor ? outerSize() : m_innerSize; }
- inline Index cols() const { return IsRowMajor ? m_innerSize : outerSize(); }
- inline Index innerSize() const { return m_innerSize; }
- inline Index outerSize() const { return static_cast<Index>(m_data.size()); }
- inline Index innerNonZeros(Index j) const { return m_data[j].size(); }
-
- std::vector<CompressedStorage<Scalar,Index> >& _data() { return m_data; }
- const std::vector<CompressedStorage<Scalar,Index> >& _data() const { return m_data; }
+
+ inline int rows() const { return IsRowMajor ? outerSize() : m_innerSize; }
+ inline int cols() const { return IsRowMajor ? m_innerSize : outerSize(); }
+ inline int innerSize() const { return m_innerSize; }
+ inline int outerSize() const { return m_data.size(); }
+ inline int innerNonZeros(int j) const { return m_data[j].size(); }
+
+ std::vector<CompressedStorage<Scalar> >& _data() { return m_data; }
+ const std::vector<CompressedStorage<Scalar> >& _data() const { return m_data; }
/** \returns the coefficient value at given position \a row, \a col
* This operation involes a log(rho*outer_size) binary search.
*/
- inline Scalar coeff(Index row, Index col) const
+ inline Scalar coeff(int row, int col) const
{
- const Index outer = IsRowMajor ? row : col;
- const Index inner = IsRowMajor ? col : row;
+ const int outer = IsRowMajor ? row : col;
+ const int inner = IsRowMajor ? col : row;
return m_data[outer].at(inner);
}
@@ -111,74 +101,73 @@ class DynamicSparseMatrix
* This operation involes a log(rho*outer_size) binary search. If the coefficient does not
* exist yet, then a sorted insertion into a sequential buffer is performed.
*/
- inline Scalar& coeffRef(Index row, Index col)
+ inline Scalar& coeffRef(int row, int col)
{
- const Index outer = IsRowMajor ? row : col;
- const Index inner = IsRowMajor ? col : row;
+ const int outer = IsRowMajor ? row : col;
+ const int inner = IsRowMajor ? col : row;
return m_data[outer].atWithInsertion(inner);
}
class InnerIterator;
- void setZero()
+ inline void setZero()
{
- for (Index j=0; j<outerSize(); ++j)
+ for (int j=0; j<outerSize(); ++j)
m_data[j].clear();
}
/** \returns the number of non zero coefficients */
- Index nonZeros() const
+ inline int nonZeros() const
{
- Index res = 0;
- for (Index j=0; j<outerSize(); ++j)
- res += static_cast<Index>(m_data[j].size());
+ int res = 0;
+ for (int j=0; j<outerSize(); ++j)
+ res += m_data[j].size();
return res;
}
-
-
- void reserve(Index reserveSize = 1000)
+ /** Set the matrix to zero and reserve the memory for \a reserveSize nonzero coefficients. */
+ inline void startFill(int reserveSize = 1000)
{
if (outerSize()>0)
{
- Index reserveSizePerVector = (std::max)(reserveSize/outerSize(),Index(4));
- for (Index j=0; j<outerSize(); ++j)
+ int reserveSizePerVector = std::max(reserveSize/outerSize(),4);
+ for (int j=0; j<outerSize(); ++j)
{
+ m_data[j].clear();
m_data[j].reserve(reserveSizePerVector);
}
}
}
- /** Does nothing: provided for compatibility with SparseMatrix */
- inline void startVec(Index /*outer*/) {}
-
- /** \returns a reference to the non zero coefficient at position \a row, \a col assuming that:
- * - the nonzero does not already exist
- * - the new coefficient is the last one of the given inner vector.
- *
- * \sa insert, insertBackByOuterInner */
- inline Scalar& insertBack(Index row, Index col)
- {
- return insertBackByOuterInner(IsRowMajor?row:col, IsRowMajor?col:row);
- }
-
- /** \sa insertBack */
- inline Scalar& insertBackByOuterInner(Index outer, Index inner)
+ /** inserts a nonzero coefficient at given coordinates \a row, \a col and returns its reference assuming that:
+ * 1 - the coefficient does not exist yet
+ * 2 - this the coefficient with greater inner coordinate for the given outer coordinate.
+ * In other words, assuming \c *this is column-major, then there must not exists any nonzero coefficient of coordinates
+ * \c i \c x \a col such that \c i >= \a row. Otherwise the matrix is invalid.
+ *
+ * \see fillrand(), coeffRef()
+ */
+ inline Scalar& fill(int row, int col)
{
- eigen_assert(outer<Index(m_data.size()) && inner<m_innerSize && "out of range");
- eigen_assert(((m_data[outer].size()==0) || (m_data[outer].index(m_data[outer].size()-1)<inner))
- && "wrong sorted insertion");
+ const int outer = IsRowMajor ? row : col;
+ const int inner = IsRowMajor ? col : row;
+ ei_assert(outer<int(m_data.size()) && inner<m_innerSize);
+ ei_assert((m_data[outer].size()==0) || (m_data[outer].index(m_data[outer].size()-1)<inner));
m_data[outer].append(0, inner);
return m_data[outer].value(m_data[outer].size()-1);
}
- inline Scalar& insert(Index row, Index col)
+ /** Like fill() but with random inner coordinates.
+ * Compared to the generic coeffRef(), the unique limitation is that we assume
+ * the coefficient does not exist yet.
+ */
+ inline Scalar& fillrand(int row, int col)
{
- const Index outer = IsRowMajor ? row : col;
- const Index inner = IsRowMajor ? col : row;
-
- Index startId = 0;
- Index id = static_cast<Index>(m_data[outer].size()) - 1;
+ const int outer = IsRowMajor ? row : col;
+ const int inner = IsRowMajor ? col : row;
+
+ int startId = 0;
+ int id = m_data[outer].size() - 1;
m_data[outer].resize(id+2,1);
while ( (id >= startId) && (m_data[outer].index(id) > inner) )
@@ -192,38 +181,37 @@ class DynamicSparseMatrix
return m_data[outer].value(id+1);
}
- /** Does nothing: provided for compatibility with SparseMatrix */
- inline void finalize() {}
-
- /** Suppress all nonzeros which are smaller than \a reference under the tolerence \a epsilon */
- void prune(Scalar reference, RealScalar epsilon = NumTraits<RealScalar>::dummy_precision())
+ /** Does nothing. Provided for compatibility with SparseMatrix. */
+ inline void endFill() {}
+
+ void prune(Scalar reference, RealScalar epsilon = precision<RealScalar>())
{
- for (Index j=0; j<outerSize(); ++j)
+ for (int j=0; j<outerSize(); ++j)
m_data[j].prune(reference,epsilon);
}
/** Resize the matrix without preserving the data (the matrix is set to zero)
*/
- void resize(Index rows, Index cols)
+ void resize(int rows, int cols)
{
- const Index outerSize = IsRowMajor ? rows : cols;
+ const int outerSize = IsRowMajor ? rows : cols;
m_innerSize = IsRowMajor ? cols : rows;
setZero();
- if (Index(m_data.size()) != outerSize)
+ if (int(m_data.size()) != outerSize)
{
m_data.resize(outerSize);
}
}
-
- void resizeAndKeepData(Index rows, Index cols)
+
+ void resizeAndKeepData(int rows, int cols)
{
- const Index outerSize = IsRowMajor ? rows : cols;
- const Index innerSize = IsRowMajor ? cols : rows;
+ const int outerSize = IsRowMajor ? rows : cols;
+ const int innerSize = IsRowMajor ? cols : rows;
if (m_innerSize>innerSize)
{
// remove all coefficients with innerCoord>=innerSize
// TODO
- //std::cerr << "not implemented yet\n";
+ std::cerr << "not implemented yet\n";
exit(2);
}
if (m_data.size() != outerSize)
@@ -235,20 +223,20 @@ class DynamicSparseMatrix
inline DynamicSparseMatrix()
: m_innerSize(0), m_data(0)
{
- eigen_assert(innerSize()==0 && outerSize()==0);
+ ei_assert(innerSize()==0 && outerSize()==0);
}
- inline DynamicSparseMatrix(Index rows, Index cols)
+ inline DynamicSparseMatrix(int rows, int cols)
: m_innerSize(0)
{
resize(rows, cols);
}
template<typename OtherDerived>
- explicit inline DynamicSparseMatrix(const SparseMatrixBase<OtherDerived>& other)
+ inline DynamicSparseMatrix(const SparseMatrixBase<OtherDerived>& other)
: m_innerSize(0)
{
- Base::operator=(other.derived());
+ *this = other.derived();
}
inline DynamicSparseMatrix(const DynamicSparseMatrix& other)
@@ -279,68 +267,33 @@ class DynamicSparseMatrix
return *this;
}
- /** Destructor */
- inline ~DynamicSparseMatrix() {}
-
- public:
-
- /** \deprecated
- * Set the matrix to zero and reserve the memory for \a reserveSize nonzero coefficients. */
- EIGEN_DEPRECATED void startFill(Index reserveSize = 1000)
- {
- setZero();
- reserve(reserveSize);
- }
-
- /** \deprecated use insert()
- * inserts a nonzero coefficient at given coordinates \a row, \a col and returns its reference assuming that:
- * 1 - the coefficient does not exist yet
- * 2 - this the coefficient with greater inner coordinate for the given outer coordinate.
- * In other words, assuming \c *this is column-major, then there must not exists any nonzero coefficient of coordinates
- * \c i \c x \a col such that \c i >= \a row. Otherwise the matrix is invalid.
- *
- * \see fillrand(), coeffRef()
- */
- EIGEN_DEPRECATED Scalar& fill(Index row, Index col)
- {
- const Index outer = IsRowMajor ? row : col;
- const Index inner = IsRowMajor ? col : row;
- return insertBack(outer,inner);
- }
-
- /** \deprecated use insert()
- * Like fill() but with random inner coordinates.
- * Compared to the generic coeffRef(), the unique limitation is that we assume
- * the coefficient does not exist yet.
- */
- EIGEN_DEPRECATED Scalar& fillrand(Index row, Index col)
+ template<typename OtherDerived>
+ inline DynamicSparseMatrix& operator=(const SparseMatrixBase<OtherDerived>& other)
{
- return insert(row,col);
+ return SparseMatrixBase<DynamicSparseMatrix>::operator=(other.derived());
}
- /** \deprecated use finalize()
- * Does nothing. Provided for compatibility with SparseMatrix. */
- EIGEN_DEPRECATED void endFill() {}
-
-# ifdef EIGEN_DYNAMICSPARSEMATRIX_PLUGIN
-# include EIGEN_DYNAMICSPARSEMATRIX_PLUGIN
-# endif
+ /** Destructor */
+ inline ~DynamicSparseMatrix() {}
};
-template<typename Scalar, int _Options, typename _Index>
-class DynamicSparseMatrix<Scalar,_Options,_Index>::InnerIterator : public SparseVector<Scalar,_Options>::InnerIterator
+template<typename Scalar, int _Flags>
+class DynamicSparseMatrix<Scalar,_Flags>::InnerIterator : public SparseVector<Scalar,_Flags>::InnerIterator
{
- typedef typename SparseVector<Scalar,_Options>::InnerIterator Base;
+ typedef typename SparseVector<Scalar,_Flags>::InnerIterator Base;
public:
- InnerIterator(const DynamicSparseMatrix& mat, Index outer)
+ InnerIterator(const DynamicSparseMatrix& mat, int outer)
: Base(mat.m_data[outer]), m_outer(outer)
{}
-
- inline Index row() const { return IsRowMajor ? m_outer : Base::index(); }
- inline Index col() const { return IsRowMajor ? Base::index() : m_outer; }
+
+ inline int row() const { return IsRowMajor ? m_outer : Base::index(); }
+ inline int col() const { return IsRowMajor ? Base::index() : m_outer; }
protected:
- const Index m_outer;
+ const int m_outer;
+
+ private:
+ InnerIterator& operator=(const InnerIterator&);
};
#endif // EIGEN_DYNAMIC_SPARSEMATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/MappedSparseMatrix.h b/extern/Eigen2/Eigen/src/Sparse/MappedSparseMatrix.h
index 31a431fb224..f4935d8344e 100644
--- a/extern/Eigen3/Eigen/src/Sparse/MappedSparseMatrix.h
+++ b/extern/Eigen2/Eigen/src/Sparse/MappedSparseMatrix.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -34,56 +34,54 @@
* See http://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme.
*
*/
-namespace internal {
-template<typename _Scalar, int _Flags, typename _Index>
-struct traits<MappedSparseMatrix<_Scalar, _Flags, _Index> > : traits<SparseMatrix<_Scalar, _Flags, _Index> >
+template<typename _Scalar, int _Flags>
+struct ei_traits<MappedSparseMatrix<_Scalar, _Flags> > : ei_traits<SparseMatrix<_Scalar, _Flags> >
{};
-}
-template<typename _Scalar, int _Flags, typename _Index>
+template<typename _Scalar, int _Flags>
class MappedSparseMatrix
- : public SparseMatrixBase<MappedSparseMatrix<_Scalar, _Flags, _Index> >
+ : public SparseMatrixBase<MappedSparseMatrix<_Scalar, _Flags> >
{
public:
- EIGEN_SPARSE_PUBLIC_INTERFACE(MappedSparseMatrix)
+ EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(MappedSparseMatrix)
protected:
enum { IsRowMajor = Base::IsRowMajor };
- Index m_outerSize;
- Index m_innerSize;
- Index m_nnz;
- Index* m_outerIndex;
- Index* m_innerIndices;
+ int m_outerSize;
+ int m_innerSize;
+ int m_nnz;
+ int* m_outerIndex;
+ int* m_innerIndices;
Scalar* m_values;
public:
- inline Index rows() const { return IsRowMajor ? m_outerSize : m_innerSize; }
- inline Index cols() const { return IsRowMajor ? m_innerSize : m_outerSize; }
- inline Index innerSize() const { return m_innerSize; }
- inline Index outerSize() const { return m_outerSize; }
- inline Index innerNonZeros(Index j) const { return m_outerIndex[j+1]-m_outerIndex[j]; }
+ inline int rows() const { return IsRowMajor ? m_outerSize : m_innerSize; }
+ inline int cols() const { return IsRowMajor ? m_innerSize : m_outerSize; }
+ inline int innerSize() const { return m_innerSize; }
+ inline int outerSize() const { return m_outerSize; }
+ inline int innerNonZeros(int j) const { return m_outerIndex[j+1]-m_outerIndex[j]; }
//----------------------------------------
// direct access interface
inline const Scalar* _valuePtr() const { return m_values; }
inline Scalar* _valuePtr() { return m_values; }
- inline const Index* _innerIndexPtr() const { return m_innerIndices; }
- inline Index* _innerIndexPtr() { return m_innerIndices; }
+ inline const int* _innerIndexPtr() const { return m_innerIndices; }
+ inline int* _innerIndexPtr() { return m_innerIndices; }
- inline const Index* _outerIndexPtr() const { return m_outerIndex; }
- inline Index* _outerIndexPtr() { return m_outerIndex; }
+ inline const int* _outerIndexPtr() const { return m_outerIndex; }
+ inline int* _outerIndexPtr() { return m_outerIndex; }
//----------------------------------------
- inline Scalar coeff(Index row, Index col) const
+ inline Scalar coeff(int row, int col) const
{
- const Index outer = IsRowMajor ? row : col;
- const Index inner = IsRowMajor ? col : row;
+ const int outer = RowMajor ? row : col;
+ const int inner = RowMajor ? col : row;
- Index start = m_outerIndex[outer];
- Index end = m_outerIndex[outer+1];
+ int start = m_outerIndex[outer];
+ int end = m_outerIndex[outer+1];
if (start==end)
return Scalar(0);
else if (end>0 && inner==m_innerIndices[end-1])
@@ -91,45 +89,57 @@ class MappedSparseMatrix
// ^^ optimization: let's first check if it is the last coefficient
// (very common in high level algorithms)
- const Index* r = std::lower_bound(&m_innerIndices[start],&m_innerIndices[end-1],inner);
- const Index id = r-&m_innerIndices[0];
+ const int* r = std::lower_bound(&m_innerIndices[start],&m_innerIndices[end-1],inner);
+ const int id = r-&m_innerIndices[0];
return ((*r==inner) && (id<end)) ? m_values[id] : Scalar(0);
}
- inline Scalar& coeffRef(Index row, Index col)
+ inline Scalar& coeffRef(int row, int col)
{
- const Index outer = IsRowMajor ? row : col;
- const Index inner = IsRowMajor ? col : row;
-
- Index start = m_outerIndex[outer];
- Index end = m_outerIndex[outer+1];
- eigen_assert(end>=start && "you probably called coeffRef on a non finalized matrix");
- eigen_assert(end>start && "coeffRef cannot be called on a zero coefficient");
- Index* r = std::lower_bound(&m_innerIndices[start],&m_innerIndices[end],inner);
- const Index id = r-&m_innerIndices[0];
- eigen_assert((*r==inner) && (id<end) && "coeffRef cannot be called on a zero coefficient");
+ const int outer = RowMajor ? row : col;
+ const int inner = RowMajor ? col : row;
+
+ int start = m_outerIndex[outer];
+ int end = m_outerIndex[outer+1];
+ ei_assert(end>=start && "you probably called coeffRef on a non finalized matrix");
+ ei_assert(end>start && "coeffRef cannot be called on a zero coefficient");
+ int* r = std::lower_bound(&m_innerIndices[start],&m_innerIndices[end],inner);
+ const int id = r-&m_innerIndices[0];
+ ei_assert((*r==inner) && (id<end) && "coeffRef cannot be called on a zero coefficient");
return m_values[id];
}
class InnerIterator;
/** \returns the number of non zero coefficients */
- inline Index nonZeros() const { return m_nnz; }
+ inline int nonZeros() const { return m_nnz; }
- inline MappedSparseMatrix(Index rows, Index cols, Index nnz, Index* outerIndexPtr, Index* innerIndexPtr, Scalar* valuePtr)
+ inline MappedSparseMatrix(int rows, int cols, int nnz, int* outerIndexPtr, int* innerIndexPtr, Scalar* valuePtr)
: m_outerSize(IsRowMajor?rows:cols), m_innerSize(IsRowMajor?cols:rows), m_nnz(nnz), m_outerIndex(outerIndexPtr),
m_innerIndices(innerIndexPtr), m_values(valuePtr)
{}
+ #ifdef EIGEN_TAUCS_SUPPORT
+ explicit MappedSparseMatrix(taucs_ccs_matrix& taucsMatrix);
+ #endif
+
+ #ifdef EIGEN_CHOLMOD_SUPPORT
+ explicit MappedSparseMatrix(cholmod_sparse& cholmodMatrix);
+ #endif
+
+ #ifdef EIGEN_SUPERLU_SUPPORT
+ explicit MappedSparseMatrix(SluMatrix& sluMatrix);
+ #endif
+
/** Empty destructor */
inline ~MappedSparseMatrix() {}
};
-template<typename Scalar, int _Flags, typename _Index>
-class MappedSparseMatrix<Scalar,_Flags,_Index>::InnerIterator
+template<typename Scalar, int _Flags>
+class MappedSparseMatrix<Scalar,_Flags>::InnerIterator
{
public:
- InnerIterator(const MappedSparseMatrix& mat, Index outer)
+ InnerIterator(const MappedSparseMatrix& mat, int outer)
: m_matrix(mat),
m_outer(outer),
m_id(mat._outerIndexPtr()[outer]),
@@ -138,7 +148,7 @@ class MappedSparseMatrix<Scalar,_Flags,_Index>::InnerIterator
{}
template<unsigned int Added, unsigned int Removed>
- InnerIterator(const Flagged<MappedSparseMatrix,Added,Removed>& mat, Index outer)
+ InnerIterator(const Flagged<MappedSparseMatrix,Added,Removed>& mat, int outer)
: m_matrix(mat._expression()), m_id(m_matrix._outerIndexPtr()[outer]),
m_start(m_id), m_end(m_matrix._outerIndexPtr()[outer+1])
{}
@@ -148,18 +158,18 @@ class MappedSparseMatrix<Scalar,_Flags,_Index>::InnerIterator
inline Scalar value() const { return m_matrix._valuePtr()[m_id]; }
inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix._valuePtr()[m_id]); }
- inline Index index() const { return m_matrix._innerIndexPtr()[m_id]; }
- inline Index row() const { return IsRowMajor ? m_outer : index(); }
- inline Index col() const { return IsRowMajor ? index() : m_outer; }
+ inline int index() const { return m_matrix._innerIndexPtr()[m_id]; }
+ inline int row() const { return IsRowMajor ? m_outer : index(); }
+ inline int col() const { return IsRowMajor ? index() : m_outer; }
inline operator bool() const { return (m_id < m_end) && (m_id>=m_start); }
protected:
const MappedSparseMatrix& m_matrix;
- const Index m_outer;
- Index m_id;
- const Index m_start;
- const Index m_end;
+ const int m_outer;
+ int m_id;
+ const int m_start;
+ const int m_end;
};
#endif // EIGEN_MAPPED_SPARSEMATRIX_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/RandomSetter.h b/extern/Eigen2/Eigen/src/Sparse/RandomSetter.h
new file mode 100644
index 00000000000..d908e315f3b
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/RandomSetter.h
@@ -0,0 +1,330 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_RANDOMSETTER_H
+#define EIGEN_RANDOMSETTER_H
+
+/** Represents a std::map
+ *
+ * \see RandomSetter
+ */
+template<typename Scalar> struct StdMapTraits
+{
+ typedef int KeyType;
+ typedef std::map<KeyType,Scalar> Type;
+ enum {
+ IsSorted = 1
+ };
+
+ static void setInvalidKey(Type&, const KeyType&) {}
+};
+
+#ifdef EIGEN_UNORDERED_MAP_SUPPORT
+/** Represents a std::unordered_map
+ *
+ * To use it you need to both define EIGEN_UNORDERED_MAP_SUPPORT and include the unordered_map header file
+ * yourself making sure that unordered_map is defined in the std namespace.
+ *
+ * For instance, with current version of gcc you can either enable C++0x standard (-std=c++0x) or do:
+ * \code
+ * #include <tr1/unordered_map>
+ * #define EIGEN_UNORDERED_MAP_SUPPORT
+ * namespace std {
+ * using std::tr1::unordered_map;
+ * }
+ * \endcode
+ *
+ * \see RandomSetter
+ */
+template<typename Scalar> struct StdUnorderedMapTraits
+{
+ typedef int KeyType;
+ typedef std::unordered_map<KeyType,Scalar> Type;
+ enum {
+ IsSorted = 0
+ };
+
+ static void setInvalidKey(Type&, const KeyType&) {}
+};
+#endif // EIGEN_UNORDERED_MAP_SUPPORT
+
+#ifdef _DENSE_HASH_MAP_H_
+/** Represents a google::dense_hash_map
+ *
+ * \see RandomSetter
+ */
+template<typename Scalar> struct GoogleDenseHashMapTraits
+{
+ typedef int KeyType;
+ typedef google::dense_hash_map<KeyType,Scalar> Type;
+ enum {
+ IsSorted = 0
+ };
+
+ static void setInvalidKey(Type& map, const KeyType& k)
+ { map.set_empty_key(k); }
+};
+#endif
+
+#ifdef _SPARSE_HASH_MAP_H_
+/** Represents a google::sparse_hash_map
+ *
+ * \see RandomSetter
+ */
+template<typename Scalar> struct GoogleSparseHashMapTraits
+{
+ typedef int KeyType;
+ typedef google::sparse_hash_map<KeyType,Scalar> Type;
+ enum {
+ IsSorted = 0
+ };
+
+ static void setInvalidKey(Type&, const KeyType&) {}
+};
+#endif
+
+/** \class RandomSetter
+ *
+ * \brief The RandomSetter is a wrapper object allowing to set/update a sparse matrix with random access
+ *
+ * \param SparseMatrixType the type of the sparse matrix we are updating
+ * \param MapTraits a traits class representing the map implementation used for the temporary sparse storage.
+ * Its default value depends on the system.
+ * \param OuterPacketBits defines the number of rows (or columns) manage by a single map object
+ * as a power of two exponent.
+ *
+ * This class temporarily represents a sparse matrix object using a generic map implementation allowing for
+ * efficient random access. The conversion from the compressed representation to a hash_map object is performed
+ * in the RandomSetter constructor, while the sparse matrix is updated back at destruction time. This strategy
+ * suggest the use of nested blocks as in this example:
+ *
+ * \code
+ * SparseMatrix<double> m(rows,cols);
+ * {
+ * RandomSetter<SparseMatrix<double> > w(m);
+ * // don't use m but w instead with read/write random access to the coefficients:
+ * for(;;)
+ * w(rand(),rand()) = rand;
+ * }
+ * // when w is deleted, the data are copied back to m
+ * // and m is ready to use.
+ * \endcode
+ *
+ * Since hash_map objects are not fully sorted, representing a full matrix as a single hash_map would
+ * involve a big and costly sort to update the compressed matrix back. To overcome this issue, a RandomSetter
+ * use multiple hash_map, each representing 2^OuterPacketBits columns or rows according to the storage order.
+ * To reach optimal performance, this value should be adjusted according to the average number of nonzeros
+ * per rows/columns.
+ *
+ * The possible values for the template parameter MapTraits are:
+ * - \b StdMapTraits: corresponds to std::map. (does not perform very well)
+ * - \b GnuHashMapTraits: corresponds to __gnu_cxx::hash_map (available only with GCC)
+ * - \b GoogleDenseHashMapTraits: corresponds to google::dense_hash_map (best efficiency, reasonable memory consumption)
+ * - \b GoogleSparseHashMapTraits: corresponds to google::sparse_hash_map (best memory consumption, relatively good performance)
+ *
+ * The default map implementation depends on the availability, and the preferred order is:
+ * GoogleSparseHashMapTraits, GnuHashMapTraits, and finally StdMapTraits.
+ *
+ * For performance and memory consumption reasons it is highly recommended to use one of
+ * the Google's hash_map implementation. To enable the support for them, you have two options:
+ * - \#include <google/dense_hash_map> yourself \b before Eigen/Sparse header
+ * - define EIGEN_GOOGLEHASH_SUPPORT
+ * In the later case the inclusion of <google/dense_hash_map> is made for you.
+ *
+ * \see http://code.google.com/p/google-sparsehash/
+ */
+template<typename SparseMatrixType,
+ template <typename T> class MapTraits =
+#if defined _DENSE_HASH_MAP_H_
+ GoogleDenseHashMapTraits
+#elif defined _HASH_MAP
+ GnuHashMapTraits
+#else
+ StdMapTraits
+#endif
+ ,int OuterPacketBits = 6>
+class RandomSetter
+{
+ typedef typename ei_traits<SparseMatrixType>::Scalar Scalar;
+ struct ScalarWrapper
+ {
+ ScalarWrapper() : value(0) {}
+ Scalar value;
+ };
+ typedef typename MapTraits<ScalarWrapper>::KeyType KeyType;
+ typedef typename MapTraits<ScalarWrapper>::Type HashMapType;
+ static const int OuterPacketMask = (1 << OuterPacketBits) - 1;
+ enum {
+ SwapStorage = 1 - MapTraits<ScalarWrapper>::IsSorted,
+ TargetRowMajor = (SparseMatrixType::Flags & RowMajorBit) ? 1 : 0,
+ SetterRowMajor = SwapStorage ? 1-TargetRowMajor : TargetRowMajor,
+ IsUpperTriangular = SparseMatrixType::Flags & UpperTriangularBit,
+ IsLowerTriangular = SparseMatrixType::Flags & LowerTriangularBit
+ };
+
+ public:
+
+ /** Constructs a random setter object from the sparse matrix \a target
+ *
+ * Note that the initial value of \a target are imported. If you want to re-set
+ * a sparse matrix from scratch, then you must set it to zero first using the
+ * setZero() function.
+ */
+ inline RandomSetter(SparseMatrixType& target)
+ : mp_target(&target)
+ {
+ const int outerSize = SwapStorage ? target.innerSize() : target.outerSize();
+ const int innerSize = SwapStorage ? target.outerSize() : target.innerSize();
+ m_outerPackets = outerSize >> OuterPacketBits;
+ if (outerSize&OuterPacketMask)
+ m_outerPackets += 1;
+ m_hashmaps = new HashMapType[m_outerPackets];
+ // compute number of bits needed to store inner indices
+ int aux = innerSize - 1;
+ m_keyBitsOffset = 0;
+ while (aux)
+ {
+ ++m_keyBitsOffset;
+ aux = aux >> 1;
+ }
+ KeyType ik = (1<<(OuterPacketBits+m_keyBitsOffset));
+ for (int k=0; k<m_outerPackets; ++k)
+ MapTraits<ScalarWrapper>::setInvalidKey(m_hashmaps[k],ik);
+
+ // insert current coeffs
+ for (int j=0; j<mp_target->outerSize(); ++j)
+ for (typename SparseMatrixType::InnerIterator it(*mp_target,j); it; ++it)
+ (*this)(TargetRowMajor?j:it.index(), TargetRowMajor?it.index():j) = it.value();
+ }
+
+ /** Destructor updating back the sparse matrix target */
+ ~RandomSetter()
+ {
+ KeyType keyBitsMask = (1<<m_keyBitsOffset)-1;
+ if (!SwapStorage) // also means the map is sorted
+ {
+ mp_target->startFill(nonZeros());
+ for (int k=0; k<m_outerPackets; ++k)
+ {
+ const int outerOffset = (1<<OuterPacketBits) * k;
+ typename HashMapType::iterator end = m_hashmaps[k].end();
+ for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it!=end; ++it)
+ {
+ const int outer = (it->first >> m_keyBitsOffset) + outerOffset;
+ const int inner = it->first & keyBitsMask;
+ mp_target->fill(TargetRowMajor ? outer : inner, TargetRowMajor ? inner : outer) = it->second.value;
+ }
+ }
+ mp_target->endFill();
+ }
+ else
+ {
+ VectorXi positions(mp_target->outerSize());
+ positions.setZero();
+ // pass 1
+ for (int k=0; k<m_outerPackets; ++k)
+ {
+ typename HashMapType::iterator end = m_hashmaps[k].end();
+ for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it!=end; ++it)
+ {
+ const int outer = it->first & keyBitsMask;
+ ++positions[outer];
+ }
+ }
+ // prefix sum
+ int count = 0;
+ for (int j=0; j<mp_target->outerSize(); ++j)
+ {
+ int tmp = positions[j];
+ mp_target->_outerIndexPtr()[j] = count;
+ positions[j] = count;
+ count += tmp;
+ }
+ mp_target->_outerIndexPtr()[mp_target->outerSize()] = count;
+ mp_target->resizeNonZeros(count);
+ // pass 2
+ for (int k=0; k<m_outerPackets; ++k)
+ {
+ const int outerOffset = (1<<OuterPacketBits) * k;
+ typename HashMapType::iterator end = m_hashmaps[k].end();
+ for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it!=end; ++it)
+ {
+ const int inner = (it->first >> m_keyBitsOffset) + outerOffset;
+ const int outer = it->first & keyBitsMask;
+ // sorted insertion
+ // Note that we have to deal with at most 2^OuterPacketBits unsorted coefficients,
+ // moreover those 2^OuterPacketBits coeffs are likely to be sparse, an so only a
+ // small fraction of them have to be sorted, whence the following simple procedure:
+ int posStart = mp_target->_outerIndexPtr()[outer];
+ int i = (positions[outer]++) - 1;
+ while ( (i >= posStart) && (mp_target->_innerIndexPtr()[i] > inner) )
+ {
+ mp_target->_valuePtr()[i+1] = mp_target->_valuePtr()[i];
+ mp_target->_innerIndexPtr()[i+1] = mp_target->_innerIndexPtr()[i];
+ --i;
+ }
+ mp_target->_innerIndexPtr()[i+1] = inner;
+ mp_target->_valuePtr()[i+1] = it->second.value;
+ }
+ }
+ }
+ delete[] m_hashmaps;
+ }
+
+ /** \returns a reference to the coefficient at given coordinates \a row, \a col */
+ Scalar& operator() (int row, int col)
+ {
+ ei_assert(((!IsUpperTriangular) || (row<=col)) && "Invalid access to an upper triangular matrix");
+ ei_assert(((!IsLowerTriangular) || (col<=row)) && "Invalid access to an upper triangular matrix");
+ const int outer = SetterRowMajor ? row : col;
+ const int inner = SetterRowMajor ? col : row;
+ const int outerMajor = outer >> OuterPacketBits; // index of the packet/map
+ const int outerMinor = outer & OuterPacketMask; // index of the inner vector in the packet
+ const KeyType key = (KeyType(outerMinor)<<m_keyBitsOffset) | inner;
+ return m_hashmaps[outerMajor][key].value;
+ }
+
+ /** \returns the number of non zero coefficients
+ *
+ * \note According to the underlying map/hash_map implementation,
+ * this function might be quite expensive.
+ */
+ int nonZeros() const
+ {
+ int nz = 0;
+ for (int k=0; k<m_outerPackets; ++k)
+ nz += m_hashmaps[k].size();
+ return nz;
+ }
+
+
+ protected:
+
+ HashMapType* m_hashmaps;
+ SparseMatrixType* mp_target;
+ int m_outerPackets;
+ unsigned char m_keyBitsOffset;
+};
+
+#endif // EIGEN_RANDOMSETTER_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseAssign.h b/extern/Eigen2/Eigen/src/Sparse/SparseAssign.h
index e69de29bb2d..e69de29bb2d 100644
--- a/extern/Eigen3/Eigen/src/Sparse/SparseAssign.h
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseAssign.h
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseBlock.h b/extern/Eigen2/Eigen/src/Sparse/SparseBlock.h
index 8079c999994..ae77a77879b 100644
--- a/extern/Eigen3/Eigen/src/Sparse/SparseBlock.h
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseBlock.h
@@ -1,7 +1,8 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -25,58 +26,49 @@
#ifndef EIGEN_SPARSE_BLOCK_H
#define EIGEN_SPARSE_BLOCK_H
-namespace internal {
template<typename MatrixType, int Size>
-struct traits<SparseInnerVectorSet<MatrixType, Size> >
+struct ei_traits<SparseInnerVectorSet<MatrixType, Size> >
{
- typedef typename traits<MatrixType>::Scalar Scalar;
- typedef typename traits<MatrixType>::Index Index;
- typedef typename traits<MatrixType>::StorageKind StorageKind;
- typedef MatrixXpr XprKind;
+ typedef typename ei_traits<MatrixType>::Scalar Scalar;
enum {
IsRowMajor = (int(MatrixType::Flags)&RowMajorBit)==RowMajorBit,
Flags = MatrixType::Flags,
RowsAtCompileTime = IsRowMajor ? Size : MatrixType::RowsAtCompileTime,
ColsAtCompileTime = IsRowMajor ? MatrixType::ColsAtCompileTime : Size,
- MaxRowsAtCompileTime = RowsAtCompileTime,
- MaxColsAtCompileTime = ColsAtCompileTime,
CoeffReadCost = MatrixType::CoeffReadCost
};
};
-} // end namespace internal
template<typename MatrixType, int Size>
-class SparseInnerVectorSet : internal::no_assignment_operator,
+class SparseInnerVectorSet : ei_no_assignment_operator,
public SparseMatrixBase<SparseInnerVectorSet<MatrixType, Size> >
{
+ enum { IsRowMajor = ei_traits<SparseInnerVectorSet>::IsRowMajor };
public:
- enum { IsRowMajor = internal::traits<SparseInnerVectorSet>::IsRowMajor };
-
- EIGEN_SPARSE_PUBLIC_INTERFACE(SparseInnerVectorSet)
+ EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseInnerVectorSet)
class InnerIterator: public MatrixType::InnerIterator
{
public:
- inline InnerIterator(const SparseInnerVectorSet& xpr, Index outer)
- : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
+ inline InnerIterator(const SparseInnerVectorSet& xpr, int outer)
+ : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + 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;
+
+ private:
+ InnerIterator& operator=(const InnerIterator&);
};
- inline SparseInnerVectorSet(const MatrixType& matrix, Index outerStart, Index outerSize)
+ inline SparseInnerVectorSet(const MatrixType& matrix, int outerStart, int outerSize)
: m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize)
{
- eigen_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
+ ei_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
}
- inline SparseInnerVectorSet(const MatrixType& matrix, Index outer)
+ inline SparseInnerVectorSet(const MatrixType& matrix, int outer)
: m_matrix(matrix), m_outerStart(outer), m_outerSize(Size)
{
- eigen_assert(Size!=Dynamic);
- eigen_assert( (outer>=0) && (outer<matrix.outerSize()) );
+ ei_assert(Size!=Dynamic);
+ ei_assert( (outer>=0) && (outer<matrix.outerSize()) );
}
// template<typename OtherDerived>
@@ -91,14 +83,15 @@ class SparseInnerVectorSet : internal::no_assignment_operator,
// return *this;
// }
- 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(); }
+ EIGEN_STRONG_INLINE int rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
+ EIGEN_STRONG_INLINE int cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
protected:
const typename MatrixType::Nested m_matrix;
- Index m_outerStart;
- const internal::variable_if_dynamic<Index, Size> m_outerSize;
+ int m_outerStart;
+ const ei_int_if_dynamic<Size> m_outerSize;
+
};
/***************************************************************************
@@ -110,34 +103,31 @@ class SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options>, Size>
: public SparseMatrixBase<SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options>, Size> >
{
typedef DynamicSparseMatrix<_Scalar, _Options> MatrixType;
+ enum { IsRowMajor = ei_traits<SparseInnerVectorSet>::IsRowMajor };
public:
- enum { IsRowMajor = internal::traits<SparseInnerVectorSet>::IsRowMajor };
-
- EIGEN_SPARSE_PUBLIC_INTERFACE(SparseInnerVectorSet)
+ EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseInnerVectorSet)
class InnerIterator: public MatrixType::InnerIterator
{
public:
- inline InnerIterator(const SparseInnerVectorSet& xpr, Index outer)
- : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
+ inline InnerIterator(const SparseInnerVectorSet& xpr, int outer)
+ : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + 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;
+ private:
+ InnerIterator& operator=(const InnerIterator&);
};
- inline SparseInnerVectorSet(const MatrixType& matrix, Index outerStart, Index outerSize)
+ inline SparseInnerVectorSet(const MatrixType& matrix, int outerStart, int outerSize)
: m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize)
{
- eigen_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
+ ei_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
}
- inline SparseInnerVectorSet(const MatrixType& matrix, Index outer)
+ inline SparseInnerVectorSet(const MatrixType& matrix, int outer)
: m_matrix(matrix), m_outerStart(outer), m_outerSize(Size)
{
- eigen_assert(Size!=Dynamic);
- eigen_assert( (outer>=0) && (outer<matrix.outerSize()) );
+ ei_assert(Size!=Dynamic);
+ ei_assert( (outer>=0) && (outer<matrix.outerSize()) );
}
template<typename OtherDerived>
@@ -152,7 +142,7 @@ class SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options>, Size>
else
{
// evaluate/copy vector per vector
- for (Index j=0; j<m_outerSize.value(); ++j)
+ for (int j=0; j<m_outerSize.value(); ++j)
{
SparseVector<Scalar,IsRowMajor ? RowMajorBit : 0> aux(other.innerVector(j));
m_matrix.const_cast_derived()._data()[m_outerStart+j].swap(aux._data());
@@ -166,35 +156,20 @@ class SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options>, Size>
return operator=<SparseInnerVectorSet>(other);
}
- Index nonZeros() const
- {
- Index count = 0;
- for (Index j=0; j<m_outerSize.value(); ++j)
- count += m_matrix._data()[m_outerStart+j].size();
- return count;
- }
-
- const Scalar& lastCoeff() const
- {
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(SparseInnerVectorSet);
- eigen_assert(m_matrix.data()[m_outerStart].size()>0);
- return m_matrix.data()[m_outerStart].vale(m_matrix.data()[m_outerStart].size()-1);
- }
-
// template<typename Sparse>
// inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
// {
// return *this;
// }
- 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(); }
+ EIGEN_STRONG_INLINE int rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
+ EIGEN_STRONG_INLINE int cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
protected:
const typename MatrixType::Nested m_matrix;
- Index m_outerStart;
- const internal::variable_if_dynamic<Index, Size> m_outerSize;
+ int m_outerStart;
+ const ei_int_if_dynamic<Size> m_outerSize;
};
@@ -202,113 +177,55 @@ class SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options>, Size>
/***************************************************************************
* specialisation for SparseMatrix
***************************************************************************/
-
-template<typename _Scalar, int _Options, typename _Index, int Size>
-class SparseInnerVectorSet<SparseMatrix<_Scalar, _Options, _Index>, Size>
+/*
+template<typename _Scalar, int _Options, int Size>
+class SparseInnerVectorSet<SparseMatrix<_Scalar, _Options>, Size>
: public SparseMatrixBase<SparseInnerVectorSet<SparseMatrix<_Scalar, _Options>, Size> >
{
- typedef SparseMatrix<_Scalar, _Options> MatrixType;
+ typedef DynamicSparseMatrix<_Scalar, _Options> MatrixType;
+ enum { IsRowMajor = ei_traits<SparseInnerVectorSet>::IsRowMajor };
public:
- enum { IsRowMajor = internal::traits<SparseInnerVectorSet>::IsRowMajor };
-
- EIGEN_SPARSE_PUBLIC_INTERFACE(SparseInnerVectorSet)
+ EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseInnerVectorSet)
class InnerIterator: public MatrixType::InnerIterator
{
public:
- inline InnerIterator(const SparseInnerVectorSet& xpr, Index outer)
- : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer)
+ inline InnerIterator(const SparseInnerVectorSet& xpr, int outer)
+ : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + 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 SparseInnerVectorSet(const MatrixType& matrix, Index outerStart, Index outerSize)
+ inline SparseInnerVectorSet(const MatrixType& matrix, int outerStart, int outerSize)
: m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize)
{
- eigen_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
+ ei_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) );
}
- inline SparseInnerVectorSet(const MatrixType& matrix, Index outer)
- : m_matrix(matrix), m_outerStart(outer), m_outerSize(Size)
+ inline SparseInnerVectorSet(const MatrixType& matrix, int outer)
+ : m_matrix(matrix), m_outerStart(outer)
{
- eigen_assert(Size==1);
- eigen_assert( (outer>=0) && (outer<matrix.outerSize()) );
+ ei_assert(Size==1);
+ ei_assert( (outer>=0) && (outer<matrix.outerSize()) );
}
template<typename OtherDerived>
inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
{
- typedef typename internal::remove_all<typename MatrixType::Nested>::type _NestedMatrixType;
- _NestedMatrixType& matrix = const_cast<_NestedMatrixType&>(m_matrix);;
- // This assignement is slow if this vector set not empty
- // and/or it is not at the end of the nonzeros of the underlying matrix.
-
- // 1 - eval to a temporary to avoid transposition and/or aliasing issues
- SparseMatrix<Scalar, IsRowMajor ? RowMajor : ColMajor, Index> tmp(other);
-
- // 2 - let's check whether there is enough allocated memory
- Index nnz = tmp.nonZeros();
- Index nnz_previous = nonZeros();
- Index free_size = matrix.data().allocatedSize() - nnz_previous;
- std::size_t nnz_head = m_outerStart==0 ? 0 : matrix._outerIndexPtr()[m_outerStart];
- std::size_t tail = m_matrix._outerIndexPtr()[m_outerStart+m_outerSize.value()];
- std::size_t nnz_tail = matrix.nonZeros() - tail;
-
- if(nnz>free_size)
+ if (IsRowMajor != ((OtherDerived::Flags&RowMajorBit)==RowMajorBit))
{
- // realloc manually to reduce copies
- typename MatrixType::Storage newdata(m_matrix.nonZeros() - nnz_previous + nnz);
-
- std::memcpy(&newdata.value(0), &m_matrix.data().value(0), nnz_head*sizeof(Scalar));
- std::memcpy(&newdata.index(0), &m_matrix.data().index(0), nnz_head*sizeof(Index));
-
- std::memcpy(&newdata.value(nnz_head), &tmp.data().value(0), nnz*sizeof(Scalar));
- std::memcpy(&newdata.index(nnz_head), &tmp.data().index(0), nnz*sizeof(Index));
-
- std::memcpy(&newdata.value(nnz_head+nnz), &matrix.data().value(tail), nnz_tail*sizeof(Scalar));
- std::memcpy(&newdata.index(nnz_head+nnz), &matrix.data().index(tail), nnz_tail*sizeof(Index));
-
- matrix.data().swap(newdata);
+ // need to transpose => perform a block evaluation followed by a big swap
+ DynamicSparseMatrix<Scalar,IsRowMajor?RowMajorBit:0> aux(other);
+ *this = aux.markAsRValue();
}
else
{
- // no need to realloc, simply copy the tail at its respective position and insert tmp
- matrix.data().resize(nnz_head + nnz + nnz_tail);
-
- if(nnz<nnz_previous)
- {
- std::memcpy(&matrix.data().value(nnz_head+nnz), &matrix.data().value(tail), nnz_tail*sizeof(Scalar));
- std::memcpy(&matrix.data().index(nnz_head+nnz), &matrix.data().index(tail), nnz_tail*sizeof(Index));
- }
- else
+ // evaluate/copy vector per vector
+ for (int j=0; j<m_outerSize.value(); ++j)
{
- for(Index i=nnz_tail-1; i>=0; --i)
- {
- matrix.data().value(nnz_head+nnz+i) = matrix.data().value(tail+i);
- matrix.data().index(nnz_head+nnz+i) = matrix.data().index(tail+i);
- }
+ SparseVector<Scalar,IsRowMajor ? RowMajorBit : 0> aux(other.innerVector(j));
+ m_matrix.const_cast_derived()._data()[m_outerStart+j].swap(aux._data());
}
-
- std::memcpy(&matrix.data().value(nnz_head), &tmp.data().value(0), nnz*sizeof(Scalar));
- std::memcpy(&matrix.data().index(nnz_head), &tmp.data().index(0), nnz*sizeof(Index));
}
-
- // update outer index pointers
- Index p = nnz_head;
- for(Index k=1; k<m_outerSize.value(); ++k)
- {
- matrix._outerIndexPtr()[m_outerStart+k] = p;
- p += tmp.innerVector(k).nonZeros();
- }
- std::ptrdiff_t offset = nnz - nnz_previous;
- for(Index k = m_outerStart + m_outerSize.value(); k<=matrix.outerSize(); ++k)
- {
- matrix._outerIndexPtr()[k] += offset;
- }
-
return *this;
}
@@ -319,31 +236,9 @@ class SparseInnerVectorSet<SparseMatrix<_Scalar, _Options, _Index>, Size>
inline const Scalar* _valuePtr() const
{ return m_matrix._valuePtr() + m_matrix._outerIndexPtr()[m_outerStart]; }
- inline Scalar* _valuePtr()
- { return m_matrix.const_cast_derived()._valuePtr() + m_matrix._outerIndexPtr()[m_outerStart]; }
-
- inline const Index* _innerIndexPtr() const
+ inline const int* _innerIndexPtr() const
{ return m_matrix._innerIndexPtr() + m_matrix._outerIndexPtr()[m_outerStart]; }
- inline Index* _innerIndexPtr()
- { return m_matrix.const_cast_derived()._innerIndexPtr() + m_matrix._outerIndexPtr()[m_outerStart]; }
-
- inline const Index* _outerIndexPtr() const
- { return m_matrix._outerIndexPtr() + m_outerStart; }
- inline Index* _outerIndexPtr()
- { return m_matrix.const_cast_derived()._outerIndexPtr() + m_outerStart; }
-
- Index nonZeros() const
- {
- return std::size_t(m_matrix._outerIndexPtr()[m_outerStart+m_outerSize.value()])
- - std::size_t(m_matrix._outerIndexPtr()[m_outerStart]);
- }
-
- const Scalar& lastCoeff() const
- {
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(SparseInnerVectorSet);
- eigen_assert(nonZeros()>0);
- return m_matrix._valuePtr()[m_matrix._outerIndexPtr()[m_outerStart+1]-1];
- }
+ inline const int* _outerIndexPtr() const { return m_matrix._outerIndexPtr() + m_outerStart; }
// template<typename Sparse>
// inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other)
@@ -351,22 +246,22 @@ class SparseInnerVectorSet<SparseMatrix<_Scalar, _Options, _Index>, Size>
// return *this;
// }
- 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(); }
+ EIGEN_STRONG_INLINE int rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); }
+ EIGEN_STRONG_INLINE int cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); }
protected:
const typename MatrixType::Nested m_matrix;
- Index m_outerStart;
- const internal::variable_if_dynamic<Index, Size> m_outerSize;
+ int m_outerStart;
+ const ei_int_if_dynamic<Size> m_outerSize;
};
-
+*/
//----------
/** \returns the i-th row of the matrix \c *this. For row-major matrix only. */
template<typename Derived>
-SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(Index i)
+SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(int i)
{
EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
return innerVector(i);
@@ -375,7 +270,7 @@ SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(Index i)
/** \returns the i-th row of the matrix \c *this. For row-major matrix only.
* (read-only version) */
template<typename Derived>
-const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(Index i) const
+const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(int i) const
{
EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
return innerVector(i);
@@ -383,7 +278,7 @@ const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::row(Index i) co
/** \returns the i-th column of the matrix \c *this. For column-major matrix only. */
template<typename Derived>
-SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(Index i)
+SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(int i)
{
EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
return innerVector(i);
@@ -392,7 +287,7 @@ SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(Index i)
/** \returns the i-th column of the matrix \c *this. For column-major matrix only.
* (read-only version) */
template<typename Derived>
-const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(Index i) const
+const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(int i) const
{
EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
return innerVector(i);
@@ -402,21 +297,21 @@ const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::col(Index i) co
* is col-major (resp. row-major).
*/
template<typename Derived>
-SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::innerVector(Index outer)
+SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::innerVector(int outer)
{ return SparseInnerVectorSet<Derived,1>(derived(), outer); }
/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
* is col-major (resp. row-major). Read-only.
*/
template<typename Derived>
-const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::innerVector(Index outer) const
+const SparseInnerVectorSet<Derived,1> SparseMatrixBase<Derived>::innerVector(int outer) const
{ return SparseInnerVectorSet<Derived,1>(derived(), outer); }
//----------
/** \returns the i-th row of the matrix \c *this. For row-major matrix only. */
template<typename Derived>
-SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subrows(Index start, Index size)
+SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subrows(int start, int size)
{
EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
return innerVectors(start, size);
@@ -425,7 +320,7 @@ SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subrows(Index s
/** \returns the i-th row of the matrix \c *this. For row-major matrix only.
* (read-only version) */
template<typename Derived>
-const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subrows(Index start, Index size) const
+const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subrows(int start, int size) const
{
EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES);
return innerVectors(start, size);
@@ -433,7 +328,7 @@ const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subrows(I
/** \returns the i-th column of the matrix \c *this. For column-major matrix only. */
template<typename Derived>
-SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subcols(Index start, Index size)
+SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subcols(int start, int size)
{
EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
return innerVectors(start, size);
@@ -442,7 +337,7 @@ SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subcols(Index s
/** \returns the i-th column of the matrix \c *this. For column-major matrix only.
* (read-only version) */
template<typename Derived>
-const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subcols(Index start, Index size) const
+const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subcols(int start, int size) const
{
EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
return innerVectors(start, size);
@@ -452,14 +347,108 @@ const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::subcols(I
* is col-major (resp. row-major).
*/
template<typename Derived>
-SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize)
+SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::innerVectors(int outerStart, int outerSize)
{ return SparseInnerVectorSet<Derived,Dynamic>(derived(), outerStart, outerSize); }
/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this
* is col-major (resp. row-major). Read-only.
*/
template<typename Derived>
-const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::innerVectors(Index outerStart, Index outerSize) const
+const SparseInnerVectorSet<Derived,Dynamic> SparseMatrixBase<Derived>::innerVectors(int outerStart, int outerSize) const
{ return SparseInnerVectorSet<Derived,Dynamic>(derived(), outerStart, outerSize); }
+# if 0
+template<typename MatrixType, int BlockRows, int BlockCols, int PacketAccess>
+class Block<MatrixType,BlockRows,BlockCols,PacketAccess,IsSparse>
+ : public SparseMatrixBase<Block<MatrixType,BlockRows,BlockCols,PacketAccess,IsSparse> >
+{
+public:
+
+ _EIGEN_GENERIC_PUBLIC_INTERFACE(Block, SparseMatrixBase<Block>)
+ class InnerIterator;
+
+ /** Column or Row constructor
+ */
+ inline Block(const MatrixType& matrix, int i)
+ : m_matrix(matrix),
+ // It is a row if and only if BlockRows==1 and BlockCols==MatrixType::ColsAtCompileTime,
+ // and it is a column if and only if BlockRows==MatrixType::RowsAtCompileTime and BlockCols==1,
+ // all other cases are invalid.
+ // The case a 1x1 matrix seems ambiguous, but the result is the same anyway.
+ m_startRow( (BlockRows==1) && (BlockCols==MatrixType::ColsAtCompileTime) ? i : 0),
+ m_startCol( (BlockRows==MatrixType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
+ m_blockRows(matrix.rows()), // if it is a row, then m_blockRows has a fixed-size of 1, so no pb to try to overwrite it
+ m_blockCols(matrix.cols()) // same for m_blockCols
+ {
+ ei_assert( (i>=0) && (
+ ((BlockRows==1) && (BlockCols==MatrixType::ColsAtCompileTime) && i<matrix.rows())
+ ||((BlockRows==MatrixType::RowsAtCompileTime) && (BlockCols==1) && i<matrix.cols())));
+ }
+
+ /** Fixed-size constructor
+ */
+ inline Block(const MatrixType& matrix, int startRow, int startCol)
+ : m_matrix(matrix), m_startRow(startRow), m_startCol(startCol),
+ m_blockRows(matrix.rows()), m_blockCols(matrix.cols())
+ {
+ EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && RowsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
+ ei_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= matrix.rows()
+ && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= matrix.cols());
+ }
+
+ /** Dynamic-size constructor
+ */
+ inline Block(const MatrixType& matrix,
+ int startRow, int startCol,
+ int blockRows, int blockCols)
+ : m_matrix(matrix), m_startRow(startRow), m_startCol(startCol),
+ m_blockRows(blockRows), m_blockCols(blockCols)
+ {
+ ei_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
+ && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
+ ei_assert(startRow >= 0 && blockRows >= 1 && startRow + blockRows <= matrix.rows()
+ && startCol >= 0 && blockCols >= 1 && startCol + blockCols <= matrix.cols());
+ }
+
+ inline int rows() const { return m_blockRows.value(); }
+ inline int cols() const { return m_blockCols.value(); }
+
+ inline int stride(void) const { return m_matrix.stride(); }
+
+ inline Scalar& coeffRef(int row, int col)
+ {
+ return m_matrix.const_cast_derived()
+ .coeffRef(row + m_startRow.value(), col + m_startCol.value());
+ }
+
+ inline const Scalar coeff(int row, int col) const
+ {
+ return m_matrix.coeff(row + m_startRow.value(), col + m_startCol.value());
+ }
+
+ inline Scalar& coeffRef(int index)
+ {
+ return m_matrix.const_cast_derived()
+ .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
+ m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
+ }
+
+ inline const Scalar coeff(int index) const
+ {
+ return m_matrix
+ .coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
+ m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
+ }
+
+ protected:
+
+ const typename MatrixType::Nested m_matrix;
+ const ei_int_if_dynamic<MatrixType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow;
+ const ei_int_if_dynamic<MatrixType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol;
+ const ei_int_if_dynamic<RowsAtCompileTime> m_blockRows;
+ const ei_int_if_dynamic<ColsAtCompileTime> m_blockCols;
+
+};
+#endif
+
#endif // EIGEN_SPARSE_BLOCK_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/SparseCwise.h b/extern/Eigen2/Eigen/src/Sparse/SparseCwise.h
new file mode 100644
index 00000000000..ac285ec1aa3
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseCwise.h
@@ -0,0 +1,178 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SPARSE_CWISE_H
+#define EIGEN_SPARSE_CWISE_H
+
+/** \internal
+ * convenient macro to defined the return type of a cwise binary operation */
+#define EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(OP) \
+ CwiseBinaryOp<OP<typename ei_traits<ExpressionType>::Scalar>, ExpressionType, OtherDerived>
+
+#define EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE \
+ SparseCwiseBinaryOp< \
+ ei_scalar_product_op< \
+ typename ei_scalar_product_traits< \
+ typename ei_traits<ExpressionType>::Scalar, \
+ typename ei_traits<OtherDerived>::Scalar \
+ >::ReturnType \
+ >, \
+ ExpressionType, \
+ OtherDerived \
+ >
+
+/** \internal
+ * convenient macro to defined the return type of a cwise unary operation */
+#define EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(OP) \
+ SparseCwiseUnaryOp<OP<typename ei_traits<ExpressionType>::Scalar>, ExpressionType>
+
+/** \internal
+ * convenient macro to defined the return type of a cwise comparison to a scalar */
+/*#define EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(OP) \
+ CwiseBinaryOp<OP<typename ei_traits<ExpressionType>::Scalar>, ExpressionType, \
+ NestByValue<typename ExpressionType::ConstantReturnType> >*/
+
+template<typename ExpressionType> class SparseCwise
+{
+ public:
+
+ typedef typename ei_traits<ExpressionType>::Scalar Scalar;
+ typedef typename ei_meta_if<ei_must_nest_by_value<ExpressionType>::ret,
+ ExpressionType, const ExpressionType&>::ret ExpressionTypeNested;
+ typedef CwiseUnaryOp<ei_scalar_add_op<Scalar>, ExpressionType> ScalarAddReturnType;
+
+ inline SparseCwise(const ExpressionType& matrix) : m_matrix(matrix) {}
+
+ /** \internal */
+ inline const ExpressionType& _expression() const { return m_matrix; }
+
+ template<typename OtherDerived>
+ const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
+ operator*(const SparseMatrixBase<OtherDerived> &other) const;
+
+ template<typename OtherDerived>
+ const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
+ operator*(const MatrixBase<OtherDerived> &other) const;
+
+// template<typename OtherDerived>
+// const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
+// operator/(const SparseMatrixBase<OtherDerived> &other) const;
+//
+// template<typename OtherDerived>
+// const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
+// operator/(const MatrixBase<OtherDerived> &other) const;
+
+ template<typename OtherDerived>
+ const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)
+ min(const SparseMatrixBase<OtherDerived> &other) const;
+
+ template<typename OtherDerived>
+ const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)
+ max(const SparseMatrixBase<OtherDerived> &other) const;
+
+ const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs_op) abs() const;
+ const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs2_op) abs2() const;
+// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_square_op) square() const;
+// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_cube_op) cube() const;
+// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_inverse_op) inverse() const;
+// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_sqrt_op) sqrt() const;
+// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_exp_op) exp() const;
+// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_log_op) log() const;
+// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_cos_op) cos() const;
+// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_sin_op) sin() const;
+// const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_pow_op) pow(const Scalar& exponent) const;
+
+ template<typename OtherDerived>
+ inline ExpressionType& operator*=(const SparseMatrixBase<OtherDerived> &other);
+
+// template<typename OtherDerived>
+// inline ExpressionType& operator/=(const SparseMatrixBase<OtherDerived> &other);
+
+ /*
+ template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)
+ operator<(const MatrixBase<OtherDerived>& other) const;
+
+ template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less_equal)
+ operator<=(const MatrixBase<OtherDerived>& other) const;
+
+ template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater)
+ operator>(const MatrixBase<OtherDerived>& other) const;
+
+ template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater_equal)
+ operator>=(const MatrixBase<OtherDerived>& other) const;
+
+ template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::equal_to)
+ operator==(const MatrixBase<OtherDerived>& other) const;
+
+ template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::not_equal_to)
+ operator!=(const MatrixBase<OtherDerived>& other) const;
+
+ // comparisons to a scalar value
+ const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less)
+ operator<(Scalar s) const;
+
+ const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less_equal)
+ operator<=(Scalar s) const;
+
+ const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater)
+ operator>(Scalar s) const;
+
+ const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater_equal)
+ operator>=(Scalar s) const;
+
+ const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::equal_to)
+ operator==(Scalar s) const;
+
+ const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)
+ operator!=(Scalar s) const;
+ */
+
+ // allow to extend SparseCwise outside Eigen
+ #ifdef EIGEN_SPARSE_CWISE_PLUGIN
+ #include EIGEN_SPARSE_CWISE_PLUGIN
+ #endif
+
+ protected:
+ ExpressionTypeNested m_matrix;
+
+ private:
+ SparseCwise& operator=(const SparseCwise&);
+};
+
+template<typename Derived>
+inline const SparseCwise<Derived>
+SparseMatrixBase<Derived>::cwise() const
+{
+ return derived();
+}
+
+template<typename Derived>
+inline SparseCwise<Derived>
+SparseMatrixBase<Derived>::cwise()
+{
+ return derived();
+}
+
+#endif // EIGEN_SPARSE_CWISE_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/SparseCwiseBinaryOp.h b/extern/Eigen2/Eigen/src/Sparse/SparseCwiseBinaryOp.h
new file mode 100644
index 00000000000..da9746e2099
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseCwiseBinaryOp.h
@@ -0,0 +1,453 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SPARSE_CWISE_BINARY_OP_H
+#define EIGEN_SPARSE_CWISE_BINARY_OP_H
+
+// Here we have to handle 3 cases:
+// 1 - sparse op dense
+// 2 - dense op sparse
+// 3 - sparse op sparse
+// We also need to implement a 4th iterator for:
+// 4 - dense op dense
+// Finally, we also need to distinguish between the product and other operations :
+// configuration returned mode
+// 1 - sparse op dense product sparse
+// generic dense
+// 2 - dense op sparse product sparse
+// generic dense
+// 3 - sparse op sparse product sparse
+// generic sparse
+// 4 - dense op dense product dense
+// generic dense
+
+template<typename BinaryOp, typename Lhs, typename Rhs>
+struct ei_traits<SparseCwiseBinaryOp<BinaryOp, Lhs, Rhs> >
+{
+ typedef typename ei_result_of<
+ BinaryOp(
+ typename Lhs::Scalar,
+ typename Rhs::Scalar
+ )
+ >::type Scalar;
+ typedef typename Lhs::Nested LhsNested;
+ typedef typename Rhs::Nested RhsNested;
+ typedef typename ei_unref<LhsNested>::type _LhsNested;
+ typedef typename ei_unref<RhsNested>::type _RhsNested;
+ enum {
+ LhsCoeffReadCost = _LhsNested::CoeffReadCost,
+ RhsCoeffReadCost = _RhsNested::CoeffReadCost,
+ LhsFlags = _LhsNested::Flags,
+ RhsFlags = _RhsNested::Flags,
+ RowsAtCompileTime = Lhs::RowsAtCompileTime,
+ ColsAtCompileTime = Lhs::ColsAtCompileTime,
+ MaxRowsAtCompileTime = Lhs::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = Lhs::MaxColsAtCompileTime,
+ Flags = (int(LhsFlags) | int(RhsFlags)) & HereditaryBits,
+ CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + ei_functor_traits<BinaryOp>::Cost
+ };
+};
+
+template<typename BinaryOp, typename Lhs, typename Rhs>
+class SparseCwiseBinaryOp : ei_no_assignment_operator,
+ public SparseMatrixBase<SparseCwiseBinaryOp<BinaryOp, Lhs, Rhs> >
+{
+ public:
+
+ class InnerIterator;
+
+ EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseCwiseBinaryOp)
+ typedef typename ei_traits<SparseCwiseBinaryOp>::LhsNested LhsNested;
+ typedef typename ei_traits<SparseCwiseBinaryOp>::RhsNested RhsNested;
+ typedef typename ei_unref<LhsNested>::type _LhsNested;
+ typedef typename ei_unref<RhsNested>::type _RhsNested;
+
+ EIGEN_STRONG_INLINE SparseCwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
+ : m_lhs(lhs), m_rhs(rhs), m_functor(func)
+ {
+ EIGEN_STATIC_ASSERT((_LhsNested::Flags&RowMajorBit)==(_RhsNested::Flags&RowMajorBit),
+ BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER)
+ EIGEN_STATIC_ASSERT((ei_functor_allows_mixing_real_and_complex<BinaryOp>::ret
+ ? int(ei_is_same_type<typename Lhs::RealScalar, typename Rhs::RealScalar>::ret)
+ : int(ei_is_same_type<typename Lhs::Scalar, typename Rhs::Scalar>::ret)),
+ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
+ // require the sizes to match
+ EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs)
+ ei_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
+ }
+
+ EIGEN_STRONG_INLINE int rows() const { return m_lhs.rows(); }
+ EIGEN_STRONG_INLINE int cols() const { return m_lhs.cols(); }
+
+ EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
+ EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
+ EIGEN_STRONG_INLINE const BinaryOp& functor() const { return m_functor; }
+
+ protected:
+ const LhsNested m_lhs;
+ const RhsNested m_rhs;
+ const BinaryOp m_functor;
+};
+
+template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived,
+ int _LhsStorageMode = int(Lhs::Flags) & SparseBit,
+ int _RhsStorageMode = int(Rhs::Flags) & SparseBit>
+class ei_sparse_cwise_binary_op_inner_iterator_selector;
+
+template<typename BinaryOp, typename Lhs, typename Rhs>
+class SparseCwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator
+ : public ei_sparse_cwise_binary_op_inner_iterator_selector<BinaryOp,Lhs,Rhs, typename SparseCwiseBinaryOp<BinaryOp,Lhs,Rhs>::InnerIterator>
+{
+ public:
+ typedef ei_sparse_cwise_binary_op_inner_iterator_selector<
+ BinaryOp,Lhs,Rhs, InnerIterator> Base;
+
+ EIGEN_STRONG_INLINE InnerIterator(const SparseCwiseBinaryOp& binOp, int outer)
+ : Base(binOp,outer)
+ {}
+ private:
+ InnerIterator& operator=(const InnerIterator&);
+};
+
+/***************************************************************************
+* Implementation of inner-iterators
+***************************************************************************/
+
+// template<typename T> struct ei_func_is_conjunction { enum { ret = false }; };
+// template<typename T> struct ei_func_is_conjunction<ei_scalar_product_op<T> > { enum { ret = true }; };
+
+// TODO generalize the ei_scalar_product_op specialization to all conjunctions if any !
+
+// sparse - sparse (generic)
+template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived>
+class ei_sparse_cwise_binary_op_inner_iterator_selector<BinaryOp, Lhs, Rhs, Derived, IsSparse, IsSparse>
+{
+ typedef SparseCwiseBinaryOp<BinaryOp, Lhs, Rhs> CwiseBinaryXpr;
+ typedef typename ei_traits<CwiseBinaryXpr>::Scalar Scalar;
+ typedef typename ei_traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
+ typedef typename ei_traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
+ typedef typename _LhsNested::InnerIterator LhsIterator;
+ typedef typename _RhsNested::InnerIterator RhsIterator;
+ public:
+
+ EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
+ : m_lhsIter(xpr.lhs(),outer), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor())
+ {
+ this->operator++();
+ }
+
+ EIGEN_STRONG_INLINE Derived& operator++()
+ {
+ if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index()))
+ {
+ m_id = m_lhsIter.index();
+ m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
+ ++m_lhsIter;
+ ++m_rhsIter;
+ }
+ else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index())))
+ {
+ m_id = m_lhsIter.index();
+ m_value = m_functor(m_lhsIter.value(), Scalar(0));
+ ++m_lhsIter;
+ }
+ else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index())))
+ {
+ m_id = m_rhsIter.index();
+ m_value = m_functor(Scalar(0), m_rhsIter.value());
+ ++m_rhsIter;
+ }
+ else
+ {
+ m_id = -1;
+ }
+ return *static_cast<Derived*>(this);
+ }
+
+ EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
+
+ EIGEN_STRONG_INLINE int index() const { return m_id; }
+ EIGEN_STRONG_INLINE int row() const { return m_lhsIter.row(); }
+ EIGEN_STRONG_INLINE int col() const { return m_lhsIter.col(); }
+
+ EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; }
+
+ protected:
+ LhsIterator m_lhsIter;
+ RhsIterator m_rhsIter;
+ const BinaryOp& m_functor;
+ Scalar m_value;
+ int m_id;
+
+ private:
+ ei_sparse_cwise_binary_op_inner_iterator_selector& operator=(const ei_sparse_cwise_binary_op_inner_iterator_selector&);
+};
+
+// sparse - sparse (product)
+template<typename T, typename Lhs, typename Rhs, typename Derived>
+class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>, Lhs, Rhs, Derived, IsSparse, IsSparse>
+{
+ typedef ei_scalar_product_op<T> BinaryFunc;
+ typedef SparseCwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
+ typedef typename CwiseBinaryXpr::Scalar Scalar;
+ typedef typename ei_traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
+ typedef typename _LhsNested::InnerIterator LhsIterator;
+ typedef typename ei_traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
+ typedef typename _RhsNested::InnerIterator RhsIterator;
+ public:
+
+ EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
+ : m_lhsIter(xpr.lhs(),outer), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor())
+ {
+ while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
+ {
+ if (m_lhsIter.index() < m_rhsIter.index())
+ ++m_lhsIter;
+ else
+ ++m_rhsIter;
+ }
+ }
+
+ EIGEN_STRONG_INLINE Derived& operator++()
+ {
+ ++m_lhsIter;
+ ++m_rhsIter;
+ while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
+ {
+ if (m_lhsIter.index() < m_rhsIter.index())
+ ++m_lhsIter;
+ else
+ ++m_rhsIter;
+ }
+ return *static_cast<Derived*>(this);
+ }
+
+ EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }
+
+ EIGEN_STRONG_INLINE int index() const { return m_lhsIter.index(); }
+ EIGEN_STRONG_INLINE int row() const { return m_lhsIter.row(); }
+ EIGEN_STRONG_INLINE int col() const { return m_lhsIter.col(); }
+
+ EIGEN_STRONG_INLINE operator bool() const { return (m_lhsIter && m_rhsIter); }
+
+ protected:
+ LhsIterator m_lhsIter;
+ RhsIterator m_rhsIter;
+ const BinaryFunc& m_functor;
+
+ private:
+ ei_sparse_cwise_binary_op_inner_iterator_selector& operator=(const ei_sparse_cwise_binary_op_inner_iterator_selector&);
+};
+
+// sparse - dense (product)
+template<typename T, typename Lhs, typename Rhs, typename Derived>
+class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>, Lhs, Rhs, Derived, IsSparse, IsDense>
+{
+ typedef ei_scalar_product_op<T> BinaryFunc;
+ typedef SparseCwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
+ typedef typename CwiseBinaryXpr::Scalar Scalar;
+ typedef typename ei_traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
+ typedef typename ei_traits<CwiseBinaryXpr>::RhsNested RhsNested;
+ typedef typename _LhsNested::InnerIterator LhsIterator;
+ enum { IsRowMajor = (int(Lhs::Flags)&RowMajorBit)==RowMajorBit };
+ public:
+
+ EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
+ : m_rhs(xpr.rhs()), m_lhsIter(xpr.lhs(),outer), m_functor(xpr.functor()), m_outer(outer)
+ {}
+
+ EIGEN_STRONG_INLINE Derived& operator++()
+ {
+ ++m_lhsIter;
+ return *static_cast<Derived*>(this);
+ }
+
+ EIGEN_STRONG_INLINE Scalar value() const
+ { return m_functor(m_lhsIter.value(),
+ m_rhs.coeff(IsRowMajor?m_outer:m_lhsIter.index(),IsRowMajor?m_lhsIter.index():m_outer)); }
+
+ EIGEN_STRONG_INLINE int index() const { return m_lhsIter.index(); }
+ EIGEN_STRONG_INLINE int row() const { return m_lhsIter.row(); }
+ EIGEN_STRONG_INLINE int col() const { return m_lhsIter.col(); }
+
+ EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; }
+
+ protected:
+ const RhsNested m_rhs;
+ LhsIterator m_lhsIter;
+ const BinaryFunc m_functor;
+ const int m_outer;
+
+ private:
+ ei_sparse_cwise_binary_op_inner_iterator_selector& operator=(const ei_sparse_cwise_binary_op_inner_iterator_selector&);
+};
+
+// sparse - dense (product)
+template<typename T, typename Lhs, typename Rhs, typename Derived>
+class ei_sparse_cwise_binary_op_inner_iterator_selector<ei_scalar_product_op<T>, Lhs, Rhs, Derived, IsDense, IsSparse>
+{
+ typedef ei_scalar_product_op<T> BinaryFunc;
+ typedef SparseCwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
+ typedef typename CwiseBinaryXpr::Scalar Scalar;
+ typedef typename ei_traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
+ typedef typename _RhsNested::InnerIterator RhsIterator;
+ enum { IsRowMajor = (int(Rhs::Flags)&RowMajorBit)==RowMajorBit };
+ public:
+
+ EIGEN_STRONG_INLINE ei_sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, int outer)
+ : m_xpr(xpr), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor()), m_outer(outer)
+ {}
+
+ EIGEN_STRONG_INLINE Derived& operator++()
+ {
+ ++m_rhsIter;
+ return *static_cast<Derived*>(this);
+ }
+
+ EIGEN_STRONG_INLINE Scalar value() const
+ { return m_functor(m_xpr.lhs().coeff(IsRowMajor?m_outer:m_rhsIter.index(),IsRowMajor?m_rhsIter.index():m_outer), m_rhsIter.value()); }
+
+ EIGEN_STRONG_INLINE int index() const { return m_rhsIter.index(); }
+ EIGEN_STRONG_INLINE int row() const { return m_rhsIter.row(); }
+ EIGEN_STRONG_INLINE int col() const { return m_rhsIter.col(); }
+
+ EIGEN_STRONG_INLINE operator bool() const { return m_rhsIter; }
+
+ protected:
+ const CwiseBinaryXpr& m_xpr;
+ RhsIterator m_rhsIter;
+ const BinaryFunc& m_functor;
+ const int m_outer;
+};
+
+
+/***************************************************************************
+* Implementation of SparseMatrixBase and SparseCwise functions/operators
+***************************************************************************/
+
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const SparseCwiseBinaryOp<ei_scalar_difference_op<typename ei_traits<Derived>::Scalar>,
+ Derived, OtherDerived>
+SparseMatrixBase<Derived>::operator-(const SparseMatrixBase<OtherDerived> &other) const
+{
+ return SparseCwiseBinaryOp<ei_scalar_difference_op<Scalar>,
+ Derived, OtherDerived>(derived(), other.derived());
+}
+
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE Derived &
+SparseMatrixBase<Derived>::operator-=(const SparseMatrixBase<OtherDerived> &other)
+{
+ return *this = derived() - other.derived();
+}
+
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const SparseCwiseBinaryOp<ei_scalar_sum_op<typename ei_traits<Derived>::Scalar>, Derived, OtherDerived>
+SparseMatrixBase<Derived>::operator+(const SparseMatrixBase<OtherDerived> &other) const
+{
+ return SparseCwiseBinaryOp<ei_scalar_sum_op<Scalar>, Derived, OtherDerived>(derived(), other.derived());
+}
+
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE Derived &
+SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& other)
+{
+ return *this = derived() + other.derived();
+}
+
+template<typename ExpressionType>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
+SparseCwise<ExpressionType>::operator*(const SparseMatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(_expression(), other.derived());
+}
+
+template<typename ExpressionType>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
+SparseCwise<ExpressionType>::operator*(const MatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(_expression(), other.derived());
+}
+
+// template<typename ExpressionType>
+// template<typename OtherDerived>
+// EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
+// SparseCwise<ExpressionType>::operator/(const SparseMatrixBase<OtherDerived> &other) const
+// {
+// return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)(_expression(), other.derived());
+// }
+//
+// template<typename ExpressionType>
+// template<typename OtherDerived>
+// EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)
+// SparseCwise<ExpressionType>::operator/(const MatrixBase<OtherDerived> &other) const
+// {
+// return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_quotient_op)(_expression(), other.derived());
+// }
+
+template<typename ExpressionType>
+template<typename OtherDerived>
+inline ExpressionType& SparseCwise<ExpressionType>::operator*=(const SparseMatrixBase<OtherDerived> &other)
+{
+ return m_matrix.const_cast_derived() = _expression() * other.derived();
+}
+
+// template<typename ExpressionType>
+// template<typename OtherDerived>
+// inline ExpressionType& SparseCwise<ExpressionType>::operator/=(const SparseMatrixBase<OtherDerived> &other)
+// {
+// return m_matrix.const_cast_derived() = *this / other;
+// }
+
+template<typename ExpressionType>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)
+SparseCwise<ExpressionType>::min(const SparseMatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_min_op)(_expression(), other.derived());
+}
+
+template<typename ExpressionType>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)
+SparseCwise<ExpressionType>::max(const SparseMatrixBase<OtherDerived> &other) const
+{
+ return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(ei_scalar_max_op)(_expression(), other.derived());
+}
+
+// template<typename Derived>
+// template<typename CustomBinaryOp, typename OtherDerived>
+// EIGEN_STRONG_INLINE const CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>
+// SparseMatrixBase<Derived>::binaryExpr(const SparseMatrixBase<OtherDerived> &other, const CustomBinaryOp& func) const
+// {
+// return CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>(derived(), other.derived(), func);
+// }
+
+#endif // EIGEN_SPARSE_CWISE_BINARY_OP_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/SparseCwiseUnaryOp.h b/extern/Eigen2/Eigen/src/Sparse/SparseCwiseUnaryOp.h
new file mode 100644
index 00000000000..2ed7a15579f
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseCwiseUnaryOp.h
@@ -0,0 +1,186 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SPARSE_CWISE_UNARY_OP_H
+#define EIGEN_SPARSE_CWISE_UNARY_OP_H
+
+template<typename UnaryOp, typename MatrixType>
+struct ei_traits<SparseCwiseUnaryOp<UnaryOp, MatrixType> > : ei_traits<MatrixType>
+{
+ typedef typename ei_result_of<
+ UnaryOp(typename MatrixType::Scalar)
+ >::type Scalar;
+ typedef typename MatrixType::Nested MatrixTypeNested;
+ typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
+ enum {
+ CoeffReadCost = _MatrixTypeNested::CoeffReadCost + ei_functor_traits<UnaryOp>::Cost
+ };
+};
+
+template<typename UnaryOp, typename MatrixType>
+class SparseCwiseUnaryOp : ei_no_assignment_operator,
+ public SparseMatrixBase<SparseCwiseUnaryOp<UnaryOp, MatrixType> >
+{
+ public:
+
+ class InnerIterator;
+// typedef typename ei_unref<LhsNested>::type _LhsNested;
+
+ EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseCwiseUnaryOp)
+
+ inline SparseCwiseUnaryOp(const MatrixType& mat, const UnaryOp& func = UnaryOp())
+ : m_matrix(mat), m_functor(func) {}
+
+ EIGEN_STRONG_INLINE int rows() const { return m_matrix.rows(); }
+ EIGEN_STRONG_INLINE int cols() const { return m_matrix.cols(); }
+
+// EIGEN_STRONG_INLINE const typename MatrixType::Nested& _matrix() const { return m_matrix; }
+// EIGEN_STRONG_INLINE const UnaryOp& _functor() const { return m_functor; }
+
+ protected:
+ const typename MatrixType::Nested m_matrix;
+ const UnaryOp m_functor;
+};
+
+
+template<typename UnaryOp, typename MatrixType>
+class SparseCwiseUnaryOp<UnaryOp,MatrixType>::InnerIterator
+{
+ typedef typename SparseCwiseUnaryOp::Scalar Scalar;
+ typedef typename ei_traits<SparseCwiseUnaryOp>::_MatrixTypeNested _MatrixTypeNested;
+ typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
+ public:
+
+ EIGEN_STRONG_INLINE InnerIterator(const SparseCwiseUnaryOp& unaryOp, int outer)
+ : m_iter(unaryOp.m_matrix,outer), m_functor(unaryOp.m_functor)
+ {}
+
+ EIGEN_STRONG_INLINE InnerIterator& operator++()
+ { ++m_iter; return *this; }
+
+ EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_iter.value()); }
+
+ EIGEN_STRONG_INLINE int index() const { return m_iter.index(); }
+ EIGEN_STRONG_INLINE int row() const { return m_iter.row(); }
+ EIGEN_STRONG_INLINE int col() const { return m_iter.col(); }
+
+ EIGEN_STRONG_INLINE operator bool() const { return m_iter; }
+
+ protected:
+ MatrixTypeIterator m_iter;
+ const UnaryOp m_functor;
+
+ private:
+ InnerIterator& operator=(const InnerIterator&);
+};
+
+template<typename Derived>
+template<typename CustomUnaryOp>
+EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<CustomUnaryOp, Derived>
+SparseMatrixBase<Derived>::unaryExpr(const CustomUnaryOp& func) const
+{
+ return SparseCwiseUnaryOp<CustomUnaryOp, Derived>(derived(), func);
+}
+
+template<typename Derived>
+EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<ei_scalar_opposite_op<typename ei_traits<Derived>::Scalar>,Derived>
+SparseMatrixBase<Derived>::operator-() const
+{
+ return derived();
+}
+
+template<typename ExpressionType>
+EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs_op)
+SparseCwise<ExpressionType>::abs() const
+{
+ return _expression();
+}
+
+template<typename ExpressionType>
+EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_UNOP_RETURN_TYPE(ei_scalar_abs2_op)
+SparseCwise<ExpressionType>::abs2() const
+{
+ return _expression();
+}
+
+template<typename Derived>
+EIGEN_STRONG_INLINE typename SparseMatrixBase<Derived>::ConjugateReturnType
+SparseMatrixBase<Derived>::conjugate() const
+{
+ return ConjugateReturnType(derived());
+}
+
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::RealReturnType
+SparseMatrixBase<Derived>::real() const { return derived(); }
+
+template<typename Derived>
+EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::ImagReturnType
+SparseMatrixBase<Derived>::imag() const { return derived(); }
+
+template<typename Derived>
+template<typename NewType>
+EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<ei_scalar_cast_op<typename ei_traits<Derived>::Scalar, NewType>, Derived>
+SparseMatrixBase<Derived>::cast() const
+{
+ return derived();
+}
+
+template<typename Derived>
+EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<ei_scalar_multiple_op<typename ei_traits<Derived>::Scalar>, Derived>
+SparseMatrixBase<Derived>::operator*(const Scalar& scalar) const
+{
+ return SparseCwiseUnaryOp<ei_scalar_multiple_op<Scalar>, Derived>
+ (derived(), ei_scalar_multiple_op<Scalar>(scalar));
+}
+
+template<typename Derived>
+EIGEN_STRONG_INLINE const SparseCwiseUnaryOp<ei_scalar_quotient1_op<typename ei_traits<Derived>::Scalar>, Derived>
+SparseMatrixBase<Derived>::operator/(const Scalar& scalar) const
+{
+ return SparseCwiseUnaryOp<ei_scalar_quotient1_op<Scalar>, Derived>
+ (derived(), ei_scalar_quotient1_op<Scalar>(scalar));
+}
+
+template<typename Derived>
+EIGEN_STRONG_INLINE Derived&
+SparseMatrixBase<Derived>::operator*=(const Scalar& other)
+{
+ for (int j=0; j<outerSize(); ++j)
+ for (typename Derived::InnerIterator i(derived(),j); i; ++i)
+ i.valueRef() *= other;
+ return derived();
+}
+
+template<typename Derived>
+EIGEN_STRONG_INLINE Derived&
+SparseMatrixBase<Derived>::operator/=(const Scalar& other)
+{
+ for (int j=0; j<outerSize(); ++j)
+ for (typename Derived::InnerIterator i(derived(),j); i; ++i)
+ i.valueRef() /= other;
+ return derived();
+}
+
+#endif // EIGEN_SPARSE_CWISE_UNARY_OP_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/SparseDiagonalProduct.h b/extern/Eigen2/Eigen/src/Sparse/SparseDiagonalProduct.h
new file mode 100644
index 00000000000..9b7432a8216
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseDiagonalProduct.h
@@ -0,0 +1,159 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2009 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SPARSE_DIAGONAL_PRODUCT_H
+#define EIGEN_SPARSE_DIAGONAL_PRODUCT_H
+
+// the product a diagonal matrix with a sparse matrix can be easily
+// implemented using expression template. We have two very different cases:
+// 1 - diag * row-major sparse
+// => each inner vector <=> scalar * sparse vector product
+// => so we can reuse CwiseUnaryOp::InnerIterator
+// 2 - diag * col-major sparse
+// => each inner vector <=> densevector * sparse vector cwise product
+// => again, we can reuse specialization of CwiseBinaryOp::InnerIterator
+// for that particular case
+// The two other cases are symmetric.
+
+template<typename Lhs, typename Rhs>
+struct ei_traits<SparseDiagonalProduct<Lhs, Rhs> > : ei_traits<SparseProduct<Lhs, Rhs, DiagonalProduct> >
+{
+ typedef typename ei_cleantype<Lhs>::type _Lhs;
+ typedef typename ei_cleantype<Rhs>::type _Rhs;
+ enum {
+ SparseFlags = ((int(_Lhs::Flags)&Diagonal)==Diagonal) ? int(_Rhs::Flags) : int(_Lhs::Flags),
+ Flags = SparseBit | (SparseFlags&RowMajorBit)
+ };
+};
+
+enum {SDP_IsDiagonal, SDP_IsSparseRowMajor, SDP_IsSparseColMajor};
+template<typename Lhs, typename Rhs, typename SparseDiagonalProductType, int RhsMode, int LhsMode>
+class ei_sparse_diagonal_product_inner_iterator_selector;
+
+template<typename LhsNested, typename RhsNested>
+class SparseDiagonalProduct : public SparseMatrixBase<SparseDiagonalProduct<LhsNested,RhsNested> >, ei_no_assignment_operator
+{
+ typedef typename ei_traits<SparseDiagonalProduct>::_LhsNested _LhsNested;
+ typedef typename ei_traits<SparseDiagonalProduct>::_RhsNested _RhsNested;
+
+ enum {
+ LhsMode = (_LhsNested::Flags&Diagonal)==Diagonal ? SDP_IsDiagonal
+ : (_LhsNested::Flags&RowMajorBit) ? SDP_IsSparseRowMajor : SDP_IsSparseColMajor,
+ RhsMode = (_RhsNested::Flags&Diagonal)==Diagonal ? SDP_IsDiagonal
+ : (_RhsNested::Flags&RowMajorBit) ? SDP_IsSparseRowMajor : SDP_IsSparseColMajor
+ };
+
+ public:
+
+ EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseDiagonalProduct)
+
+ typedef ei_sparse_diagonal_product_inner_iterator_selector
+ <_LhsNested,_RhsNested,SparseDiagonalProduct,LhsMode,RhsMode> InnerIterator;
+
+ template<typename Lhs, typename Rhs>
+ EIGEN_STRONG_INLINE SparseDiagonalProduct(const Lhs& lhs, const Rhs& rhs)
+ : m_lhs(lhs), m_rhs(rhs)
+ {
+ ei_assert(lhs.cols() == rhs.rows() && "invalid sparse matrix * diagonal matrix product");
+ }
+
+ EIGEN_STRONG_INLINE int rows() const { return m_lhs.rows(); }
+ EIGEN_STRONG_INLINE int cols() const { return m_rhs.cols(); }
+
+ EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
+ EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
+
+ protected:
+ LhsNested m_lhs;
+ RhsNested m_rhs;
+};
+
+
+template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
+class ei_sparse_diagonal_product_inner_iterator_selector
+<Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseRowMajor>
+ : public SparseCwiseUnaryOp<ei_scalar_multiple_op<typename Lhs::Scalar>,Rhs>::InnerIterator
+{
+ typedef typename SparseCwiseUnaryOp<ei_scalar_multiple_op<typename Lhs::Scalar>,Rhs>::InnerIterator Base;
+ public:
+ inline ei_sparse_diagonal_product_inner_iterator_selector(
+ const SparseDiagonalProductType& expr, int outer)
+ : Base(expr.rhs()*(expr.lhs().diagonal().coeff(outer)), outer)
+ {}
+};
+
+template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
+class ei_sparse_diagonal_product_inner_iterator_selector
+<Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseColMajor>
+ : public SparseCwiseBinaryOp<
+ ei_scalar_product_op<typename Lhs::Scalar>,
+ SparseInnerVectorSet<Rhs,1>,
+ typename Lhs::_CoeffsVectorType>::InnerIterator
+{
+ typedef typename SparseCwiseBinaryOp<
+ ei_scalar_product_op<typename Lhs::Scalar>,
+ SparseInnerVectorSet<Rhs,1>,
+ typename Lhs::_CoeffsVectorType>::InnerIterator Base;
+ public:
+ inline ei_sparse_diagonal_product_inner_iterator_selector(
+ const SparseDiagonalProductType& expr, int outer)
+ : Base(expr.rhs().innerVector(outer) .cwise()* expr.lhs().diagonal(), 0)
+ {}
+ private:
+ ei_sparse_diagonal_product_inner_iterator_selector& operator=(const ei_sparse_diagonal_product_inner_iterator_selector&);
+};
+
+template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
+class ei_sparse_diagonal_product_inner_iterator_selector
+<Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseColMajor,SDP_IsDiagonal>
+ : public SparseCwiseUnaryOp<ei_scalar_multiple_op<typename Rhs::Scalar>,Lhs>::InnerIterator
+{
+ typedef typename SparseCwiseUnaryOp<ei_scalar_multiple_op<typename Rhs::Scalar>,Lhs>::InnerIterator Base;
+ public:
+ inline ei_sparse_diagonal_product_inner_iterator_selector(
+ const SparseDiagonalProductType& expr, int outer)
+ : Base(expr.lhs()*expr.rhs().diagonal().coeff(outer), outer)
+ {}
+};
+
+template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
+class ei_sparse_diagonal_product_inner_iterator_selector
+<Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseRowMajor,SDP_IsDiagonal>
+ : public SparseCwiseBinaryOp<
+ ei_scalar_product_op<typename Rhs::Scalar>,
+ SparseInnerVectorSet<Lhs,1>,
+ NestByValue<Transpose<typename Rhs::_CoeffsVectorType> > >::InnerIterator
+{
+ typedef typename SparseCwiseBinaryOp<
+ ei_scalar_product_op<typename Rhs::Scalar>,
+ SparseInnerVectorSet<Lhs,1>,
+ NestByValue<Transpose<typename Rhs::_CoeffsVectorType> > >::InnerIterator Base;
+ public:
+ inline ei_sparse_diagonal_product_inner_iterator_selector(
+ const SparseDiagonalProductType& expr, int outer)
+ : Base(expr.lhs().innerVector(outer) .cwise()* expr.rhs().diagonal().transpose().nestByValue(), 0)
+ {}
+};
+
+#endif // EIGEN_SPARSE_DIAGONAL_PRODUCT_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseDot.h b/extern/Eigen2/Eigen/src/Sparse/SparseDot.h
index 1f10f71a402..7a26e0f4ba5 100644
--- a/extern/Eigen3/Eigen/src/Sparse/SparseDot.h
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseDot.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -27,23 +27,23 @@
template<typename Derived>
template<typename OtherDerived>
-typename internal::traits<Derived>::Scalar
+typename ei_traits<Derived>::Scalar
SparseMatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
- EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
+ EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
- eigen_assert(size() == other.size());
- eigen_assert(other.size()>0 && "you are using a non initialized vector");
-
+ ei_assert(size() == other.size());
+ ei_assert(other.size()>0 && "you are using a non initialized vector");
+
typename Derived::InnerIterator i(derived(),0);
Scalar res = 0;
while (i)
{
- res += internal::conj(i.value()) * other.coeff(i.index());
+ res += i.value() * ei_conj(other.coeff(i.index()));
++i;
}
return res;
@@ -51,17 +51,17 @@ SparseMatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
template<typename Derived>
template<typename OtherDerived>
-typename internal::traits<Derived>::Scalar
+typename ei_traits<Derived>::Scalar
SparseMatrixBase<Derived>::dot(const SparseMatrixBase<OtherDerived>& other) const
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
- EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
+ EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
-
- eigen_assert(size() == other.size());
-
+
+ ei_assert(size() == other.size());
+
typename Derived::InnerIterator i(derived(),0);
typename OtherDerived::InnerIterator j(other.derived(),0);
Scalar res = 0;
@@ -69,7 +69,7 @@ SparseMatrixBase<Derived>::dot(const SparseMatrixBase<OtherDerived>& other) cons
{
if (i.index()==j.index())
{
- res += internal::conj(i.value()) * j.value();
+ res += i.value() * ei_conj(j.value());
++i; ++j;
}
else if (i.index()<j.index())
@@ -81,17 +81,17 @@ SparseMatrixBase<Derived>::dot(const SparseMatrixBase<OtherDerived>& other) cons
}
template<typename Derived>
-inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
+inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real
SparseMatrixBase<Derived>::squaredNorm() const
{
- return internal::real((*this).cwiseAbs2().sum());
+ return ei_real((*this).cwise().abs2().sum());
}
template<typename Derived>
-inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
+inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real
SparseMatrixBase<Derived>::norm() const
{
- return internal::sqrt(squaredNorm());
+ return ei_sqrt(squaredNorm());
}
#endif // EIGEN_SPARSE_DOT_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/SparseFlagged.h b/extern/Eigen2/Eigen/src/Sparse/SparseFlagged.h
new file mode 100644
index 00000000000..315ec4af39f
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseFlagged.h
@@ -0,0 +1,102 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SPARSE_FLAGGED_H
+#define EIGEN_SPARSE_FLAGGED_H
+
+template<typename ExpressionType, unsigned int Added, unsigned int Removed>
+struct ei_traits<SparseFlagged<ExpressionType, Added, Removed> > : ei_traits<ExpressionType>
+{
+ enum { Flags = (ExpressionType::Flags | Added) & ~Removed };
+};
+
+template<typename ExpressionType, unsigned int Added, unsigned int Removed> class SparseFlagged
+ : public SparseMatrixBase<SparseFlagged<ExpressionType, Added, Removed> >
+{
+ public:
+
+ EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseFlagged)
+ class InnerIterator;
+ class ReverseInnerIterator;
+
+ typedef typename ei_meta_if<ei_must_nest_by_value<ExpressionType>::ret,
+ ExpressionType, const ExpressionType&>::ret ExpressionTypeNested;
+
+ inline SparseFlagged(const ExpressionType& matrix) : m_matrix(matrix) {}
+
+ inline int rows() const { return m_matrix.rows(); }
+ inline int cols() const { return m_matrix.cols(); }
+
+ // FIXME should be keep them ?
+ inline Scalar& coeffRef(int row, int col)
+ { return m_matrix.const_cast_derived().coeffRef(col, row); }
+
+ inline const Scalar coeff(int row, int col) const
+ { return m_matrix.coeff(col, row); }
+
+ inline const Scalar coeff(int index) const
+ { return m_matrix.coeff(index); }
+
+ inline Scalar& coeffRef(int index)
+ { return m_matrix.const_cast_derived().coeffRef(index); }
+
+ protected:
+ ExpressionTypeNested m_matrix;
+
+ private:
+ SparseFlagged& operator=(const SparseFlagged&);
+};
+
+template<typename ExpressionType, unsigned int Added, unsigned int Removed>
+ class SparseFlagged<ExpressionType,Added,Removed>::InnerIterator : public ExpressionType::InnerIterator
+{
+ public:
+ EIGEN_STRONG_INLINE InnerIterator(const SparseFlagged& xpr, int outer)
+ : ExpressionType::InnerIterator(xpr.m_matrix, outer)
+ {}
+
+ private:
+ InnerIterator& operator=(const InnerIterator&);
+};
+
+template<typename ExpressionType, unsigned int Added, unsigned int Removed>
+ class SparseFlagged<ExpressionType,Added,Removed>::ReverseInnerIterator : public ExpressionType::ReverseInnerIterator
+{
+ public:
+
+ EIGEN_STRONG_INLINE ReverseInnerIterator(const SparseFlagged& xpr, int outer)
+ : ExpressionType::ReverseInnerIterator(xpr.m_matrix, outer)
+ {}
+};
+
+template<typename Derived>
+template<unsigned int Added>
+inline const SparseFlagged<Derived, Added, 0>
+SparseMatrixBase<Derived>::marked() const
+{
+ return derived();
+}
+
+#endif // EIGEN_SPARSE_FLAGGED_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseFuzzy.h b/extern/Eigen2/Eigen/src/Sparse/SparseFuzzy.h
index f00b3d6469b..355f4d52eab 100644
--- a/extern/Eigen3/Eigen/src/Sparse/SparseFuzzy.h
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseFuzzy.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -32,10 +32,10 @@
// typename NumTraits<Scalar>::Real prec
// ) const
// {
-// const typename internal::nested<Derived,2>::type nested(derived());
-// const typename internal::nested<OtherDerived,2>::type otherNested(other.derived());
+// const typename ei_nested<Derived,2>::type nested(derived());
+// const typename ei_nested<OtherDerived,2>::type otherNested(other.derived());
// return (nested - otherNested).cwise().abs2().sum()
-// <= prec * prec * (std::min)(nested.cwise().abs2().sum(), otherNested.cwise().abs2().sum());
+// <= prec * prec * std::min(nested.cwise().abs2().sum(), otherNested.cwise().abs2().sum());
// }
#endif // EIGEN_SPARSE_FUZZY_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/SparseLDLT.h b/extern/Eigen2/Eigen/src/Sparse/SparseLDLT.h
new file mode 100644
index 00000000000..a1bac4d084d
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseLDLT.h
@@ -0,0 +1,346 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+/*
+
+NOTE: the _symbolic, and _numeric functions has been adapted from
+ the LDL library:
+
+LDL Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved.
+
+LDL License:
+
+ Your use or distribution of LDL or any modified version of
+ LDL implies that you agree to this License.
+
+ 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.
+ */
+
+#ifndef EIGEN_SPARSELDLT_H
+#define EIGEN_SPARSELDLT_H
+
+/** \ingroup Sparse_Module
+ *
+ * \class SparseLDLT
+ *
+ * \brief LDLT Cholesky decomposition of a sparse matrix and associated features
+ *
+ * \param MatrixType the type of the matrix of which we are computing the LDLT Cholesky decomposition
+ *
+ * \sa class LDLT, class LDLT
+ */
+template<typename MatrixType, int Backend = DefaultBackend>
+class SparseLDLT
+{
+ protected:
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+ typedef SparseMatrix<Scalar,LowerTriangular|UnitDiagBit> CholMatrixType;
+ typedef Matrix<Scalar,MatrixType::ColsAtCompileTime,1> VectorType;
+
+ enum {
+ SupernodalFactorIsDirty = 0x10000,
+ MatrixLIsDirty = 0x20000
+ };
+
+ public:
+
+ /** Creates a dummy LDLT factorization object with flags \a flags. */
+ SparseLDLT(int flags = 0)
+ : m_flags(flags), m_status(0)
+ {
+ ei_assert((MatrixType::Flags&RowMajorBit)==0);
+ m_precision = RealScalar(0.1) * Eigen::precision<RealScalar>();
+ }
+
+ /** Creates a LDLT object and compute the respective factorization of \a matrix using
+ * flags \a flags. */
+ SparseLDLT(const MatrixType& matrix, int flags = 0)
+ : m_matrix(matrix.rows(), matrix.cols()), m_flags(flags), m_status(0)
+ {
+ ei_assert((MatrixType::Flags&RowMajorBit)==0);
+ m_precision = RealScalar(0.1) * Eigen::precision<RealScalar>();
+ compute(matrix);
+ }
+
+ /** Sets the relative threshold value used to prune zero coefficients during the decomposition.
+ *
+ * Setting a value greater than zero speeds up computation, and yields to an imcomplete
+ * factorization with fewer non zero coefficients. Such approximate factors are especially
+ * useful to initialize an iterative solver.
+ *
+ * \warning if precision is greater that zero, the LDLT factorization is not guaranteed to succeed
+ * even if the matrix is positive definite.
+ *
+ * Note that the exact meaning of this parameter might depends on the actual
+ * backend. Moreover, not all backends support this feature.
+ *
+ * \sa precision() */
+ void setPrecision(RealScalar v) { m_precision = v; }
+
+ /** \returns the current precision.
+ *
+ * \sa setPrecision() */
+ RealScalar precision() const { return m_precision; }
+
+ /** Sets the flags. Possible values are:
+ * - CompleteFactorization
+ * - IncompleteFactorization
+ * - MemoryEfficient (hint to use the memory most efficient method offered by the backend)
+ * - SupernodalMultifrontal (implies a complete factorization if supported by the backend,
+ * overloads the MemoryEfficient flags)
+ * - SupernodalLeftLooking (implies a complete factorization if supported by the backend,
+ * overloads the MemoryEfficient flags)
+ *
+ * \sa flags() */
+ void settagss(int f) { m_flags = f; }
+ /** \returns the current flags */
+ int flags() const { return m_flags; }
+
+ /** Computes/re-computes the LDLT factorization */
+ void compute(const MatrixType& matrix);
+
+ /** Perform a symbolic factorization */
+ void _symbolic(const MatrixType& matrix);
+ /** Perform the actual factorization using the previously
+ * computed symbolic factorization */
+ bool _numeric(const MatrixType& matrix);
+
+ /** \returns the lower triangular matrix L */
+ inline const CholMatrixType& matrixL(void) const { return m_matrix; }
+
+ /** \returns the coefficients of the diagonal matrix D */
+ inline VectorType vectorD(void) const { return m_diag; }
+
+ template<typename Derived>
+ bool solveInPlace(MatrixBase<Derived> &b) const;
+
+ /** \returns true if the factorization succeeded */
+ inline bool succeeded(void) const { return m_succeeded; }
+
+ protected:
+ CholMatrixType m_matrix;
+ VectorType m_diag;
+ VectorXi m_parent; // elimination tree
+ VectorXi m_nonZerosPerCol;
+// VectorXi m_w; // workspace
+ RealScalar m_precision;
+ int m_flags;
+ mutable int m_status;
+ bool m_succeeded;
+};
+
+/** Computes / recomputes the LDLT decomposition of matrix \a a
+ * using the default algorithm.
+ */
+template<typename MatrixType, int Backend>
+void SparseLDLT<MatrixType,Backend>::compute(const MatrixType& a)
+{
+ _symbolic(a);
+ m_succeeded = _numeric(a);
+}
+
+template<typename MatrixType, int Backend>
+void SparseLDLT<MatrixType,Backend>::_symbolic(const MatrixType& a)
+{
+ assert(a.rows()==a.cols());
+ const int size = a.rows();
+ m_matrix.resize(size, size);
+ m_parent.resize(size);
+ m_nonZerosPerCol.resize(size);
+ int * tags = ei_aligned_stack_new(int, size);
+
+ const int* Ap = a._outerIndexPtr();
+ const int* Ai = a._innerIndexPtr();
+ int* Lp = m_matrix._outerIndexPtr();
+ const int* P = 0;
+ int* Pinv = 0;
+
+ if (P)
+ {
+ /* If P is present then compute Pinv, the inverse of P */
+ for (int k = 0; k < size; ++k)
+ Pinv[P[k]] = k;
+ }
+ for (int k = 0; k < size; ++k)
+ {
+ /* L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k) */
+ m_parent[k] = -1; /* parent of k is not yet known */
+ tags[k] = k; /* mark node k as visited */
+ m_nonZerosPerCol[k] = 0; /* count of nonzeros in column k of L */
+ int kk = P ? P[k] : k; /* kth original, or permuted, column */
+ int p2 = Ap[kk+1];
+ for (int p = Ap[kk]; p < p2; ++p)
+ {
+ /* A (i,k) is nonzero (original or permuted A) */
+ int i = Pinv ? Pinv[Ai[p]] : Ai[p];
+ if (i < k)
+ {
+ /* follow path from i to root of etree, stop at flagged node */
+ for (; tags[i] != k; i = m_parent[i])
+ {
+ /* find parent of i if not yet determined */
+ if (m_parent[i] == -1)
+ m_parent[i] = k;
+ ++m_nonZerosPerCol[i]; /* L (k,i) is nonzero */
+ tags[i] = k; /* mark i as visited */
+ }
+ }
+ }
+ }
+ /* construct Lp index array from m_nonZerosPerCol column counts */
+ Lp[0] = 0;
+ for (int k = 0; k < size; ++k)
+ Lp[k+1] = Lp[k] + m_nonZerosPerCol[k];
+
+ m_matrix.resizeNonZeros(Lp[size]);
+ ei_aligned_stack_delete(int, tags, size);
+}
+
+template<typename MatrixType, int Backend>
+bool SparseLDLT<MatrixType,Backend>::_numeric(const MatrixType& a)
+{
+ assert(a.rows()==a.cols());
+ const int size = a.rows();
+ assert(m_parent.size()==size);
+ assert(m_nonZerosPerCol.size()==size);
+
+ const int* Ap = a._outerIndexPtr();
+ const int* Ai = a._innerIndexPtr();
+ const Scalar* Ax = a._valuePtr();
+ const int* Lp = m_matrix._outerIndexPtr();
+ int* Li = m_matrix._innerIndexPtr();
+ Scalar* Lx = m_matrix._valuePtr();
+ m_diag.resize(size);
+
+ Scalar * y = ei_aligned_stack_new(Scalar, size);
+ int * pattern = ei_aligned_stack_new(int, size);
+ int * tags = ei_aligned_stack_new(int, size);
+
+ const int* P = 0;
+ const int* Pinv = 0;
+ bool ok = true;
+
+ for (int k = 0; k < size; ++k)
+ {
+ /* compute nonzero pattern of kth row of L, in topological order */
+ y[k] = 0.0; /* Y(0:k) is now all zero */
+ int top = size; /* stack for pattern is empty */
+ tags[k] = k; /* mark node k as visited */
+ m_nonZerosPerCol[k] = 0; /* count of nonzeros in column k of L */
+ int kk = (P) ? (P[k]) : (k); /* kth original, or permuted, column */
+ int p2 = Ap[kk+1];
+ for (int p = Ap[kk]; p < p2; ++p)
+ {
+ int i = Pinv ? Pinv[Ai[p]] : Ai[p]; /* get A(i,k) */
+ if (i <= k)
+ {
+ y[i] += Ax[p]; /* scatter A(i,k) into Y (sum duplicates) */
+ int len;
+ for (len = 0; tags[i] != k; i = m_parent[i])
+ {
+ pattern[len++] = i; /* L(k,i) is nonzero */
+ tags[i] = k; /* mark i as visited */
+ }
+ while (len > 0)
+ pattern[--top] = pattern[--len];
+ }
+ }
+ /* compute numerical values kth row of L (a sparse triangular solve) */
+ m_diag[k] = y[k]; /* get D(k,k) and clear Y(k) */
+ y[k] = 0.0;
+ for (; top < size; ++top)
+ {
+ int i = pattern[top]; /* pattern[top:n-1] is pattern of L(:,k) */
+ Scalar yi = y[i]; /* get and clear Y(i) */
+ y[i] = 0.0;
+ int p2 = Lp[i] + m_nonZerosPerCol[i];
+ int p;
+ for (p = Lp[i]; p < p2; ++p)
+ y[Li[p]] -= Lx[p] * yi;
+ Scalar l_ki = yi / m_diag[i]; /* the nonzero entry L(k,i) */
+ m_diag[k] -= l_ki * yi;
+ Li[p] = k; /* store L(k,i) in column form of L */
+ Lx[p] = l_ki;
+ ++m_nonZerosPerCol[i]; /* increment count of nonzeros in col i */
+ }
+ if (m_diag[k] == 0.0)
+ {
+ ok = false; /* failure, D(k,k) is zero */
+ break;
+ }
+ }
+
+ ei_aligned_stack_delete(Scalar, y, size);
+ ei_aligned_stack_delete(int, pattern, size);
+ ei_aligned_stack_delete(int, tags, size);
+
+ return ok; /* success, diagonal of D is all nonzero */
+}
+
+/** Computes b = L^-T L^-1 b */
+template<typename MatrixType, int Backend>
+template<typename Derived>
+bool SparseLDLT<MatrixType, Backend>::solveInPlace(MatrixBase<Derived> &b) const
+{
+ const int size = m_matrix.rows();
+ ei_assert(size==b.rows());
+ if (!m_succeeded)
+ return false;
+
+ if (m_matrix.nonZeros()>0) // otherwise L==I
+ m_matrix.solveTriangularInPlace(b);
+ b = b.cwise() / m_diag;
+ // FIXME should be .adjoint() but it fails to compile...
+
+ if (m_matrix.nonZeros()>0) // otherwise L==I
+ m_matrix.transpose().solveTriangularInPlace(b);
+
+ return true;
+}
+
+#endif // EIGEN_SPARSELDLT_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/SparseLLT.h b/extern/Eigen2/Eigen/src/Sparse/SparseLLT.h
new file mode 100644
index 00000000000..e7c314c2cad
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseLLT.h
@@ -0,0 +1,205 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SPARSELLT_H
+#define EIGEN_SPARSELLT_H
+
+/** \ingroup Sparse_Module
+ *
+ * \class SparseLLT
+ *
+ * \brief LLT Cholesky decomposition of a sparse matrix and associated features
+ *
+ * \param MatrixType the type of the matrix of which we are computing the LLT Cholesky decomposition
+ *
+ * \sa class LLT, class LDLT
+ */
+template<typename MatrixType, int Backend = DefaultBackend>
+class SparseLLT
+{
+ protected:
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+ typedef SparseMatrix<Scalar,LowerTriangular> CholMatrixType;
+
+ enum {
+ SupernodalFactorIsDirty = 0x10000,
+ MatrixLIsDirty = 0x20000
+ };
+
+ public:
+
+ /** Creates a dummy LLT factorization object with flags \a flags. */
+ SparseLLT(int flags = 0)
+ : m_flags(flags), m_status(0)
+ {
+ m_precision = RealScalar(0.1) * Eigen::precision<RealScalar>();
+ }
+
+ /** Creates a LLT object and compute the respective factorization of \a matrix using
+ * flags \a flags. */
+ SparseLLT(const MatrixType& matrix, int flags = 0)
+ : m_matrix(matrix.rows(), matrix.cols()), m_flags(flags), m_status(0)
+ {
+ m_precision = RealScalar(0.1) * Eigen::precision<RealScalar>();
+ compute(matrix);
+ }
+
+ /** Sets the relative threshold value used to prune zero coefficients during the decomposition.
+ *
+ * Setting a value greater than zero speeds up computation, and yields to an imcomplete
+ * factorization with fewer non zero coefficients. Such approximate factors are especially
+ * useful to initialize an iterative solver.
+ *
+ * \warning if precision is greater that zero, the LLT factorization is not guaranteed to succeed
+ * even if the matrix is positive definite.
+ *
+ * Note that the exact meaning of this parameter might depends on the actual
+ * backend. Moreover, not all backends support this feature.
+ *
+ * \sa precision() */
+ void setPrecision(RealScalar v) { m_precision = v; }
+
+ /** \returns the current precision.
+ *
+ * \sa setPrecision() */
+ RealScalar precision() const { return m_precision; }
+
+ /** Sets the flags. Possible values are:
+ * - CompleteFactorization
+ * - IncompleteFactorization
+ * - MemoryEfficient (hint to use the memory most efficient method offered by the backend)
+ * - SupernodalMultifrontal (implies a complete factorization if supported by the backend,
+ * overloads the MemoryEfficient flags)
+ * - SupernodalLeftLooking (implies a complete factorization if supported by the backend,
+ * overloads the MemoryEfficient flags)
+ *
+ * \sa flags() */
+ void setFlags(int f) { m_flags = f; }
+ /** \returns the current flags */
+ int flags() const { return m_flags; }
+
+ /** Computes/re-computes the LLT factorization */
+ void compute(const MatrixType& matrix);
+
+ /** \returns the lower triangular matrix L */
+ inline const CholMatrixType& matrixL(void) const { return m_matrix; }
+
+ template<typename Derived>
+ bool solveInPlace(MatrixBase<Derived> &b) const;
+
+ /** \returns true if the factorization succeeded */
+ inline bool succeeded(void) const { return m_succeeded; }
+
+ protected:
+ CholMatrixType m_matrix;
+ RealScalar m_precision;
+ int m_flags;
+ mutable int m_status;
+ bool m_succeeded;
+};
+
+/** Computes / recomputes the LLT decomposition of matrix \a a
+ * using the default algorithm.
+ */
+template<typename MatrixType, int Backend>
+void SparseLLT<MatrixType,Backend>::compute(const MatrixType& a)
+{
+ assert(a.rows()==a.cols());
+ const int size = a.rows();
+ m_matrix.resize(size, size);
+
+ // allocate a temporary vector for accumulations
+ AmbiVector<Scalar> tempVector(size);
+ RealScalar density = a.nonZeros()/RealScalar(size*size);
+
+ // TODO estimate the number of non zeros
+ m_matrix.startFill(a.nonZeros()*2);
+ for (int j = 0; j < size; ++j)
+ {
+ Scalar x = ei_real(a.coeff(j,j));
+
+ // TODO better estimate of the density !
+ tempVector.init(density>0.001? IsDense : IsSparse);
+ tempVector.setBounds(j+1,size);
+ tempVector.setZero();
+ // init with current matrix a
+ {
+ typename MatrixType::InnerIterator it(a,j);
+ ++it; // skip diagonal element
+ for (; it; ++it)
+ tempVector.coeffRef(it.index()) = it.value();
+ }
+ for (int k=0; k<j+1; ++k)
+ {
+ typename CholMatrixType::InnerIterator it(m_matrix, k);
+ while (it && it.index()<j)
+ ++it;
+ if (it && it.index()==j)
+ {
+ Scalar y = it.value();
+ x -= ei_abs2(y);
+ ++it; // skip j-th element, and process remaining column coefficients
+ tempVector.restart();
+ for (; it; ++it)
+ {
+ tempVector.coeffRef(it.index()) -= it.value() * y;
+ }
+ }
+ }
+ // copy the temporary vector to the respective m_matrix.col()
+ // while scaling the result by 1/real(x)
+ RealScalar rx = ei_sqrt(ei_real(x));
+ m_matrix.fill(j,j) = rx;
+ Scalar y = Scalar(1)/rx;
+ for (typename AmbiVector<Scalar>::Iterator it(tempVector, m_precision*rx); it; ++it)
+ {
+ m_matrix.fill(it.index(), j) = it.value() * y;
+ }
+ }
+ m_matrix.endFill();
+}
+
+/** Computes b = L^-T L^-1 b */
+template<typename MatrixType, int Backend>
+template<typename Derived>
+bool SparseLLT<MatrixType, Backend>::solveInPlace(MatrixBase<Derived> &b) const
+{
+ const int size = m_matrix.rows();
+ ei_assert(size==b.rows());
+
+ m_matrix.solveTriangularInPlace(b);
+ // FIXME should be simply .adjoint() but it fails to compile...
+ if (NumTraits<Scalar>::IsComplex)
+ {
+ CholMatrixType aux = m_matrix.conjugate();
+ aux.transpose().solveTriangularInPlace(b);
+ }
+ else
+ m_matrix.transpose().solveTriangularInPlace(b);
+
+ return true;
+}
+
+#endif // EIGEN_SPARSELLT_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/SparseLU.h b/extern/Eigen2/Eigen/src/Sparse/SparseLU.h
new file mode 100644
index 00000000000..1425920509f
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseLU.h
@@ -0,0 +1,148 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SPARSELU_H
+#define EIGEN_SPARSELU_H
+
+/** \ingroup Sparse_Module
+ *
+ * \class SparseLU
+ *
+ * \brief LU decomposition of a sparse matrix and associated features
+ *
+ * \param MatrixType the type of the matrix of which we are computing the LU factorization
+ *
+ * \sa class LU, class SparseLLT
+ */
+template<typename MatrixType, int Backend = DefaultBackend>
+class SparseLU
+{
+ protected:
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+ typedef SparseMatrix<Scalar,LowerTriangular> LUMatrixType;
+
+ enum {
+ MatrixLUIsDirty = 0x10000
+ };
+
+ public:
+
+ /** Creates a dummy LU factorization object with flags \a flags. */
+ SparseLU(int flags = 0)
+ : m_flags(flags), m_status(0)
+ {
+ m_precision = RealScalar(0.1) * Eigen::precision<RealScalar>();
+ }
+
+ /** Creates a LU object and compute the respective factorization of \a matrix using
+ * flags \a flags. */
+ SparseLU(const MatrixType& matrix, int flags = 0)
+ : /*m_matrix(matrix.rows(), matrix.cols()),*/ m_flags(flags), m_status(0)
+ {
+ m_precision = RealScalar(0.1) * Eigen::precision<RealScalar>();
+ compute(matrix);
+ }
+
+ /** Sets the relative threshold value used to prune zero coefficients during the decomposition.
+ *
+ * Setting a value greater than zero speeds up computation, and yields to an imcomplete
+ * factorization with fewer non zero coefficients. Such approximate factors are especially
+ * useful to initialize an iterative solver.
+ *
+ * Note that the exact meaning of this parameter might depends on the actual
+ * backend. Moreover, not all backends support this feature.
+ *
+ * \sa precision() */
+ void setPrecision(RealScalar v) { m_precision = v; }
+
+ /** \returns the current precision.
+ *
+ * \sa setPrecision() */
+ RealScalar precision() const { return m_precision; }
+
+ /** Sets the flags. Possible values are:
+ * - CompleteFactorization
+ * - IncompleteFactorization
+ * - MemoryEfficient
+ * - one of the ordering methods
+ * - etc...
+ *
+ * \sa flags() */
+ void setFlags(int f) { m_flags = f; }
+ /** \returns the current flags */
+ int flags() const { return m_flags; }
+
+ void setOrderingMethod(int m)
+ {
+ ei_assert(m&~OrderingMask == 0 && m!=0 && "invalid ordering method");
+ m_flags = m_flags&~OrderingMask | m&OrderingMask;
+ }
+
+ int orderingMethod() const
+ {
+ return m_flags&OrderingMask;
+ }
+
+ /** Computes/re-computes the LU factorization */
+ void compute(const MatrixType& matrix);
+
+ /** \returns the lower triangular matrix L */
+ //inline const MatrixType& matrixL() const { return m_matrixL; }
+
+ /** \returns the upper triangular matrix U */
+ //inline const MatrixType& matrixU() const { return m_matrixU; }
+
+ template<typename BDerived, typename XDerived>
+ bool solve(const MatrixBase<BDerived> &b, MatrixBase<XDerived>* x) const;
+
+ /** \returns true if the factorization succeeded */
+ inline bool succeeded(void) const { return m_succeeded; }
+
+ protected:
+ RealScalar m_precision;
+ int m_flags;
+ mutable int m_status;
+ bool m_succeeded;
+};
+
+/** Computes / recomputes the LU decomposition of matrix \a a
+ * using the default algorithm.
+ */
+template<typename MatrixType, int Backend>
+void SparseLU<MatrixType,Backend>::compute(const MatrixType& a)
+{
+ ei_assert(false && "not implemented yet");
+}
+
+/** Computes *x = U^-1 L^-1 b */
+template<typename MatrixType, int Backend>
+template<typename BDerived, typename XDerived>
+bool SparseLU<MatrixType,Backend>::solve(const MatrixBase<BDerived> &b, MatrixBase<XDerived>* x) const
+{
+ ei_assert(false && "not implemented yet");
+ return false;
+}
+
+#endif // EIGEN_SPARSELU_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/SparseMatrix.h b/extern/Eigen2/Eigen/src/Sparse/SparseMatrix.h
new file mode 100644
index 00000000000..65c609686d2
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseMatrix.h
@@ -0,0 +1,452 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SPARSEMATRIX_H
+#define EIGEN_SPARSEMATRIX_H
+
+/** \class SparseMatrix
+ *
+ * \brief Sparse matrix
+ *
+ * \param _Scalar the scalar type, i.e. the type of the coefficients
+ *
+ * See http://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme.
+ *
+ */
+template<typename _Scalar, int _Flags>
+struct ei_traits<SparseMatrix<_Scalar, _Flags> >
+{
+ typedef _Scalar Scalar;
+ enum {
+ RowsAtCompileTime = Dynamic,
+ ColsAtCompileTime = Dynamic,
+ MaxRowsAtCompileTime = Dynamic,
+ MaxColsAtCompileTime = Dynamic,
+ Flags = SparseBit | _Flags,
+ CoeffReadCost = NumTraits<Scalar>::ReadCost,
+ SupportedAccessPatterns = InnerRandomAccessPattern
+ };
+};
+
+
+
+template<typename _Scalar, int _Flags>
+class SparseMatrix
+ : public SparseMatrixBase<SparseMatrix<_Scalar, _Flags> >
+{
+ public:
+ EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseMatrix)
+ EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, +=)
+ EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, -=)
+ // FIXME: why are these operator already alvailable ???
+ // EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(SparseMatrix, *=)
+ // EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(SparseMatrix, /=)
+
+ typedef MappedSparseMatrix<Scalar,Flags> Map;
+
+ protected:
+
+ enum { IsRowMajor = Base::IsRowMajor };
+ typedef SparseMatrix<Scalar,(Flags&~RowMajorBit)|(IsRowMajor?RowMajorBit:0)> TransposedSparseMatrix;
+
+ int m_outerSize;
+ int m_innerSize;
+ int* m_outerIndex;
+ CompressedStorage<Scalar> m_data;
+
+ public:
+
+ inline int rows() const { return IsRowMajor ? m_outerSize : m_innerSize; }
+ inline int cols() const { return IsRowMajor ? m_innerSize : m_outerSize; }
+
+ inline int innerSize() const { return m_innerSize; }
+ inline int outerSize() const { return m_outerSize; }
+ inline int innerNonZeros(int j) const { return m_outerIndex[j+1]-m_outerIndex[j]; }
+
+ inline const Scalar* _valuePtr() const { return &m_data.value(0); }
+ inline Scalar* _valuePtr() { return &m_data.value(0); }
+
+ inline const int* _innerIndexPtr() const { return &m_data.index(0); }
+ inline int* _innerIndexPtr() { return &m_data.index(0); }
+
+ inline const int* _outerIndexPtr() const { return m_outerIndex; }
+ inline int* _outerIndexPtr() { return m_outerIndex; }
+
+ inline Scalar coeff(int row, int col) const
+ {
+ const int outer = IsRowMajor ? row : col;
+ const int inner = IsRowMajor ? col : row;
+ return m_data.atInRange(m_outerIndex[outer], m_outerIndex[outer+1], inner);
+ }
+
+ inline Scalar& coeffRef(int row, int col)
+ {
+ const int outer = IsRowMajor ? row : col;
+ const int inner = IsRowMajor ? col : row;
+
+ int start = m_outerIndex[outer];
+ int end = m_outerIndex[outer+1];
+ ei_assert(end>=start && "you probably called coeffRef on a non finalized matrix");
+ ei_assert(end>start && "coeffRef cannot be called on a zero coefficient");
+ const int id = m_data.searchLowerIndex(start,end-1,inner);
+ ei_assert((id<end) && (m_data.index(id)==inner) && "coeffRef cannot be called on a zero coefficient");
+ return m_data.value(id);
+ }
+
+ public:
+
+ class InnerIterator;
+
+ inline void setZero()
+ {
+ m_data.clear();
+ //if (m_outerSize)
+ memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(int));
+// for (int i=0; i<m_outerSize; ++i)
+// m_outerIndex[i] = 0;
+// if (m_outerSize)
+// m_outerIndex[i] = 0;
+ }
+
+ /** \returns the number of non zero coefficients */
+ inline int nonZeros() const { return m_data.size(); }
+
+ /** Initializes the filling process of \c *this.
+ * \param reserveSize approximate number of nonzeros
+ * Note that the matrix \c *this is zero-ed.
+ */
+ inline void startFill(int reserveSize = 1000)
+ {
+ setZero();
+ m_data.reserve(reserveSize);
+ }
+
+ /**
+ */
+ inline Scalar& fill(int row, int col)
+ {
+ const int outer = IsRowMajor ? row : col;
+ const int inner = IsRowMajor ? col : row;
+
+ if (m_outerIndex[outer+1]==0)
+ {
+ // we start a new inner vector
+ int i = outer;
+ while (i>=0 && m_outerIndex[i]==0)
+ {
+ m_outerIndex[i] = m_data.size();
+ --i;
+ }
+ m_outerIndex[outer+1] = m_outerIndex[outer];
+ }
+ else
+ {
+ ei_assert(m_data.index(m_data.size()-1)<inner && "wrong sorted insertion");
+ }
+ assert(size_t(m_outerIndex[outer+1]) == m_data.size());
+ int id = m_outerIndex[outer+1];
+ ++m_outerIndex[outer+1];
+
+ m_data.append(0, inner);
+ return m_data.value(id);
+ }
+
+ /** Like fill() but with random inner coordinates.
+ */
+ inline Scalar& fillrand(int row, int col)
+ {
+ const int outer = IsRowMajor ? row : col;
+ const int inner = IsRowMajor ? col : row;
+ if (m_outerIndex[outer+1]==0)
+ {
+ // we start a new inner vector
+ // nothing special to do here
+ int i = outer;
+ while (i>=0 && m_outerIndex[i]==0)
+ {
+ m_outerIndex[i] = m_data.size();
+ --i;
+ }
+ m_outerIndex[outer+1] = m_outerIndex[outer];
+ }
+ assert(size_t(m_outerIndex[outer+1]) == m_data.size() && "invalid outer index");
+ size_t startId = m_outerIndex[outer];
+ // FIXME let's make sure sizeof(long int) == sizeof(size_t)
+ size_t id = m_outerIndex[outer+1];
+ ++m_outerIndex[outer+1];
+
+ float reallocRatio = 1;
+ if (m_data.allocatedSize()<id+1)
+ {
+ // we need to reallocate the data, to reduce multiple reallocations
+ // we use a smart resize algorithm based on the current filling ratio
+ // we use float to avoid overflows
+ float nnzEstimate = float(m_outerIndex[outer])*float(m_outerSize)/float(outer);
+ reallocRatio = (nnzEstimate-float(m_data.size()))/float(m_data.size());
+ // let's bounds 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);
+ }
+ m_data.resize(id+1,reallocRatio);
+
+ while ( (id > startId) && (m_data.index(id-1) > inner) )
+ {
+ m_data.index(id) = m_data.index(id-1);
+ m_data.value(id) = m_data.value(id-1);
+ --id;
+ }
+
+ m_data.index(id) = inner;
+ return (m_data.value(id) = 0);
+ }
+
+ inline void endFill()
+ {
+ int size = m_data.size();
+ int i = m_outerSize;
+ // find the last filled column
+ while (i>=0 && m_outerIndex[i]==0)
+ --i;
+ ++i;
+ while (i<=m_outerSize)
+ {
+ m_outerIndex[i] = size;
+ ++i;
+ }
+ }
+
+ void prune(Scalar reference, RealScalar epsilon = precision<RealScalar>())
+ {
+ int k = 0;
+ for (int j=0; j<m_outerSize; ++j)
+ {
+ int previousStart = m_outerIndex[j];
+ m_outerIndex[j] = k;
+ int end = m_outerIndex[j+1];
+ for (int i=previousStart; i<end; ++i)
+ {
+ if (!ei_isMuchSmallerThan(m_data.value(i), reference, epsilon))
+ {
+ m_data.value(k) = m_data.value(i);
+ m_data.index(k) = m_data.index(i);
+ ++k;
+ }
+ }
+ }
+ m_outerIndex[m_outerSize] = k;
+ m_data.resize(k,0);
+ }
+
+ /** Resizes the matrix to a \a rows x \a cols matrix and initializes it to zero
+ * \sa resizeNonZeros(int), reserve(), setZero()
+ */
+ void resize(int rows, int cols)
+ {
+ const int outerSize = IsRowMajor ? rows : cols;
+ m_innerSize = IsRowMajor ? cols : rows;
+ m_data.clear();
+ if (m_outerSize != outerSize || m_outerSize==0)
+ {
+ delete[] m_outerIndex;
+ m_outerIndex = new int [outerSize+1];
+ m_outerSize = outerSize;
+ }
+ memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(int));
+ }
+ void resizeNonZeros(int size)
+ {
+ m_data.resize(size);
+ }
+
+ inline SparseMatrix()
+ : m_outerSize(-1), m_innerSize(0), m_outerIndex(0)
+ {
+ resize(0, 0);
+ }
+
+ inline SparseMatrix(int rows, int cols)
+ : m_outerSize(0), m_innerSize(0), m_outerIndex(0)
+ {
+ resize(rows, cols);
+ }
+
+ template<typename OtherDerived>
+ inline SparseMatrix(const SparseMatrixBase<OtherDerived>& other)
+ : m_outerSize(0), m_innerSize(0), m_outerIndex(0)
+ {
+ *this = other.derived();
+ }
+
+ inline SparseMatrix(const SparseMatrix& other)
+ : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0)
+ {
+ *this = other.derived();
+ }
+
+ inline void swap(SparseMatrix& other)
+ {
+ //EIGEN_DBG_SPARSE(std::cout << "SparseMatrix:: swap\n");
+ std::swap(m_outerIndex, other.m_outerIndex);
+ std::swap(m_innerSize, other.m_innerSize);
+ std::swap(m_outerSize, other.m_outerSize);
+ m_data.swap(other.m_data);
+ }
+
+ inline SparseMatrix& operator=(const SparseMatrix& other)
+ {
+// std::cout << "SparseMatrix& operator=(const SparseMatrix& other)\n";
+ if (other.isRValue())
+ {
+ swap(other.const_cast_derived());
+ }
+ else
+ {
+ resize(other.rows(), other.cols());
+ memcpy(m_outerIndex, other.m_outerIndex, (m_outerSize+1)*sizeof(int));
+ m_data = other.m_data;
+ }
+ return *this;
+ }
+
+ template<typename OtherDerived>
+ inline SparseMatrix& operator=(const SparseMatrixBase<OtherDerived>& other)
+ {
+ const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
+ if (needToTranspose)
+ {
+ // two passes algorithm:
+ // 1 - compute the number of coeffs per dest inner vector
+ // 2 - do the actual copy/eval
+ // Since each coeff of the rhs has to be evaluated twice, let's evauluate it if needed
+ //typedef typename ei_nested<OtherDerived,2>::type OtherCopy;
+ typedef typename ei_eval<OtherDerived>::type OtherCopy;
+ typedef typename ei_cleantype<OtherCopy>::type _OtherCopy;
+ OtherCopy otherCopy(other.derived());
+
+ resize(other.rows(), other.cols());
+ Eigen::Map<VectorXi>(m_outerIndex,outerSize()).setZero();
+ // pass 1
+ // FIXME the above copy could be merged with that pass
+ for (int j=0; j<otherCopy.outerSize(); ++j)
+ for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
+ ++m_outerIndex[it.index()];
+
+ // prefix sum
+ int count = 0;
+ VectorXi positions(outerSize());
+ for (int j=0; j<outerSize(); ++j)
+ {
+ int tmp = m_outerIndex[j];
+ m_outerIndex[j] = count;
+ positions[j] = count;
+ count += tmp;
+ }
+ m_outerIndex[outerSize()] = count;
+ // alloc
+ m_data.resize(count);
+ // pass 2
+ for (int j=0; j<otherCopy.outerSize(); ++j)
+ for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
+ {
+ int pos = positions[it.index()]++;
+ m_data.index(pos) = j;
+ m_data.value(pos) = it.value();
+ }
+
+ return *this;
+ }
+ else
+ {
+ // there is no special optimization
+ return SparseMatrixBase<SparseMatrix>::operator=(other.derived());
+ }
+ }
+
+ friend std::ostream & operator << (std::ostream & s, const SparseMatrix& m)
+ {
+ EIGEN_DBG_SPARSE(
+ s << "Nonzero entries:\n";
+ for (int i=0; i<m.nonZeros(); ++i)
+ {
+ s << "(" << m.m_data.value(i) << "," << m.m_data.index(i) << ") ";
+ }
+ s << std::endl;
+ s << std::endl;
+ s << "Column pointers:\n";
+ for (int i=0; i<m.outerSize(); ++i)
+ {
+ s << m.m_outerIndex[i] << " ";
+ }
+ s << " $" << std::endl;
+ s << std::endl;
+ );
+ s << static_cast<const SparseMatrixBase<SparseMatrix>&>(m);
+ return s;
+ }
+
+ /** Destructor */
+ inline ~SparseMatrix()
+ {
+ delete[] m_outerIndex;
+ }
+};
+
+template<typename Scalar, int _Flags>
+class SparseMatrix<Scalar,_Flags>::InnerIterator
+{
+ public:
+ InnerIterator(const SparseMatrix& mat, int outer)
+ : m_matrix(mat), m_outer(outer), m_id(mat.m_outerIndex[outer]), m_start(m_id), m_end(mat.m_outerIndex[outer+1])
+ {}
+
+ template<unsigned int Added, unsigned int Removed>
+ InnerIterator(const Flagged<SparseMatrix,Added,Removed>& mat, int outer)
+ : m_matrix(mat._expression()), m_outer(outer), m_id(m_matrix.m_outerIndex[outer]),
+ m_start(m_id), m_end(m_matrix.m_outerIndex[outer+1])
+ {}
+
+ inline InnerIterator& operator++() { m_id++; return *this; }
+
+ inline Scalar value() const { return m_matrix.m_data.value(m_id); }
+ inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix.m_data.value(m_id)); }
+
+ inline int index() const { return m_matrix.m_data.index(m_id); }
+ inline int row() const { return IsRowMajor ? m_outer : index(); }
+ inline int col() const { return IsRowMajor ? index() : m_outer; }
+
+ inline operator bool() const { return (m_id < m_end) && (m_id>=m_start); }
+
+ protected:
+ const SparseMatrix& m_matrix;
+ const int m_outer;
+ int m_id;
+ const int m_start;
+ const int m_end;
+
+ private:
+ InnerIterator& operator=(const InnerIterator&);
+};
+
+#endif // EIGEN_SPARSEMATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseMatrixBase.h b/extern/Eigen2/Eigen/src/Sparse/SparseMatrixBase.h
index c01981bc935..468bc9e227c 100644
--- a/extern/Eigen3/Eigen/src/Sparse/SparseMatrixBase.h
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseMatrixBase.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -25,55 +25,30 @@
#ifndef EIGEN_SPARSEMATRIXBASE_H
#define EIGEN_SPARSEMATRIXBASE_H
-/** \ingroup Sparse_Module
- *
- * \class SparseMatrixBase
- *
- * \brief Base class of any sparse matrices or sparse expressions
- *
- * \tparam Derived
- *
- * 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
{
public:
- typedef typename internal::traits<Derived>::Scalar Scalar;
- typedef typename internal::packet_traits<Scalar>::type PacketScalar;
- typedef typename internal::traits<Derived>::StorageKind StorageKind;
- typedef typename internal::traits<Derived>::Index Index;
-
- typedef SparseMatrixBase StorageBaseType;
- typedef EigenBase<Derived> Base;
-
- template<typename OtherDerived>
- Derived& operator=(const EigenBase<OtherDerived> &other)
- {
- other.derived().evalTo(derived());
- return derived();
- }
-
-// using Base::operator=;
+ typedef typename ei_traits<Derived>::Scalar Scalar;
+// typedef typename Derived::InnerIterator InnerIterator;
enum {
- RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
+ RowsAtCompileTime = ei_traits<Derived>::RowsAtCompileTime,
/**< The number of rows at compile-time. This is just a copy of the value provided
* by the \a Derived type. If a value is not known at compile-time,
* it is set to the \a Dynamic constant.
* \sa MatrixBase::rows(), MatrixBase::cols(), ColsAtCompileTime, SizeAtCompileTime */
- ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
+ ColsAtCompileTime = ei_traits<Derived>::ColsAtCompileTime,
/**< The number of columns at compile-time. This is just a copy of the value provided
* by the \a Derived type. If a value is not known at compile-time,
* it is set to the \a Dynamic constant.
* \sa MatrixBase::rows(), MatrixBase::cols(), RowsAtCompileTime, SizeAtCompileTime */
- SizeAtCompileTime = (internal::size_at_compile_time<internal::traits<Derived>::RowsAtCompileTime,
- internal::traits<Derived>::ColsAtCompileTime>::ret),
+ SizeAtCompileTime = (ei_size_at_compile_time<ei_traits<Derived>::RowsAtCompileTime,
+ ei_traits<Derived>::ColsAtCompileTime>::ret),
/**< This is equal to the number of coefficients, i.e. the number of
* rows times the number of columns, or to \a Dynamic if this is not
* known at compile-time. \sa RowsAtCompileTime, ColsAtCompileTime */
@@ -81,7 +56,7 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
MaxRowsAtCompileTime = RowsAtCompileTime,
MaxColsAtCompileTime = ColsAtCompileTime,
- MaxSizeAtCompileTime = (internal::size_at_compile_time<MaxRowsAtCompileTime,
+ MaxSizeAtCompileTime = (ei_size_at_compile_time<MaxRowsAtCompileTime,
MaxColsAtCompileTime>::ret),
IsVectorAtCompileTime = RowsAtCompileTime == 1 || ColsAtCompileTime == 1,
@@ -90,51 +65,31 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
* we are dealing with a column-vector (if there is only one column) or with
* a row-vector (if there is only one row). */
- Flags = internal::traits<Derived>::Flags,
+ Flags = ei_traits<Derived>::Flags,
/**< This stores expression \ref flags flags which may or may not be inherited by new expressions
* constructed from this one. See the \ref flags "list of flags".
*/
-
- CoeffReadCost = internal::traits<Derived>::CoeffReadCost,
+
+ CoeffReadCost = ei_traits<Derived>::CoeffReadCost,
/**< This is a rough measure of how expensive it is to read one coefficient from
* this expression.
*/
- IsRowMajor = Flags&RowMajorBit ? 1 : 0,
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- _HasDirectAccess = (int(Flags)&DirectAccessBit) ? 1 : 0 // workaround sunCC
- #endif
+ IsRowMajor = Flags&RowMajorBit ? 1 : 0
};
- /* \internal the return type of MatrixBase::conjugate() */
-// typedef typename internal::conditional<NumTraits<Scalar>::IsComplex,
-// const SparseCwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, Derived>,
-// const Derived&
-// >::type ConjugateReturnType;
- /* \internal the return type of MatrixBase::real() */
-// typedef SparseCwiseUnaryOp<internal::scalar_real_op<Scalar>, Derived> RealReturnType;
- /* \internal the return type of MatrixBase::imag() */
-// typedef SparseCwiseUnaryOp<internal::scalar_imag_op<Scalar>, Derived> ImagReturnType;
+ /** \internal the return type of MatrixBase::conjugate() */
+ typedef typename ei_meta_if<NumTraits<Scalar>::IsComplex,
+ const SparseCwiseUnaryOp<ei_scalar_conjugate_op<Scalar>, Derived>,
+ const Derived&
+ >::ret ConjugateReturnType;
+ /** \internal the return type of MatrixBase::real() */
+ typedef CwiseUnaryOp<ei_scalar_real_op<Scalar>, Derived> RealReturnType;
+ /** \internal the return type of MatrixBase::imag() */
+ typedef CwiseUnaryOp<ei_scalar_imag_op<Scalar>, Derived> ImagReturnType;
/** \internal the return type of MatrixBase::adjoint() */
- typedef typename internal::conditional<NumTraits<Scalar>::IsComplex,
- CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, Eigen::Transpose<const Derived> >,
- Transpose<const Derived>
- >::type AdjointReturnType;
-
-
- typedef SparseMatrix<Scalar, Flags&RowMajorBit ? RowMajor : ColMajor> PlainObject;
-
-#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::SparseMatrixBase
-# include "../plugins/CommonCwiseUnaryOps.h"
-# include "../plugins/CommonCwiseBinaryOps.h"
-# include "../plugins/MatrixCwiseUnaryOps.h"
-# include "../plugins/MatrixCwiseBinaryOps.h"
-# ifdef EIGEN_SPARSEMATRIXBASE_PLUGIN
-# include EIGEN_SPARSEMATRIXBASE_PLUGIN
-# endif
-# undef EIGEN_CURRENT_STORAGE_BASE_CLASS
-#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
+ typedef SparseTranspose</*NestByValue<*/typename ei_cleantype<ConjugateReturnType>::type> /*>*/
+ AdjointReturnType;
#ifndef EIGEN_PARSED_BY_DOXYGEN
/** This is the "real scalar" type; if the \a Scalar type is already real numbers
@@ -145,16 +100,9 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
*/
typedef typename NumTraits<Scalar>::Real RealScalar;
- /** \internal the return type of coeff()
- */
- typedef typename internal::conditional<_HasDirectAccess, const Scalar&, Scalar>::type CoeffReturnType;
-
- /** \internal Represents a matrix with all coefficients equal to one another*/
- typedef CwiseNullaryOp<internal::scalar_constant_op<Scalar>,Matrix<Scalar,Dynamic,Dynamic> > ConstantReturnType;
-
/** type of the equivalent square matrix */
- typedef Matrix<Scalar,EIGEN_SIZE_MAX(RowsAtCompileTime,ColsAtCompileTime),
- EIGEN_SIZE_MAX(RowsAtCompileTime,ColsAtCompileTime)> SquareMatrixType;
+ typedef Matrix<Scalar,EIGEN_ENUM_MAX(RowsAtCompileTime,ColsAtCompileTime),
+ EIGEN_ENUM_MAX(RowsAtCompileTime,ColsAtCompileTime)> SquareMatrixType;
inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
inline Derived& derived() { return *static_cast<Derived*>(this); }
@@ -163,15 +111,15 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
#endif // not EIGEN_PARSED_BY_DOXYGEN
/** \returns the number of rows. \sa cols(), RowsAtCompileTime */
- inline Index rows() const { return derived().rows(); }
+ inline int rows() const { return derived().rows(); }
/** \returns the number of columns. \sa rows(), ColsAtCompileTime*/
- inline Index cols() const { return derived().cols(); }
+ inline int cols() const { return derived().cols(); }
/** \returns the number of coefficients, which is \a rows()*cols().
* \sa rows(), cols(), SizeAtCompileTime. */
- inline Index size() const { return rows() * cols(); }
+ inline int size() const { return rows() * cols(); }
/** \returns the number of nonzero coefficients which is in practice the number
* of stored coefficients. */
- inline Index nonZeros() const { return derived().nonZeros(); }
+ inline int nonZeros() const { return derived().nonZeros(); }
/** \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
@@ -179,16 +127,16 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
inline bool isVector() const { return rows()==1 || cols()==1; }
/** \returns the size of the storage major dimension,
* i.e., the number of columns for a columns major matrix, and the number of rows otherwise */
- Index outerSize() const { return (int(Flags)&RowMajorBit) ? this->rows() : this->cols(); }
+ int outerSize() const { return (int(Flags)&RowMajorBit) ? this->rows() : this->cols(); }
/** \returns the size of the inner dimension according to the storage order,
* i.e., the number of rows for a columns major matrix, and the number of cols otherwise */
- Index innerSize() const { return (int(Flags)&RowMajorBit) ? this->cols() : this->rows(); }
+ int innerSize() const { return (int(Flags)&RowMajorBit) ? this->cols() : this->rows(); }
bool isRValue() const { return m_isRValue; }
Derived& markAsRValue() { m_isRValue = true; return derived(); }
SparseMatrixBase() : m_isRValue(false) { /* TODO check flags */ }
-
+
inline Derived& operator=(const Derived& other)
{
// std::cout << "Derived& operator=(const Derived& other)\n";
@@ -198,13 +146,6 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
this->operator=<Derived>(other);
return derived();
}
-
- template<typename OtherDerived>
- Derived& operator=(const ReturnByValue<OtherDerived>& other)
- {
- other.evalTo(derived());
- return derived();
- }
template<typename OtherDerived>
@@ -212,29 +153,29 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
{
// std::cout << "Derived& operator=(const MatrixBase<OtherDerived>& other)\n";
//const bool transpose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
- eigen_assert(( ((internal::traits<Derived>::SupportedAccessPatterns&OuterRandomAccessPattern)==OuterRandomAccessPattern) ||
+ ei_assert(( ((ei_traits<Derived>::SupportedAccessPatterns&OuterRandomAccessPattern)==OuterRandomAccessPattern) ||
(!((Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit)))) &&
"the transpose operation is supposed to be handled in SparseMatrix::operator=");
- enum { Flip = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit) };
-
- const Index outerSize = other.outerSize();
- //typedef typename internal::conditional<transpose, LinkedVectorMatrix<Scalar,Flags&RowMajorBit>, Derived>::type TempType;
+ const int outerSize = other.outerSize();
+ //typedef typename ei_meta_if<transpose, LinkedVectorMatrix<Scalar,Flags&RowMajorBit>, Derived>::ret TempType;
// thanks to shallow copies, we always eval to a tempary
Derived temp(other.rows(), other.cols());
- temp.reserve((std::max)(this->rows(),this->cols())*2);
- for (Index j=0; j<outerSize; ++j)
+ temp.startFill(std::max(this->rows(),this->cols())*2);
+ for (int j=0; j<outerSize; ++j)
{
- temp.startVec(j);
for (typename OtherDerived::InnerIterator it(other.derived(), j); it; ++it)
{
Scalar v = it.value();
if (v!=Scalar(0))
- temp.insertBackByOuterInner(Flip?it.index():j,Flip?j:it.index()) = v;
+ {
+ if (OtherDerived::Flags & RowMajorBit) temp.fill(j,it.index()) = v;
+ else temp.fill(it.index(),j) = v;
+ }
}
}
- temp.finalize();
+ temp.endFill();
derived() = temp.markAsRValue();
}
@@ -247,24 +188,25 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
// std::cout << Flags << " " << OtherDerived::Flags << "\n";
const bool transpose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
// std::cout << "eval transpose = " << transpose << "\n";
- const Index outerSize = (int(OtherDerived::Flags) & RowMajorBit) ? other.rows() : other.cols();
+ const int outerSize = (int(OtherDerived::Flags) & RowMajorBit) ? other.rows() : other.cols();
if ((!transpose) && other.isRValue())
{
// eval without temporary
derived().resize(other.rows(), other.cols());
- derived().setZero();
- derived().reserve((std::max)(this->rows(),this->cols())*2);
- for (Index j=0; j<outerSize; ++j)
+ derived().startFill(std::max(this->rows(),this->cols())*2);
+ for (int j=0; j<outerSize; ++j)
{
- derived().startVec(j);
for (typename OtherDerived::InnerIterator it(other.derived(), j); it; ++it)
{
Scalar v = it.value();
if (v!=Scalar(0))
- derived().insertBackByOuterInner(j,it.index()) = v;
+ {
+ if (IsRowMajor) derived().fill(j,it.index()) = v;
+ else derived().fill(it.index(),j) = v;
+ }
}
}
- derived().finalize();
+ derived().endFill();
}
else
{
@@ -274,18 +216,15 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
}
template<typename Lhs, typename Rhs>
- inline Derived& operator=(const SparseSparseProduct<Lhs,Rhs>& product);
-
- template<typename Lhs, typename Rhs>
- inline void _experimentalNewProduct(const Lhs& lhs, const Rhs& rhs);
+ inline Derived& operator=(const SparseProduct<Lhs,Rhs,SparseTimeSparseProduct>& product);
friend std::ostream & operator << (std::ostream & s, const SparseMatrixBase& m)
{
if (Flags&RowMajorBit)
{
- for (Index row=0; row<m.outerSize(); ++row)
+ for (int row=0; row<m.outerSize(); ++row)
{
- Index col = 0;
+ int col = 0;
for (typename Derived::InnerIterator it(m.derived(), row); it; ++it)
{
for ( ; col<it.index(); ++col)
@@ -301,7 +240,7 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
else
{
if (m.cols() == 1) {
- Index row = 0;
+ int row = 0;
for (typename Derived::InnerIterator it(m.derived(), 0); it; ++it)
{
for ( ; row<it.index(); ++row)
@@ -321,15 +260,15 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
return s;
}
-// const SparseCwiseUnaryOp<internal::scalar_opposite_op<typename internal::traits<Derived>::Scalar>,Derived> operator-() const;
+ const SparseCwiseUnaryOp<ei_scalar_opposite_op<typename ei_traits<Derived>::Scalar>,Derived> operator-() const;
-// template<typename OtherDerived>
-// const CwiseBinaryOp<internal::scalar_sum_op<typename internal::traits<Derived>::Scalar>, Derived, OtherDerived>
-// operator+(const SparseMatrixBase<OtherDerived> &other) const;
+ template<typename OtherDerived>
+ const SparseCwiseBinaryOp<ei_scalar_sum_op<typename ei_traits<Derived>::Scalar>, Derived, OtherDerived>
+ operator+(const SparseMatrixBase<OtherDerived> &other) const;
-// template<typename OtherDerived>
-// const CwiseBinaryOp<internal::scalar_difference_op<typename internal::traits<Derived>::Scalar>, Derived, OtherDerived>
-// operator-(const SparseMatrixBase<OtherDerived> &other) const;
+ template<typename OtherDerived>
+ const SparseCwiseBinaryOp<ei_scalar_difference_op<typename ei_traits<Derived>::Scalar>, Derived, OtherDerived>
+ operator-(const SparseMatrixBase<OtherDerived> &other) const;
template<typename OtherDerived>
Derived& operator+=(const SparseMatrixBase<OtherDerived>& other);
@@ -342,108 +281,67 @@ 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 \
- >, \
- Derived, \
- OtherDerived \
- >
-
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
- cwiseProduct(const MatrixBase<OtherDerived> &other) const;
-
-// const SparseCwiseUnaryOp<internal::scalar_multiple_op<typename internal::traits<Derived>::Scalar>, Derived>
-// operator*(const Scalar& scalar) const;
-// const SparseCwiseUnaryOp<internal::scalar_quotient1_op<typename internal::traits<Derived>::Scalar>, Derived>
-// operator/(const Scalar& scalar) const;
+ const SparseCwiseUnaryOp<ei_scalar_multiple_op<typename ei_traits<Derived>::Scalar>, Derived>
+ operator*(const Scalar& scalar) const;
+ const SparseCwiseUnaryOp<ei_scalar_quotient1_op<typename ei_traits<Derived>::Scalar>, Derived>
+ operator/(const Scalar& scalar) const;
-// inline friend const SparseCwiseUnaryOp<internal::scalar_multiple_op<typename internal::traits<Derived>::Scalar>, Derived>
-// operator*(const Scalar& scalar, const SparseMatrixBase& matrix)
-// { return matrix*scalar; }
+ inline friend const SparseCwiseUnaryOp<ei_scalar_multiple_op<typename ei_traits<Derived>::Scalar>, Derived>
+ operator*(const Scalar& scalar, const SparseMatrixBase& matrix)
+ { return matrix*scalar; }
- // sparse * sparse
template<typename OtherDerived>
- const typename SparseSparseProductReturnType<Derived,OtherDerived>::Type
+ const typename SparseProductReturnType<Derived,OtherDerived>::Type
operator*(const SparseMatrixBase<OtherDerived> &other) const;
-
- // sparse * diagonal
- template<typename OtherDerived>
- const SparseDiagonalProduct<Derived,OtherDerived>
- operator*(const DiagonalBase<OtherDerived> &other) const;
-
- // diagonal * sparse
- template<typename OtherDerived> friend
- const SparseDiagonalProduct<OtherDerived,Derived>
- operator*(const DiagonalBase<OtherDerived> &lhs, const SparseMatrixBase& rhs)
- { return SparseDiagonalProduct<OtherDerived,Derived>(lhs.derived(), rhs.derived()); }
-
- /** dense * sparse (return a dense object unless it is an outer product) */
- template<typename OtherDerived> friend
- const typename DenseSparseProductReturnType<OtherDerived,Derived>::Type
+
+ // dense * sparse (return a dense object)
+ template<typename OtherDerived> friend
+ const typename SparseProductReturnType<OtherDerived,Derived>::Type
operator*(const MatrixBase<OtherDerived>& lhs, const Derived& rhs)
- { return typename DenseSparseProductReturnType<OtherDerived,Derived>::Type(lhs.derived(),rhs); }
-
- /** sparse * dense (returns a dense object unless it is an outer product) */
+ { return typename SparseProductReturnType<OtherDerived,Derived>::Type(lhs.derived(),rhs); }
+
template<typename OtherDerived>
- const typename SparseDenseProductReturnType<Derived,OtherDerived>::Type
+ const typename SparseProductReturnType<Derived,OtherDerived>::Type
operator*(const MatrixBase<OtherDerived> &other) const;
template<typename OtherDerived>
Derived& operator*=(const SparseMatrixBase<OtherDerived>& other);
- #ifdef EIGEN2_SUPPORT
- // deprecated
template<typename OtherDerived>
- typename internal::plain_matrix_type_column_major<OtherDerived>::type
+ typename ei_plain_matrix_type_column_major<OtherDerived>::type
solveTriangular(const MatrixBase<OtherDerived>& other) const;
- // deprecated
template<typename OtherDerived>
void solveTriangularInPlace(MatrixBase<OtherDerived>& other) const;
-// template<typename OtherDerived>
-// void solveTriangularInPlace(SparseMatrixBase<OtherDerived>& other) const;
- #endif // EIGEN2_SUPPORT
-
- template<int Mode>
- inline const SparseTriangularView<Derived, Mode> triangularView() const;
-
- template<unsigned int UpLo> inline const SparseSelfAdjointView<Derived, UpLo> selfadjointView() const;
- template<unsigned int UpLo> inline SparseSelfAdjointView<Derived, UpLo> selfadjointView();
template<typename OtherDerived> Scalar dot(const MatrixBase<OtherDerived>& other) const;
template<typename OtherDerived> Scalar dot(const SparseMatrixBase<OtherDerived>& other) const;
RealScalar squaredNorm() const;
RealScalar norm() const;
-// const PlainObject normalized() const;
+// const PlainMatrixType normalized() const;
// void normalize();
- Transpose<Derived> transpose() { return derived(); }
- const Transpose<const Derived> transpose() const { return derived(); }
+ SparseTranspose<Derived> transpose() { return derived(); }
+ const SparseTranspose<Derived> transpose() const { return derived(); }
// void transposeInPlace();
- const AdjointReturnType adjoint() const { return transpose(); }
+ const AdjointReturnType adjoint() const { return conjugate()/*.nestByValue()*/; }
// sub-vector
- SparseInnerVectorSet<Derived,1> row(Index i);
- const SparseInnerVectorSet<Derived,1> row(Index i) const;
- SparseInnerVectorSet<Derived,1> col(Index j);
- const SparseInnerVectorSet<Derived,1> col(Index j) const;
- SparseInnerVectorSet<Derived,1> innerVector(Index outer);
- const SparseInnerVectorSet<Derived,1> innerVector(Index outer) const;
-
+ SparseInnerVectorSet<Derived,1> row(int i);
+ const SparseInnerVectorSet<Derived,1> row(int i) const;
+ SparseInnerVectorSet<Derived,1> col(int j);
+ const SparseInnerVectorSet<Derived,1> col(int j) const;
+ SparseInnerVectorSet<Derived,1> innerVector(int outer);
+ const SparseInnerVectorSet<Derived,1> innerVector(int outer) const;
+
// set of sub-vectors
- SparseInnerVectorSet<Derived,Dynamic> subrows(Index start, Index size);
- const SparseInnerVectorSet<Derived,Dynamic> subrows(Index start, Index size) const;
- SparseInnerVectorSet<Derived,Dynamic> subcols(Index start, Index size);
- const SparseInnerVectorSet<Derived,Dynamic> subcols(Index start, Index size) const;
- SparseInnerVectorSet<Derived,Dynamic> innerVectors(Index outerStart, Index outerSize);
- const SparseInnerVectorSet<Derived,Dynamic> innerVectors(Index outerStart, Index outerSize) const;
+ SparseInnerVectorSet<Derived,Dynamic> subrows(int start, int size);
+ const SparseInnerVectorSet<Derived,Dynamic> subrows(int start, int size) const;
+ SparseInnerVectorSet<Derived,Dynamic> subcols(int start, int size);
+ const SparseInnerVectorSet<Derived,Dynamic> subcols(int start, int size) const;
+ SparseInnerVectorSet<Derived,Dynamic> innerVectors(int outerStart, int outerSize);
+ const SparseInnerVectorSet<Derived,Dynamic> innerVectors(int outerStart, int outerSize) const;
// typename BlockReturnType<Derived>::Type block(int startRow, int startCol, int blockRows, int blockCols);
// const typename BlockReturnType<Derived>::Type
@@ -458,11 +356,19 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
// typename BlockReturnType<Derived,Dynamic>::SubVectorType end(int size);
// const typename BlockReturnType<Derived,Dynamic>::SubVectorType end(int size) const;
//
+// typename BlockReturnType<Derived>::Type corner(CornerType type, int cRows, int cCols);
+// const typename BlockReturnType<Derived>::Type corner(CornerType type, int cRows, int cCols) const;
+//
// template<int BlockRows, int BlockCols>
// typename BlockReturnType<Derived, BlockRows, BlockCols>::Type block(int startRow, int startCol);
// template<int BlockRows, int BlockCols>
// const typename BlockReturnType<Derived, BlockRows, BlockCols>::Type block(int startRow, int startCol) const;
+// template<int CRows, int CCols>
+// typename BlockReturnType<Derived, CRows, CCols>::Type corner(CornerType type);
+// template<int CRows, int CCols>
+// const typename BlockReturnType<Derived, CRows, CCols>::Type corner(CornerType type) const;
+
// template<int Size> typename BlockReturnType<Derived,Size>::SubVectorType start(void);
// template<int Size> const typename BlockReturnType<Derived,Size>::SubVectorType start() const;
@@ -472,8 +378,8 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
// template<int Size> typename BlockReturnType<Derived,Size>::SubVectorType segment(int start);
// template<int Size> const typename BlockReturnType<Derived,Size>::SubVectorType segment(int start) const;
-// Diagonal<Derived> diagonal();
-// const Diagonal<Derived> diagonal() const;
+// DiagonalCoeffs<Derived> diagonal();
+// const DiagonalCoeffs<Derived> diagonal() const;
// template<unsigned int Mode> Part<Derived, Mode> part();
// template<unsigned int Mode> const Part<Derived, Mode> part() const;
@@ -513,49 +419,49 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
// Derived& setRandom();
// Derived& setIdentity();
- /** \internal use operator= */
- template<typename DenseDerived>
- void evalTo(MatrixBase<DenseDerived>& dst) const
- {
- dst.setZero();
- for (Index j=0; j<outerSize(); ++j)
- for (typename Derived::InnerIterator i(derived(),j); i; ++i)
- dst.coeffRef(i.row(),i.col()) = i.value();
- }
-
Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime> toDense() const
{
- return derived();
+ Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime> res(rows(),cols());
+ res.setZero();
+ for (int j=0; j<outerSize(); ++j)
+ {
+ for (typename Derived::InnerIterator i(derived(),j); i; ++i)
+ if(IsRowMajor)
+ res.coeffRef(j,i.index()) = i.value();
+ else
+ res.coeffRef(i.index(),j) = i.value();
+ }
+ return res;
}
template<typename OtherDerived>
bool isApprox(const SparseMatrixBase<OtherDerived>& other,
- RealScalar prec = NumTraits<Scalar>::dummy_precision()) const
+ RealScalar prec = precision<Scalar>()) const
{ return toDense().isApprox(other.toDense(),prec); }
template<typename OtherDerived>
bool isApprox(const MatrixBase<OtherDerived>& other,
- RealScalar prec = NumTraits<Scalar>::dummy_precision()) const
+ RealScalar prec = precision<Scalar>()) const
{ return toDense().isApprox(other,prec); }
// bool isMuchSmallerThan(const RealScalar& other,
-// RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
+// RealScalar prec = precision<Scalar>()) const;
// template<typename OtherDerived>
// bool isMuchSmallerThan(const MatrixBase<OtherDerived>& other,
-// RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
+// RealScalar prec = precision<Scalar>()) const;
-// bool isApproxToConstant(const Scalar& value, RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
-// bool isZero(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
-// bool isOnes(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
-// bool isIdentity(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
-// bool isDiagonal(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
+// bool isApproxToConstant(const Scalar& value, RealScalar prec = precision<Scalar>()) const;
+// bool isZero(RealScalar prec = precision<Scalar>()) const;
+// bool isOnes(RealScalar prec = precision<Scalar>()) const;
+// bool isIdentity(RealScalar prec = precision<Scalar>()) const;
+// bool isDiagonal(RealScalar prec = precision<Scalar>()) const;
-// bool isUpper(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
-// bool isLower(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
+// bool isUpperTriangular(RealScalar prec = precision<Scalar>()) const;
+// bool isLowerTriangular(RealScalar prec = precision<Scalar>()) const;
// template<typename OtherDerived>
// bool isOrthogonal(const MatrixBase<OtherDerived>& other,
-// RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
-// bool isUnitary(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
+// RealScalar prec = precision<Scalar>()) const;
+// bool isUnitary(RealScalar prec = precision<Scalar>()) const;
// template<typename OtherDerived>
// inline bool operator==(const MatrixBase<OtherDerived>& other) const
@@ -566,22 +472,22 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
// { return (cwise() != other).any(); }
-// template<typename NewType>
-// const SparseCwiseUnaryOp<internal::scalar_cast_op<typename internal::traits<Derived>::Scalar, NewType>, Derived> cast() const;
+ template<typename NewType>
+ const SparseCwiseUnaryOp<ei_scalar_cast_op<typename ei_traits<Derived>::Scalar, NewType>, Derived> cast() const;
/** \returns the matrix or vector obtained by evaluating this expression.
*
* Notice that in the case of a plain matrix or vector (not an expression) this function just returns
* a const reference, in order to avoid a useless copy.
*/
- inline const typename internal::eval<Derived>::type eval() const
- { return typename internal::eval<Derived>::type(derived()); }
+ EIGEN_STRONG_INLINE const typename ei_eval<Derived>::type eval() const
+ { return typename ei_eval<Derived>::type(derived()); }
// template<typename OtherDerived>
-// void swap(MatrixBase<OtherDerived> const & other);
+// void swap(const MatrixBase<OtherDerived>& other);
-// template<unsigned int Added>
-// const SparseFlagged<Derived, Added, 0> marked() const;
+ template<unsigned int Added>
+ const SparseFlagged<Derived, Added, 0> marked() const;
// const Flagged<Derived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit> lazy() const;
/** \returns number of elements to skip to pass from one row (resp. column) to another
@@ -591,13 +497,15 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
*/
// inline int stride(void) const { return derived().stride(); }
-// FIXME
-// ConjugateReturnType conjugate() const;
-// const RealReturnType real() const;
-// const ImagReturnType imag() const;
+// inline const NestByValue<Derived> nestByValue() const;
+
+
+ ConjugateReturnType conjugate() const;
+ const RealReturnType real() const;
+ const ImagReturnType imag() const;
-// template<typename CustomUnaryOp>
-// const SparseCwiseUnaryOp<CustomUnaryOp, Derived> unaryExpr(const CustomUnaryOp& func = CustomUnaryOp()) const;
+ template<typename CustomUnaryOp>
+ const SparseCwiseUnaryOp<CustomUnaryOp, Derived> unaryExpr(const CustomUnaryOp& func = CustomUnaryOp()) const;
// template<typename CustomBinaryOp, typename OtherDerived>
// const CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>
@@ -607,22 +515,22 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
Scalar sum() const;
// Scalar trace() const;
-// typename internal::traits<Derived>::Scalar minCoeff() const;
-// typename internal::traits<Derived>::Scalar maxCoeff() const;
+// typename ei_traits<Derived>::Scalar minCoeff() const;
+// typename ei_traits<Derived>::Scalar maxCoeff() const;
-// typename internal::traits<Derived>::Scalar minCoeff(int* row, int* col = 0) const;
-// typename internal::traits<Derived>::Scalar maxCoeff(int* row, int* col = 0) const;
+// typename ei_traits<Derived>::Scalar minCoeff(int* row, int* col = 0) const;
+// typename ei_traits<Derived>::Scalar maxCoeff(int* row, int* col = 0) const;
// template<typename BinaryOp>
-// typename internal::result_of<BinaryOp(typename internal::traits<Derived>::Scalar)>::type
+// typename ei_result_of<BinaryOp(typename ei_traits<Derived>::Scalar)>::type
// redux(const BinaryOp& func) const;
// template<typename Visitor>
// void visit(Visitor& func) const;
-// const SparseCwise<Derived> cwise() const;
-// SparseCwise<Derived> cwise();
+ const SparseCwise<Derived> cwise() const;
+ SparseCwise<Derived> cwise();
// inline const WithFormat<Derived> format(const IOFormat& fmt) const;
@@ -631,12 +539,12 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
bool all(void) const;
bool any(void) const;
- const VectorwiseOp<Derived,Horizontal> rowwise() const;
- const VectorwiseOp<Derived,Vertical> colwise() const;
+ const PartialRedux<Derived,Horizontal> rowwise() const;
+ const PartialRedux<Derived,Vertical> colwise() const;
- static const CwiseNullaryOp<internal::scalar_random_op<Scalar>,Derived> Random(int rows, int cols);
- static const CwiseNullaryOp<internal::scalar_random_op<Scalar>,Derived> Random(int size);
- static const CwiseNullaryOp<internal::scalar_random_op<Scalar>,Derived> Random();
+ static const CwiseNullaryOp<ei_scalar_random_op<Scalar>,Derived> Random(int rows, int cols);
+ static const CwiseNullaryOp<ei_scalar_random_op<Scalar>,Derived> Random(int size);
+ static const CwiseNullaryOp<ei_scalar_random_op<Scalar>,Derived> Random();
template<typename ThenDerived,typename ElseDerived>
const Select<Derived,ThenDerived,ElseDerived>
@@ -644,11 +552,11 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
const MatrixBase<ElseDerived>& elseMatrix) const;
template<typename ThenDerived>
- inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType>
+ inline const Select<Derived,ThenDerived, NestByValue<typename ThenDerived::ConstantReturnType> >
select(const MatrixBase<ThenDerived>& thenMatrix, typename ThenDerived::Scalar elseScalar) const;
template<typename ElseDerived>
- inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived >
+ inline const Select<Derived, NestByValue<typename ElseDerived::ConstantReturnType>, ElseDerived >
select(typename ElseDerived::Scalar thenScalar, const MatrixBase<ElseDerived>& elseMatrix) const;
template<int p> RealScalar lpNorm() const;
@@ -660,10 +568,10 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
// {
// EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
// EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
-// EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
+// EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
// YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
//
-// eigen_assert(derived().size() == other.size());
+// ei_assert(derived().size() == other.size());
// // short version, but the assembly looks more complicated because
// // of the CwiseBinaryOp iterator complexity
// // return res = (derived().cwise() * other.derived().conjugate()).sum();
@@ -677,7 +585,7 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
// if (i.index()==j.index())
// {
// // std::cerr << i.value() << " * " << j.value() << "\n";
-// res += i.value() * internal::conj(j.value());
+// res += i.value() * ei_conj(j.value());
// ++i; ++j;
// }
// else if (i.index()<j.index())
@@ -698,6 +606,18 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
// return res;
// }
+ #ifdef EIGEN_TAUCS_SUPPORT
+ taucs_ccs_matrix asTaucsMatrix();
+ #endif
+
+ #ifdef EIGEN_CHOLMOD_SUPPORT
+ cholmod_sparse asCholmodMatrix();
+ #endif
+
+ #ifdef EIGEN_SUPERLU_SUPPORT
+ SluMatrix asSluMatrix();
+ #endif
+
protected:
bool m_isRValue;
diff --git a/extern/Eigen2/Eigen/src/Sparse/SparseProduct.h b/extern/Eigen2/Eigen/src/Sparse/SparseProduct.h
new file mode 100644
index 00000000000..c98a71e993b
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseProduct.h
@@ -0,0 +1,415 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SPARSEPRODUCT_H
+#define EIGEN_SPARSEPRODUCT_H
+
+template<typename Lhs, typename Rhs> struct ei_sparse_product_mode
+{
+ enum {
+
+ value = ((Lhs::Flags&Diagonal)==Diagonal || (Rhs::Flags&Diagonal)==Diagonal)
+ ? DiagonalProduct
+ : (Rhs::Flags&Lhs::Flags&SparseBit)==SparseBit
+ ? SparseTimeSparseProduct
+ : (Lhs::Flags&SparseBit)==SparseBit
+ ? SparseTimeDenseProduct
+ : DenseTimeSparseProduct };
+};
+
+template<typename Lhs, typename Rhs, int ProductMode>
+struct SparseProductReturnType
+{
+ typedef const typename ei_nested<Lhs,Rhs::RowsAtCompileTime>::type LhsNested;
+ typedef const typename ei_nested<Rhs,Lhs::RowsAtCompileTime>::type RhsNested;
+
+ typedef SparseProduct<LhsNested, RhsNested, ProductMode> Type;
+};
+
+template<typename Lhs, typename Rhs>
+struct SparseProductReturnType<Lhs,Rhs,DiagonalProduct>
+{
+ typedef const typename ei_nested<Lhs,Rhs::RowsAtCompileTime>::type LhsNested;
+ typedef const typename ei_nested<Rhs,Lhs::RowsAtCompileTime>::type RhsNested;
+
+ typedef SparseDiagonalProduct<LhsNested, RhsNested> Type;
+};
+
+// sparse product return type specialization
+template<typename Lhs, typename Rhs>
+struct SparseProductReturnType<Lhs,Rhs,SparseTimeSparseProduct>
+{
+ typedef typename ei_traits<Lhs>::Scalar Scalar;
+ enum {
+ LhsRowMajor = ei_traits<Lhs>::Flags & RowMajorBit,
+ RhsRowMajor = ei_traits<Rhs>::Flags & RowMajorBit,
+ TransposeRhs = (!LhsRowMajor) && RhsRowMajor,
+ TransposeLhs = LhsRowMajor && (!RhsRowMajor)
+ };
+
+ // FIXME if we transpose let's evaluate to a LinkedVectorMatrix since it is the
+ // type of the temporary to perform the transpose op
+ typedef typename ei_meta_if<TransposeLhs,
+ SparseMatrix<Scalar,0>,
+ const typename ei_nested<Lhs,Rhs::RowsAtCompileTime>::type>::ret LhsNested;
+
+ typedef typename ei_meta_if<TransposeRhs,
+ SparseMatrix<Scalar,0>,
+ const typename ei_nested<Rhs,Lhs::RowsAtCompileTime>::type>::ret RhsNested;
+
+ typedef SparseProduct<LhsNested, RhsNested, SparseTimeSparseProduct> Type;
+};
+
+template<typename LhsNested, typename RhsNested, int ProductMode>
+struct ei_traits<SparseProduct<LhsNested, RhsNested, ProductMode> >
+{
+ // clean the nested types:
+ typedef typename ei_cleantype<LhsNested>::type _LhsNested;
+ typedef typename ei_cleantype<RhsNested>::type _RhsNested;
+ typedef typename _LhsNested::Scalar Scalar;
+
+ enum {
+ LhsCoeffReadCost = _LhsNested::CoeffReadCost,
+ RhsCoeffReadCost = _RhsNested::CoeffReadCost,
+ LhsFlags = _LhsNested::Flags,
+ RhsFlags = _RhsNested::Flags,
+
+ RowsAtCompileTime = _LhsNested::RowsAtCompileTime,
+ ColsAtCompileTime = _RhsNested::ColsAtCompileTime,
+ InnerSize = EIGEN_ENUM_MIN(_LhsNested::ColsAtCompileTime, _RhsNested::RowsAtCompileTime),
+
+ MaxRowsAtCompileTime = _LhsNested::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = _RhsNested::MaxColsAtCompileTime,
+
+// LhsIsRowMajor = (LhsFlags & RowMajorBit)==RowMajorBit,
+// RhsIsRowMajor = (RhsFlags & RowMajorBit)==RowMajorBit,
+
+ EvalToRowMajor = (RhsFlags & LhsFlags & RowMajorBit),
+ ResultIsSparse = ProductMode==SparseTimeSparseProduct || ProductMode==DiagonalProduct,
+
+ RemovedBits = ~( (EvalToRowMajor ? 0 : RowMajorBit) | (ResultIsSparse ? 0 : SparseBit) ),
+
+ Flags = (int(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
+ | EvalBeforeAssigningBit
+ | EvalBeforeNestingBit,
+
+ CoeffReadCost = Dynamic
+ };
+
+ typedef typename ei_meta_if<ResultIsSparse,
+ SparseMatrixBase<SparseProduct<LhsNested, RhsNested, ProductMode> >,
+ MatrixBase<SparseProduct<LhsNested, RhsNested, ProductMode> > >::ret Base;
+};
+
+template<typename LhsNested, typename RhsNested, int ProductMode>
+class SparseProduct : ei_no_assignment_operator,
+ public ei_traits<SparseProduct<LhsNested, RhsNested, ProductMode> >::Base
+{
+ public:
+
+ EIGEN_GENERIC_PUBLIC_INTERFACE(SparseProduct)
+
+ private:
+
+ typedef typename ei_traits<SparseProduct>::_LhsNested _LhsNested;
+ typedef typename ei_traits<SparseProduct>::_RhsNested _RhsNested;
+
+ public:
+
+ template<typename Lhs, typename Rhs>
+ EIGEN_STRONG_INLINE SparseProduct(const Lhs& lhs, const Rhs& rhs)
+ : m_lhs(lhs), m_rhs(rhs)
+ {
+ ei_assert(lhs.cols() == rhs.rows());
+
+ enum {
+ ProductIsValid = _LhsNested::ColsAtCompileTime==Dynamic
+ || _RhsNested::RowsAtCompileTime==Dynamic
+ || int(_LhsNested::ColsAtCompileTime)==int(_RhsNested::RowsAtCompileTime),
+ AreVectors = _LhsNested::IsVectorAtCompileTime && _RhsNested::IsVectorAtCompileTime,
+ SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(_LhsNested,_RhsNested)
+ };
+ // note to the lost user:
+ // * for a dot product use: v1.dot(v2)
+ // * for a coeff-wise product use: v1.cwise()*v2
+ EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
+ INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
+ EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
+ INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
+ EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
+ }
+
+ EIGEN_STRONG_INLINE int rows() const { return m_lhs.rows(); }
+ EIGEN_STRONG_INLINE int cols() const { return m_rhs.cols(); }
+
+ EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
+ EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
+
+ protected:
+ LhsNested m_lhs;
+ RhsNested m_rhs;
+};
+
+// perform a pseudo in-place sparse * sparse product assuming all matrices are col major
+template<typename Lhs, typename Rhs, typename ResultType>
+static void ei_sparse_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res)
+{
+ typedef typename ei_traits<typename ei_cleantype<Lhs>::type>::Scalar Scalar;
+
+ // make sure to call innerSize/outerSize since we fake the storage order.
+ int rows = lhs.innerSize();
+ int cols = rhs.outerSize();
+ //int size = lhs.outerSize();
+ ei_assert(lhs.outerSize() == rhs.innerSize());
+
+ // allocate a temporary buffer
+ AmbiVector<Scalar> tempVector(rows);
+
+ // estimate the number of non zero entries
+ float ratioLhs = float(lhs.nonZeros())/(float(lhs.rows())*float(lhs.cols()));
+ float avgNnzPerRhsColumn = float(rhs.nonZeros())/float(cols);
+ float ratioRes = std::min(ratioLhs * avgNnzPerRhsColumn, 1.f);
+
+ res.resize(rows, cols);
+ res.startFill(int(ratioRes*rows*cols));
+ for (int j=0; j<cols; ++j)
+ {
+ // let's do a more accurate determination of the nnz ratio for the current column j of res
+ //float ratioColRes = std::min(ratioLhs * rhs.innerNonZeros(j), 1.f);
+ // FIXME find a nice way to get the number of nonzeros of a sub matrix (here an inner vector)
+ float ratioColRes = ratioRes;
+ tempVector.init(ratioColRes);
+ tempVector.setZero();
+ for (typename Rhs::InnerIterator rhsIt(rhs, j); rhsIt; ++rhsIt)
+ {
+ // FIXME should be written like this: tmp += rhsIt.value() * lhs.col(rhsIt.index())
+ tempVector.restart();
+ Scalar x = rhsIt.value();
+ for (typename Lhs::InnerIterator lhsIt(lhs, rhsIt.index()); lhsIt; ++lhsIt)
+ {
+ tempVector.coeffRef(lhsIt.index()) += lhsIt.value() * x;
+ }
+ }
+ for (typename AmbiVector<Scalar>::Iterator it(tempVector); it; ++it)
+ if (ResultType::Flags&RowMajorBit)
+ res.fill(j,it.index()) = it.value();
+ else
+ res.fill(it.index(), j) = it.value();
+ }
+ res.endFill();
+}
+
+template<typename Lhs, typename Rhs, typename ResultType,
+ int LhsStorageOrder = ei_traits<Lhs>::Flags&RowMajorBit,
+ int RhsStorageOrder = ei_traits<Rhs>::Flags&RowMajorBit,
+ int ResStorageOrder = ei_traits<ResultType>::Flags&RowMajorBit>
+struct ei_sparse_product_selector;
+
+template<typename Lhs, typename Rhs, typename ResultType>
+struct ei_sparse_product_selector<Lhs,Rhs,ResultType,ColMajor,ColMajor,ColMajor>
+{
+ typedef typename ei_traits<typename ei_cleantype<Lhs>::type>::Scalar Scalar;
+
+ static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
+ {
+ typename ei_cleantype<ResultType>::type _res(res.rows(), res.cols());
+ ei_sparse_product_impl<Lhs,Rhs,ResultType>(lhs, rhs, _res);
+ res.swap(_res);
+ }
+};
+
+template<typename Lhs, typename Rhs, typename ResultType>
+struct ei_sparse_product_selector<Lhs,Rhs,ResultType,ColMajor,ColMajor,RowMajor>
+{
+ static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
+ {
+ // we need a col-major matrix to hold the result
+ typedef SparseMatrix<typename ResultType::Scalar> SparseTemporaryType;
+ SparseTemporaryType _res(res.rows(), res.cols());
+ ei_sparse_product_impl<Lhs,Rhs,SparseTemporaryType>(lhs, rhs, _res);
+ res = _res;
+ }
+};
+
+template<typename Lhs, typename Rhs, typename ResultType>
+struct ei_sparse_product_selector<Lhs,Rhs,ResultType,RowMajor,RowMajor,RowMajor>
+{
+ static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
+ {
+ // let's transpose the product to get a column x column product
+ typename ei_cleantype<ResultType>::type _res(res.rows(), res.cols());
+ ei_sparse_product_impl<Rhs,Lhs,ResultType>(rhs, lhs, _res);
+ res.swap(_res);
+ }
+};
+
+template<typename Lhs, typename Rhs, typename ResultType>
+struct ei_sparse_product_selector<Lhs,Rhs,ResultType,RowMajor,RowMajor,ColMajor>
+{
+ static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
+ {
+ // let's transpose the product to get a column x column product
+ typedef SparseMatrix<typename ResultType::Scalar> SparseTemporaryType;
+ SparseTemporaryType _res(res.cols(), res.rows());
+ ei_sparse_product_impl<Rhs,Lhs,SparseTemporaryType>(rhs, lhs, _res);
+ res = _res.transpose();
+ }
+};
+
+// NOTE eventually let's transpose one argument even in this case since it might be expensive if
+// the result is not dense.
+// template<typename Lhs, typename Rhs, typename ResultType, int ResStorageOrder>
+// struct ei_sparse_product_selector<Lhs,Rhs,ResultType,RowMajor,ColMajor,ResStorageOrder>
+// {
+// static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
+// {
+// // trivial product as lhs.row/rhs.col dot products
+// // loop over the preferred order of the result
+// }
+// };
+
+// NOTE the 2 others cases (col row *) must never occurs since they are caught
+// by ProductReturnType which transform it to (col col *) by evaluating rhs.
+
+
+// template<typename Derived>
+// template<typename Lhs, typename Rhs>
+// inline Derived& SparseMatrixBase<Derived>::lazyAssign(const SparseProduct<Lhs,Rhs>& product)
+// {
+// // std::cout << "sparse product to dense\n";
+// ei_sparse_product_selector<
+// typename ei_cleantype<Lhs>::type,
+// typename ei_cleantype<Rhs>::type,
+// typename ei_cleantype<Derived>::type>::run(product.lhs(),product.rhs(),derived());
+// return derived();
+// }
+
+// sparse = sparse * sparse
+template<typename Derived>
+template<typename Lhs, typename Rhs>
+inline Derived& SparseMatrixBase<Derived>::operator=(const SparseProduct<Lhs,Rhs,SparseTimeSparseProduct>& product)
+{
+ ei_sparse_product_selector<
+ typename ei_cleantype<Lhs>::type,
+ typename ei_cleantype<Rhs>::type,
+ Derived>::run(product.lhs(),product.rhs(),derived());
+ return derived();
+}
+
+// dense = sparse * dense
+// template<typename Derived>
+// template<typename Lhs, typename Rhs>
+// Derived& MatrixBase<Derived>::lazyAssign(const SparseProduct<Lhs,Rhs,SparseTimeDenseProduct>& product)
+// {
+// typedef typename ei_cleantype<Lhs>::type _Lhs;
+// typedef typename _Lhs::InnerIterator LhsInnerIterator;
+// enum { LhsIsRowMajor = (_Lhs::Flags&RowMajorBit)==RowMajorBit };
+// derived().setZero();
+// for (int j=0; j<product.lhs().outerSize(); ++j)
+// for (LhsInnerIterator i(product.lhs(),j); i; ++i)
+// derived().row(LhsIsRowMajor ? j : i.index()) += i.value() * product.rhs().row(LhsIsRowMajor ? i.index() : j);
+// return derived();
+// }
+
+template<typename Derived>
+template<typename Lhs, typename Rhs>
+Derived& MatrixBase<Derived>::lazyAssign(const SparseProduct<Lhs,Rhs,SparseTimeDenseProduct>& product)
+{
+ typedef typename ei_cleantype<Lhs>::type _Lhs;
+ typedef typename ei_cleantype<Rhs>::type _Rhs;
+ typedef typename _Lhs::InnerIterator LhsInnerIterator;
+ enum {
+ LhsIsRowMajor = (_Lhs::Flags&RowMajorBit)==RowMajorBit,
+ LhsIsSelfAdjoint = (_Lhs::Flags&SelfAdjointBit)==SelfAdjointBit,
+ ProcessFirstHalf = LhsIsSelfAdjoint
+ && ( ((_Lhs::Flags&(UpperTriangularBit|LowerTriangularBit))==0)
+ || ( (_Lhs::Flags&UpperTriangularBit) && !LhsIsRowMajor)
+ || ( (_Lhs::Flags&LowerTriangularBit) && LhsIsRowMajor) ),
+ ProcessSecondHalf = LhsIsSelfAdjoint && (!ProcessFirstHalf)
+ };
+ derived().setZero();
+ for (int j=0; j<product.lhs().outerSize(); ++j)
+ {
+ LhsInnerIterator i(product.lhs(),j);
+ if (ProcessSecondHalf && i && (i.index()==j))
+ {
+ derived().row(j) += i.value() * product.rhs().row(j);
+ ++i;
+ }
+ Block<Derived,1,Derived::ColsAtCompileTime> res(derived().row(LhsIsRowMajor ? j : 0));
+ for (; (ProcessFirstHalf ? i && i.index() < j : i) ; ++i)
+ {
+ if (LhsIsSelfAdjoint)
+ {
+ int a = LhsIsRowMajor ? j : i.index();
+ int b = LhsIsRowMajor ? i.index() : j;
+ Scalar v = i.value();
+ derived().row(a) += (v) * product.rhs().row(b);
+ derived().row(b) += ei_conj(v) * product.rhs().row(a);
+ }
+ else if (LhsIsRowMajor)
+ res += i.value() * product.rhs().row(i.index());
+ else
+ derived().row(i.index()) += i.value() * product.rhs().row(j);
+ }
+ if (ProcessFirstHalf && i && (i.index()==j))
+ derived().row(j) += i.value() * product.rhs().row(j);
+ }
+ return derived();
+}
+
+// dense = dense * sparse
+template<typename Derived>
+template<typename Lhs, typename Rhs>
+Derived& MatrixBase<Derived>::lazyAssign(const SparseProduct<Lhs,Rhs,DenseTimeSparseProduct>& product)
+{
+ typedef typename ei_cleantype<Rhs>::type _Rhs;
+ typedef typename _Rhs::InnerIterator RhsInnerIterator;
+ enum { RhsIsRowMajor = (_Rhs::Flags&RowMajorBit)==RowMajorBit };
+ derived().setZero();
+ for (int j=0; j<product.rhs().outerSize(); ++j)
+ for (RhsInnerIterator i(product.rhs(),j); i; ++i)
+ derived().col(RhsIsRowMajor ? i.index() : j) += i.value() * product.lhs().col(RhsIsRowMajor ? j : i.index());
+ return derived();
+}
+
+// sparse * sparse
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const typename SparseProductReturnType<Derived,OtherDerived>::Type
+SparseMatrixBase<Derived>::operator*(const SparseMatrixBase<OtherDerived> &other) const
+{
+ return typename SparseProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
+}
+
+// sparse * dense
+template<typename Derived>
+template<typename OtherDerived>
+EIGEN_STRONG_INLINE const typename SparseProductReturnType<Derived,OtherDerived>::Type
+SparseMatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
+{
+ return typename SparseProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
+}
+
+#endif // EIGEN_SPARSEPRODUCT_H
diff --git a/extern/Eigen3/Eigen/StdDeque b/extern/Eigen2/Eigen/src/Sparse/SparseRedux.h
index a4f96232d8c..f0d3705488e 100644
--- a/extern/Eigen3/Eigen/StdDeque
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseRedux.h
@@ -1,8 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -23,20 +22,19 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
-#ifndef EIGEN_STDDEQUE_MODULE_H
-#define EIGEN_STDDEQUE_MODULE_H
-
-#include "Core"
-#include <deque>
-
-#if (defined(_MSC_VER) && defined(_WIN64)) /* MSVC auto aligns in 64 bit builds */
-
-#define EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(...)
-
-#else
-
-#include "src/StlSupport/StdDeque.h"
-
-#endif
-
-#endif // EIGEN_STDDEQUE_MODULE_H
+#ifndef EIGEN_SPARSEREDUX_H
+#define EIGEN_SPARSEREDUX_H
+
+template<typename Derived>
+typename ei_traits<Derived>::Scalar
+SparseMatrixBase<Derived>::sum() const
+{
+ ei_assert(rows()>0 && cols()>0 && "you are using a non initialized matrix");
+ Scalar res = 0;
+ for (int j=0; j<outerSize(); ++j)
+ for (typename Derived::InnerIterator iter(derived(),j); iter; ++iter)
+ res += iter.value();
+ return res;
+}
+
+#endif // EIGEN_SPARSEREDUX_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/SparseTranspose.h b/extern/Eigen2/Eigen/src/Sparse/SparseTranspose.h
new file mode 100644
index 00000000000..7386294e4d4
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseTranspose.h
@@ -0,0 +1,90 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SPARSETRANSPOSE_H
+#define EIGEN_SPARSETRANSPOSE_H
+
+template<typename MatrixType>
+struct ei_traits<SparseTranspose<MatrixType> > : ei_traits<Transpose<MatrixType> >
+{};
+
+template<typename MatrixType> class SparseTranspose
+ : public SparseMatrixBase<SparseTranspose<MatrixType> >
+{
+ public:
+
+ EIGEN_GENERIC_PUBLIC_INTERFACE(SparseTranspose)
+
+ class InnerIterator;
+ class ReverseInnerIterator;
+
+ inline SparseTranspose(const MatrixType& matrix) : m_matrix(matrix) {}
+
+ //EIGEN_INHERIT_ASSIGNMENT_OPERATORS(SparseTranspose)
+
+ inline int rows() const { return m_matrix.cols(); }
+ inline int cols() const { return m_matrix.rows(); }
+ inline int nonZeros() const { return m_matrix.nonZeros(); }
+
+ // FIXME should be keep them ?
+ inline Scalar& coeffRef(int row, int col)
+ { return m_matrix.const_cast_derived().coeffRef(col, row); }
+
+ inline const Scalar coeff(int row, int col) const
+ { return m_matrix.coeff(col, row); }
+
+ inline const Scalar coeff(int index) const
+ { return m_matrix.coeff(index); }
+
+ inline Scalar& coeffRef(int index)
+ { return m_matrix.const_cast_derived().coeffRef(index); }
+
+ protected:
+ const typename MatrixType::Nested m_matrix;
+
+ private:
+ SparseTranspose& operator=(const SparseTranspose&);
+};
+
+template<typename MatrixType> class SparseTranspose<MatrixType>::InnerIterator : public MatrixType::InnerIterator
+{
+ public:
+ EIGEN_STRONG_INLINE InnerIterator(const SparseTranspose& trans, int outer)
+ : MatrixType::InnerIterator(trans.m_matrix, outer)
+ {}
+
+ private:
+ InnerIterator& operator=(const InnerIterator&);
+};
+
+template<typename MatrixType> class SparseTranspose<MatrixType>::ReverseInnerIterator : public MatrixType::ReverseInnerIterator
+{
+ public:
+
+ EIGEN_STRONG_INLINE ReverseInnerIterator(const SparseTranspose& xpr, int outer)
+ : MatrixType::ReverseInnerIterator(xpr.m_matrix, outer)
+ {}
+};
+
+#endif // EIGEN_SPARSETRANSPOSE_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/SparseUtil.h b/extern/Eigen2/Eigen/src/Sparse/SparseUtil.h
new file mode 100644
index 00000000000..393cdda6ea2
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseUtil.h
@@ -0,0 +1,148 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SPARSEUTIL_H
+#define EIGEN_SPARSEUTIL_H
+
+#ifdef NDEBUG
+#define EIGEN_DBG_SPARSE(X)
+#else
+#define EIGEN_DBG_SPARSE(X) X
+#endif
+
+#define EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(Derived, Op) \
+template<typename OtherDerived> \
+EIGEN_STRONG_INLINE Derived& operator Op(const Eigen::SparseMatrixBase<OtherDerived>& other) \
+{ \
+ return Base::operator Op(other.derived()); \
+} \
+EIGEN_STRONG_INLINE Derived& operator Op(const Derived& other) \
+{ \
+ return Base::operator Op(other); \
+}
+
+#define EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, Op) \
+template<typename Other> \
+EIGEN_STRONG_INLINE Derived& operator Op(const Other& scalar) \
+{ \
+ return Base::operator Op(scalar); \
+}
+
+#define EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATORS(Derived) \
+EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(Derived, =) \
+EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(Derived, +=) \
+EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(Derived, -=) \
+EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, *=) \
+EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, /=)
+
+#define _EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(Derived, BaseClass) \
+typedef BaseClass Base; \
+typedef typename Eigen::ei_traits<Derived>::Scalar Scalar; \
+typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; \
+typedef typename Eigen::ei_nested<Derived>::type Nested; \
+enum { RowsAtCompileTime = Eigen::ei_traits<Derived>::RowsAtCompileTime, \
+ ColsAtCompileTime = Eigen::ei_traits<Derived>::ColsAtCompileTime, \
+ Flags = Eigen::ei_traits<Derived>::Flags, \
+ CoeffReadCost = Eigen::ei_traits<Derived>::CoeffReadCost, \
+ SizeAtCompileTime = Base::SizeAtCompileTime, \
+ IsVectorAtCompileTime = Base::IsVectorAtCompileTime };
+
+#define EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(Derived) \
+_EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(Derived, Eigen::SparseMatrixBase<Derived>)
+
+enum SparseBackend {
+ DefaultBackend,
+ Taucs,
+ Cholmod,
+ SuperLU,
+ UmfPack
+};
+
+// solver flags
+enum {
+ CompleteFactorization = 0x0000, // the default
+ IncompleteFactorization = 0x0001,
+ MemoryEfficient = 0x0002,
+
+ // For LLT Cholesky:
+ SupernodalMultifrontal = 0x0010,
+ SupernodalLeftLooking = 0x0020,
+
+ // Ordering methods:
+ NaturalOrdering = 0x0100, // the default
+ MinimumDegree_AT_PLUS_A = 0x0200,
+ MinimumDegree_ATA = 0x0300,
+ ColApproxMinimumDegree = 0x0400,
+ Metis = 0x0500,
+ Scotch = 0x0600,
+ Chaco = 0x0700,
+ OrderingMask = 0x0f00
+};
+
+template<typename Derived> class SparseMatrixBase;
+template<typename _Scalar, int _Flags = 0> class SparseMatrix;
+template<typename _Scalar, int _Flags = 0> class DynamicSparseMatrix;
+template<typename _Scalar, int _Flags = 0> class SparseVector;
+template<typename _Scalar, int _Flags = 0> class MappedSparseMatrix;
+
+template<typename MatrixType> class SparseTranspose;
+template<typename MatrixType, int Size> class SparseInnerVectorSet;
+template<typename Derived> class SparseCwise;
+template<typename UnaryOp, typename MatrixType> class SparseCwiseUnaryOp;
+template<typename BinaryOp, typename Lhs, typename Rhs> class SparseCwiseBinaryOp;
+template<typename ExpressionType,
+ unsigned int Added, unsigned int Removed> class SparseFlagged;
+template<typename Lhs, typename Rhs> class SparseDiagonalProduct;
+
+template<typename Lhs, typename Rhs> struct ei_sparse_product_mode;
+template<typename Lhs, typename Rhs, int ProductMode = ei_sparse_product_mode<Lhs,Rhs>::value> struct SparseProductReturnType;
+
+const int CoherentAccessPattern = 0x1;
+const int InnerRandomAccessPattern = 0x2 | CoherentAccessPattern;
+const int OuterRandomAccessPattern = 0x4 | CoherentAccessPattern;
+const int RandomAccessPattern = 0x8 | OuterRandomAccessPattern | InnerRandomAccessPattern;
+
+// const int AccessPatternNotSupported = 0x0;
+// const int AccessPatternSupported = 0x1;
+//
+// template<typename MatrixType, int AccessPattern> struct ei_support_access_pattern
+// {
+// enum { ret = (int(ei_traits<MatrixType>::SupportedAccessPatterns) & AccessPattern) == AccessPattern
+// ? AccessPatternSupported
+// : AccessPatternNotSupported
+// };
+// };
+
+template<typename T> class ei_eval<T,IsSparse>
+{
+ typedef typename ei_traits<T>::Scalar _Scalar;
+ enum {
+ _Flags = ei_traits<T>::Flags
+ };
+
+ public:
+ typedef SparseMatrix<_Scalar, _Flags> type;
+};
+
+#endif // EIGEN_SPARSEUTIL_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseVector.h b/extern/Eigen2/Eigen/src/Sparse/SparseVector.h
index ce4bb51a27e..5d47209f790 100644
--- a/extern/Eigen3/Eigen/src/Sparse/SparseVector.h
+++ b/extern/Eigen2/Eigen/src/Sparse/SparseVector.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
+// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -29,42 +29,34 @@
*
* \brief a sparse vector class
*
- * \tparam _Scalar the scalar type, i.e. the type of the coefficients
+ * \param _Scalar the scalar type, i.e. the type of the coefficients
*
* See http://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme.
*
- * 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_SPARSEVECTOR_PLUGIN.
*/
-
-namespace internal {
-template<typename _Scalar, int _Options, typename _Index>
-struct traits<SparseVector<_Scalar, _Options, _Index> >
+template<typename _Scalar, int _Flags>
+struct ei_traits<SparseVector<_Scalar, _Flags> >
{
typedef _Scalar Scalar;
- typedef _Index Index;
- typedef Sparse StorageKind;
- typedef MatrixXpr XprKind;
enum {
- IsColVector = _Options & RowMajorBit ? 0 : 1,
+ IsColVector = _Flags & RowMajorBit ? 0 : 1,
RowsAtCompileTime = IsColVector ? Dynamic : 1,
ColsAtCompileTime = IsColVector ? 1 : Dynamic,
MaxRowsAtCompileTime = RowsAtCompileTime,
MaxColsAtCompileTime = ColsAtCompileTime,
- Flags = _Options | NestByRefBit | LvalueBit,
+ Flags = SparseBit | _Flags,
CoeffReadCost = NumTraits<Scalar>::ReadCost,
SupportedAccessPatterns = InnerRandomAccessPattern
};
};
-}
-template<typename _Scalar, int _Options, typename _Index>
+template<typename _Scalar, int _Flags>
class SparseVector
- : public SparseMatrixBase<SparseVector<_Scalar, _Options, _Index> >
+ : public SparseMatrixBase<SparseVector<_Scalar, _Flags> >
{
public:
- EIGEN_SPARSE_PUBLIC_INTERFACE(SparseVector)
+ EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseVector)
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, +=)
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, -=)
// EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, =)
@@ -73,52 +65,48 @@ class SparseVector
public:
typedef SparseMatrixBase<SparseVector> SparseBase;
- enum { IsColVector = internal::traits<SparseVector>::IsColVector };
-
- enum {
- Options = _Options
- };
-
- CompressedStorage<Scalar,Index> m_data;
- Index m_size;
+ enum { IsColVector = ei_traits<SparseVector>::IsColVector };
- CompressedStorage<Scalar,Index>& _data() { return m_data; }
- CompressedStorage<Scalar,Index>& _data() const { return m_data; }
+ CompressedStorage<Scalar> m_data;
+ int m_size;
+
+ CompressedStorage<Scalar>& _data() { return m_data; }
+ CompressedStorage<Scalar>& _data() const { return m_data; }
public:
- EIGEN_STRONG_INLINE Index rows() const { return IsColVector ? m_size : 1; }
- EIGEN_STRONG_INLINE Index cols() const { return IsColVector ? 1 : m_size; }
- EIGEN_STRONG_INLINE Index innerSize() const { return m_size; }
- EIGEN_STRONG_INLINE Index outerSize() const { return 1; }
- EIGEN_STRONG_INLINE Index innerNonZeros(Index j) const { eigen_assert(j==0); return m_size; }
+ EIGEN_STRONG_INLINE int rows() const { return IsColVector ? m_size : 1; }
+ EIGEN_STRONG_INLINE int cols() const { return IsColVector ? 1 : m_size; }
+ EIGEN_STRONG_INLINE int innerSize() const { return m_size; }
+ EIGEN_STRONG_INLINE int outerSize() const { return 1; }
+ EIGEN_STRONG_INLINE int innerNonZeros(int j) const { ei_assert(j==0); return m_size; }
EIGEN_STRONG_INLINE const Scalar* _valuePtr() const { return &m_data.value(0); }
EIGEN_STRONG_INLINE Scalar* _valuePtr() { return &m_data.value(0); }
- EIGEN_STRONG_INLINE const Index* _innerIndexPtr() const { return &m_data.index(0); }
- EIGEN_STRONG_INLINE Index* _innerIndexPtr() { return &m_data.index(0); }
+ EIGEN_STRONG_INLINE const int* _innerIndexPtr() const { return &m_data.index(0); }
+ EIGEN_STRONG_INLINE int* _innerIndexPtr() { return &m_data.index(0); }
- inline Scalar coeff(Index row, Index col) const
+ inline Scalar coeff(int row, int col) const
{
- eigen_assert((IsColVector ? col : row)==0);
+ ei_assert((IsColVector ? col : row)==0);
return coeff(IsColVector ? row : col);
}
- inline Scalar coeff(Index i) const { return m_data.at(i); }
+ inline Scalar coeff(int i) const { return m_data.at(i); }
- inline Scalar& coeffRef(Index row, Index col)
+ inline Scalar& coeffRef(int row, int col)
{
- eigen_assert((IsColVector ? col : row)==0);
+ ei_assert((IsColVector ? col : row)==0);
return coeff(IsColVector ? row : col);
}
/** \returns a reference to the coefficient value at given index \a i
* This operation involes a log(rho*size) binary search. If the coefficient does not
* exist yet, then a sorted insertion into a sequential buffer is performed.
- *
+ *
* This insertion might be very costly if the number of nonzeros above \a i is large.
*/
- inline Scalar& coeffRef(Index i)
+ inline Scalar& coeffRef(int i)
{
return m_data.atWithInsertion(i);
}
@@ -130,80 +118,83 @@ class SparseVector
inline void setZero() { m_data.clear(); }
/** \returns the number of non zero coefficients */
- inline Index nonZeros() const { return static_cast<Index>(m_data.size()); }
+ inline int nonZeros() const { return m_data.size(); }
- inline void startVec(Index outer)
+ /**
+ */
+ inline void reserve(int reserveSize) { m_data.reserve(reserveSize); }
+
+ inline void startFill(int reserve)
{
- eigen_assert(outer==0);
+ setZero();
+ m_data.reserve(reserve);
}
- inline Scalar& insertBackByOuterInner(Index outer, Index inner)
+ /**
+ */
+ inline Scalar& fill(int r, int c)
{
- eigen_assert(outer==0);
- return insertBack(inner);
+ ei_assert(r==0 || c==0);
+ return fill(IsColVector ? r : c);
}
- inline Scalar& insertBack(Index i)
+
+ inline Scalar& fill(int i)
{
m_data.append(0, i);
return m_data.value(m_data.size()-1);
}
-
- inline Scalar& insert(Index row, Index col)
+
+ inline Scalar& fillrand(int r, int c)
{
- Index inner = IsColVector ? row : col;
- Index outer = IsColVector ? col : row;
- eigen_assert(outer==0);
- return insert(inner);
+ ei_assert(r==0 || c==0);
+ return fillrand(IsColVector ? r : c);
}
- Scalar& insert(Index i)
+
+ /** Like fill() but with random coordinates.
+ */
+ inline Scalar& fillrand(int i)
{
- Index startId = 0;
- Index p = m_data.size() - 1;
- // TODO smart realloc
- m_data.resize(p+2,1);
+ int startId = 0;
+ int id = m_data.size() - 1;
+ m_data.resize(id+2,1);
- while ( (p >= startId) && (m_data.index(p) > i) )
+ while ( (id >= startId) && (m_data.index(id) > i) )
{
- m_data.index(p+1) = m_data.index(p);
- m_data.value(p+1) = m_data.value(p);
- --p;
+ m_data.index(id+1) = m_data.index(id);
+ m_data.value(id+1) = m_data.value(id);
+ --id;
}
- m_data.index(p+1) = i;
- m_data.value(p+1) = 0;
- return m_data.value(p+1);
+ m_data.index(id+1) = i;
+ m_data.value(id+1) = 0;
+ return m_data.value(id+1);
}
-
- /**
- */
- inline void reserve(Index reserveSize) { m_data.reserve(reserveSize); }
-
-
- inline void finalize() {}
-
- void prune(Scalar reference, RealScalar epsilon = NumTraits<RealScalar>::dummy_precision())
+
+ inline void endFill() {}
+
+ void prune(Scalar reference, RealScalar epsilon = precision<RealScalar>())
{
m_data.prune(reference,epsilon);
}
-
- void resize(Index rows, Index cols)
+
+ void resize(int rows, int cols)
{
- eigen_assert(rows==1 || cols==1);
+ ei_assert(rows==1 || cols==1);
resize(IsColVector ? rows : cols);
}
- void resize(Index newSize)
+ void resize(int newSize)
{
m_size = newSize;
m_data.clear();
}
- void resizeNonZeros(Index size) { m_data.resize(size); }
+ void resizeNonZeros(int size) { m_data.resize(size); }
inline SparseVector() : m_size(0) { resize(0); }
- inline SparseVector(Index size) : m_size(0) { resize(size); }
-
- inline SparseVector(Index rows, Index cols) : m_size(0) { resize(rows,cols); }
+ inline SparseVector(int size) : m_size(0) { resize(size); }
+
+ inline SparseVector(int rows, int cols) : m_size(0) { resize(rows,cols); }
template<typename OtherDerived>
inline SparseVector(const MatrixBase<OtherDerived>& other)
@@ -211,7 +202,7 @@ class SparseVector
{
*this = other.derived();
}
-
+
template<typename OtherDerived>
inline SparseVector(const SparseMatrixBase<OtherDerived>& other)
: m_size(0)
@@ -248,20 +239,9 @@ class SparseVector
template<typename OtherDerived>
inline SparseVector& operator=(const SparseMatrixBase<OtherDerived>& other)
{
- if (int(RowsAtCompileTime)!=int(OtherDerived::RowsAtCompileTime))
- return Base::operator=(other.transpose());
- else
- return Base::operator=(other);
+ return Base::operator=(other);
}
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- template<typename Lhs, typename Rhs>
- inline SparseVector& operator=(const SparseSparseProduct<Lhs,Rhs>& product)
- {
- return Base::operator=(product);
- }
- #endif
-
+
// const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
// if (needToTranspose)
// {
@@ -269,9 +249,9 @@ class SparseVector
// // 1 - compute the number of coeffs per dest inner vector
// // 2 - do the actual copy/eval
// // Since each coeff of the rhs has to be evaluated twice, let's evauluate it if needed
-// typedef typename internal::nested<OtherDerived,2>::type OtherCopy;
+// typedef typename ei_nested<OtherDerived,2>::type OtherCopy;
// OtherCopy otherCopy(other.derived());
-// typedef typename internal::remove_all<OtherCopy>::type _OtherCopy;
+// typedef typename ei_cleantype<OtherCopy>::type _OtherCopy;
//
// resize(other.rows(), other.cols());
// Eigen::Map<VectorXi>(m_outerIndex,outerSize()).setZero();
@@ -314,7 +294,7 @@ class SparseVector
friend std::ostream & operator << (std::ostream & s, const SparseVector& m)
{
- for (Index i=0; i<m.nonZeros(); ++i)
+ for (unsigned int i=0; i<m.nonZeros(); ++i)
s << "(" << m.m_data.value(i) << "," << m.m_data.index(i) << ") ";
s << std::endl;
return s;
@@ -330,7 +310,7 @@ class SparseVector
// {
// if (m_data.index(i)==other.m_data.index(j))
// {
-// res += m_data.value(i) * internal::conj(other.m_data.value(j));
+// res += m_data.value(i) * ei_conj(other.m_data.value(j));
// ++i; ++j;
// }
// else if (m_data.index(i)<other.m_data.index(j))
@@ -344,70 +324,24 @@ class SparseVector
/** Destructor */
inline ~SparseVector() {}
-
- /** Overloaded for performance */
- Scalar sum() const;
-
- public:
-
- /** \deprecated use setZero() and reserve() */
- EIGEN_DEPRECATED void startFill(Index reserve)
- {
- setZero();
- m_data.reserve(reserve);
- }
-
- /** \deprecated use insertBack(Index,Index) */
- EIGEN_DEPRECATED Scalar& fill(Index r, Index c)
- {
- eigen_assert(r==0 || c==0);
- return fill(IsColVector ? r : c);
- }
-
- /** \deprecated use insertBack(Index) */
- EIGEN_DEPRECATED Scalar& fill(Index i)
- {
- m_data.append(0, i);
- return m_data.value(m_data.size()-1);
- }
-
- /** \deprecated use insert(Index,Index) */
- EIGEN_DEPRECATED Scalar& fillrand(Index r, Index c)
- {
- eigen_assert(r==0 || c==0);
- return fillrand(IsColVector ? r : c);
- }
-
- /** \deprecated use insert(Index) */
- EIGEN_DEPRECATED Scalar& fillrand(Index i)
- {
- return insert(i);
- }
-
- /** \deprecated use finalize() */
- EIGEN_DEPRECATED void endFill() {}
-
-# ifdef EIGEN_SPARSEVECTOR_PLUGIN
-# include EIGEN_SPARSEVECTOR_PLUGIN
-# endif
};
-template<typename Scalar, int _Options, typename _Index>
-class SparseVector<Scalar,_Options,_Index>::InnerIterator
+template<typename Scalar, int _Flags>
+class SparseVector<Scalar,_Flags>::InnerIterator
{
public:
- InnerIterator(const SparseVector& vec, Index outer=0)
- : m_data(vec.m_data), m_id(0), m_end(static_cast<Index>(m_data.size()))
+ InnerIterator(const SparseVector& vec, int outer=0)
+ : m_data(vec.m_data), m_id(0), m_end(m_data.size())
{
- eigen_assert(outer==0);
+ ei_assert(outer==0);
}
-
- InnerIterator(const CompressedStorage<Scalar,Index>& data)
- : m_data(data), m_id(0), m_end(static_cast<Index>(m_data.size()))
+
+ InnerIterator(const CompressedStorage<Scalar>& data)
+ : m_data(data), m_id(0), m_end(m_data.size())
{}
template<unsigned int Added, unsigned int Removed>
- InnerIterator(const Flagged<SparseVector,Added,Removed>& vec, Index )
+ InnerIterator(const Flagged<SparseVector,Added,Removed>& vec, int outer)
: m_data(vec._expression().m_data), m_id(0), m_end(m_data.size())
{}
@@ -416,16 +350,19 @@ class SparseVector<Scalar,_Options,_Index>::InnerIterator
inline Scalar value() const { return m_data.value(m_id); }
inline Scalar& valueRef() { return const_cast<Scalar&>(m_data.value(m_id)); }
- inline Index index() const { return m_data.index(m_id); }
- inline Index row() const { return IsColVector ? index() : 0; }
- inline Index col() const { return IsColVector ? 0 : index(); }
+ inline int index() const { return m_data.index(m_id); }
+ inline int row() const { return IsColVector ? index() : 0; }
+ inline int col() const { return IsColVector ? 0 : index(); }
inline operator bool() const { return (m_id < m_end); }
protected:
- const CompressedStorage<Scalar,Index>& m_data;
- Index m_id;
- const Index m_end;
+ const CompressedStorage<Scalar>& m_data;
+ int m_id;
+ const int m_end;
+
+ private:
+ InnerIterator& operator=(const InnerIterator&);
};
#endif // EIGEN_SPARSEVECTOR_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/SuperLUSupport.h b/extern/Eigen2/Eigen/src/Sparse/SuperLUSupport.h
new file mode 100644
index 00000000000..3c9a4fcced6
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/SuperLUSupport.h
@@ -0,0 +1,565 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SUPERLUSUPPORT_H
+#define EIGEN_SUPERLUSUPPORT_H
+
+// declaration of gssvx taken from GMM++
+#define DECL_GSSVX(NAMESPACE,FNAME,FLOATTYPE,KEYTYPE) \
+ inline float SuperLU_gssvx(superlu_options_t *options, SuperMatrix *A, \
+ int *perm_c, int *perm_r, int *etree, char *equed, \
+ FLOATTYPE *R, FLOATTYPE *C, SuperMatrix *L, \
+ SuperMatrix *U, void *work, int lwork, \
+ SuperMatrix *B, SuperMatrix *X, \
+ FLOATTYPE *recip_pivot_growth, \
+ FLOATTYPE *rcond, FLOATTYPE *ferr, FLOATTYPE *berr, \
+ SuperLUStat_t *stats, int *info, KEYTYPE) { \
+ using namespace NAMESPACE; \
+ mem_usage_t mem_usage; \
+ NAMESPACE::FNAME(options, A, perm_c, perm_r, etree, equed, R, C, L, \
+ U, work, lwork, B, X, recip_pivot_growth, rcond, \
+ ferr, berr, &mem_usage, stats, info); \
+ return mem_usage.for_lu; /* bytes used by the factor storage */ \
+ }
+
+DECL_GSSVX(SuperLU_S,sgssvx,float,float)
+DECL_GSSVX(SuperLU_C,cgssvx,float,std::complex<float>)
+DECL_GSSVX(SuperLU_D,dgssvx,double,double)
+DECL_GSSVX(SuperLU_Z,zgssvx,double,std::complex<double>)
+
+template<typename MatrixType>
+struct SluMatrixMapHelper;
+
+/** \internal
+ *
+ * A wrapper class for SuperLU matrices. It supports only compressed sparse matrices
+ * and dense matrices. Supernodal and other fancy format are not supported by this wrapper.
+ *
+ * This wrapper class mainly aims to avoids the need of dynamic allocation of the storage structure.
+ */
+struct SluMatrix : SuperMatrix
+{
+ SluMatrix()
+ {
+ Store = &storage;
+ }
+
+ SluMatrix(const SluMatrix& other)
+ : SuperMatrix(other)
+ {
+ Store = &storage;
+ storage = other.storage;
+ }
+
+ SluMatrix& operator=(const SluMatrix& other)
+ {
+ SuperMatrix::operator=(static_cast<const SuperMatrix&>(other));
+ Store = &storage;
+ storage = other.storage;
+ return *this;
+ }
+
+ struct
+ {
+ union {int nnz;int lda;};
+ void *values;
+ int *innerInd;
+ int *outerInd;
+ } storage;
+
+ void setStorageType(Stype_t t)
+ {
+ Stype = t;
+ if (t==SLU_NC || t==SLU_NR || t==SLU_DN)
+ Store = &storage;
+ else
+ {
+ ei_assert(false && "storage type not supported");
+ Store = 0;
+ }
+ }
+
+ template<typename Scalar>
+ void setScalarType()
+ {
+ if (ei_is_same_type<Scalar,float>::ret)
+ Dtype = SLU_S;
+ else if (ei_is_same_type<Scalar,double>::ret)
+ Dtype = SLU_D;
+ else if (ei_is_same_type<Scalar,std::complex<float> >::ret)
+ Dtype = SLU_C;
+ else if (ei_is_same_type<Scalar,std::complex<double> >::ret)
+ Dtype = SLU_Z;
+ else
+ {
+ ei_assert(false && "Scalar type not supported by SuperLU");
+ }
+ }
+
+ template<typename Scalar, int Rows, int Cols, int Options, int MRows, int MCols>
+ static SluMatrix Map(Matrix<Scalar,Rows,Cols,Options,MRows,MCols>& mat)
+ {
+ typedef Matrix<Scalar,Rows,Cols,Options,MRows,MCols> MatrixType;
+ ei_assert( ((Options&RowMajor)!=RowMajor) && "row-major dense matrices is not supported by SuperLU");
+ SluMatrix res;
+ res.setStorageType(SLU_DN);
+ res.setScalarType<Scalar>();
+ res.Mtype = SLU_GE;
+
+ res.nrow = mat.rows();
+ res.ncol = mat.cols();
+
+ res.storage.lda = mat.stride();
+ res.storage.values = mat.data();
+ return res;
+ }
+
+ template<typename MatrixType>
+ static SluMatrix Map(SparseMatrixBase<MatrixType>& mat)
+ {
+ SluMatrix res;
+ if ((MatrixType::Flags&RowMajorBit)==RowMajorBit)
+ {
+ res.setStorageType(SLU_NR);
+ res.nrow = mat.cols();
+ res.ncol = mat.rows();
+ }
+ else
+ {
+ res.setStorageType(SLU_NC);
+ res.nrow = mat.rows();
+ res.ncol = mat.cols();
+ }
+
+ res.Mtype = SLU_GE;
+
+ res.storage.nnz = mat.nonZeros();
+ res.storage.values = mat.derived()._valuePtr();
+ res.storage.innerInd = mat.derived()._innerIndexPtr();
+ res.storage.outerInd = mat.derived()._outerIndexPtr();
+
+ res.setScalarType<typename MatrixType::Scalar>();
+
+ // FIXME the following is not very accurate
+ if (MatrixType::Flags & UpperTriangular)
+ res.Mtype = SLU_TRU;
+ if (MatrixType::Flags & LowerTriangular)
+ res.Mtype = SLU_TRL;
+ if (MatrixType::Flags & SelfAdjoint)
+ ei_assert(false && "SelfAdjoint matrix shape not supported by SuperLU");
+ return res;
+ }
+};
+
+template<typename Scalar, int Rows, int Cols, int Options, int MRows, int MCols>
+struct SluMatrixMapHelper<Matrix<Scalar,Rows,Cols,Options,MRows,MCols> >
+{
+ typedef Matrix<Scalar,Rows,Cols,Options,MRows,MCols> MatrixType;
+ static void run(MatrixType& mat, SluMatrix& res)
+ {
+ ei_assert( ((Options&RowMajor)!=RowMajor) && "row-major dense matrices is not supported by SuperLU");
+ res.setStorageType(SLU_DN);
+ res.setScalarType<Scalar>();
+ res.Mtype = SLU_GE;
+
+ res.nrow = mat.rows();
+ res.ncol = mat.cols();
+
+ res.storage.lda = mat.stride();
+ res.storage.values = mat.data();
+ }
+};
+
+template<typename Derived>
+struct SluMatrixMapHelper<SparseMatrixBase<Derived> >
+{
+ typedef Derived MatrixType;
+ static void run(MatrixType& mat, SluMatrix& res)
+ {
+ if ((MatrixType::Flags&RowMajorBit)==RowMajorBit)
+ {
+ res.setStorageType(SLU_NR);
+ res.nrow = mat.cols();
+ res.ncol = mat.rows();
+ }
+ else
+ {
+ res.setStorageType(SLU_NC);
+ res.nrow = mat.rows();
+ res.ncol = mat.cols();
+ }
+
+ res.Mtype = SLU_GE;
+
+ res.storage.nnz = mat.nonZeros();
+ res.storage.values = mat._valuePtr();
+ res.storage.innerInd = mat._innerIndexPtr();
+ res.storage.outerInd = mat._outerIndexPtr();
+
+ res.setScalarType<typename MatrixType::Scalar>();
+
+ // FIXME the following is not very accurate
+ if (MatrixType::Flags & UpperTriangular)
+ res.Mtype = SLU_TRU;
+ if (MatrixType::Flags & LowerTriangular)
+ res.Mtype = SLU_TRL;
+ if (MatrixType::Flags & SelfAdjoint)
+ ei_assert(false && "SelfAdjoint matrix shape not supported by SuperLU");
+ }
+};
+
+template<typename Derived>
+SluMatrix SparseMatrixBase<Derived>::asSluMatrix()
+{
+ return SluMatrix::Map(derived());
+}
+
+/** View a Super LU matrix as an Eigen expression */
+template<typename Scalar, int Flags>
+MappedSparseMatrix<Scalar,Flags>::MappedSparseMatrix(SluMatrix& sluMat)
+{
+ if ((Flags&RowMajorBit)==RowMajorBit)
+ {
+ assert(sluMat.Stype == SLU_NR);
+ m_innerSize = sluMat.ncol;
+ m_outerSize = sluMat.nrow;
+ }
+ else
+ {
+ assert(sluMat.Stype == SLU_NC);
+ m_innerSize = sluMat.nrow;
+ m_outerSize = sluMat.ncol;
+ }
+ m_outerIndex = sluMat.storage.outerInd;
+ m_innerIndices = sluMat.storage.innerInd;
+ m_values = reinterpret_cast<Scalar*>(sluMat.storage.values);
+ m_nnz = sluMat.storage.outerInd[m_outerSize];
+}
+
+template<typename MatrixType>
+class SparseLU<MatrixType,SuperLU> : public SparseLU<MatrixType>
+{
+ protected:
+ typedef SparseLU<MatrixType> Base;
+ typedef typename Base::Scalar Scalar;
+ typedef typename Base::RealScalar RealScalar;
+ typedef Matrix<Scalar,Dynamic,1> Vector;
+ typedef Matrix<int, 1, MatrixType::ColsAtCompileTime> IntRowVectorType;
+ typedef Matrix<int, MatrixType::RowsAtCompileTime, 1> IntColVectorType;
+ typedef SparseMatrix<Scalar,LowerTriangular|UnitDiagBit> LMatrixType;
+ typedef SparseMatrix<Scalar,UpperTriangular> UMatrixType;
+ using Base::m_flags;
+ using Base::m_status;
+
+ public:
+
+ SparseLU(int flags = NaturalOrdering)
+ : Base(flags)
+ {
+ }
+
+ SparseLU(const MatrixType& matrix, int flags = NaturalOrdering)
+ : Base(flags)
+ {
+ compute(matrix);
+ }
+
+ ~SparseLU()
+ {
+ }
+
+ inline const LMatrixType& matrixL() const
+ {
+ if (m_extractedDataAreDirty) extractData();
+ return m_l;
+ }
+
+ inline const UMatrixType& matrixU() const
+ {
+ if (m_extractedDataAreDirty) extractData();
+ return m_u;
+ }
+
+ inline const IntColVectorType& permutationP() const
+ {
+ if (m_extractedDataAreDirty) extractData();
+ return m_p;
+ }
+
+ inline const IntRowVectorType& permutationQ() const
+ {
+ if (m_extractedDataAreDirty) extractData();
+ return m_q;
+ }
+
+ Scalar determinant() const;
+
+ template<typename BDerived, typename XDerived>
+ bool solve(const MatrixBase<BDerived> &b, MatrixBase<XDerived>* x) const;
+
+ void compute(const MatrixType& matrix);
+
+ protected:
+
+ void extractData() const;
+
+ protected:
+ // cached data to reduce reallocation, etc.
+ mutable LMatrixType m_l;
+ mutable UMatrixType m_u;
+ mutable IntColVectorType m_p;
+ mutable IntRowVectorType m_q;
+
+ mutable SparseMatrix<Scalar> m_matrix;
+ mutable SluMatrix m_sluA;
+ mutable SuperMatrix m_sluL, m_sluU;
+ mutable SluMatrix m_sluB, m_sluX;
+ mutable SuperLUStat_t m_sluStat;
+ mutable superlu_options_t m_sluOptions;
+ mutable std::vector<int> m_sluEtree;
+ mutable std::vector<RealScalar> m_sluRscale, m_sluCscale;
+ mutable std::vector<RealScalar> m_sluFerr, m_sluBerr;
+ mutable char m_sluEqued;
+ mutable bool m_extractedDataAreDirty;
+};
+
+template<typename MatrixType>
+void SparseLU<MatrixType,SuperLU>::compute(const MatrixType& a)
+{
+ const int size = a.rows();
+ m_matrix = a;
+
+ set_default_options(&m_sluOptions);
+ m_sluOptions.ColPerm = NATURAL;
+ m_sluOptions.PrintStat = NO;
+ m_sluOptions.ConditionNumber = NO;
+ m_sluOptions.Trans = NOTRANS;
+ // m_sluOptions.Equil = NO;
+
+ switch (Base::orderingMethod())
+ {
+ case NaturalOrdering : m_sluOptions.ColPerm = NATURAL; break;
+ case MinimumDegree_AT_PLUS_A : m_sluOptions.ColPerm = MMD_AT_PLUS_A; break;
+ case MinimumDegree_ATA : m_sluOptions.ColPerm = MMD_ATA; break;
+ case ColApproxMinimumDegree : m_sluOptions.ColPerm = COLAMD; break;
+ default:
+ std::cerr << "Eigen: ordering method \"" << Base::orderingMethod() << "\" not supported by the SuperLU backend\n";
+ m_sluOptions.ColPerm = NATURAL;
+ };
+
+ m_sluA = m_matrix.asSluMatrix();
+ memset(&m_sluL,0,sizeof m_sluL);
+ memset(&m_sluU,0,sizeof m_sluU);
+ m_sluEqued = 'B';
+ int info = 0;
+
+ m_p.resize(size);
+ m_q.resize(size);
+ m_sluRscale.resize(size);
+ m_sluCscale.resize(size);
+ m_sluEtree.resize(size);
+
+ RealScalar recip_pivot_gross, rcond;
+ RealScalar ferr, berr;
+
+ // set empty B and X
+ m_sluB.setStorageType(SLU_DN);
+ m_sluB.setScalarType<Scalar>();
+ m_sluB.Mtype = SLU_GE;
+ m_sluB.storage.values = 0;
+ m_sluB.nrow = m_sluB.ncol = 0;
+ m_sluB.storage.lda = size;
+ m_sluX = m_sluB;
+
+ StatInit(&m_sluStat);
+ SuperLU_gssvx(&m_sluOptions, &m_sluA, m_q.data(), m_p.data(), &m_sluEtree[0],
+ &m_sluEqued, &m_sluRscale[0], &m_sluCscale[0],
+ &m_sluL, &m_sluU,
+ NULL, 0,
+ &m_sluB, &m_sluX,
+ &recip_pivot_gross, &rcond,
+ &ferr, &berr,
+ &m_sluStat, &info, Scalar());
+ StatFree(&m_sluStat);
+
+ m_extractedDataAreDirty = true;
+
+ // FIXME how to better check for errors ???
+ Base::m_succeeded = (info == 0);
+}
+
+template<typename MatrixType>
+template<typename BDerived,typename XDerived>
+bool SparseLU<MatrixType,SuperLU>::solve(const MatrixBase<BDerived> &b, MatrixBase<XDerived> *x) const
+{
+ const int size = m_matrix.rows();
+ const int rhsCols = b.cols();
+ ei_assert(size==b.rows());
+
+ m_sluOptions.Fact = FACTORED;
+ m_sluOptions.IterRefine = NOREFINE;
+
+ m_sluFerr.resize(rhsCols);
+ m_sluBerr.resize(rhsCols);
+ m_sluB = SluMatrix::Map(b.const_cast_derived());
+ m_sluX = SluMatrix::Map(x->derived());
+
+ StatInit(&m_sluStat);
+ int info = 0;
+ RealScalar recip_pivot_gross, rcond;
+ SuperLU_gssvx(
+ &m_sluOptions, &m_sluA,
+ m_q.data(), m_p.data(),
+ &m_sluEtree[0], &m_sluEqued,
+ &m_sluRscale[0], &m_sluCscale[0],
+ &m_sluL, &m_sluU,
+ NULL, 0,
+ &m_sluB, &m_sluX,
+ &recip_pivot_gross, &rcond,
+ &m_sluFerr[0], &m_sluBerr[0],
+ &m_sluStat, &info, Scalar());
+ StatFree(&m_sluStat);
+
+ return info==0;
+}
+
+//
+// the code of this extractData() function has been adapted from the SuperLU's Matlab support code,
+//
+// Copyright (c) 1994 by Xerox Corporation. All rights reserved.
+//
+// THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
+// EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+//
+template<typename MatrixType>
+void SparseLU<MatrixType,SuperLU>::extractData() const
+{
+ if (m_extractedDataAreDirty)
+ {
+ int upper;
+ int fsupc, istart, nsupr;
+ int lastl = 0, lastu = 0;
+ SCformat *Lstore = static_cast<SCformat*>(m_sluL.Store);
+ NCformat *Ustore = static_cast<NCformat*>(m_sluU.Store);
+ Scalar *SNptr;
+
+ const int size = m_matrix.rows();
+ m_l.resize(size,size);
+ m_l.resizeNonZeros(Lstore->nnz);
+ m_u.resize(size,size);
+ m_u.resizeNonZeros(Ustore->nnz);
+
+ int* Lcol = m_l._outerIndexPtr();
+ int* Lrow = m_l._innerIndexPtr();
+ Scalar* Lval = m_l._valuePtr();
+
+ int* Ucol = m_u._outerIndexPtr();
+ int* Urow = m_u._innerIndexPtr();
+ Scalar* Uval = m_u._valuePtr();
+
+ Ucol[0] = 0;
+ Ucol[0] = 0;
+
+ /* for each supernode */
+ for (int k = 0; k <= Lstore->nsuper; ++k)
+ {
+ fsupc = L_FST_SUPC(k);
+ istart = L_SUB_START(fsupc);
+ nsupr = L_SUB_START(fsupc+1) - istart;
+ upper = 1;
+
+ /* for each column in the supernode */
+ for (int j = fsupc; j < L_FST_SUPC(k+1); ++j)
+ {
+ SNptr = &((Scalar*)Lstore->nzval)[L_NZ_START(j)];
+
+ /* Extract U */
+ for (int i = U_NZ_START(j); i < U_NZ_START(j+1); ++i)
+ {
+ Uval[lastu] = ((Scalar*)Ustore->nzval)[i];
+ /* Matlab doesn't like explicit zero. */
+ if (Uval[lastu] != 0.0)
+ Urow[lastu++] = U_SUB(i);
+ }
+ for (int i = 0; i < upper; ++i)
+ {
+ /* upper triangle in the supernode */
+ Uval[lastu] = SNptr[i];
+ /* Matlab doesn't like explicit zero. */
+ if (Uval[lastu] != 0.0)
+ Urow[lastu++] = L_SUB(istart+i);
+ }
+ Ucol[j+1] = lastu;
+
+ /* Extract L */
+ Lval[lastl] = 1.0; /* unit diagonal */
+ Lrow[lastl++] = L_SUB(istart + upper - 1);
+ for (int i = upper; i < nsupr; ++i)
+ {
+ Lval[lastl] = SNptr[i];
+ /* Matlab doesn't like explicit zero. */
+ if (Lval[lastl] != 0.0)
+ Lrow[lastl++] = L_SUB(istart+i);
+ }
+ Lcol[j+1] = lastl;
+
+ ++upper;
+ } /* for j ... */
+
+ } /* for k ... */
+
+ // squeeze the matrices :
+ m_l.resizeNonZeros(lastl);
+ m_u.resizeNonZeros(lastu);
+
+ m_extractedDataAreDirty = false;
+ }
+}
+
+template<typename MatrixType>
+typename SparseLU<MatrixType,SuperLU>::Scalar SparseLU<MatrixType,SuperLU>::determinant() const
+{
+ if (m_extractedDataAreDirty)
+ extractData();
+
+ // TODO this code coule be moved to the default/base backend
+ // FIXME perhaps we have to take into account the scale factors m_sluRscale and m_sluCscale ???
+ Scalar det = Scalar(1);
+ for (int j=0; j<m_u.cols(); ++j)
+ {
+ if (m_u._outerIndexPtr()[j+1]-m_u._outerIndexPtr()[j] > 0)
+ {
+ int lastId = m_u._outerIndexPtr()[j+1]-1;
+ ei_assert(m_u._innerIndexPtr()[lastId]<=j);
+ if (m_u._innerIndexPtr()[lastId]==j)
+ {
+ det *= m_u._valuePtr()[lastId];
+ }
+ }
+ // std::cout << m_sluRscale[j] << " " << m_sluCscale[j] << " ";
+ }
+ return det;
+}
+
+#endif // EIGEN_SUPERLUSUPPORT_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/TaucsSupport.h b/extern/Eigen2/Eigen/src/Sparse/TaucsSupport.h
new file mode 100644
index 00000000000..4dddca7b622
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/TaucsSupport.h
@@ -0,0 +1,210 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_TAUCSSUPPORT_H
+#define EIGEN_TAUCSSUPPORT_H
+
+template<typename Derived>
+taucs_ccs_matrix SparseMatrixBase<Derived>::asTaucsMatrix()
+{
+ taucs_ccs_matrix res;
+ res.n = cols();
+ res.m = rows();
+ res.flags = 0;
+ res.colptr = derived()._outerIndexPtr();
+ res.rowind = derived()._innerIndexPtr();
+ res.values.v = derived()._valuePtr();
+ if (ei_is_same_type<Scalar,int>::ret)
+ res.flags |= TAUCS_INT;
+ else if (ei_is_same_type<Scalar,float>::ret)
+ res.flags |= TAUCS_SINGLE;
+ else if (ei_is_same_type<Scalar,double>::ret)
+ res.flags |= TAUCS_DOUBLE;
+ else if (ei_is_same_type<Scalar,std::complex<float> >::ret)
+ res.flags |= TAUCS_SCOMPLEX;
+ else if (ei_is_same_type<Scalar,std::complex<double> >::ret)
+ res.flags |= TAUCS_DCOMPLEX;
+ else
+ {
+ ei_assert(false && "Scalar type not supported by TAUCS");
+ }
+
+ if (Flags & UpperTriangular)
+ res.flags |= TAUCS_UPPER;
+ if (Flags & LowerTriangular)
+ res.flags |= TAUCS_LOWER;
+ if (Flags & SelfAdjoint)
+ res.flags |= (NumTraits<Scalar>::IsComplex ? TAUCS_HERMITIAN : TAUCS_SYMMETRIC);
+ else if ((Flags & UpperTriangular) || (Flags & LowerTriangular))
+ res.flags |= TAUCS_TRIANGULAR;
+
+ return res;
+}
+
+template<typename Scalar, int Flags>
+MappedSparseMatrix<Scalar,Flags>::MappedSparseMatrix(taucs_ccs_matrix& taucsMat)
+{
+ m_innerSize = taucsMat.m;
+ m_outerSize = taucsMat.n;
+ m_outerIndex = taucsMat.colptr;
+ m_innerIndices = taucsMat.rowind;
+ m_values = reinterpret_cast<Scalar*>(taucsMat.values.v);
+ m_nnz = taucsMat.colptr[taucsMat.n];
+}
+
+template<typename MatrixType>
+class SparseLLT<MatrixType,Taucs> : public SparseLLT<MatrixType>
+{
+ protected:
+ typedef SparseLLT<MatrixType> Base;
+ typedef typename Base::Scalar Scalar;
+ typedef typename Base::RealScalar RealScalar;
+ using Base::MatrixLIsDirty;
+ using Base::SupernodalFactorIsDirty;
+ using Base::m_flags;
+ using Base::m_matrix;
+ using Base::m_status;
+
+ public:
+
+ SparseLLT(int flags = 0)
+ : Base(flags), m_taucsSupernodalFactor(0)
+ {
+ }
+
+ SparseLLT(const MatrixType& matrix, int flags = 0)
+ : Base(flags), m_taucsSupernodalFactor(0)
+ {
+ compute(matrix);
+ }
+
+ ~SparseLLT()
+ {
+ if (m_taucsSupernodalFactor)
+ taucs_supernodal_factor_free(m_taucsSupernodalFactor);
+ }
+
+ inline const typename Base::CholMatrixType& matrixL(void) const;
+
+ template<typename Derived>
+ void solveInPlace(MatrixBase<Derived> &b) const;
+
+ void compute(const MatrixType& matrix);
+
+ protected:
+ void* m_taucsSupernodalFactor;
+};
+
+template<typename MatrixType>
+void SparseLLT<MatrixType,Taucs>::compute(const MatrixType& a)
+{
+ if (m_taucsSupernodalFactor)
+ {
+ taucs_supernodal_factor_free(m_taucsSupernodalFactor);
+ m_taucsSupernodalFactor = 0;
+ }
+
+ if (m_flags & IncompleteFactorization)
+ {
+ taucs_ccs_matrix taucsMatA = const_cast<MatrixType&>(a).asTaucsMatrix();
+ taucs_ccs_matrix* taucsRes = taucs_ccs_factor_llt(&taucsMatA, Base::m_precision, 0);
+ // the matrix returned by Taucs is not necessarily sorted,
+ // so let's copy it in two steps
+ DynamicSparseMatrix<Scalar,RowMajor> tmp = MappedSparseMatrix<Scalar>(*taucsRes);
+ m_matrix = tmp;
+ free(taucsRes);
+ m_status = (m_status & ~(CompleteFactorization|MatrixLIsDirty))
+ | IncompleteFactorization
+ | SupernodalFactorIsDirty;
+ }
+ else
+ {
+ taucs_ccs_matrix taucsMatA = const_cast<MatrixType&>(a).asTaucsMatrix();
+ if ( (m_flags & SupernodalLeftLooking)
+ || ((!(m_flags & SupernodalMultifrontal)) && (m_flags & MemoryEfficient)) )
+ {
+ m_taucsSupernodalFactor = taucs_ccs_factor_llt_ll(&taucsMatA);
+ }
+ else
+ {
+ // use the faster Multifrontal routine
+ m_taucsSupernodalFactor = taucs_ccs_factor_llt_mf(&taucsMatA);
+ }
+ m_status = (m_status & ~IncompleteFactorization) | CompleteFactorization | MatrixLIsDirty;
+ }
+}
+
+template<typename MatrixType>
+inline const typename SparseLLT<MatrixType>::CholMatrixType&
+SparseLLT<MatrixType,Taucs>::matrixL() const
+{
+ if (m_status & MatrixLIsDirty)
+ {
+ ei_assert(!(m_status & SupernodalFactorIsDirty));
+
+ taucs_ccs_matrix* taucsL = taucs_supernodal_factor_to_ccs(m_taucsSupernodalFactor);
+
+ // the matrix returned by Taucs is not necessarily sorted,
+ // so let's copy it in two steps
+ DynamicSparseMatrix<Scalar,RowMajor> tmp = MappedSparseMatrix<Scalar>(*taucsL);
+ const_cast<typename Base::CholMatrixType&>(m_matrix) = tmp;
+ free(taucsL);
+ m_status = (m_status & ~MatrixLIsDirty);
+ }
+ return m_matrix;
+}
+
+template<typename MatrixType>
+template<typename Derived>
+void SparseLLT<MatrixType,Taucs>::solveInPlace(MatrixBase<Derived> &b) const
+{
+ bool inputIsCompatibleWithTaucs = (Derived::Flags&RowMajorBit)==0;
+
+ if (!inputIsCompatibleWithTaucs)
+ {
+ matrixL();
+ Base::solveInPlace(b);
+ }
+ else if (m_flags & IncompleteFactorization)
+ {
+ taucs_ccs_matrix taucsLLT = const_cast<typename Base::CholMatrixType&>(m_matrix).asTaucsMatrix();
+ typename ei_plain_matrix_type<Derived>::type x(b.rows());
+ for (int j=0; j<b.cols(); ++j)
+ {
+ taucs_ccs_solve_llt(&taucsLLT,x.data(),&b.col(j).coeffRef(0));
+ b.col(j) = x;
+ }
+ }
+ else
+ {
+ typename ei_plain_matrix_type<Derived>::type x(b.rows());
+ for (int j=0; j<b.cols(); ++j)
+ {
+ taucs_supernodal_solve_llt(m_taucsSupernodalFactor,x.data(),&b.col(j).coeffRef(0));
+ b.col(j) = x;
+ }
+ }
+}
+
+#endif // EIGEN_TAUCSSUPPORT_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/TriangularSolver.h b/extern/Eigen2/Eigen/src/Sparse/TriangularSolver.h
new file mode 100644
index 00000000000..8948ae45e1d
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/TriangularSolver.h
@@ -0,0 +1,178 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_SPARSETRIANGULARSOLVER_H
+#define EIGEN_SPARSETRIANGULARSOLVER_H
+
+// forward substitution, row-major
+template<typename Lhs, typename Rhs>
+struct ei_solve_triangular_selector<Lhs,Rhs,LowerTriangular,RowMajor|IsSparse>
+{
+ typedef typename Rhs::Scalar Scalar;
+ static void run(const Lhs& lhs, Rhs& other)
+ {
+ for(int col=0 ; col<other.cols() ; ++col)
+ {
+ for(int i=0; i<lhs.rows(); ++i)
+ {
+ Scalar tmp = other.coeff(i,col);
+ Scalar lastVal = 0;
+ int lastIndex = 0;
+ for(typename Lhs::InnerIterator it(lhs, i); it; ++it)
+ {
+ lastVal = it.value();
+ lastIndex = it.index();
+ tmp -= lastVal * other.coeff(lastIndex,col);
+ }
+ if (Lhs::Flags & UnitDiagBit)
+ other.coeffRef(i,col) = tmp;
+ else
+ {
+ ei_assert(lastIndex==i);
+ other.coeffRef(i,col) = tmp/lastVal;
+ }
+ }
+ }
+ }
+};
+
+// backward substitution, row-major
+template<typename Lhs, typename Rhs>
+struct ei_solve_triangular_selector<Lhs,Rhs,UpperTriangular,RowMajor|IsSparse>
+{
+ typedef typename Rhs::Scalar Scalar;
+ static void run(const Lhs& lhs, Rhs& other)
+ {
+ for(int col=0 ; col<other.cols() ; ++col)
+ {
+ for(int i=lhs.rows()-1 ; i>=0 ; --i)
+ {
+ Scalar tmp = other.coeff(i,col);
+ typename Lhs::InnerIterator it(lhs, i);
+ if (it.index() == i)
+ ++it;
+ for(; it; ++it)
+ {
+ tmp -= it.value() * other.coeff(it.index(),col);
+ }
+
+ if (Lhs::Flags & UnitDiagBit)
+ other.coeffRef(i,col) = tmp;
+ else
+ {
+ typename Lhs::InnerIterator it(lhs, i);
+ ei_assert(it.index() == i);
+ other.coeffRef(i,col) = tmp/it.value();
+ }
+ }
+ }
+ }
+};
+
+// forward substitution, col-major
+template<typename Lhs, typename Rhs>
+struct ei_solve_triangular_selector<Lhs,Rhs,LowerTriangular,ColMajor|IsSparse>
+{
+ typedef typename Rhs::Scalar Scalar;
+ static void run(const Lhs& lhs, Rhs& other)
+ {
+ for(int col=0 ; col<other.cols() ; ++col)
+ {
+ for(int i=0; i<lhs.cols(); ++i)
+ {
+ typename Lhs::InnerIterator it(lhs, i);
+ if(!(Lhs::Flags & UnitDiagBit))
+ {
+ // std::cerr << it.value() << " ; " << it.index() << " == " << i << "\n";
+ ei_assert(it.index()==i);
+ other.coeffRef(i,col) /= it.value();
+ }
+ Scalar tmp = other.coeffRef(i,col);
+ if (it.index()==i)
+ ++it;
+ for(; it; ++it)
+ other.coeffRef(it.index(), col) -= tmp * it.value();
+ }
+ }
+ }
+};
+
+// backward substitution, col-major
+template<typename Lhs, typename Rhs>
+struct ei_solve_triangular_selector<Lhs,Rhs,UpperTriangular,ColMajor|IsSparse>
+{
+ typedef typename Rhs::Scalar Scalar;
+ static void run(const Lhs& lhs, Rhs& other)
+ {
+ for(int col=0 ; col<other.cols() ; ++col)
+ {
+ for(int i=lhs.cols()-1; i>=0; --i)
+ {
+ if(!(Lhs::Flags & UnitDiagBit))
+ {
+ // FIXME lhs.coeff(i,i) might not be always efficient while it must simply be the
+ // last element of the column !
+ other.coeffRef(i,col) /= lhs.coeff(i,i);
+ }
+ Scalar tmp = other.coeffRef(i,col);
+ typename Lhs::InnerIterator it(lhs, i);
+ for(; it && it.index()<i; ++it)
+ other.coeffRef(it.index(), col) -= tmp * it.value();
+ }
+ }
+ }
+};
+
+template<typename Derived>
+template<typename OtherDerived>
+void SparseMatrixBase<Derived>::solveTriangularInPlace(MatrixBase<OtherDerived>& other) const
+{
+ ei_assert(derived().cols() == derived().rows());
+ ei_assert(derived().cols() == other.rows());
+ ei_assert(!(Flags & ZeroDiagBit));
+ ei_assert(Flags & (UpperTriangularBit|LowerTriangularBit));
+
+ enum { copy = ei_traits<OtherDerived>::Flags & RowMajorBit };
+
+ typedef typename ei_meta_if<copy,
+ typename ei_plain_matrix_type_column_major<OtherDerived>::type, OtherDerived&>::ret OtherCopy;
+ OtherCopy otherCopy(other.derived());
+
+ ei_solve_triangular_selector<Derived, typename ei_unref<OtherCopy>::type>::run(derived(), otherCopy);
+
+ if (copy)
+ other = otherCopy;
+}
+
+template<typename Derived>
+template<typename OtherDerived>
+typename ei_plain_matrix_type_column_major<OtherDerived>::type
+SparseMatrixBase<Derived>::solveTriangular(const MatrixBase<OtherDerived>& other) const
+{
+ typename ei_plain_matrix_type_column_major<OtherDerived>::type res(other);
+ solveTriangularInPlace(res);
+ return res;
+}
+
+#endif // EIGEN_SPARSETRIANGULARSOLVER_H
diff --git a/extern/Eigen2/Eigen/src/Sparse/UmfPackSupport.h b/extern/Eigen2/Eigen/src/Sparse/UmfPackSupport.h
new file mode 100644
index 00000000000..b76ffb25248
--- /dev/null
+++ b/extern/Eigen2/Eigen/src/Sparse/UmfPackSupport.h
@@ -0,0 +1,289 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen 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 3 of the License, or (at your option) any later version.
+//
+// Alternatively, 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.
+//
+// Eigen 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 or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef EIGEN_UMFPACKSUPPORT_H
+#define EIGEN_UMFPACKSUPPORT_H
+
+/* TODO extract L, extract U, compute det, etc... */
+
+// generic double/complex<double> wrapper functions:
+
+inline void umfpack_free_numeric(void **Numeric, double)
+{ umfpack_di_free_numeric(Numeric); }
+
+inline void umfpack_free_numeric(void **Numeric, std::complex<double>)
+{ umfpack_zi_free_numeric(Numeric); }
+
+inline void umfpack_free_symbolic(void **Symbolic, double)
+{ umfpack_di_free_symbolic(Symbolic); }
+
+inline void umfpack_free_symbolic(void **Symbolic, std::complex<double>)
+{ umfpack_zi_free_symbolic(Symbolic); }
+
+inline int umfpack_symbolic(int n_row,int n_col,
+ const int Ap[], const int Ai[], const double Ax[], void **Symbolic,
+ const double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
+{
+ return umfpack_di_symbolic(n_row,n_col,Ap,Ai,Ax,Symbolic,Control,Info);
+}
+
+inline int umfpack_symbolic(int n_row,int n_col,
+ const int Ap[], const int Ai[], const std::complex<double> Ax[], void **Symbolic,
+ const double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
+{
+ return umfpack_zi_symbolic(n_row,n_col,Ap,Ai,&Ax[0].real(),0,Symbolic,Control,Info);
+}
+
+inline int umfpack_numeric( const int Ap[], const int Ai[], const double Ax[],
+ void *Symbolic, void **Numeric,
+ const double Control[UMFPACK_CONTROL],double Info [UMFPACK_INFO])
+{
+ return umfpack_di_numeric(Ap,Ai,Ax,Symbolic,Numeric,Control,Info);
+}
+
+inline int umfpack_numeric( const int Ap[], const int Ai[], const std::complex<double> Ax[],
+ void *Symbolic, void **Numeric,
+ const double Control[UMFPACK_CONTROL],double Info [UMFPACK_INFO])
+{
+ return umfpack_zi_numeric(Ap,Ai,&Ax[0].real(),0,Symbolic,Numeric,Control,Info);
+}
+
+inline int umfpack_solve( int sys, const int Ap[], const int Ai[], const double Ax[],
+ double X[], const double B[], void *Numeric,
+ const double Control[UMFPACK_CONTROL], double Info[UMFPACK_INFO])
+{
+ return umfpack_di_solve(sys,Ap,Ai,Ax,X,B,Numeric,Control,Info);
+}
+
+inline int umfpack_solve( int sys, const int Ap[], const int Ai[], const std::complex<double> Ax[],
+ std::complex<double> X[], const std::complex<double> B[], void *Numeric,
+ const double Control[UMFPACK_CONTROL], double Info[UMFPACK_INFO])
+{
+ return umfpack_zi_solve(sys,Ap,Ai,&Ax[0].real(),0,&X[0].real(),0,&B[0].real(),0,Numeric,Control,Info);
+}
+
+inline int umfpack_get_lunz(int *lnz, int *unz, int *n_row, int *n_col, int *nz_udiag, void *Numeric, double)
+{
+ return umfpack_di_get_lunz(lnz,unz,n_row,n_col,nz_udiag,Numeric);
+}
+
+inline int umfpack_get_lunz(int *lnz, int *unz, int *n_row, int *n_col, int *nz_udiag, void *Numeric, std::complex<double>)
+{
+ return umfpack_zi_get_lunz(lnz,unz,n_row,n_col,nz_udiag,Numeric);
+}
+
+inline int umfpack_get_numeric(int Lp[], int Lj[], double Lx[], int Up[], int Ui[], double Ux[],
+ int P[], int Q[], double Dx[], int *do_recip, double Rs[], void *Numeric)
+{
+ return umfpack_di_get_numeric(Lp,Lj,Lx,Up,Ui,Ux,P,Q,Dx,do_recip,Rs,Numeric);
+}
+
+inline int umfpack_get_numeric(int Lp[], int Lj[], std::complex<double> Lx[], int Up[], int Ui[], std::complex<double> Ux[],
+ int P[], int Q[], std::complex<double> Dx[], int *do_recip, double Rs[], void *Numeric)
+{
+ return umfpack_zi_get_numeric(Lp,Lj,Lx?&Lx[0].real():0,0,Up,Ui,Ux?&Ux[0].real():0,0,P,Q,
+ Dx?&Dx[0].real():0,0,do_recip,Rs,Numeric);
+}
+
+inline int umfpack_get_determinant(double *Mx, double *Ex, void *NumericHandle, double User_Info [UMFPACK_INFO])
+{
+ return umfpack_di_get_determinant(Mx,Ex,NumericHandle,User_Info);
+}
+
+inline int umfpack_get_determinant(std::complex<double> *Mx, double *Ex, void *NumericHandle, double User_Info [UMFPACK_INFO])
+{
+ return umfpack_zi_get_determinant(&Mx->real(),0,Ex,NumericHandle,User_Info);
+}
+
+
+template<typename MatrixType>
+class SparseLU<MatrixType,UmfPack> : public SparseLU<MatrixType>
+{
+ protected:
+ typedef SparseLU<MatrixType> Base;
+ typedef typename Base::Scalar Scalar;
+ typedef typename Base::RealScalar RealScalar;
+ typedef Matrix<Scalar,Dynamic,1> Vector;
+ typedef Matrix<int, 1, MatrixType::ColsAtCompileTime> IntRowVectorType;
+ typedef Matrix<int, MatrixType::RowsAtCompileTime, 1> IntColVectorType;
+ typedef SparseMatrix<Scalar,LowerTriangular|UnitDiagBit> LMatrixType;
+ typedef SparseMatrix<Scalar,UpperTriangular> UMatrixType;
+ using Base::m_flags;
+ using Base::m_status;
+
+ public:
+
+ SparseLU(int flags = NaturalOrdering)
+ : Base(flags), m_numeric(0)
+ {
+ }
+
+ SparseLU(const MatrixType& matrix, int flags = NaturalOrdering)
+ : Base(flags), m_numeric(0)
+ {
+ compute(matrix);
+ }
+
+ ~SparseLU()
+ {
+ if (m_numeric)
+ umfpack_free_numeric(&m_numeric,Scalar());
+ }
+
+ inline const LMatrixType& matrixL() const
+ {
+ if (m_extractedDataAreDirty) extractData();
+ return m_l;
+ }
+
+ inline const UMatrixType& matrixU() const
+ {
+ if (m_extractedDataAreDirty) extractData();
+ return m_u;
+ }
+
+ inline const IntColVectorType& permutationP() const
+ {
+ if (m_extractedDataAreDirty) extractData();
+ return m_p;
+ }
+
+ inline const IntRowVectorType& permutationQ() const
+ {
+ if (m_extractedDataAreDirty) extractData();
+ return m_q;
+ }
+
+ Scalar determinant() const;
+
+ template<typename BDerived, typename XDerived>
+ bool solve(const MatrixBase<BDerived> &b, MatrixBase<XDerived>* x) const;
+
+ void compute(const MatrixType& matrix);
+
+ protected:
+
+ void extractData() const;
+
+ protected:
+ // cached data:
+ void* m_numeric;
+ const MatrixType* m_matrixRef;
+ mutable LMatrixType m_l;
+ mutable UMatrixType m_u;
+ mutable IntColVectorType m_p;
+ mutable IntRowVectorType m_q;
+ mutable bool m_extractedDataAreDirty;
+};
+
+template<typename MatrixType>
+void SparseLU<MatrixType,UmfPack>::compute(const MatrixType& a)
+{
+ const int rows = a.rows();
+ const int cols = a.cols();
+ ei_assert((MatrixType::Flags&RowMajorBit)==0 && "Row major matrices are not supported yet");
+
+ m_matrixRef = &a;
+
+ if (m_numeric)
+ umfpack_free_numeric(&m_numeric,Scalar());
+
+ void* symbolic;
+ int errorCode = 0;
+ errorCode = umfpack_symbolic(rows, cols, a._outerIndexPtr(), a._innerIndexPtr(), a._valuePtr(),
+ &symbolic, 0, 0);
+ if (errorCode==0)
+ errorCode = umfpack_numeric(a._outerIndexPtr(), a._innerIndexPtr(), a._valuePtr(),
+ symbolic, &m_numeric, 0, 0);
+
+ umfpack_free_symbolic(&symbolic,Scalar());
+
+ m_extractedDataAreDirty = true;
+
+ Base::m_succeeded = (errorCode==0);
+}
+
+template<typename MatrixType>
+void SparseLU<MatrixType,UmfPack>::extractData() const
+{
+ if (m_extractedDataAreDirty)
+ {
+ // get size of the data
+ int lnz, unz, rows, cols, nz_udiag;
+ umfpack_get_lunz(&lnz, &unz, &rows, &cols, &nz_udiag, m_numeric, Scalar());
+
+ // allocate data
+ m_l.resize(rows,std::min(rows,cols));
+ m_l.resizeNonZeros(lnz);
+
+ m_u.resize(std::min(rows,cols),cols);
+ m_u.resizeNonZeros(unz);
+
+ m_p.resize(rows);
+ m_q.resize(cols);
+
+ // extract
+ umfpack_get_numeric(m_l._outerIndexPtr(), m_l._innerIndexPtr(), m_l._valuePtr(),
+ m_u._outerIndexPtr(), m_u._innerIndexPtr(), m_u._valuePtr(),
+ m_p.data(), m_q.data(), 0, 0, 0, m_numeric);
+
+ m_extractedDataAreDirty = false;
+ }
+}
+
+template<typename MatrixType>
+typename SparseLU<MatrixType,UmfPack>::Scalar SparseLU<MatrixType,UmfPack>::determinant() const
+{
+ Scalar det;
+ umfpack_get_determinant(&det, 0, m_numeric, 0);
+ return det;
+}
+
+template<typename MatrixType>
+template<typename BDerived,typename XDerived>
+bool SparseLU<MatrixType,UmfPack>::solve(const MatrixBase<BDerived> &b, MatrixBase<XDerived> *x) const
+{
+ //const int size = m_matrix.rows();
+ const int rhsCols = b.cols();
+// ei_assert(size==b.rows());
+ ei_assert((BDerived::Flags&RowMajorBit)==0 && "UmfPack backend does not support non col-major rhs yet");
+ ei_assert((XDerived::Flags&RowMajorBit)==0 && "UmfPack backend does not support non col-major result yet");
+
+ int errorCode;
+ for (int j=0; j<rhsCols; ++j)
+ {
+ errorCode = umfpack_solve(UMFPACK_A,
+ m_matrixRef->_outerIndexPtr(), m_matrixRef->_innerIndexPtr(), m_matrixRef->_valuePtr(),
+ &x->col(j).coeffRef(0), &b.const_cast_derived().col(j).coeffRef(0), m_numeric, 0, 0);
+ if (errorCode!=0)
+ return false;
+ }
+// errorCode = umfpack_di_solve(UMFPACK_A,
+// m_matrixRef._outerIndexPtr(), m_matrixRef._innerIndexPtr(), m_matrixRef._valuePtr(),
+// x->derived().data(), b.derived().data(), m_numeric, 0, 0);
+
+ return true;
+}
+
+#endif // EIGEN_UMFPACKSUPPORT_H
diff --git a/extern/Eigen3/eigen-update.sh b/extern/Eigen2/eigen-update.sh
index 7be67890173..797c710c196 100755
--- a/extern/Eigen3/eigen-update.sh
+++ b/extern/Eigen2/eigen-update.sh
@@ -1,7 +1,7 @@
#!/bin/sh
-echo "*** EIGEN#-HG Update utility"
-echo "*** This gets a new eigen3-hg tree and adapts it to blenders build structure"
+echo "*** EIGEN2-HG Update utility"
+echo "*** This gets a new eigen2-hg tree and adapts it to blenders build structure"
echo "*** Warning! This script will wipe all the header file"
if [ "x$1" = "x--i-really-know-what-im-doing" ] ; then
@@ -12,16 +12,16 @@ else
fi
# get the latest revision from repository.
-hg clone http://bitbucket.org/eigen/eigen
-if [ -d eigen ]
+hg clone http://bitbucket.org/eigen/eigen2
+if [ -d eigen2 ]
then
- cd eigen
+ cd eigen2
# put here the version you want to use
- hg up 3.0
+ hg up 2.0
rm -f `find Eigen/ -type f -name "CMakeLists.txt"`
cp -r Eigen ..
cd ..
- rm -rf eigen
+ rm -rf eigen2
else
echo "Did you install Mercurial?"
fi
diff --git a/extern/Eigen3/Eigen/Array b/extern/Eigen3/Eigen/Array
deleted file mode 100644
index 3d004fb69e8..00000000000
--- a/extern/Eigen3/Eigen/Array
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef EIGEN_ARRAY_MODULE_H
-#define EIGEN_ARRAY_MODULE_H
-
-// include Core first to handle Eigen2 support macros
-#include "Core"
-
-#ifndef EIGEN2_SUPPORT
- #error The Eigen/Array header does no longer exist in Eigen3. All that functionality has moved to Eigen/Core.
-#endif
-
-#endif // EIGEN_ARRAY_MODULE_H
diff --git a/extern/Eigen3/Eigen/Cholesky b/extern/Eigen3/Eigen/Cholesky
deleted file mode 100644
index 53f7bf911a4..00000000000
--- a/extern/Eigen3/Eigen/Cholesky
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef EIGEN_CHOLESKY_MODULE_H
-#define EIGEN_CHOLESKY_MODULE_H
-
-#include "Core"
-
-#include "src/Core/util/DisableStupidWarnings.h"
-
-namespace Eigen {
-
-/** \defgroup Cholesky_Module Cholesky module
- *
- *
- *
- * This module provides two variants of the Cholesky decomposition for selfadjoint (hermitian) matrices.
- * Those decompositions are accessible via the following MatrixBase methods:
- * - MatrixBase::llt(),
- * - MatrixBase::ldlt()
- *
- * \code
- * #include <Eigen/Cholesky>
- * \endcode
- */
-
-#include "src/misc/Solve.h"
-#include "src/Cholesky/LLT.h"
-#include "src/Cholesky/LDLT.h"
-
-} // namespace Eigen
-
-#include "src/Core/util/ReenableStupidWarnings.h"
-
-#endif // EIGEN_CHOLESKY_MODULE_H
-/* vim: set filetype=cpp et sw=2 ts=2 ai: */
diff --git a/extern/Eigen3/Eigen/Core b/extern/Eigen3/Eigen/Core
deleted file mode 100644
index 6e855427c33..00000000000
--- a/extern/Eigen3/Eigen/Core
+++ /dev/null
@@ -1,360 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2007-2011 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_CORE_H
-#define EIGEN_CORE_H
-
-// first thing Eigen does: stop the compiler from committing suicide
-#include "src/Core/util/DisableStupidWarnings.h"
-
-// then include this file where all our macros are defined. It's really important to do it first because
-// it's where we do all the alignment settings (platform detection and honoring the user's will if he
-// defined e.g. EIGEN_DONT_ALIGN) so it needs to be done before we do anything with vectorization.
-#include "src/Core/util/Macros.h"
-
-// if alignment is disabled, then disable vectorization. Note: EIGEN_ALIGN is the proper check, it takes into
-// account both the user's will (EIGEN_DONT_ALIGN) and our own platform checks
-#if !EIGEN_ALIGN
- #ifndef EIGEN_DONT_VECTORIZE
- #define EIGEN_DONT_VECTORIZE
- #endif
-#endif
-
-#ifdef _MSC_VER
- #include <malloc.h> // for _aligned_malloc -- need it regardless of whether vectorization is enabled
- #if (_MSC_VER >= 1500) // 2008 or later
- // Remember that usage of defined() in a #define is undefined by the standard.
- // a user reported that in 64-bit mode, MSVC doesn't care to define _M_IX86_FP.
- #if (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || defined(_M_X64)
- #define EIGEN_SSE2_ON_MSVC_2008_OR_LATER
- #endif
- #endif
-#else
- // Remember that usage of defined() in a #define is undefined by the standard
- #if (defined __SSE2__) && ( (!defined __GNUC__) || EIGEN_GNUC_AT_LEAST(4,2) )
- #define EIGEN_SSE2_ON_NON_MSVC_BUT_NOT_OLD_GCC
- #endif
-#endif
-
-#ifndef EIGEN_DONT_VECTORIZE
-
- #if defined (EIGEN_SSE2_ON_NON_MSVC_BUT_NOT_OLD_GCC) || defined(EIGEN_SSE2_ON_MSVC_2008_OR_LATER)
-
- // Defines symbols for compile-time detection of which instructions are
- // used.
- // EIGEN_VECTORIZE_YY is defined if and only if the instruction set YY is used
- #define EIGEN_VECTORIZE
- #define EIGEN_VECTORIZE_SSE
- #define EIGEN_VECTORIZE_SSE2
-
- // Detect sse3/ssse3/sse4:
- // gcc and icc defines __SSE3__, ...
- // there is no way to know about this on msvc. You can define EIGEN_VECTORIZE_SSE* if you
- // want to force the use of those instructions with msvc.
- #ifdef __SSE3__
- #define EIGEN_VECTORIZE_SSE3
- #endif
- #ifdef __SSSE3__
- #define EIGEN_VECTORIZE_SSSE3
- #endif
- #ifdef __SSE4_1__
- #define EIGEN_VECTORIZE_SSE4_1
- #endif
- #ifdef __SSE4_2__
- #define EIGEN_VECTORIZE_SSE4_2
- #endif
-
- // include files
-
- // This extern "C" works around a MINGW-w64 compilation issue
- // https://sourceforge.net/tracker/index.php?func=detail&aid=3018394&group_id=202880&atid=983354
- // In essence, intrin.h is included by windows.h and also declares intrinsics (just as emmintrin.h etc. below do).
- // However, intrin.h uses an extern "C" declaration, and g++ thus complains of duplicate declarations
- // with conflicting linkage. The linkage for intrinsics doesn't matter, but at that stage the compiler doesn't know;
- // so, to avoid compile errors when windows.h is included after Eigen/Core, ensure intrinsics are extern "C" here too.
- // notice that since these are C headers, the extern "C" is theoretically needed anyways.
- extern "C" {
- #include <emmintrin.h>
- #include <xmmintrin.h>
- #ifdef EIGEN_VECTORIZE_SSE3
- #include <pmmintrin.h>
- #endif
- #ifdef EIGEN_VECTORIZE_SSSE3
- #include <tmmintrin.h>
- #endif
- #ifdef EIGEN_VECTORIZE_SSE4_1
- #include <smmintrin.h>
- #endif
- #ifdef EIGEN_VECTORIZE_SSE4_2
- #include <nmmintrin.h>
- #endif
- } // end extern "C"
- #elif defined __ALTIVEC__
- #define EIGEN_VECTORIZE
- #define EIGEN_VECTORIZE_ALTIVEC
- #include <altivec.h>
- // We need to #undef all these ugly tokens defined in <altivec.h>
- // => use __vector instead of vector
- #undef bool
- #undef vector
- #undef pixel
- #elif defined __ARM_NEON__
- #define EIGEN_VECTORIZE
- #define EIGEN_VECTORIZE_NEON
- #include <arm_neon.h>
- #endif
-#endif
-
-#if (defined _OPENMP) && (!defined EIGEN_DONT_PARALLELIZE)
- #define EIGEN_HAS_OPENMP
-#endif
-
-#ifdef EIGEN_HAS_OPENMP
-#include <omp.h>
-#endif
-
-// MSVC for windows mobile does not have the errno.h file
-#if !(defined(_MSC_VER) && defined(_WIN32_WCE))
-#define EIGEN_HAS_ERRNO
-#endif
-
-#ifdef EIGEN_HAS_ERRNO
-#include <cerrno>
-#endif
-#include <cstddef>
-#include <cstdlib>
-#include <cmath>
-#include <complex>
-#include <cassert>
-#include <functional>
-#include <iosfwd>
-#include <cstring>
-#include <string>
-#include <limits>
-#include <climits> // for CHAR_BIT
-// for min/max:
-#include <algorithm>
-
-// for outputting debug info
-#ifdef EIGEN_DEBUG_ASSIGN
-#include <iostream>
-#endif
-
-// required for __cpuid, needs to be included after cmath
-#if defined(_MSC_VER) && (defined(_M_IX86)||defined(_M_X64))
- #include <intrin.h>
-#endif
-
-#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(EIGEN_NO_EXCEPTIONS)
- #define EIGEN_EXCEPTIONS
-#endif
-
-#ifdef EIGEN_EXCEPTIONS
- #include <new>
-#endif
-
-// defined in bits/termios.h
-#undef B0
-
-/** \brief Namespace containing all symbols from the %Eigen library. */
-namespace Eigen {
-
-inline static const char *SimdInstructionSetsInUse(void) {
-#if defined(EIGEN_VECTORIZE_SSE4_2)
- return "SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
-#elif defined(EIGEN_VECTORIZE_SSE4_1)
- return "SSE, SSE2, SSE3, SSSE3, SSE4.1";
-#elif defined(EIGEN_VECTORIZE_SSSE3)
- return "SSE, SSE2, SSE3, SSSE3";
-#elif defined(EIGEN_VECTORIZE_SSE3)
- return "SSE, SSE2, SSE3";
-#elif defined(EIGEN_VECTORIZE_SSE2)
- return "SSE, SSE2";
-#elif defined(EIGEN_VECTORIZE_ALTIVEC)
- return "AltiVec";
-#elif defined(EIGEN_VECTORIZE_NEON)
- return "ARM NEON";
-#else
- return "None";
-#endif
-}
-
-#define STAGE10_FULL_EIGEN2_API 10
-#define STAGE20_RESOLVE_API_CONFLICTS 20
-#define STAGE30_FULL_EIGEN3_API 30
-#define STAGE40_FULL_EIGEN3_STRICTNESS 40
-#define STAGE99_NO_EIGEN2_SUPPORT 99
-
-#if defined EIGEN2_SUPPORT_STAGE40_FULL_EIGEN3_STRICTNESS
- #define EIGEN2_SUPPORT
- #define EIGEN2_SUPPORT_STAGE STAGE40_FULL_EIGEN3_STRICTNESS
-#elif defined EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API
- #define EIGEN2_SUPPORT
- #define EIGEN2_SUPPORT_STAGE STAGE30_FULL_EIGEN3_API
-#elif defined EIGEN2_SUPPORT_STAGE20_RESOLVE_API_CONFLICTS
- #define EIGEN2_SUPPORT
- #define EIGEN2_SUPPORT_STAGE STAGE20_RESOLVE_API_CONFLICTS
-#elif defined EIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API
- #define EIGEN2_SUPPORT
- #define EIGEN2_SUPPORT_STAGE STAGE10_FULL_EIGEN2_API
-#elif defined EIGEN2_SUPPORT
- // default to stage 3, that's what it's always meant
- #define EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API
- #define EIGEN2_SUPPORT_STAGE STAGE30_FULL_EIGEN3_API
-#else
- #define EIGEN2_SUPPORT_STAGE STAGE99_NO_EIGEN2_SUPPORT
-#endif
-
-#ifdef EIGEN2_SUPPORT
-#undef minor
-#endif
-
-// we use size_t frequently and we'll never remember to prepend it with std:: everytime just to
-// ensure QNX/QCC support
-using std::size_t;
-// gcc 4.6.0 wants std:: for ptrdiff_t
-using std::ptrdiff_t;
-
-/** \defgroup Core_Module Core module
- * This is the main module of Eigen providing dense matrix and vector support
- * (both fixed and dynamic size) with all the features corresponding to a BLAS library
- * and much more...
- *
- * \code
- * #include <Eigen/Core>
- * \endcode
- */
-
-#include "src/Core/util/Constants.h"
-#include "src/Core/util/ForwardDeclarations.h"
-#include "src/Core/util/Meta.h"
-#include "src/Core/util/XprHelper.h"
-#include "src/Core/util/StaticAssert.h"
-#include "src/Core/util/Memory.h"
-
-#include "src/Core/NumTraits.h"
-#include "src/Core/MathFunctions.h"
-#include "src/Core/GenericPacketMath.h"
-
-#if defined EIGEN_VECTORIZE_SSE
- #include "src/Core/arch/SSE/PacketMath.h"
- #include "src/Core/arch/SSE/MathFunctions.h"
- #include "src/Core/arch/SSE/Complex.h"
-#elif defined EIGEN_VECTORIZE_ALTIVEC
- #include "src/Core/arch/AltiVec/PacketMath.h"
- #include "src/Core/arch/AltiVec/Complex.h"
-#elif defined EIGEN_VECTORIZE_NEON
- #include "src/Core/arch/NEON/PacketMath.h"
- #include "src/Core/arch/NEON/Complex.h"
-#endif
-
-#include "src/Core/arch/Default/Settings.h"
-
-#include "src/Core/Functors.h"
-#include "src/Core/DenseCoeffsBase.h"
-#include "src/Core/DenseBase.h"
-#include "src/Core/MatrixBase.h"
-#include "src/Core/EigenBase.h"
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN // work around Doxygen bug triggered by Assign.h r814874
- // at least confirmed with Doxygen 1.5.5 and 1.5.6
- #include "src/Core/Assign.h"
-#endif
-
-#include "src/Core/util/BlasUtil.h"
-#include "src/Core/DenseStorage.h"
-#include "src/Core/NestByValue.h"
-#include "src/Core/ForceAlignedAccess.h"
-#include "src/Core/ReturnByValue.h"
-#include "src/Core/NoAlias.h"
-#include "src/Core/PlainObjectBase.h"
-#include "src/Core/Matrix.h"
-#include "src/Core/Array.h"
-#include "src/Core/CwiseBinaryOp.h"
-#include "src/Core/CwiseUnaryOp.h"
-#include "src/Core/CwiseNullaryOp.h"
-#include "src/Core/CwiseUnaryView.h"
-#include "src/Core/SelfCwiseBinaryOp.h"
-#include "src/Core/Dot.h"
-#include "src/Core/StableNorm.h"
-#include "src/Core/MapBase.h"
-#include "src/Core/Stride.h"
-#include "src/Core/Map.h"
-#include "src/Core/Block.h"
-#include "src/Core/VectorBlock.h"
-#include "src/Core/Transpose.h"
-#include "src/Core/DiagonalMatrix.h"
-#include "src/Core/Diagonal.h"
-#include "src/Core/DiagonalProduct.h"
-#include "src/Core/PermutationMatrix.h"
-#include "src/Core/Transpositions.h"
-#include "src/Core/Redux.h"
-#include "src/Core/Visitor.h"
-#include "src/Core/Fuzzy.h"
-#include "src/Core/IO.h"
-#include "src/Core/Swap.h"
-#include "src/Core/CommaInitializer.h"
-#include "src/Core/Flagged.h"
-#include "src/Core/ProductBase.h"
-#include "src/Core/Product.h"
-#include "src/Core/TriangularMatrix.h"
-#include "src/Core/SelfAdjointView.h"
-#include "src/Core/SolveTriangular.h"
-#include "src/Core/products/Parallelizer.h"
-#include "src/Core/products/CoeffBasedProduct.h"
-#include "src/Core/products/GeneralBlockPanelKernel.h"
-#include "src/Core/products/GeneralMatrixVector.h"
-#include "src/Core/products/GeneralMatrixMatrix.h"
-#include "src/Core/products/GeneralMatrixMatrixTriangular.h"
-#include "src/Core/products/SelfadjointMatrixVector.h"
-#include "src/Core/products/SelfadjointMatrixMatrix.h"
-#include "src/Core/products/SelfadjointProduct.h"
-#include "src/Core/products/SelfadjointRank2Update.h"
-#include "src/Core/products/TriangularMatrixVector.h"
-#include "src/Core/products/TriangularMatrixMatrix.h"
-#include "src/Core/products/TriangularSolverMatrix.h"
-#include "src/Core/products/TriangularSolverVector.h"
-#include "src/Core/BandMatrix.h"
-
-#include "src/Core/BooleanRedux.h"
-#include "src/Core/Select.h"
-#include "src/Core/VectorwiseOp.h"
-#include "src/Core/Random.h"
-#include "src/Core/Replicate.h"
-#include "src/Core/Reverse.h"
-#include "src/Core/ArrayBase.h"
-#include "src/Core/ArrayWrapper.h"
-
-} // namespace Eigen
-
-#include "src/Core/GlobalFunctions.h"
-
-#include "src/Core/util/ReenableStupidWarnings.h"
-
-#ifdef EIGEN2_SUPPORT
-#include "Eigen2Support"
-#endif
-
-#endif // EIGEN_CORE_H
diff --git a/extern/Eigen3/Eigen/Eigen b/extern/Eigen3/Eigen/Eigen
deleted file mode 100644
index 19b40ea4e7e..00000000000
--- a/extern/Eigen3/Eigen/Eigen
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "Dense"
-//#include "Sparse"
diff --git a/extern/Eigen3/Eigen/Eigen2Support b/extern/Eigen3/Eigen/Eigen2Support
deleted file mode 100644
index d96592a8de9..00000000000
--- a/extern/Eigen3/Eigen/Eigen2Support
+++ /dev/null
@@ -1,82 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN2SUPPORT_H
-#define EIGEN2SUPPORT_H
-
-#if (!defined(EIGEN2_SUPPORT)) || (!defined(EIGEN_CORE_H))
-#error Eigen2 support must be enabled by defining EIGEN2_SUPPORT before including any Eigen header
-#endif
-
-#include "src/Core/util/DisableStupidWarnings.h"
-
-namespace Eigen {
-
-/** \defgroup Eigen2Support_Module Eigen2 support module
- * This module provides a couple of deprecated functions improving the compatibility with Eigen2.
- *
- * To use it, define EIGEN2_SUPPORT before including any Eigen header
- * \code
- * #define EIGEN2_SUPPORT
- * \endcode
- *
- */
-
-#include "src/Eigen2Support/Macros.h"
-#include "src/Eigen2Support/Memory.h"
-#include "src/Eigen2Support/Meta.h"
-#include "src/Eigen2Support/Lazy.h"
-#include "src/Eigen2Support/Cwise.h"
-#include "src/Eigen2Support/CwiseOperators.h"
-#include "src/Eigen2Support/TriangularSolver.h"
-#include "src/Eigen2Support/Block.h"
-#include "src/Eigen2Support/VectorBlock.h"
-#include "src/Eigen2Support/Minor.h"
-#include "src/Eigen2Support/MathFunctions.h"
-
-
-} // namespace Eigen
-
-#include "src/Core/util/ReenableStupidWarnings.h"
-
-// Eigen2 used to include iostream
-#include<iostream>
-
-#define USING_PART_OF_NAMESPACE_EIGEN \
-EIGEN_USING_MATRIX_TYPEDEFS \
-using Eigen::Matrix; \
-using Eigen::MatrixBase; \
-using Eigen::ei_random; \
-using Eigen::ei_real; \
-using Eigen::ei_imag; \
-using Eigen::ei_conj; \
-using Eigen::ei_abs; \
-using Eigen::ei_abs2; \
-using Eigen::ei_sqrt; \
-using Eigen::ei_exp; \
-using Eigen::ei_log; \
-using Eigen::ei_sin; \
-using Eigen::ei_cos;
-
-#endif // EIGEN2SUPPORT_H
diff --git a/extern/Eigen3/Eigen/Eigenvalues b/extern/Eigen3/Eigen/Eigenvalues
deleted file mode 100644
index 250c0f46652..00000000000
--- a/extern/Eigen3/Eigen/Eigenvalues
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef EIGEN_EIGENVALUES_MODULE_H
-#define EIGEN_EIGENVALUES_MODULE_H
-
-#include "Core"
-
-#include "src/Core/util/DisableStupidWarnings.h"
-
-#include "Cholesky"
-#include "Jacobi"
-#include "Householder"
-#include "LU"
-
-namespace Eigen {
-
-/** \defgroup Eigenvalues_Module Eigenvalues module
- *
- *
- *
- * This module mainly provides various eigenvalue solvers.
- * This module also provides some MatrixBase methods, including:
- * - MatrixBase::eigenvalues(),
- * - MatrixBase::operatorNorm()
- *
- * \code
- * #include <Eigen/Eigenvalues>
- * \endcode
- */
-
-#include "src/Eigenvalues/Tridiagonalization.h"
-#include "src/Eigenvalues/RealSchur.h"
-#include "src/Eigenvalues/EigenSolver.h"
-#include "src/Eigenvalues/SelfAdjointEigenSolver.h"
-#include "src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h"
-#include "src/Eigenvalues/HessenbergDecomposition.h"
-#include "src/Eigenvalues/ComplexSchur.h"
-#include "src/Eigenvalues/ComplexEigenSolver.h"
-#include "src/Eigenvalues/MatrixBaseEigenvalues.h"
-
-} // namespace Eigen
-
-#include "src/Core/util/ReenableStupidWarnings.h"
-
-#endif // EIGEN_EIGENVALUES_MODULE_H
-/* vim: set filetype=cpp et sw=2 ts=2 ai: */
diff --git a/extern/Eigen3/Eigen/Geometry b/extern/Eigen3/Eigen/Geometry
deleted file mode 100644
index 78277c0c560..00000000000
--- a/extern/Eigen3/Eigen/Geometry
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef EIGEN_GEOMETRY_MODULE_H
-#define EIGEN_GEOMETRY_MODULE_H
-
-#include "Core"
-
-#include "src/Core/util/DisableStupidWarnings.h"
-
-#include "SVD"
-#include "LU"
-#include <limits>
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-namespace Eigen {
-
-/** \defgroup Geometry_Module Geometry module
- *
- *
- *
- * This module provides support for:
- * - fixed-size homogeneous transformations
- * - translation, scaling, 2D and 3D rotations
- * - quaternions
- * - \ref MatrixBase::cross() "cross product"
- * - \ref MatrixBase::unitOrthogonal() "orthognal vector generation"
- * - some linear components: parametrized-lines and hyperplanes
- *
- * \code
- * #include <Eigen/Geometry>
- * \endcode
- */
-
-#include "src/Geometry/OrthoMethods.h"
-#include "src/Geometry/EulerAngles.h"
-
-#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
- #include "src/Geometry/Homogeneous.h"
- #include "src/Geometry/RotationBase.h"
- #include "src/Geometry/Rotation2D.h"
- #include "src/Geometry/Quaternion.h"
- #include "src/Geometry/AngleAxis.h"
- #include "src/Geometry/Transform.h"
- #include "src/Geometry/Translation.h"
- #include "src/Geometry/Scaling.h"
- #include "src/Geometry/Hyperplane.h"
- #include "src/Geometry/ParametrizedLine.h"
- #include "src/Geometry/AlignedBox.h"
- #include "src/Geometry/Umeyama.h"
-
- #if defined EIGEN_VECTORIZE_SSE
- #include "src/Geometry/arch/Geometry_SSE.h"
- #endif
-#endif
-
-#ifdef EIGEN2_SUPPORT
-#include "src/Eigen2Support/Geometry/All.h"
-#endif
-
-} // namespace Eigen
-
-#include "src/Core/util/ReenableStupidWarnings.h"
-
-#endif // EIGEN_GEOMETRY_MODULE_H
-/* vim: set filetype=cpp et sw=2 ts=2 ai: */
-
diff --git a/extern/Eigen3/Eigen/Householder b/extern/Eigen3/Eigen/Householder
deleted file mode 100644
index 6b86cf65c55..00000000000
--- a/extern/Eigen3/Eigen/Householder
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef EIGEN_HOUSEHOLDER_MODULE_H
-#define EIGEN_HOUSEHOLDER_MODULE_H
-
-#include "Core"
-
-#include "src/Core/util/DisableStupidWarnings.h"
-
-namespace Eigen {
-
-/** \defgroup Householder_Module Householder module
- * This module provides Householder transformations.
- *
- * \code
- * #include <Eigen/Householder>
- * \endcode
- */
-
-#include "src/Householder/Householder.h"
-#include "src/Householder/HouseholderSequence.h"
-#include "src/Householder/BlockHouseholder.h"
-
-} // namespace Eigen
-
-#include "src/Core/util/ReenableStupidWarnings.h"
-
-#endif // EIGEN_HOUSEHOLDER_MODULE_H
-/* vim: set filetype=cpp et sw=2 ts=2 ai: */
diff --git a/extern/Eigen3/Eigen/Jacobi b/extern/Eigen3/Eigen/Jacobi
deleted file mode 100644
index afa67681379..00000000000
--- a/extern/Eigen3/Eigen/Jacobi
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef EIGEN_JACOBI_MODULE_H
-#define EIGEN_JACOBI_MODULE_H
-
-#include "Core"
-
-#include "src/Core/util/DisableStupidWarnings.h"
-
-namespace Eigen {
-
-/** \defgroup Jacobi_Module Jacobi module
- * This module provides Jacobi and Givens rotations.
- *
- * \code
- * #include <Eigen/Jacobi>
- * \endcode
- *
- * In addition to listed classes, it defines the two following MatrixBase methods to apply a Jacobi or Givens rotation:
- * - MatrixBase::applyOnTheLeft()
- * - MatrixBase::applyOnTheRight().
- */
-
-#include "src/Jacobi/Jacobi.h"
-
-} // namespace Eigen
-
-#include "src/Core/util/ReenableStupidWarnings.h"
-
-#endif // EIGEN_JACOBI_MODULE_H
-/* vim: set filetype=cpp et sw=2 ts=2 ai: */
-
diff --git a/extern/Eigen3/Eigen/LeastSquares b/extern/Eigen3/Eigen/LeastSquares
deleted file mode 100644
index 93a6302dcd9..00000000000
--- a/extern/Eigen3/Eigen/LeastSquares
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef EIGEN_REGRESSION_MODULE_H
-#define EIGEN_REGRESSION_MODULE_H
-
-#ifndef EIGEN2_SUPPORT
-#error LeastSquares is only available in Eigen2 support mode (define EIGEN2_SUPPORT)
-#endif
-
-// exclude from normal eigen3-only documentation
-#ifdef EIGEN2_SUPPORT
-
-#include "Core"
-
-#include "src/Core/util/DisableStupidWarnings.h"
-
-#include "Eigenvalues"
-#include "Geometry"
-
-namespace Eigen {
-
-/** \defgroup LeastSquares_Module LeastSquares module
- * This module provides linear regression and related features.
- *
- * \code
- * #include <Eigen/LeastSquares>
- * \endcode
- */
-
-#include "src/Eigen2Support/LeastSquares.h"
-
-} // namespace Eigen
-
-#include "src/Core/util/ReenableStupidWarnings.h"
-
-#endif // EIGEN2_SUPPORT
-
-#endif // EIGEN_REGRESSION_MODULE_H
diff --git a/extern/Eigen3/Eigen/QR b/extern/Eigen3/Eigen/QR
deleted file mode 100644
index 97c1788ee30..00000000000
--- a/extern/Eigen3/Eigen/QR
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef EIGEN_QR_MODULE_H
-#define EIGEN_QR_MODULE_H
-
-#include "Core"
-
-#include "src/Core/util/DisableStupidWarnings.h"
-
-#include "Cholesky"
-#include "Jacobi"
-#include "Householder"
-
-namespace Eigen {
-
-/** \defgroup QR_Module QR module
- *
- *
- *
- * This module provides various QR decompositions
- * This module also provides some MatrixBase methods, including:
- * - MatrixBase::qr(),
- *
- * \code
- * #include <Eigen/QR>
- * \endcode
- */
-
-#include "src/misc/Solve.h"
-#include "src/QR/HouseholderQR.h"
-#include "src/QR/FullPivHouseholderQR.h"
-#include "src/QR/ColPivHouseholderQR.h"
-
-#ifdef EIGEN2_SUPPORT
-#include "src/Eigen2Support/QR.h"
-#endif
-
-} // namespace Eigen
-
-#include "src/Core/util/ReenableStupidWarnings.h"
-
-#ifdef EIGEN2_SUPPORT
-#include "Eigenvalues"
-#endif
-
-#endif // EIGEN_QR_MODULE_H
-/* vim: set filetype=cpp et sw=2 ts=2 ai: */
diff --git a/extern/Eigen3/Eigen/QtAlignedMalloc b/extern/Eigen3/Eigen/QtAlignedMalloc
deleted file mode 100644
index 46f7d83b70f..00000000000
--- a/extern/Eigen3/Eigen/QtAlignedMalloc
+++ /dev/null
@@ -1,34 +0,0 @@
-
-#ifndef EIGEN_QTMALLOC_MODULE_H
-#define EIGEN_QTMALLOC_MODULE_H
-
-#include "Core"
-
-#if (!EIGEN_MALLOC_ALREADY_ALIGNED)
-
-#include "src/Core/util/DisableStupidWarnings.h"
-
-void *qMalloc(size_t size)
-{
- return Eigen::internal::aligned_malloc(size);
-}
-
-void qFree(void *ptr)
-{
- Eigen::internal::aligned_free(ptr);
-}
-
-void *qRealloc(void *ptr, size_t size)
-{
- void* newPtr = Eigen::internal::aligned_malloc(size);
- memcpy(newPtr, ptr, size);
- Eigen::internal::aligned_free(ptr);
- return newPtr;
-}
-
-#include "src/Core/util/ReenableStupidWarnings.h"
-
-#endif
-
-#endif // EIGEN_QTMALLOC_MODULE_H
-/* vim: set filetype=cpp et sw=2 ts=2 ai: */
diff --git a/extern/Eigen3/Eigen/Sparse b/extern/Eigen3/Eigen/Sparse
deleted file mode 100644
index 7425b3a412a..00000000000
--- a/extern/Eigen3/Eigen/Sparse
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef EIGEN_SPARSE_MODULE_H
-#define EIGEN_SPARSE_MODULE_H
-
-#include "Core"
-
-#include "src/Core/util/DisableStupidWarnings.h"
-
-#include <vector>
-#include <map>
-#include <cstdlib>
-#include <cstring>
-#include <algorithm>
-
-#ifdef EIGEN2_SUPPORT
-#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
-#endif
-
-#ifndef EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
-#error The sparse module API is not stable yet. To use it anyway, please define the EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET preprocessor token.
-#endif
-
-namespace Eigen {
-
-/** \defgroup Sparse_Module Sparse module
- *
- *
- *
- * See the \ref TutorialSparse "Sparse tutorial"
- *
- * \code
- * #include <Eigen/Sparse>
- * \endcode
- */
-
-/** The type used to identify a general sparse storage. */
-struct Sparse {};
-
-#include "src/Sparse/SparseUtil.h"
-#include "src/Sparse/SparseMatrixBase.h"
-#include "src/Sparse/CompressedStorage.h"
-#include "src/Sparse/AmbiVector.h"
-#include "src/Sparse/SparseMatrix.h"
-#include "src/Sparse/DynamicSparseMatrix.h"
-#include "src/Sparse/MappedSparseMatrix.h"
-#include "src/Sparse/SparseVector.h"
-#include "src/Sparse/CoreIterators.h"
-#include "src/Sparse/SparseBlock.h"
-#include "src/Sparse/SparseTranspose.h"
-#include "src/Sparse/SparseCwiseUnaryOp.h"
-#include "src/Sparse/SparseCwiseBinaryOp.h"
-#include "src/Sparse/SparseDot.h"
-#include "src/Sparse/SparseAssign.h"
-#include "src/Sparse/SparseRedux.h"
-#include "src/Sparse/SparseFuzzy.h"
-#include "src/Sparse/SparseProduct.h"
-#include "src/Sparse/SparseSparseProduct.h"
-#include "src/Sparse/SparseDenseProduct.h"
-#include "src/Sparse/SparseDiagonalProduct.h"
-#include "src/Sparse/SparseTriangularView.h"
-#include "src/Sparse/SparseSelfAdjointView.h"
-#include "src/Sparse/TriangularSolver.h"
-#include "src/Sparse/SparseView.h"
-
-} // namespace Eigen
-
-#include "src/Core/util/ReenableStupidWarnings.h"
-
-#endif // EIGEN_SPARSE_MODULE_H
-
diff --git a/extern/Eigen3/Eigen/src/Cholesky/LDLT.h b/extern/Eigen3/Eigen/src/Cholesky/LDLT.h
deleted file mode 100644
index f47b2ea5669..00000000000
--- a/extern/Eigen3/Eigen/src/Cholesky/LDLT.h
+++ /dev/null
@@ -1,484 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2009 Keir Mierle <mierle@gmail.com>
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_LDLT_H
-#define EIGEN_LDLT_H
-
-namespace internal {
-template<typename MatrixType, int UpLo> struct LDLT_Traits;
-}
-
-/** \ingroup cholesky_Module
- *
- * \class LDLT
- *
- * \brief Robust Cholesky decomposition of a matrix with pivoting
- *
- * \param MatrixType the type of the matrix of which to compute the LDL^T Cholesky decomposition
- *
- * Perform a robust Cholesky decomposition of a positive semidefinite or negative semidefinite
- * matrix \f$ A \f$ such that \f$ A = P^TLDL^*P \f$, where P is a permutation matrix, L
- * is lower triangular with a unit diagonal and D is a diagonal matrix.
- *
- * The decomposition uses pivoting to ensure stability, so that L will have
- * zeros in the bottom right rank(A) - n submatrix. Avoiding the square root
- * on D also stabilizes the computation.
- *
- * Remember that Cholesky decompositions are not rank-revealing. Also, do not use a Cholesky
- * decomposition to determine whether a system of equations has a solution.
- *
- * \sa MatrixBase::ldlt(), class LLT
- */
- /* THIS PART OF THE DOX IS CURRENTLY DISABLED BECAUSE INACCURATE BECAUSE OF BUG IN THE DECOMPOSITION CODE
- * Note that during the decomposition, only the upper triangular part of A is considered. Therefore,
- * the strict lower part does not have to store correct values.
- */
-template<typename _MatrixType, int _UpLo> class LDLT
-{
- public:
- typedef _MatrixType MatrixType;
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- Options = MatrixType::Options & ~RowMajorBit, // these are the options for the TmpMatrixType, we need a ColMajor matrix here!
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
- UpLo = _UpLo
- };
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
- typedef typename MatrixType::Index Index;
- typedef Matrix<Scalar, RowsAtCompileTime, 1, Options, MaxRowsAtCompileTime, 1> TmpMatrixType;
-
- typedef Transpositions<RowsAtCompileTime, MaxRowsAtCompileTime> TranspositionType;
- typedef PermutationMatrix<RowsAtCompileTime, MaxRowsAtCompileTime> PermutationType;
-
- typedef internal::LDLT_Traits<MatrixType,UpLo> Traits;
-
- /** \brief Default Constructor.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via LDLT::compute(const MatrixType&).
- */
- LDLT() : m_matrix(), m_transpositions(), m_isInitialized(false) {}
-
- /** \brief Default Constructor with memory preallocation
- *
- * Like the default constructor but with preallocation of the internal data
- * according to the specified problem \a size.
- * \sa LDLT()
- */
- LDLT(Index size)
- : m_matrix(size, size),
- m_transpositions(size),
- m_temporary(size),
- m_isInitialized(false)
- {}
-
- LDLT(const MatrixType& matrix)
- : m_matrix(matrix.rows(), matrix.cols()),
- m_transpositions(matrix.rows()),
- m_temporary(matrix.rows()),
- m_isInitialized(false)
- {
- compute(matrix);
- }
-
- /** \returns a view of the upper triangular matrix U */
- inline typename Traits::MatrixU matrixU() const
- {
- eigen_assert(m_isInitialized && "LDLT is not initialized.");
- return Traits::getU(m_matrix);
- }
-
- /** \returns a view of the lower triangular matrix L */
- inline typename Traits::MatrixL matrixL() const
- {
- eigen_assert(m_isInitialized && "LDLT is not initialized.");
- return Traits::getL(m_matrix);
- }
-
- /** \returns the permutation matrix P as a transposition sequence.
- */
- inline const TranspositionType& transpositionsP() const
- {
- eigen_assert(m_isInitialized && "LDLT is not initialized.");
- return m_transpositions;
- }
-
- /** \returns the coefficients of the diagonal matrix D */
- inline Diagonal<const MatrixType> vectorD(void) const
- {
- eigen_assert(m_isInitialized && "LDLT is not initialized.");
- return m_matrix.diagonal();
- }
-
- /** \returns true if the matrix is positive (semidefinite) */
- inline bool isPositive(void) const
- {
- eigen_assert(m_isInitialized && "LDLT is not initialized.");
- return m_sign == 1;
- }
-
- #ifdef EIGEN2_SUPPORT
- inline bool isPositiveDefinite() const
- {
- return isPositive();
- }
- #endif
-
- /** \returns true if the matrix is negative (semidefinite) */
- inline bool isNegative(void) const
- {
- eigen_assert(m_isInitialized && "LDLT is not initialized.");
- return m_sign == -1;
- }
-
- /** \returns a solution x of \f$ A x = b \f$ using the current decomposition of A.
- *
- * This function also supports in-place solves using the syntax <tt>x = decompositionObject.solve(x)</tt> .
- *
- * \note_about_checking_solutions
- *
- * More precisely, this method solves \f$ A x = b \f$ using the decomposition \f$ A = P^T L D L^* P \f$
- * by solving the systems \f$ P^T y_1 = b \f$, \f$ L y_2 = y_1 \f$, \f$ D y_3 = y_2 \f$,
- * \f$ L^* y_4 = y_3 \f$ and \f$ P x = y_4 \f$ in succession. If the matrix \f$ A \f$ is singular, then
- * \f$ D \f$ will also be singular (all the other matrices are invertible). In that case, the
- * least-square solution of \f$ D y_3 = y_2 \f$ is computed. This does not mean that this function
- * computes the least-square solution of \f$ A x = b \f$ is \f$ A \f$ is singular.
- *
- * \sa MatrixBase::ldlt()
- */
- template<typename Rhs>
- inline const internal::solve_retval<LDLT, Rhs>
- solve(const MatrixBase<Rhs>& b) const
- {
- eigen_assert(m_isInitialized && "LDLT is not initialized.");
- eigen_assert(m_matrix.rows()==b.rows()
- && "LDLT::solve(): invalid number of rows of the right hand side matrix b");
- return internal::solve_retval<LDLT, Rhs>(*this, b.derived());
- }
-
- #ifdef EIGEN2_SUPPORT
- template<typename OtherDerived, typename ResultType>
- bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
- {
- *result = this->solve(b);
- return true;
- }
- #endif
-
- template<typename Derived>
- bool solveInPlace(MatrixBase<Derived> &bAndX) const;
-
- LDLT& compute(const MatrixType& matrix);
-
- /** \returns the internal LDLT decomposition matrix
- *
- * TODO: document the storage layout
- */
- inline const MatrixType& matrixLDLT() const
- {
- eigen_assert(m_isInitialized && "LDLT is not initialized.");
- return m_matrix;
- }
-
- MatrixType reconstructedMatrix() const;
-
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
-
- protected:
-
- /** \internal
- * Used to compute and store the Cholesky decomposition A = L D L^* = U^* D U.
- * The strict upper part is used during the decomposition, the strict lower
- * part correspond to the coefficients of L (its diagonal is equal to 1 and
- * is not stored), and the diagonal entries correspond to D.
- */
- MatrixType m_matrix;
- TranspositionType m_transpositions;
- TmpMatrixType m_temporary;
- int m_sign;
- bool m_isInitialized;
-};
-
-namespace internal {
-
-template<int UpLo> struct ldlt_inplace;
-
-template<> struct ldlt_inplace<Lower>
-{
- template<typename MatrixType, typename TranspositionType, typename Workspace>
- static bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, int* sign=0)
- {
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
- typedef typename MatrixType::Index Index;
- eigen_assert(mat.rows()==mat.cols());
- const Index size = mat.rows();
-
- if (size <= 1)
- {
- transpositions.setIdentity();
- if(sign)
- *sign = real(mat.coeff(0,0))>0 ? 1:-1;
- 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);
- 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);
-
- if(sign)
- *sign = real(mat.diagonal().coeff(index_of_biggest_in_corner)) > 0 ? 1 : -1;
- }
-
- // 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)
- {
- // apply the transposition while taking care to consider only
- // the lower triangular part
- Index s = size-index_of_biggest_in_corner-1; // trailing size after the biggest element
- mat.row(k).head(k).swap(mat.row(index_of_biggest_in_corner).head(k));
- mat.col(k).tail(s).swap(mat.col(index_of_biggest_in_corner).tail(s));
- std::swap(mat.coeffRef(k,k),mat.coeffRef(index_of_biggest_in_corner,index_of_biggest_in_corner));
- for(int i=k+1;i<index_of_biggest_in_corner;++i)
- {
- Scalar tmp = mat.coeffRef(i,k);
- mat.coeffRef(i,k) = conj(mat.coeffRef(index_of_biggest_in_corner,i));
- mat.coeffRef(index_of_biggest_in_corner,i) = conj(tmp);
- }
- if(NumTraits<Scalar>::IsComplex)
- mat.coeffRef(index_of_biggest_in_corner,k) = conj(mat.coeff(index_of_biggest_in_corner,k));
- }
-
- // partition the matrix:
- // A00 | - | -
- // lu = A10 | A11 | -
- // A20 | A21 | A22
- Index rs = size - k - 1;
- Block<MatrixType,Dynamic,1> A21(mat,k+1,k,rs,1);
- Block<MatrixType,1,Dynamic> A10(mat,k,0,1,k);
- Block<MatrixType,Dynamic,Dynamic> A20(mat,k+1,0,rs,k);
-
- if(k>0)
- {
- temp.head(k) = mat.diagonal().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);
- }
-
- return true;
- }
-};
-
-template<> struct ldlt_inplace<Upper>
-{
- template<typename MatrixType, typename TranspositionType, typename Workspace>
- static EIGEN_STRONG_INLINE bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, int* sign=0)
- {
- Transpose<MatrixType> matt(mat);
- return ldlt_inplace<Lower>::unblocked(matt, transpositions, temp, sign);
- }
-};
-
-template<typename MatrixType> struct LDLT_Traits<MatrixType,Lower>
-{
- typedef TriangularView<MatrixType, UnitLower> MatrixL;
- typedef TriangularView<typename MatrixType::AdjointReturnType, UnitUpper> MatrixU;
- inline static MatrixL getL(const MatrixType& m) { return m; }
- inline static MatrixU getU(const MatrixType& m) { return m.adjoint(); }
-};
-
-template<typename MatrixType> struct LDLT_Traits<MatrixType,Upper>
-{
- typedef TriangularView<typename MatrixType::AdjointReturnType, UnitLower> MatrixL;
- typedef TriangularView<MatrixType, UnitUpper> MatrixU;
- inline static MatrixL getL(const MatrixType& m) { return m.adjoint(); }
- inline static MatrixU getU(const MatrixType& m) { return m; }
-};
-
-} // end namespace internal
-
-/** Compute / recompute the LDLT decomposition A = L D L^* = U^* D U of \a matrix
- */
-template<typename MatrixType, int _UpLo>
-LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a)
-{
- eigen_assert(a.rows()==a.cols());
- const Index size = a.rows();
-
- m_matrix = a;
-
- m_transpositions.resize(size);
- m_isInitialized = false;
- m_temporary.resize(size);
-
- internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, &m_sign);
-
- m_isInitialized = true;
- return *this;
-}
-
-namespace internal {
-template<typename _MatrixType, int _UpLo, typename Rhs>
-struct solve_retval<LDLT<_MatrixType,_UpLo>, Rhs>
- : solve_retval_base<LDLT<_MatrixType,_UpLo>, Rhs>
-{
- typedef LDLT<_MatrixType,_UpLo> LDLTType;
- EIGEN_MAKE_SOLVE_HELPERS(LDLTType,Rhs)
-
- template<typename Dest> void evalTo(Dest& dst) const
- {
- eigen_assert(rhs().rows() == dec().matrixLDLT().rows());
- // dst = P b
- dst = dec().transpositionsP() * rhs();
-
- // dst = L^-1 (P b)
- dec().matrixL().solveInPlace(dst);
-
- // dst = D^-1 (L^-1 P b)
- // more precisely, use pseudo-inverse of D (see bug 241)
- 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
- for (Index i = 0; i < vectorD.size(); ++i) {
- if(abs(vectorD(i)) > tolerance)
- dst.row(i) /= vectorD(i);
- else
- dst.row(i).setZero();
- }
-
- // dst = L^-T (D^-1 L^-1 P b)
- dec().matrixU().solveInPlace(dst);
-
- // dst = P^-1 (L^-T D^-1 L^-1 P b) = A^-1 b
- dst = dec().transpositionsP().transpose() * dst;
- }
-};
-}
-
-/** \internal use x = ldlt_object.solve(x);
- *
- * This is the \em in-place version of solve().
- *
- * \param bAndX represents both the right-hand side matrix b and result x.
- *
- * \returns true always! If you need to check for existence of solutions, use another decomposition like LU, QR, or SVD.
- *
- * This version avoids a copy when the right hand side matrix b is not
- * needed anymore.
- *
- * \sa LDLT::solve(), MatrixBase::ldlt()
- */
-template<typename MatrixType,int _UpLo>
-template<typename Derived>
-bool LDLT<MatrixType,_UpLo>::solveInPlace(MatrixBase<Derived> &bAndX) const
-{
- eigen_assert(m_isInitialized && "LDLT is not initialized.");
- const Index size = m_matrix.rows();
- eigen_assert(size == bAndX.rows());
-
- bAndX = this->solve(bAndX);
-
- return true;
-}
-
-/** \returns the matrix represented by the decomposition,
- * i.e., it returns the product: P^T L D L^* P.
- * This function is provided for debug purpose. */
-template<typename MatrixType, int _UpLo>
-MatrixType LDLT<MatrixType,_UpLo>::reconstructedMatrix() const
-{
- eigen_assert(m_isInitialized && "LDLT is not initialized.");
- const Index size = m_matrix.rows();
- MatrixType res(size,size);
-
- // P
- res.setIdentity();
- res = transpositionsP() * res;
- // L^* P
- res = matrixU() * res;
- // D(L^*P)
- res = vectorD().asDiagonal() * res;
- // L(DL^*P)
- res = matrixL() * res;
- // P^T (LDL^*P)
- res = transpositionsP().transpose() * res;
-
- return res;
-}
-
-/** \cholesky_module
- * \returns the Cholesky decomposition with full pivoting without square root of \c *this
- */
-template<typename MatrixType, unsigned int UpLo>
-inline const LDLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo>
-SelfAdjointView<MatrixType, UpLo>::ldlt() const
-{
- return LDLT<PlainObject,UpLo>(m_matrix);
-}
-
-/** \cholesky_module
- * \returns the Cholesky decomposition with full pivoting without square root of \c *this
- */
-template<typename Derived>
-inline const LDLT<typename MatrixBase<Derived>::PlainObject>
-MatrixBase<Derived>::ldlt() const
-{
- return LDLT<PlainObject>(derived());
-}
-
-#endif // EIGEN_LDLT_H
diff --git a/extern/Eigen3/Eigen/src/Cholesky/LLT.h b/extern/Eigen3/Eigen/src/Cholesky/LLT.h
deleted file mode 100644
index a4ee5b11cb9..00000000000
--- a/extern/Eigen3/Eigen/src/Cholesky/LLT.h
+++ /dev/null
@@ -1,386 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_LLT_H
-#define EIGEN_LLT_H
-
-namespace internal{
-template<typename MatrixType, int UpLo> struct LLT_Traits;
-}
-
-/** \ingroup cholesky_Module
- *
- * \class LLT
- *
- * \brief Standard Cholesky decomposition (LL^T) of a matrix and associated features
- *
- * \param MatrixType the type of the matrix of which we are computing the LL^T Cholesky decomposition
- *
- * This class performs a LL^T Cholesky decomposition of a symmetric, positive definite
- * matrix A such that A = LL^* = U^*U, where L is lower triangular.
- *
- * While the Cholesky decomposition is particularly useful to solve selfadjoint problems like D^*D x = b,
- * for that purpose, we recommend the Cholesky decomposition without square root which is more stable
- * and even faster. Nevertheless, this standard Cholesky decomposition remains useful in many other
- * situations like generalised eigen problems with hermitian matrices.
- *
- * Remember that Cholesky decompositions are not rank-revealing. This LLT decomposition is only stable on positive definite matrices,
- * use LDLT instead for the semidefinite case. Also, do not use a Cholesky decomposition to determine whether a system of equations
- * has a solution.
- *
- * \sa MatrixBase::llt(), class LDLT
- */
- /* HEY THIS DOX IS DISABLED BECAUSE THERE's A BUG EITHER HERE OR IN LDLT ABOUT THAT (OR BOTH)
- * Note that during the decomposition, only the upper triangular part of A is considered. Therefore,
- * the strict lower part does not have to store correct values.
- */
-template<typename _MatrixType, int _UpLo> class LLT
-{
- public:
- typedef _MatrixType MatrixType;
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- Options = MatrixType::Options,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
- };
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
- typedef typename MatrixType::Index Index;
-
- enum {
- PacketSize = internal::packet_traits<Scalar>::size,
- AlignmentMask = int(PacketSize)-1,
- UpLo = _UpLo
- };
-
- typedef internal::LLT_Traits<MatrixType,UpLo> Traits;
-
- /**
- * \brief Default Constructor.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via LLT::compute(const MatrixType&).
- */
- LLT() : m_matrix(), m_isInitialized(false) {}
-
- /** \brief Default Constructor with memory preallocation
- *
- * Like the default constructor but with preallocation of the internal data
- * according to the specified problem \a size.
- * \sa LLT()
- */
- LLT(Index size) : m_matrix(size, size),
- m_isInitialized(false) {}
-
- LLT(const MatrixType& matrix)
- : m_matrix(matrix.rows(), matrix.cols()),
- m_isInitialized(false)
- {
- compute(matrix);
- }
-
- /** \returns a view of the upper triangular matrix U */
- inline typename Traits::MatrixU matrixU() const
- {
- eigen_assert(m_isInitialized && "LLT is not initialized.");
- return Traits::getU(m_matrix);
- }
-
- /** \returns a view of the lower triangular matrix L */
- inline typename Traits::MatrixL matrixL() const
- {
- eigen_assert(m_isInitialized && "LLT is not initialized.");
- return Traits::getL(m_matrix);
- }
-
- /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A.
- *
- * Since this LLT class assumes anyway that the matrix A is invertible, the solution
- * theoretically exists and is unique regardless of b.
- *
- * Example: \include LLT_solve.cpp
- * Output: \verbinclude LLT_solve.out
- *
- * \sa solveInPlace(), MatrixBase::llt()
- */
- template<typename Rhs>
- inline const internal::solve_retval<LLT, Rhs>
- solve(const MatrixBase<Rhs>& b) const
- {
- eigen_assert(m_isInitialized && "LLT is not initialized.");
- eigen_assert(m_matrix.rows()==b.rows()
- && "LLT::solve(): invalid number of rows of the right hand side matrix b");
- return internal::solve_retval<LLT, Rhs>(*this, b.derived());
- }
-
- #ifdef EIGEN2_SUPPORT
- template<typename OtherDerived, typename ResultType>
- bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
- {
- *result = this->solve(b);
- return true;
- }
-
- bool isPositiveDefinite() const { return true; }
- #endif
-
- template<typename Derived>
- void solveInPlace(MatrixBase<Derived> &bAndX) const;
-
- LLT& compute(const MatrixType& matrix);
-
- /** \returns the LLT decomposition matrix
- *
- * TODO: document the storage layout
- */
- inline const MatrixType& matrixLLT() const
- {
- eigen_assert(m_isInitialized && "LLT is not initialized.");
- return m_matrix;
- }
-
- MatrixType reconstructedMatrix() const;
-
-
- /** \brief Reports whether previous computation was successful.
- *
- * \returns \c Success if computation was succesful,
- * \c NumericalIssue if the matrix.appears to be negative.
- */
- ComputationInfo info() const
- {
- eigen_assert(m_isInitialized && "LLT is not initialized.");
- return m_info;
- }
-
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
-
- protected:
- /** \internal
- * Used to compute and store L
- * The strict upper part is not used and even not initialized.
- */
- MatrixType m_matrix;
- bool m_isInitialized;
- ComputationInfo m_info;
-};
-
-namespace internal {
-
-template<int UpLo> struct llt_inplace;
-
-template<> struct llt_inplace<Lower>
-{
- template<typename MatrixType>
- static typename MatrixType::Index unblocked(MatrixType& mat)
- {
- typedef typename MatrixType::Index Index;
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
-
- eigen_assert(mat.rows()==mat.cols());
- const Index size = mat.rows();
- for(Index k = 0; k < size; ++k)
- {
- Index rs = size-k-1; // remaining size
-
- Block<MatrixType,Dynamic,1> A21(mat,k+1,k,rs,1);
- Block<MatrixType,1,Dynamic> A10(mat,k,0,1,k);
- Block<MatrixType,Dynamic,Dynamic> A20(mat,k+1,0,rs,k);
-
- RealScalar x = real(mat.coeff(k,k));
- if (k>0) x -= A10.squaredNorm();
- if (x<=RealScalar(0))
- 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;
- }
- return -1;
- }
-
- template<typename MatrixType>
- static typename MatrixType::Index blocked(MatrixType& m)
- {
- typedef typename MatrixType::Index Index;
- eigen_assert(m.rows()==m.cols());
- Index size = m.rows();
- if(size<32)
- return unblocked(m);
-
- Index blockSize = size/8;
- blockSize = (blockSize/16)*16;
- blockSize = (std::min)((std::max)(blockSize,Index(8)), Index(128));
-
- for (Index k=0; k<size; k+=blockSize)
- {
- // partition the matrix:
- // A00 | - | -
- // lu = A10 | A11 | -
- // A20 | A21 | A22
- Index bs = (std::min)(blockSize, size-k);
- Index rs = size - k - bs;
- Block<MatrixType,Dynamic,Dynamic> A11(m,k, k, bs,bs);
- Block<MatrixType,Dynamic,Dynamic> A21(m,k+bs,k, rs,bs);
- Block<MatrixType,Dynamic,Dynamic> A22(m,k+bs,k+bs,rs,rs);
-
- Index ret;
- if((ret=unblocked(A11))>=0) return k+ret;
- if(rs>0) A11.adjoint().template triangularView<Upper>().template solveInPlace<OnTheRight>(A21);
- if(rs>0) A22.template selfadjointView<Lower>().rankUpdate(A21,-1); // bottleneck
- }
- return -1;
- }
-};
-
-template<> struct llt_inplace<Upper>
-{
- template<typename MatrixType>
- static EIGEN_STRONG_INLINE typename MatrixType::Index unblocked(MatrixType& mat)
- {
- Transpose<MatrixType> matt(mat);
- return llt_inplace<Lower>::unblocked(matt);
- }
- template<typename MatrixType>
- static EIGEN_STRONG_INLINE typename MatrixType::Index blocked(MatrixType& mat)
- {
- Transpose<MatrixType> matt(mat);
- return llt_inplace<Lower>::blocked(matt);
- }
-};
-
-template<typename MatrixType> struct LLT_Traits<MatrixType,Lower>
-{
- typedef TriangularView<MatrixType, Lower> MatrixL;
- typedef TriangularView<typename MatrixType::AdjointReturnType, Upper> MatrixU;
- inline static MatrixL getL(const MatrixType& m) { return m; }
- inline static MatrixU getU(const MatrixType& m) { return m.adjoint(); }
- static bool inplace_decomposition(MatrixType& m)
- { return llt_inplace<Lower>::blocked(m)==-1; }
-};
-
-template<typename MatrixType> struct LLT_Traits<MatrixType,Upper>
-{
- typedef TriangularView<typename MatrixType::AdjointReturnType, Lower> MatrixL;
- typedef TriangularView<MatrixType, Upper> MatrixU;
- inline static MatrixL getL(const MatrixType& m) { return m.adjoint(); }
- inline static MatrixU getU(const MatrixType& m) { return m; }
- static bool inplace_decomposition(MatrixType& m)
- { return llt_inplace<Upper>::blocked(m)==-1; }
-};
-
-} // end namespace internal
-
-/** Computes / recomputes the Cholesky decomposition A = LL^* = U^*U of \a matrix
- *
- *
- * \returns a reference to *this
- */
-template<typename MatrixType, int _UpLo>
-LLT<MatrixType,_UpLo>& LLT<MatrixType,_UpLo>::compute(const MatrixType& a)
-{
- assert(a.rows()==a.cols());
- const Index size = a.rows();
- m_matrix.resize(size, size);
- m_matrix = a;
-
- m_isInitialized = true;
- bool ok = Traits::inplace_decomposition(m_matrix);
- m_info = ok ? Success : NumericalIssue;
-
- return *this;
-}
-
-namespace internal {
-template<typename _MatrixType, int UpLo, typename Rhs>
-struct solve_retval<LLT<_MatrixType, UpLo>, Rhs>
- : solve_retval_base<LLT<_MatrixType, UpLo>, Rhs>
-{
- typedef LLT<_MatrixType,UpLo> LLTType;
- EIGEN_MAKE_SOLVE_HELPERS(LLTType,Rhs)
-
- template<typename Dest> void evalTo(Dest& dst) const
- {
- dst = rhs();
- dec().solveInPlace(dst);
- }
-};
-}
-
-/** \internal use x = llt_object.solve(x);
- *
- * This is the \em in-place version of solve().
- *
- * \param bAndX represents both the right-hand side matrix b and result x.
- *
- * \returns true always! If you need to check for existence of solutions, use another decomposition like LU, QR, or SVD.
- *
- * This version avoids a copy when the right hand side matrix b is not
- * needed anymore.
- *
- * \sa LLT::solve(), MatrixBase::llt()
- */
-template<typename MatrixType, int _UpLo>
-template<typename Derived>
-void LLT<MatrixType,_UpLo>::solveInPlace(MatrixBase<Derived> &bAndX) const
-{
- eigen_assert(m_isInitialized && "LLT is not initialized.");
- eigen_assert(m_matrix.rows()==bAndX.rows());
- matrixL().solveInPlace(bAndX);
- matrixU().solveInPlace(bAndX);
-}
-
-/** \returns the matrix represented by the decomposition,
- * i.e., it returns the product: L L^*.
- * This function is provided for debug purpose. */
-template<typename MatrixType, int _UpLo>
-MatrixType LLT<MatrixType,_UpLo>::reconstructedMatrix() const
-{
- eigen_assert(m_isInitialized && "LLT is not initialized.");
- return matrixL() * matrixL().adjoint().toDenseMatrix();
-}
-
-/** \cholesky_module
- * \returns the LLT decomposition of \c *this
- */
-template<typename Derived>
-inline const LLT<typename MatrixBase<Derived>::PlainObject>
-MatrixBase<Derived>::llt() const
-{
- return LLT<PlainObject>(derived());
-}
-
-/** \cholesky_module
- * \returns the LLT decomposition of \c *this
- */
-template<typename MatrixType, unsigned int UpLo>
-inline const LLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo>
-SelfAdjointView<MatrixType, UpLo>::llt() const
-{
- return LLT<PlainObject,UpLo>(m_matrix);
-}
-
-#endif // EIGEN_LLT_H
diff --git a/extern/Eigen3/Eigen/src/Core/Array.h b/extern/Eigen3/Eigen/src/Core/Array.h
deleted file mode 100644
index a3a2167ad3e..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Array.h
+++ /dev/null
@@ -1,322 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_ARRAY_H
-#define EIGEN_ARRAY_H
-
-/** \class Array
- * \ingroup Core_Module
- *
- * \brief General-purpose arrays with easy API for coefficient-wise operations
- *
- * The %Array class is very similar to the Matrix class. It provides
- * general-purpose one- and two-dimensional arrays. The difference between the
- * %Array and the %Matrix class is primarily in the API: the API for the
- * %Array class provides easy access to coefficient-wise operations, while the
- * API for the %Matrix class provides easy access to linear-algebra
- * operations.
- *
- * 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_ARRAY_PLUGIN.
- *
- * \sa \ref TutorialArrayClass, \ref TopicClassHierarchy
- */
-namespace internal {
-template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
-struct traits<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > : traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
-{
- typedef ArrayXpr XprKind;
- typedef ArrayBase<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > XprBase;
-};
-}
-
-template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
-class Array
- : public PlainObjectBase<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
-{
- public:
-
- typedef PlainObjectBase<Array> Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Array)
-
- enum { Options = _Options };
- typedef typename Base::PlainObject PlainObject;
-
- protected:
- template <typename Derived, typename OtherDerived, bool IsVector>
- friend struct internal::conservative_resize_like_impl;
-
- using Base::m_storage;
- public:
- enum { NeedsToAlign = (!(Options&DontAlign))
- && SizeAtCompileTime!=Dynamic && ((static_cast<int>(sizeof(Scalar))*SizeAtCompileTime)%16)==0 };
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
-
- using Base::base;
- using Base::coeff;
- using Base::coeffRef;
-
- /**
- * The usage of
- * using Base::operator=;
- * fails on MSVC. Since the code below is working with GCC and MSVC, we skipped
- * the usage of 'using'. This should be done only for operator=.
- */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Array& operator=(const EigenBase<OtherDerived> &other)
- {
- return Base::operator=(other);
- }
-
- /** Copies the value of the expression \a other into \c *this with automatic resizing.
- *
- * *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized),
- * it will be initialized.
- *
- * Note that copying a row-vector into a vector (and conversely) is allowed.
- * The resizing, if any, is then done in the appropriate way so that row-vectors
- * remain row-vectors and vectors remain vectors.
- */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Array& operator=(const ArrayBase<OtherDerived>& other)
- {
- return Base::_set(other);
- }
-
- /** This is a special case of the templated operator=. Its purpose is to
- * prevent a default operator= from hiding the templated operator=.
- */
- EIGEN_STRONG_INLINE Array& operator=(const Array& other)
- {
- return Base::_set(other);
- }
-
- /** Default constructor.
- *
- * For fixed-size matrices, does nothing.
- *
- * For dynamic-size matrices, creates an empty matrix of size 0. Does not allocate any array. Such a matrix
- * is called a null matrix. This constructor is the unique way to create null matrices: resizing
- * a matrix to 0 is not supported.
- *
- * \sa resize(Index,Index)
- */
- EIGEN_STRONG_INLINE explicit Array() : Base()
- {
- Base::_check_template_params();
- EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
- }
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
- // FIXME is it still needed ??
- /** \internal */
- Array(internal::constructor_without_unaligned_array_assert)
- : Base(internal::constructor_without_unaligned_array_assert())
- {
- Base::_check_template_params();
- EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
- }
-#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,
- * it is redundant to pass the dimension here, so it makes more sense to use the default
- * constructor Matrix() instead.
- */
- EIGEN_STRONG_INLINE explicit Array(Index dim)
- : Base(dim, RowsAtCompileTime == 1 ? 1 : dim, ColsAtCompileTime == 1 ? 1 : dim)
- {
- Base::_check_template_params();
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Array)
- eigen_assert(dim >= 0);
- eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == dim);
- EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
- }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- template<typename T0, typename T1>
- EIGEN_STRONG_INLINE Array(const T0& x, const T1& y)
- {
- Base::_check_template_params();
- this->template _init2<T0,T1>(x, y);
- }
- #else
- /** constructs an uninitialized matrix with \a rows rows and \a cols columns.
- *
- * This is useful for dynamic-size matrices. For fixed-size matrices,
- * it is redundant to pass these parameters, so one should use the default constructor
- * Matrix() instead. */
- Array(Index rows, Index cols);
- /** constructs an initialized 2D vector with given coefficients */
- Array(const Scalar& x, const Scalar& y);
- #endif
-
- /** constructs an initialized 3D vector with given coefficients */
- EIGEN_STRONG_INLINE Array(const Scalar& x, const Scalar& y, const Scalar& z)
- {
- Base::_check_template_params();
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 3)
- m_storage.data()[0] = x;
- m_storage.data()[1] = y;
- m_storage.data()[2] = z;
- }
- /** constructs an initialized 4D vector with given coefficients */
- EIGEN_STRONG_INLINE Array(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w)
- {
- Base::_check_template_params();
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 4)
- m_storage.data()[0] = x;
- m_storage.data()[1] = y;
- m_storage.data()[2] = z;
- m_storage.data()[3] = w;
- }
-
- explicit Array(const Scalar *data);
-
- /** Constructor copying the value of the expression \a other */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Array(const ArrayBase<OtherDerived>& other)
- : Base(other.rows() * other.cols(), other.rows(), other.cols())
- {
- Base::_check_template_params();
- Base::_set_noalias(other);
- }
- /** Copy constructor */
- EIGEN_STRONG_INLINE Array(const Array& other)
- : Base(other.rows() * other.cols(), other.rows(), other.cols())
- {
- Base::_check_template_params();
- Base::_set_noalias(other);
- }
- /** Copy constructor with in-place evaluation */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Array(const ReturnByValue<OtherDerived>& other)
- {
- Base::_check_template_params();
- Base::resize(other.rows(), other.cols());
- other.evalTo(*this);
- }
-
- /** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Array(const EigenBase<OtherDerived> &other)
- : Base(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
- {
- Base::_check_template_params();
- Base::resize(other.rows(), other.cols());
- *this = other;
- }
-
- /** Override MatrixBase::swap() since for dynamic-sized matrices of same type it is enough to swap the
- * data pointers.
- */
- template<typename OtherDerived>
- void swap(ArrayBase<OtherDerived> const & other)
- { this->_swap(other.derived()); }
-
- inline Index innerStride() const { return 1; }
- inline Index outerStride() const { return this->innerSize(); }
-
- #ifdef EIGEN_ARRAY_PLUGIN
- #include EIGEN_ARRAY_PLUGIN
- #endif
-
- private:
-
- template<typename MatrixType, typename OtherDerived, bool SwapPointers>
- friend struct internal::matrix_swap_impl;
-};
-
-/** \defgroup arraytypedefs Global array typedefs
- * \ingroup Core_Module
- *
- * Eigen defines several typedef shortcuts for most common 1D and 2D array types.
- *
- * The general patterns are the following:
- *
- * \c ArrayRowsColsType where \c Rows and \c Cols can be \c 2,\c 3,\c 4 for fixed size square matrices or \c X for dynamic size,
- * and where \c Type can be \c i for integer, \c f for float, \c d for double, \c cf for complex float, \c cd
- * for complex double.
- *
- * For example, \c Array33d is a fixed-size 3x3 array type of doubles, and \c ArrayXXf is a dynamic-size matrix of floats.
- *
- * There are also \c ArraySizeType which are self-explanatory. For example, \c Array4cf is
- * a fixed-size 1D array of 4 complex floats.
- *
- * \sa class Array
- */
-
-#define EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \
-/** \ingroup arraytypedefs */ \
-typedef Array<Type, Size, Size> Array##SizeSuffix##SizeSuffix##TypeSuffix; \
-/** \ingroup arraytypedefs */ \
-typedef Array<Type, Size, 1> Array##SizeSuffix##TypeSuffix;
-
-#define EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, Size) \
-/** \ingroup arraytypedefs */ \
-typedef Array<Type, Size, Dynamic> Array##Size##X##TypeSuffix; \
-/** \ingroup arraytypedefs */ \
-typedef Array<Type, Dynamic, Size> Array##X##Size##TypeSuffix;
-
-#define EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \
-EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, 2, 2) \
-EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, 3, 3) \
-EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, 4, 4) \
-EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, Dynamic, X) \
-EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, 2) \
-EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, 3) \
-EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, 4)
-
-EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(int, i)
-EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(float, f)
-EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(double, d)
-EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(std::complex<float>, cf)
-EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(std::complex<double>, cd)
-
-#undef EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES
-#undef EIGEN_MAKE_ARRAY_TYPEDEFS
-
-#undef EIGEN_MAKE_ARRAY_TYPEDEFS_LARGE
-
-#define EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, SizeSuffix) \
-using Eigen::Matrix##SizeSuffix##TypeSuffix; \
-using Eigen::Vector##SizeSuffix##TypeSuffix; \
-using Eigen::RowVector##SizeSuffix##TypeSuffix;
-
-#define EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(TypeSuffix) \
-EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 2) \
-EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 3) \
-EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 4) \
-EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, X) \
-
-#define EIGEN_USING_ARRAY_TYPEDEFS \
-EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(i) \
-EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(f) \
-EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(d) \
-EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(cf) \
-EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(cd)
-
-
-#endif // EIGEN_ARRAY_H
diff --git a/extern/Eigen3/Eigen/src/Core/ArrayBase.h b/extern/Eigen3/Eigen/src/Core/ArrayBase.h
deleted file mode 100644
index 9399ac3d15c..00000000000
--- a/extern/Eigen3/Eigen/src/Core/ArrayBase.h
+++ /dev/null
@@ -1,239 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_ARRAYBASE_H
-#define EIGEN_ARRAYBASE_H
-
-template<typename ExpressionType> class MatrixWrapper;
-
-/** \class ArrayBase
- * \ingroup Core_Module
- *
- * \brief Base class for all 1D and 2D array, and related expressions
- *
- * An array is similar to a dense vector or matrix. While matrices are mathematical
- * objects with well defined linear algebra operators, an array is just a collection
- * of scalar values arranged in a one or two dimensionnal fashion. As the main consequence,
- * all operations applied to an array are performed coefficient wise. Furthermore,
- * arrays support scalar math functions of the c++ standard library (e.g., std::sin(x)), and convenient
- * constructors allowing to easily write generic code working for both scalar values
- * and arrays.
- *
- * This class is the base that is inherited by all array expression types.
- *
- * \tparam Derived is the derived type, e.g., an array or an expression type.
- *
- * 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_ARRAYBASE_PLUGIN.
- *
- * \sa class MatrixBase, \ref TopicClassHierarchy
- */
-template<typename Derived> class ArrayBase
- : public DenseBase<Derived>
-{
- public:
-#ifndef EIGEN_PARSED_BY_DOXYGEN
- /** The base class for a given storage type. */
- typedef ArrayBase StorageBaseType;
-
- 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;
- typedef typename internal::packet_traits<Scalar>::type PacketScalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
- typedef DenseBase<Derived> Base;
- using Base::RowsAtCompileTime;
- using Base::ColsAtCompileTime;
- using Base::SizeAtCompileTime;
- using Base::MaxRowsAtCompileTime;
- using Base::MaxColsAtCompileTime;
- using Base::MaxSizeAtCompileTime;
- using Base::IsVectorAtCompileTime;
- using Base::Flags;
- using Base::CoeffReadCost;
-
- using Base::derived;
- using Base::const_cast_derived;
- using Base::rows;
- using Base::cols;
- using Base::size;
- using Base::coeff;
- using Base::coeffRef;
- using Base::lazyAssign;
- using Base::operator=;
- using Base::operator+=;
- using Base::operator-=;
- using Base::operator*=;
- using Base::operator/=;
-
- typedef typename Base::CoeffReturnType CoeffReturnType;
-
-#endif // not EIGEN_PARSED_BY_DOXYGEN
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
- /** \internal the plain matrix type corresponding to this expression. Note that is not necessarily
- * exactly the return type of eval(): in the case of plain matrices, the return type of eval() is a const
- * reference to a matrix, not a matrix! It is however guaranteed that the return type of eval() is either
- * PlainObject or const PlainObject&.
- */
- typedef Array<typename internal::traits<Derived>::Scalar,
- internal::traits<Derived>::RowsAtCompileTime,
- internal::traits<Derived>::ColsAtCompileTime,
- AutoAlign | (internal::traits<Derived>::Flags&RowMajorBit ? RowMajor : ColMajor),
- internal::traits<Derived>::MaxRowsAtCompileTime,
- internal::traits<Derived>::MaxColsAtCompileTime
- > PlainObject;
-
-
- /** \internal Represents a matrix with all coefficients equal to one another*/
- typedef CwiseNullaryOp<internal::scalar_constant_op<Scalar>,Derived> ConstantReturnType;
-#endif // not EIGEN_PARSED_BY_DOXYGEN
-
-#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::ArrayBase
-# include "../plugins/CommonCwiseUnaryOps.h"
-# include "../plugins/MatrixCwiseUnaryOps.h"
-# include "../plugins/ArrayCwiseUnaryOps.h"
-# include "../plugins/CommonCwiseBinaryOps.h"
-# include "../plugins/MatrixCwiseBinaryOps.h"
-# include "../plugins/ArrayCwiseBinaryOps.h"
-# ifdef EIGEN_ARRAYBASE_PLUGIN
-# include EIGEN_ARRAYBASE_PLUGIN
-# endif
-#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
-
- /** Special case of the template operator=, in order to prevent the compiler
- * from generating a default operator= (issue hit with g++ 4.1)
- */
- Derived& operator=(const ArrayBase& other)
- {
- return internal::assign_selector<Derived,Derived>::run(derived(), other.derived());
- }
-
- Derived& operator+=(const Scalar& scalar)
- { return *this = derived() + scalar; }
- Derived& operator-=(const Scalar& scalar)
- { return *this = derived() - scalar; }
-
- template<typename OtherDerived>
- Derived& operator+=(const ArrayBase<OtherDerived>& other);
- template<typename OtherDerived>
- Derived& operator-=(const ArrayBase<OtherDerived>& other);
-
- template<typename OtherDerived>
- Derived& operator*=(const ArrayBase<OtherDerived>& other);
-
- template<typename OtherDerived>
- Derived& operator/=(const ArrayBase<OtherDerived>& other);
-
- public:
- ArrayBase<Derived>& array() { return *this; }
- const ArrayBase<Derived>& array() const { return *this; }
-
- /** \returns an \link MatrixBase Matrix \endlink expression of this array
- * \sa MatrixBase::array() */
- MatrixWrapper<Derived> matrix() { return derived(); }
- const MatrixWrapper<Derived> matrix() const { return derived(); }
-
-// template<typename Dest>
-// inline void evalTo(Dest& dst) const { dst = matrix(); }
-
- protected:
- ArrayBase() : Base() {}
-
- private:
- explicit ArrayBase(Index);
- ArrayBase(Index,Index);
- template<typename OtherDerived> explicit ArrayBase(const ArrayBase<OtherDerived>&);
- protected:
- // mixing arrays and matrices is not legal
- template<typename OtherDerived> Derived& operator+=(const MatrixBase<OtherDerived>& )
- {EIGEN_STATIC_ASSERT(sizeof(typename OtherDerived::Scalar)==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES);}
- // mixing arrays and matrices is not legal
- template<typename OtherDerived> Derived& operator-=(const MatrixBase<OtherDerived>& )
- {EIGEN_STATIC_ASSERT(sizeof(typename OtherDerived::Scalar)==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES);}
-};
-
-/** replaces \c *this by \c *this - \a other.
- *
- * \returns a reference to \c *this
- */
-template<typename Derived>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE Derived &
-ArrayBase<Derived>::operator-=(const ArrayBase<OtherDerived> &other)
-{
- SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, Derived, OtherDerived> tmp(derived());
- tmp = other.derived();
- return derived();
-}
-
-/** replaces \c *this by \c *this + \a other.
- *
- * \returns a reference to \c *this
- */
-template<typename Derived>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE Derived &
-ArrayBase<Derived>::operator+=(const ArrayBase<OtherDerived>& other)
-{
- SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, Derived, OtherDerived> tmp(derived());
- tmp = other.derived();
- return derived();
-}
-
-/** replaces \c *this by \c *this * \a other coefficient wise.
- *
- * \returns a reference to \c *this
- */
-template<typename Derived>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE Derived &
-ArrayBase<Derived>::operator*=(const ArrayBase<OtherDerived>& other)
-{
- SelfCwiseBinaryOp<internal::scalar_product_op<Scalar>, Derived, OtherDerived> tmp(derived());
- tmp = other.derived();
- return derived();
-}
-
-/** replaces \c *this by \c *this / \a other coefficient wise.
- *
- * \returns a reference to \c *this
- */
-template<typename Derived>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE Derived &
-ArrayBase<Derived>::operator/=(const ArrayBase<OtherDerived>& other)
-{
- SelfCwiseBinaryOp<internal::scalar_quotient_op<Scalar>, Derived, OtherDerived> tmp(derived());
- tmp = other.derived();
- return derived();
-}
-
-#endif // EIGEN_ARRAYBASE_H
diff --git a/extern/Eigen3/Eigen/src/Core/ArrayWrapper.h b/extern/Eigen3/Eigen/src/Core/ArrayWrapper.h
deleted file mode 100644
index 07f082e1edc..00000000000
--- a/extern/Eigen3/Eigen/src/Core/ArrayWrapper.h
+++ /dev/null
@@ -1,239 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_ARRAYWRAPPER_H
-#define EIGEN_ARRAYWRAPPER_H
-
-/** \class ArrayWrapper
- * \ingroup Core_Module
- *
- * \brief Expression of a mathematical vector or matrix as an array object
- *
- * This class is the return type of MatrixBase::array(), and most of the time
- * this is the only way it is use.
- *
- * \sa MatrixBase::array(), class MatrixWrapper
- */
-
-namespace internal {
-template<typename ExpressionType>
-struct traits<ArrayWrapper<ExpressionType> >
- : public traits<typename remove_all<typename ExpressionType::Nested>::type >
-{
- typedef ArrayXpr XprKind;
-};
-}
-
-template<typename ExpressionType>
-class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
-{
- public:
- typedef ArrayBase<ArrayWrapper> Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(ArrayWrapper)
- EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ArrayWrapper)
-
- typedef typename internal::conditional<
- internal::is_lvalue<ExpressionType>::value,
- Scalar,
- const Scalar
- >::type ScalarWithConstIfNotLvalue;
-
- typedef typename internal::nested<ExpressionType>::type NestedExpressionType;
-
- inline ArrayWrapper(const ExpressionType& matrix) : m_expression(matrix) {}
-
- inline Index rows() const { return m_expression.rows(); }
- inline Index cols() const { return m_expression.cols(); }
- inline Index outerStride() const { return m_expression.outerStride(); }
- inline Index innerStride() const { return m_expression.innerStride(); }
-
- inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
- inline const Scalar* data() const { return m_expression.data(); }
-
- inline const CoeffReturnType coeff(Index row, Index col) const
- {
- return m_expression.coeff(row, col);
- }
-
- inline Scalar& coeffRef(Index row, Index col)
- {
- return m_expression.const_cast_derived().coeffRef(row, col);
- }
-
- inline const Scalar& coeffRef(Index row, Index col) const
- {
- return m_expression.const_cast_derived().coeffRef(row, col);
- }
-
- inline const CoeffReturnType coeff(Index index) const
- {
- return m_expression.coeff(index);
- }
-
- inline Scalar& coeffRef(Index index)
- {
- return m_expression.const_cast_derived().coeffRef(index);
- }
-
- inline const Scalar& coeffRef(Index index) const
- {
- return m_expression.const_cast_derived().coeffRef(index);
- }
-
- template<int LoadMode>
- inline const PacketScalar packet(Index row, Index col) const
- {
- return m_expression.template packet<LoadMode>(row, col);
- }
-
- template<int LoadMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
- {
- m_expression.const_cast_derived().template writePacket<LoadMode>(row, col, x);
- }
-
- template<int LoadMode>
- inline const PacketScalar packet(Index index) const
- {
- return m_expression.template packet<LoadMode>(index);
- }
-
- template<int LoadMode>
- inline void writePacket(Index index, const PacketScalar& x)
- {
- m_expression.const_cast_derived().template writePacket<LoadMode>(index, x);
- }
-
- template<typename Dest>
- inline void evalTo(Dest& dst) const { dst = m_expression; }
-
- protected:
- const NestedExpressionType m_expression;
-};
-
-/** \class MatrixWrapper
- * \ingroup Core_Module
- *
- * \brief Expression of an array as a mathematical vector or matrix
- *
- * This class is the return type of ArrayBase::matrix(), and most of the time
- * this is the only way it is use.
- *
- * \sa MatrixBase::matrix(), class ArrayWrapper
- */
-
-namespace internal {
-template<typename ExpressionType>
-struct traits<MatrixWrapper<ExpressionType> >
- : public traits<typename remove_all<typename ExpressionType::Nested>::type >
-{
- typedef MatrixXpr XprKind;
-};
-}
-
-template<typename ExpressionType>
-class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
-{
- public:
- typedef MatrixBase<MatrixWrapper<ExpressionType> > Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(MatrixWrapper)
- EIGEN_INHERIT_ASSIGNMENT_OPERATORS(MatrixWrapper)
-
- typedef typename internal::conditional<
- internal::is_lvalue<ExpressionType>::value,
- Scalar,
- const Scalar
- >::type ScalarWithConstIfNotLvalue;
-
- typedef typename internal::nested<ExpressionType>::type NestedExpressionType;
-
- inline MatrixWrapper(const ExpressionType& matrix) : m_expression(matrix) {}
-
- inline Index rows() const { return m_expression.rows(); }
- inline Index cols() const { return m_expression.cols(); }
- inline Index outerStride() const { return m_expression.outerStride(); }
- inline Index innerStride() const { return m_expression.innerStride(); }
-
- inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); }
- inline const Scalar* data() const { return m_expression.data(); }
-
- inline const CoeffReturnType coeff(Index row, Index col) const
- {
- return m_expression.coeff(row, col);
- }
-
- inline Scalar& coeffRef(Index row, Index col)
- {
- return m_expression.const_cast_derived().coeffRef(row, col);
- }
-
- inline const Scalar& coeffRef(Index row, Index col) const
- {
- return m_expression.derived().coeffRef(row, col);
- }
-
- inline const CoeffReturnType coeff(Index index) const
- {
- return m_expression.coeff(index);
- }
-
- inline Scalar& coeffRef(Index index)
- {
- return m_expression.const_cast_derived().coeffRef(index);
- }
-
- inline const Scalar& coeffRef(Index index) const
- {
- return m_expression.const_cast_derived().coeffRef(index);
- }
-
- template<int LoadMode>
- inline const PacketScalar packet(Index row, Index col) const
- {
- return m_expression.template packet<LoadMode>(row, col);
- }
-
- template<int LoadMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
- {
- m_expression.const_cast_derived().template writePacket<LoadMode>(row, col, x);
- }
-
- template<int LoadMode>
- inline const PacketScalar packet(Index index) const
- {
- return m_expression.template packet<LoadMode>(index);
- }
-
- template<int LoadMode>
- inline void writePacket(Index index, const PacketScalar& x)
- {
- m_expression.const_cast_derived().template writePacket<LoadMode>(index, x);
- }
-
- protected:
- const NestedExpressionType m_expression;
-};
-
-#endif // EIGEN_ARRAYWRAPPER_H
diff --git a/extern/Eigen3/Eigen/src/Core/Assign.h b/extern/Eigen3/Eigen/src/Core/Assign.h
deleted file mode 100644
index 3a17152f043..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Assign.h
+++ /dev/null
@@ -1,593 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2007 Michael Olbrich <michael.olbrich@gmx.net>
-// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_ASSIGN_H
-#define EIGEN_ASSIGN_H
-
-namespace internal {
-
-/***************************************************************************
-* Part 1 : the logic deciding a strategy for traversal and unrolling *
-***************************************************************************/
-
-template <typename Derived, typename OtherDerived>
-struct assign_traits
-{
-public:
- enum {
- DstIsAligned = Derived::Flags & AlignedBit,
- DstHasDirectAccess = Derived::Flags & DirectAccessBit,
- SrcIsAligned = OtherDerived::Flags & AlignedBit,
- JointAlignment = bool(DstIsAligned) && bool(SrcIsAligned) ? Aligned : Unaligned
- };
-
-private:
- enum {
- InnerSize = int(Derived::IsVectorAtCompileTime) ? int(Derived::SizeAtCompileTime)
- : int(Derived::Flags)&RowMajorBit ? int(Derived::ColsAtCompileTime)
- : int(Derived::RowsAtCompileTime),
- InnerMaxSize = int(Derived::IsVectorAtCompileTime) ? int(Derived::MaxSizeAtCompileTime)
- : int(Derived::Flags)&RowMajorBit ? int(Derived::MaxColsAtCompileTime)
- : int(Derived::MaxRowsAtCompileTime),
- MaxSizeAtCompileTime = Derived::SizeAtCompileTime,
- PacketSize = packet_traits<typename Derived::Scalar>::size
- };
-
- enum {
- StorageOrdersAgree = (int(Derived::IsRowMajor) == int(OtherDerived::IsRowMajor)),
- MightVectorize = StorageOrdersAgree
- && (int(Derived::Flags) & int(OtherDerived::Flags) & ActualPacketAccessBit),
- MayInnerVectorize = MightVectorize && int(InnerSize)!=Dynamic && int(InnerSize)%int(PacketSize)==0
- && int(DstIsAligned) && int(SrcIsAligned),
- MayLinearize = StorageOrdersAgree && (int(Derived::Flags) & int(OtherDerived::Flags) & LinearAccessBit),
- MayLinearVectorize = MightVectorize && MayLinearize && DstHasDirectAccess
- && (DstIsAligned || MaxSizeAtCompileTime == Dynamic),
- /* If the destination isn't aligned, we have to do runtime checks and we don't unroll,
- so it's only good for large enough sizes. */
- MaySliceVectorize = MightVectorize && DstHasDirectAccess
- && (int(InnerMaxSize)==Dynamic || int(InnerMaxSize)>=3*PacketSize)
- /* slice vectorization can be slow, so we only want it if the slices are big, which is
- indicated by InnerMaxSize rather than InnerSize, think of the case of a dynamic block
- in a fixed-size matrix */
- };
-
-public:
- enum {
- Traversal = int(MayInnerVectorize) ? int(InnerVectorizedTraversal)
- : int(MayLinearVectorize) ? int(LinearVectorizedTraversal)
- : int(MaySliceVectorize) ? int(SliceVectorizedTraversal)
- : int(MayLinearize) ? int(LinearTraversal)
- : int(DefaultTraversal),
- Vectorized = int(Traversal) == InnerVectorizedTraversal
- || int(Traversal) == LinearVectorizedTraversal
- || int(Traversal) == SliceVectorizedTraversal
- };
-
-private:
- enum {
- UnrollingLimit = EIGEN_UNROLLING_LIMIT * (Vectorized ? int(PacketSize) : 1),
- MayUnrollCompletely = int(Derived::SizeAtCompileTime) != Dynamic
- && int(OtherDerived::CoeffReadCost) != Dynamic
- && int(Derived::SizeAtCompileTime) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit),
- MayUnrollInner = int(InnerSize) != Dynamic
- && int(OtherDerived::CoeffReadCost) != Dynamic
- && int(InnerSize) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit)
- };
-
-public:
- enum {
- Unrolling = (int(Traversal) == int(InnerVectorizedTraversal) || int(Traversal) == int(DefaultTraversal))
- ? (
- int(MayUnrollCompletely) ? int(CompleteUnrolling)
- : int(MayUnrollInner) ? int(InnerUnrolling)
- : int(NoUnrolling)
- )
- : int(Traversal) == int(LinearVectorizedTraversal)
- ? ( bool(MayUnrollCompletely) && bool(DstIsAligned) ? int(CompleteUnrolling) : int(NoUnrolling) )
- : int(Traversal) == int(LinearTraversal)
- ? ( bool(MayUnrollCompletely) ? int(CompleteUnrolling) : int(NoUnrolling) )
- : int(NoUnrolling)
- };
-
-#ifdef EIGEN_DEBUG_ASSIGN
- static void debug()
- {
- EIGEN_DEBUG_VAR(DstIsAligned)
- EIGEN_DEBUG_VAR(SrcIsAligned)
- EIGEN_DEBUG_VAR(JointAlignment)
- EIGEN_DEBUG_VAR(InnerSize)
- EIGEN_DEBUG_VAR(InnerMaxSize)
- EIGEN_DEBUG_VAR(PacketSize)
- EIGEN_DEBUG_VAR(StorageOrdersAgree)
- EIGEN_DEBUG_VAR(MightVectorize)
- EIGEN_DEBUG_VAR(MayLinearize)
- EIGEN_DEBUG_VAR(MayInnerVectorize)
- EIGEN_DEBUG_VAR(MayLinearVectorize)
- EIGEN_DEBUG_VAR(MaySliceVectorize)
- EIGEN_DEBUG_VAR(Traversal)
- EIGEN_DEBUG_VAR(UnrollingLimit)
- EIGEN_DEBUG_VAR(MayUnrollCompletely)
- EIGEN_DEBUG_VAR(MayUnrollInner)
- EIGEN_DEBUG_VAR(Unrolling)
- }
-#endif
-};
-
-/***************************************************************************
-* Part 2 : meta-unrollers
-***************************************************************************/
-
-/************************
-*** Default traversal ***
-************************/
-
-template<typename Derived1, typename Derived2, int Index, int Stop>
-struct assign_DefaultTraversal_CompleteUnrolling
-{
- enum {
- outer = Index / Derived1::InnerSizeAtCompileTime,
- inner = Index % Derived1::InnerSizeAtCompileTime
- };
-
- EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
- {
- dst.copyCoeffByOuterInner(outer, inner, src);
- assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src);
- }
-};
-
-template<typename Derived1, typename Derived2, int Stop>
-struct assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
-{
- EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &) {}
-};
-
-template<typename Derived1, typename Derived2, int Index, int Stop>
-struct assign_DefaultTraversal_InnerUnrolling
-{
- EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src, int outer)
- {
- dst.copyCoeffByOuterInner(outer, Index, src);
- assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src, outer);
- }
-};
-
-template<typename Derived1, typename Derived2, int Stop>
-struct assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Stop, Stop>
-{
- EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &, int) {}
-};
-
-/***********************
-*** Linear traversal ***
-***********************/
-
-template<typename Derived1, typename Derived2, int Index, int Stop>
-struct assign_LinearTraversal_CompleteUnrolling
-{
- EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
- {
- dst.copyCoeff(Index, src);
- assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src);
- }
-};
-
-template<typename Derived1, typename Derived2, int Stop>
-struct assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
-{
- EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &) {}
-};
-
-/**************************
-*** Inner vectorization ***
-**************************/
-
-template<typename Derived1, typename Derived2, int Index, int Stop>
-struct assign_innervec_CompleteUnrolling
-{
- enum {
- outer = Index / Derived1::InnerSizeAtCompileTime,
- inner = Index % Derived1::InnerSizeAtCompileTime,
- JointAlignment = assign_traits<Derived1,Derived2>::JointAlignment
- };
-
- EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
- {
- dst.template copyPacketByOuterInner<Derived2, Aligned, JointAlignment>(outer, inner, src);
- assign_innervec_CompleteUnrolling<Derived1, Derived2,
- Index+packet_traits<typename Derived1::Scalar>::size, Stop>::run(dst, src);
- }
-};
-
-template<typename Derived1, typename Derived2, int Stop>
-struct assign_innervec_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
-{
- EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &) {}
-};
-
-template<typename Derived1, typename Derived2, int Index, int Stop>
-struct assign_innervec_InnerUnrolling
-{
- EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src, int outer)
- {
- dst.template copyPacketByOuterInner<Derived2, Aligned, Aligned>(outer, Index, src);
- assign_innervec_InnerUnrolling<Derived1, Derived2,
- Index+packet_traits<typename Derived1::Scalar>::size, Stop>::run(dst, src, outer);
- }
-};
-
-template<typename Derived1, typename Derived2, int Stop>
-struct assign_innervec_InnerUnrolling<Derived1, Derived2, Stop, Stop>
-{
- EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &, int) {}
-};
-
-/***************************************************************************
-* Part 3 : implementation of all cases
-***************************************************************************/
-
-template<typename Derived1, typename Derived2,
- int Traversal = assign_traits<Derived1, Derived2>::Traversal,
- int Unrolling = assign_traits<Derived1, Derived2>::Unrolling>
-struct assign_impl;
-
-/************************
-*** Default traversal ***
-************************/
-
-template<typename Derived1, typename Derived2, int Unrolling>
-struct assign_impl<Derived1, Derived2, InvalidTraversal, Unrolling>
-{
- inline static void run(Derived1 &, const Derived2 &) { }
-};
-
-template<typename Derived1, typename Derived2>
-struct assign_impl<Derived1, Derived2, DefaultTraversal, NoUnrolling>
-{
- typedef typename Derived1::Index Index;
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- const Index innerSize = dst.innerSize();
- const Index outerSize = dst.outerSize();
- for(Index outer = 0; outer < outerSize; ++outer)
- for(Index inner = 0; inner < innerSize; ++inner)
- dst.copyCoeffByOuterInner(outer, inner, src);
- }
-};
-
-template<typename Derived1, typename Derived2>
-struct assign_impl<Derived1, Derived2, DefaultTraversal, CompleteUnrolling>
-{
- EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
- {
- assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
- ::run(dst, src);
- }
-};
-
-template<typename Derived1, typename Derived2>
-struct assign_impl<Derived1, Derived2, DefaultTraversal, InnerUnrolling>
-{
- typedef typename Derived1::Index Index;
- EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
- {
- const Index outerSize = dst.outerSize();
- for(Index outer = 0; outer < outerSize; ++outer)
- assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, 0, Derived1::InnerSizeAtCompileTime>
- ::run(dst, src, outer);
- }
-};
-
-/***********************
-*** Linear traversal ***
-***********************/
-
-template<typename Derived1, typename Derived2>
-struct assign_impl<Derived1, Derived2, LinearTraversal, NoUnrolling>
-{
- typedef typename Derived1::Index Index;
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- const Index size = dst.size();
- for(Index i = 0; i < size; ++i)
- dst.copyCoeff(i, src);
- }
-};
-
-template<typename Derived1, typename Derived2>
-struct assign_impl<Derived1, Derived2, LinearTraversal, CompleteUnrolling>
-{
- EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
- {
- assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
- ::run(dst, src);
- }
-};
-
-/**************************
-*** Inner vectorization ***
-**************************/
-
-template<typename Derived1, typename Derived2>
-struct assign_impl<Derived1, Derived2, InnerVectorizedTraversal, NoUnrolling>
-{
- typedef typename Derived1::Index Index;
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- const Index innerSize = dst.innerSize();
- const Index outerSize = dst.outerSize();
- const Index packetSize = packet_traits<typename Derived1::Scalar>::size;
- for(Index outer = 0; outer < outerSize; ++outer)
- for(Index inner = 0; inner < innerSize; inner+=packetSize)
- dst.template copyPacketByOuterInner<Derived2, Aligned, Aligned>(outer, inner, src);
- }
-};
-
-template<typename Derived1, typename Derived2>
-struct assign_impl<Derived1, Derived2, InnerVectorizedTraversal, CompleteUnrolling>
-{
- EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
- {
- assign_innervec_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
- ::run(dst, src);
- }
-};
-
-template<typename Derived1, typename Derived2>
-struct assign_impl<Derived1, Derived2, InnerVectorizedTraversal, InnerUnrolling>
-{
- typedef typename Derived1::Index Index;
- EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
- {
- const Index outerSize = dst.outerSize();
- for(Index outer = 0; outer < outerSize; ++outer)
- assign_innervec_InnerUnrolling<Derived1, Derived2, 0, Derived1::InnerSizeAtCompileTime>
- ::run(dst, src, outer);
- }
-};
-
-/***************************
-*** Linear vectorization ***
-***************************/
-
-template <bool IsAligned = false>
-struct unaligned_assign_impl
-{
- template <typename Derived, typename OtherDerived>
- static EIGEN_STRONG_INLINE void run(const Derived&, OtherDerived&, typename Derived::Index, typename Derived::Index) {}
-};
-
-template <>
-struct unaligned_assign_impl<false>
-{
- // MSVC must not inline this functions. If it does, it fails to optimize the
- // packet access path.
-#ifdef _MSC_VER
- template <typename Derived, typename OtherDerived>
- static EIGEN_DONT_INLINE void run(const Derived& src, OtherDerived& dst, typename Derived::Index start, typename Derived::Index end)
-#else
- template <typename Derived, typename OtherDerived>
- static EIGEN_STRONG_INLINE void run(const Derived& src, OtherDerived& dst, typename Derived::Index start, typename Derived::Index end)
-#endif
- {
- for (typename Derived::Index index = start; index < end; ++index)
- dst.copyCoeff(index, src);
- }
-};
-
-template<typename Derived1, typename Derived2>
-struct assign_impl<Derived1, Derived2, LinearVectorizedTraversal, NoUnrolling>
-{
- typedef typename Derived1::Index Index;
- EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
- {
- const Index size = dst.size();
- typedef packet_traits<typename Derived1::Scalar> PacketTraits;
- enum {
- packetSize = PacketTraits::size,
- dstAlignment = PacketTraits::AlignedOnScalar ? Aligned : int(assign_traits<Derived1,Derived2>::DstIsAligned) ,
- srcAlignment = assign_traits<Derived1,Derived2>::JointAlignment
- };
- const Index alignedStart = assign_traits<Derived1,Derived2>::DstIsAligned ? 0
- : first_aligned(&dst.coeffRef(0), size);
- const Index alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize;
-
- unaligned_assign_impl<assign_traits<Derived1,Derived2>::DstIsAligned!=0>::run(src,dst,0,alignedStart);
-
- for(Index index = alignedStart; index < alignedEnd; index += packetSize)
- {
- dst.template copyPacket<Derived2, dstAlignment, srcAlignment>(index, src);
- }
-
- unaligned_assign_impl<>::run(src,dst,alignedEnd,size);
- }
-};
-
-template<typename Derived1, typename Derived2>
-struct assign_impl<Derived1, Derived2, LinearVectorizedTraversal, CompleteUnrolling>
-{
- typedef typename Derived1::Index Index;
- EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
- {
- enum { size = Derived1::SizeAtCompileTime,
- packetSize = packet_traits<typename Derived1::Scalar>::size,
- alignedSize = (size/packetSize)*packetSize };
-
- assign_innervec_CompleteUnrolling<Derived1, Derived2, 0, alignedSize>::run(dst, src);
- assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, alignedSize, size>::run(dst, src);
- }
-};
-
-/**************************
-*** Slice vectorization ***
-***************************/
-
-template<typename Derived1, typename Derived2>
-struct assign_impl<Derived1, Derived2, SliceVectorizedTraversal, NoUnrolling>
-{
- typedef typename Derived1::Index Index;
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- typedef packet_traits<typename Derived1::Scalar> PacketTraits;
- enum {
- packetSize = PacketTraits::size,
- alignable = PacketTraits::AlignedOnScalar,
- dstAlignment = alignable ? Aligned : int(assign_traits<Derived1,Derived2>::DstIsAligned) ,
- srcAlignment = assign_traits<Derived1,Derived2>::JointAlignment
- };
- 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
- : first_aligned(&dst.coeffRef(0,0), innerSize);
-
- for(Index outer = 0; outer < outerSize; ++outer)
- {
- const Index alignedEnd = alignedStart + ((innerSize-alignedStart) & ~packetAlignedMask);
- // do the non-vectorizable part of the assignment
- for(Index inner = 0; inner<alignedStart ; ++inner)
- dst.copyCoeffByOuterInner(outer, inner, src);
-
- // do the vectorizable part of the assignment
- for(Index inner = alignedStart; inner<alignedEnd; inner+=packetSize)
- dst.template copyPacketByOuterInner<Derived2, dstAlignment, Unaligned>(outer, inner, src);
-
- // do the non-vectorizable part of the assignment
- for(Index inner = alignedEnd; inner<innerSize ; ++inner)
- dst.copyCoeffByOuterInner(outer, inner, src);
-
- alignedStart = std::min<Index>((alignedStart+alignedStep)%packetSize, innerSize);
- }
- }
-};
-
-} // end namespace internal
-
-/***************************************************************************
-* Part 4 : implementation of DenseBase methods
-***************************************************************************/
-
-template<typename Derived>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE Derived& DenseBase<Derived>
- ::lazyAssign(const DenseBase<OtherDerived>& other)
-{
- enum{
- SameType = internal::is_same<typename Derived::Scalar,typename OtherDerived::Scalar>::value
- };
-
- EIGEN_STATIC_ASSERT_LVALUE(Derived)
- EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived)
- EIGEN_STATIC_ASSERT(SameType,YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
-
-#ifdef EIGEN_DEBUG_ASSIGN
- internal::assign_traits<Derived, OtherDerived>::debug();
-#endif
- eigen_assert(rows() == other.rows() && cols() == other.cols());
- internal::assign_impl<Derived, OtherDerived, int(SameType) ? int(internal::assign_traits<Derived, OtherDerived>::Traversal)
- : int(InvalidTraversal)>::run(derived(),other.derived());
-#ifndef EIGEN_NO_DEBUG
- checkTransposeAliasing(other.derived());
-#endif
- return derived();
-}
-
-namespace internal {
-
-template<typename Derived, typename OtherDerived,
- bool EvalBeforeAssigning = (int(OtherDerived::Flags) & EvalBeforeAssigningBit) != 0,
- bool NeedToTranspose = Derived::IsVectorAtCompileTime
- && OtherDerived::IsVectorAtCompileTime
- && ((int(Derived::RowsAtCompileTime) == 1 && int(OtherDerived::ColsAtCompileTime) == 1)
- | // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
- // revert to || as soon as not needed anymore.
- (int(Derived::ColsAtCompileTime) == 1 && int(OtherDerived::RowsAtCompileTime) == 1))
- && int(Derived::SizeAtCompileTime) != 1>
-struct assign_selector;
-
-template<typename Derived, typename OtherDerived>
-struct assign_selector<Derived,OtherDerived,false,false> {
- EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); }
-};
-template<typename Derived, typename OtherDerived>
-struct assign_selector<Derived,OtherDerived,true,false> {
- EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); }
-};
-template<typename Derived, typename OtherDerived>
-struct assign_selector<Derived,OtherDerived,false,true> {
- EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); }
-};
-template<typename Derived, typename OtherDerived>
-struct assign_selector<Derived,OtherDerived,true,true> {
- EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); }
-};
-
-} // end namespace internal
-
-template<typename Derived>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase<OtherDerived>& other)
-{
- return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
-}
-
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase& other)
-{
- return internal::assign_selector<Derived,Derived>::run(derived(), other.derived());
-}
-
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const MatrixBase& other)
-{
- return internal::assign_selector<Derived,Derived>::run(derived(), other.derived());
-}
-
-template<typename Derived>
-template <typename OtherDerived>
-EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const DenseBase<OtherDerived>& other)
-{
- return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
-}
-
-template<typename Derived>
-template <typename OtherDerived>
-EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const EigenBase<OtherDerived>& other)
-{
- other.derived().evalTo(derived());
- return derived();
-}
-
-template<typename Derived>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
-{
- other.evalTo(derived());
- return derived();
-}
-
-#endif // EIGEN_ASSIGN_H
diff --git a/extern/Eigen3/Eigen/src/Core/BandMatrix.h b/extern/Eigen3/Eigen/src/Core/BandMatrix.h
deleted file mode 100644
index 2570d7b559f..00000000000
--- a/extern/Eigen3/Eigen/src/Core/BandMatrix.h
+++ /dev/null
@@ -1,346 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_BANDMATRIX_H
-#define EIGEN_BANDMATRIX_H
-
-namespace internal {
-
-
-template<typename Derived>
-class BandMatrixBase : public EigenBase<Derived>
-{
- public:
-
- enum {
- Flags = internal::traits<Derived>::Flags,
- CoeffReadCost = internal::traits<Derived>::CoeffReadCost,
- RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
- ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
- MaxRowsAtCompileTime = internal::traits<Derived>::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = internal::traits<Derived>::MaxColsAtCompileTime,
- Supers = internal::traits<Derived>::Supers,
- Subs = internal::traits<Derived>::Subs,
- Options = internal::traits<Derived>::Options
- };
- typedef typename internal::traits<Derived>::Scalar Scalar;
- typedef Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime> DenseMatrixType;
- typedef typename DenseMatrixType::Index Index;
- typedef typename internal::traits<Derived>::CoefficientsType CoefficientsType;
- typedef EigenBase<Derived> Base;
-
- protected:
- enum {
- DataRowsAtCompileTime = ((Supers!=Dynamic) && (Subs!=Dynamic))
- ? 1 + Supers + Subs
- : Dynamic,
- SizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime,ColsAtCompileTime)
- };
-
- public:
-
- using Base::derived;
- using Base::rows;
- using Base::cols;
-
- /** \returns the number of super diagonals */
- inline Index supers() const { return derived().supers(); }
-
- /** \returns the number of sub diagonals */
- inline Index subs() const { return derived().subs(); }
-
- /** \returns an expression of the underlying coefficient matrix */
- inline const CoefficientsType& coeffs() const { return derived().coeffs(); }
-
- /** \returns an expression of the underlying coefficient matrix */
- inline CoefficientsType& coeffs() { return derived().coeffs(); }
-
- /** \returns a vector expression of the \a i -th column,
- * only the meaningful part is returned.
- * \warning the internal storage must be column major. */
- inline Block<CoefficientsType,Dynamic,1> col(Index i)
- {
- EIGEN_STATIC_ASSERT((Options&RowMajor)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
- Index start = 0;
- Index len = coeffs().rows();
- if (i<=supers())
- {
- start = supers()-i;
- len = (std::min)(rows(),std::max<Index>(0,coeffs().rows() - (supers()-i)));
- }
- else if (i>=rows()-subs())
- len = std::max<Index>(0,coeffs().rows() - (i + 1 - rows() + subs()));
- return Block<CoefficientsType,Dynamic,1>(coeffs(), start, i, len, 1);
- }
-
- /** \returns a vector expression of the main diagonal */
- inline Block<CoefficientsType,1,SizeAtCompileTime> diagonal()
- { return Block<CoefficientsType,1,SizeAtCompileTime>(coeffs(),supers(),0,1,(std::min)(rows(),cols())); }
-
- /** \returns a vector expression of the main diagonal (const version) */
- inline const Block<const CoefficientsType,1,SizeAtCompileTime> diagonal() const
- { return Block<const CoefficientsType,1,SizeAtCompileTime>(coeffs(),supers(),0,1,(std::min)(rows(),cols())); }
-
- template<int Index> struct DiagonalIntReturnType {
- enum {
- ReturnOpposite = (Options&SelfAdjoint) && (((Index)>0 && Supers==0) || ((Index)<0 && Subs==0)),
- Conjugate = ReturnOpposite && NumTraits<Scalar>::IsComplex,
- ActualIndex = ReturnOpposite ? -Index : Index,
- DiagonalSize = (RowsAtCompileTime==Dynamic || ColsAtCompileTime==Dynamic)
- ? Dynamic
- : (ActualIndex<0
- ? EIGEN_SIZE_MIN_PREFER_DYNAMIC(ColsAtCompileTime, RowsAtCompileTime + ActualIndex)
- : EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime, ColsAtCompileTime - ActualIndex))
- };
- typedef Block<CoefficientsType,1, DiagonalSize> BuildType;
- typedef typename internal::conditional<Conjugate,
- CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>,BuildType >,
- BuildType>::type Type;
- };
-
- /** \returns a vector expression of the \a N -th sub or super diagonal */
- template<int N> inline typename DiagonalIntReturnType<N>::Type diagonal()
- {
- return typename DiagonalIntReturnType<N>::BuildType(coeffs(), supers()-N, (std::max)(0,N), 1, diagonalLength(N));
- }
-
- /** \returns a vector expression of the \a N -th sub or super diagonal */
- template<int N> inline const typename DiagonalIntReturnType<N>::Type diagonal() const
- {
- return typename DiagonalIntReturnType<N>::BuildType(coeffs(), supers()-N, (std::max)(0,N), 1, diagonalLength(N));
- }
-
- /** \returns a vector expression of the \a i -th sub or super diagonal */
- inline Block<CoefficientsType,1,Dynamic> diagonal(Index i)
- {
- eigen_assert((i<0 && -i<=subs()) || (i>=0 && i<=supers()));
- return Block<CoefficientsType,1,Dynamic>(coeffs(), supers()-i, std::max<Index>(0,i), 1, diagonalLength(i));
- }
-
- /** \returns a vector expression of the \a i -th sub or super diagonal */
- inline const Block<const CoefficientsType,1,Dynamic> diagonal(Index i) const
- {
- eigen_assert((i<0 && -i<=subs()) || (i>=0 && i<=supers()));
- return Block<const CoefficientsType,1,Dynamic>(coeffs(), supers()-i, std::max<Index>(0,i), 1, diagonalLength(i));
- }
-
- template<typename Dest> inline void evalTo(Dest& dst) const
- {
- dst.resize(rows(),cols());
- dst.setZero();
- dst.diagonal() = diagonal();
- for (Index i=1; i<=supers();++i)
- dst.diagonal(i) = diagonal(i);
- for (Index i=1; i<=subs();++i)
- dst.diagonal(-i) = diagonal(-i);
- }
-
- DenseMatrixType toDenseMatrix() const
- {
- DenseMatrixType res(rows(),cols());
- evalTo(res);
- return res;
- }
-
- protected:
-
- inline Index diagonalLength(Index i) const
- { return i<0 ? (std::min)(cols(),rows()+i) : (std::min)(rows(),cols()-i); }
-};
-
-/**
- * \class BandMatrix
- * \ingroup Core_Module
- *
- * \brief Represents a rectangular matrix with a banded storage
- *
- * \param _Scalar Numeric type, i.e. float, double, int
- * \param Rows Number of rows, or \b Dynamic
- * \param Cols Number of columns, or \b Dynamic
- * \param Supers Number of super diagonal
- * \param Subs Number of sub diagonal
- * \param _Options A combination of either \b #RowMajor or \b #ColMajor, and of \b #SelfAdjoint
- * The former controls \ref TopicStorageOrders "storage order", and defaults to
- * column-major. The latter controls whether the matrix represents a selfadjoint
- * matrix in which case either Supers of Subs have to be null.
- *
- * \sa class TridiagonalMatrix
- */
-
-template<typename _Scalar, int _Rows, int _Cols, int _Supers, int _Subs, int _Options>
-struct traits<BandMatrix<_Scalar,_Rows,_Cols,_Supers,_Subs,_Options> >
-{
- typedef _Scalar Scalar;
- typedef Dense StorageKind;
- typedef DenseIndex Index;
- enum {
- CoeffReadCost = NumTraits<Scalar>::ReadCost,
- RowsAtCompileTime = _Rows,
- ColsAtCompileTime = _Cols,
- MaxRowsAtCompileTime = _Rows,
- MaxColsAtCompileTime = _Cols,
- Flags = LvalueBit,
- Supers = _Supers,
- Subs = _Subs,
- Options = _Options,
- DataRowsAtCompileTime = ((Supers!=Dynamic) && (Subs!=Dynamic)) ? 1 + Supers + Subs : Dynamic
- };
- typedef Matrix<Scalar,DataRowsAtCompileTime,ColsAtCompileTime,Options&RowMajor?RowMajor:ColMajor> CoefficientsType;
-};
-
-template<typename _Scalar, int Rows, int Cols, int Supers, int Subs, int Options>
-class BandMatrix : public BandMatrixBase<BandMatrix<_Scalar,Rows,Cols,Supers,Subs,Options> >
-{
- public:
-
- typedef typename internal::traits<BandMatrix>::Scalar Scalar;
- typedef typename internal::traits<BandMatrix>::Index Index;
- typedef typename internal::traits<BandMatrix>::CoefficientsType CoefficientsType;
-
- inline BandMatrix(Index rows=Rows, Index cols=Cols, Index supers=Supers, Index subs=Subs)
- : m_coeffs(1+supers+subs,cols),
- m_rows(rows), m_supers(supers), m_subs(subs)
- {
- }
-
- /** \returns the number of columns */
- inline Index rows() const { return m_rows.value(); }
-
- /** \returns the number of rows */
- inline Index cols() const { return m_coeffs.cols(); }
-
- /** \returns the number of super diagonals */
- inline Index supers() const { return m_supers.value(); }
-
- /** \returns the number of sub diagonals */
- inline Index subs() const { return m_subs.value(); }
-
- inline const CoefficientsType& coeffs() const { return m_coeffs; }
- inline CoefficientsType& coeffs() { return m_coeffs; }
-
- protected:
-
- CoefficientsType m_coeffs;
- internal::variable_if_dynamic<Index, Rows> m_rows;
- internal::variable_if_dynamic<Index, Supers> m_supers;
- internal::variable_if_dynamic<Index, Subs> m_subs;
-};
-
-template<typename _CoefficientsType,int _Rows, int _Cols, int _Supers, int _Subs,int _Options>
-class BandMatrixWrapper;
-
-template<typename _CoefficientsType,int _Rows, int _Cols, int _Supers, int _Subs,int _Options>
-struct traits<BandMatrixWrapper<_CoefficientsType,_Rows,_Cols,_Supers,_Subs,_Options> >
-{
- typedef typename _CoefficientsType::Scalar Scalar;
- typedef typename _CoefficientsType::StorageKind StorageKind;
- typedef typename _CoefficientsType::Index Index;
- enum {
- CoeffReadCost = internal::traits<_CoefficientsType>::CoeffReadCost,
- RowsAtCompileTime = _Rows,
- ColsAtCompileTime = _Cols,
- MaxRowsAtCompileTime = _Rows,
- MaxColsAtCompileTime = _Cols,
- Flags = LvalueBit,
- Supers = _Supers,
- Subs = _Subs,
- Options = _Options,
- DataRowsAtCompileTime = ((Supers!=Dynamic) && (Subs!=Dynamic)) ? 1 + Supers + Subs : Dynamic
- };
- typedef _CoefficientsType CoefficientsType;
-};
-
-template<typename _CoefficientsType,int _Rows, int _Cols, int _Supers, int _Subs,int _Options>
-class BandMatrixWrapper : public BandMatrixBase<BandMatrixWrapper<_CoefficientsType,_Rows,_Cols,_Supers,_Subs,_Options> >
-{
- public:
-
- typedef typename internal::traits<BandMatrixWrapper>::Scalar Scalar;
- typedef typename internal::traits<BandMatrixWrapper>::CoefficientsType CoefficientsType;
- typedef typename internal::traits<BandMatrixWrapper>::Index Index;
-
- inline BandMatrixWrapper(const CoefficientsType& coeffs, Index rows=_Rows, Index cols=_Cols, Index supers=_Supers, Index subs=_Subs)
- : m_coeffs(coeffs),
- m_rows(rows), m_supers(supers), m_subs(subs)
- {
- EIGEN_UNUSED_VARIABLE(cols);
- //internal::assert(coeffs.cols()==cols() && (supers()+subs()+1)==coeffs.rows());
- }
-
- /** \returns the number of columns */
- inline Index rows() const { return m_rows.value(); }
-
- /** \returns the number of rows */
- inline Index cols() const { return m_coeffs.cols(); }
-
- /** \returns the number of super diagonals */
- inline Index supers() const { return m_supers.value(); }
-
- /** \returns the number of sub diagonals */
- inline Index subs() const { return m_subs.value(); }
-
- inline const CoefficientsType& coeffs() const { return m_coeffs; }
-
- protected:
-
- const CoefficientsType& m_coeffs;
- internal::variable_if_dynamic<Index, _Rows> m_rows;
- internal::variable_if_dynamic<Index, _Supers> m_supers;
- internal::variable_if_dynamic<Index, _Subs> m_subs;
-};
-
-/**
- * \class TridiagonalMatrix
- * \ingroup Core_Module
- *
- * \brief Represents a tridiagonal matrix with a compact banded storage
- *
- * \param _Scalar Numeric type, i.e. float, double, int
- * \param Size Number of rows and cols, or \b Dynamic
- * \param _Options Can be 0 or \b SelfAdjoint
- *
- * \sa class BandMatrix
- */
-template<typename Scalar, int Size, int Options>
-class TridiagonalMatrix : public BandMatrix<Scalar,Size,Size,Options&SelfAdjoint?0:1,1,Options|RowMajor>
-{
- typedef BandMatrix<Scalar,Size,Size,Options&SelfAdjoint?0:1,1,Options|RowMajor> Base;
- typedef typename Base::Index Index;
- public:
- TridiagonalMatrix(Index size = Size) : Base(size,size,Options&SelfAdjoint?0:1,1) {}
-
- inline typename Base::template DiagonalIntReturnType<1>::Type super()
- { return Base::template diagonal<1>(); }
- inline const typename Base::template DiagonalIntReturnType<1>::Type super() const
- { return Base::template diagonal<1>(); }
- inline typename Base::template DiagonalIntReturnType<-1>::Type sub()
- { return Base::template diagonal<-1>(); }
- inline const typename Base::template DiagonalIntReturnType<-1>::Type sub() const
- { return Base::template diagonal<-1>(); }
- protected:
-};
-
-} // end namespace internal
-
-#endif // EIGEN_BANDMATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Core/Block.h b/extern/Eigen3/Eigen/src/Core/Block.h
deleted file mode 100644
index 2b251bc2ca9..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Block.h
+++ /dev/null
@@ -1,349 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_BLOCK_H
-#define EIGEN_BLOCK_H
-
-/** \class Block
- * \ingroup Core_Module
- *
- * \brief Expression of a fixed-size or dynamic-size block
- *
- * \param XprType the type of the expression in which we are taking a block
- * \param BlockRows the number of rows of the block we are taking at compile time (optional)
- * \param BlockCols the number of columns of the block we are taking at compile time (optional)
- * \param _DirectAccessStatus \internal used for partial specialization
- *
- * This class represents an expression of either a fixed-size or dynamic-size block. It is the return
- * type of DenseBase::block(Index,Index,Index,Index) and DenseBase::block<int,int>(Index,Index) and
- * most of the time this is the only way it is used.
- *
- * However, if you want to directly maniputate block expressions,
- * for instance if you want to write a function returning such an expression, you
- * will need to use this class.
- *
- * Here is an example illustrating the dynamic case:
- * \include class_Block.cpp
- * Output: \verbinclude class_Block.out
- *
- * \note Even though this expression has dynamic size, in the case where \a XprType
- * has fixed size, this expression inherits a fixed maximal size which means that evaluating
- * it does not cause a dynamic memory allocation.
- *
- * Here is an example illustrating the fixed-size case:
- * \include class_FixedBlock.cpp
- * Output: \verbinclude class_FixedBlock.out
- *
- * \sa DenseBase::block(Index,Index,Index,Index), DenseBase::block(Index,Index), class VectorBlock
- */
-
-namespace internal {
-template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess>
-struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> > : traits<XprType>
-{
- typedef typename traits<XprType>::Scalar Scalar;
- typedef typename traits<XprType>::StorageKind StorageKind;
- typedef typename traits<XprType>::XprKind XprKind;
- typedef typename nested<XprType>::type XprTypeNested;
- typedef typename remove_reference<XprTypeNested>::type _XprTypeNested;
- enum{
- MatrixRows = traits<XprType>::RowsAtCompileTime,
- MatrixCols = traits<XprType>::ColsAtCompileTime,
- RowsAtCompileTime = MatrixRows == 0 ? 0 : BlockRows,
- ColsAtCompileTime = MatrixCols == 0 ? 0 : BlockCols,
- MaxRowsAtCompileTime = BlockRows==0 ? 0
- : RowsAtCompileTime != Dynamic ? int(RowsAtCompileTime)
- : int(traits<XprType>::MaxRowsAtCompileTime),
- MaxColsAtCompileTime = BlockCols==0 ? 0
- : 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
- : XprTypeIsRowMajor,
- HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
- InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
- InnerStrideAtCompileTime = HasSameStorageOrderAsXprType
- ? int(inner_stride_at_compile_time<XprType>::ret)
- : int(outer_stride_at_compile_time<XprType>::ret),
- OuterStrideAtCompileTime = HasSameStorageOrderAsXprType
- ? int(outer_stride_at_compile_time<XprType>::ret)
- : int(inner_stride_at_compile_time<XprType>::ret),
- MaskPacketAccessBit = (InnerSize == Dynamic || (InnerSize % packet_traits<Scalar>::size) == 0)
- && (InnerStrideAtCompileTime == 1)
- ? PacketAccessBit : 0,
- MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && ((OuterStrideAtCompileTime % packet_traits<Scalar>::size) == 0)) ? AlignedBit : 0,
- FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
- FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0,
- FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
- Flags0 = traits<XprType>::Flags & ( (HereditaryBits & ~RowMajorBit) |
- DirectAccessBit |
- MaskPacketAccessBit |
- MaskAlignedBit),
- Flags = Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit
- };
-};
-}
-
-template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class Block
- : public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> >::type
-{
- public:
-
- typedef typename internal::dense_xpr_base<Block>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Block)
-
- class InnerIterator;
-
- /** Column or Row constructor
- */
- inline Block(XprType& xpr, Index i)
- : m_xpr(xpr),
- // It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime,
- // and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1,
- // all other cases are invalid.
- // The case a 1x1 matrix seems ambiguous, but the result is the same anyway.
- m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0),
- m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
- m_blockRows(BlockRows==1 ? 1 : xpr.rows()),
- m_blockCols(BlockCols==1 ? 1 : xpr.cols())
- {
- eigen_assert( (i>=0) && (
- ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
- ||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols())));
- }
-
- /** Fixed-size constructor
- */
- inline Block(XprType& xpr, Index startRow, Index startCol)
- : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol),
- m_blockRows(BlockRows), m_blockCols(BlockCols)
- {
- EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
- eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows()
- && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols());
- }
-
- /** Dynamic-size constructor
- */
- inline Block(XprType& xpr,
- Index startRow, Index startCol,
- Index blockRows, Index blockCols)
- : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol),
- m_blockRows(blockRows), m_blockCols(blockCols)
- {
- eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
- && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
- eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows()
- && startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols());
- }
-
- EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
-
- inline Index rows() const { return m_blockRows.value(); }
- inline Index cols() const { return m_blockCols.value(); }
-
- inline Scalar& coeffRef(Index row, Index col)
- {
- EIGEN_STATIC_ASSERT_LVALUE(XprType)
- return m_xpr.const_cast_derived()
- .coeffRef(row + m_startRow.value(), col + m_startCol.value());
- }
-
- inline const Scalar& coeffRef(Index row, Index col) const
- {
- return m_xpr.derived()
- .coeffRef(row + m_startRow.value(), col + m_startCol.value());
- }
-
- EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index row, Index col) const
- {
- return m_xpr.coeff(row + m_startRow.value(), col + m_startCol.value());
- }
-
- inline Scalar& coeffRef(Index index)
- {
- EIGEN_STATIC_ASSERT_LVALUE(XprType)
- return m_xpr.const_cast_derived()
- .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
- m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
- }
-
- inline const Scalar& coeffRef(Index index) const
- {
- return m_xpr.const_cast_derived()
- .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
- m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
- }
-
- inline const CoeffReturnType coeff(Index index) const
- {
- return m_xpr
- .coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
- m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
- }
-
- template<int LoadMode>
- inline PacketScalar packet(Index row, Index col) const
- {
- return m_xpr.template packet<Unaligned>
- (row + m_startRow.value(), col + m_startCol.value());
- }
-
- template<int LoadMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
- {
- m_xpr.const_cast_derived().template writePacket<Unaligned>
- (row + m_startRow.value(), col + m_startCol.value(), x);
- }
-
- template<int LoadMode>
- inline PacketScalar packet(Index index) const
- {
- return m_xpr.template packet<Unaligned>
- (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
- m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
- }
-
- template<int LoadMode>
- inline void writePacket(Index index, const PacketScalar& x)
- {
- m_xpr.const_cast_derived().template writePacket<Unaligned>
- (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
- m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), x);
- }
-
- #ifdef EIGEN_PARSED_BY_DOXYGEN
- /** \sa MapBase::data() */
- inline const Scalar* data() const;
- inline Index innerStride() const;
- inline Index outerStride() const;
- #endif
-
- protected:
-
- const typename XprType::Nested m_xpr;
- const internal::variable_if_dynamic<Index, XprType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow;
- const internal::variable_if_dynamic<Index, XprType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol;
- const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_blockRows;
- const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols;
-};
-
-/** \internal */
-template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
-class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
- : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel, true> >
-{
- public:
-
- typedef MapBase<Block> Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Block)
-
- EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
-
- /** Column or Row constructor
- */
- inline Block(XprType& xpr, Index i)
- : Base(internal::const_cast_ptr(&xpr.coeffRef(
- (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0,
- (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0)),
- BlockRows==1 ? 1 : xpr.rows(),
- BlockCols==1 ? 1 : xpr.cols()),
- m_xpr(xpr)
- {
- eigen_assert( (i>=0) && (
- ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
- ||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols())));
- init();
- }
-
- /** Fixed-size constructor
- */
- inline Block(XprType& xpr, Index startRow, Index startCol)
- : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr)
- {
- eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows()
- && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols());
- init();
- }
-
- /** Dynamic-size constructor
- */
- inline Block(XprType& xpr,
- Index startRow, Index startCol,
- Index blockRows, Index blockCols)
- : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol)), blockRows, blockCols),
- m_xpr(xpr)
- {
- eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
- && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
- eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows()
- && startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols());
- init();
- }
-
- /** \sa MapBase::innerStride() */
- inline Index innerStride() const
- {
- return internal::traits<Block>::HasSameStorageOrderAsXprType
- ? m_xpr.innerStride()
- : m_xpr.outerStride();
- }
-
- /** \sa MapBase::outerStride() */
- inline Index outerStride() const
- {
- return m_outerStride;
- }
-
- #ifndef __SUNPRO_CC
- // FIXME sunstudio is not friendly with the above friend...
- // META-FIXME there is no 'friend' keyword around here. Is this obsolete?
- protected:
- #endif
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- /** \internal used by allowAligned() */
- inline Block(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols)
- : Base(data, blockRows, blockCols), m_xpr(xpr)
- {
- init();
- }
- #endif
-
- protected:
- void init()
- {
- m_outerStride = internal::traits<Block>::HasSameStorageOrderAsXprType
- ? m_xpr.outerStride()
- : m_xpr.innerStride();
- }
-
- const typename XprType::Nested m_xpr;
- int m_outerStride;
-};
-
-
-#endif // EIGEN_BLOCK_H
diff --git a/extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h b/extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h
deleted file mode 100644
index 7386b2e1843..00000000000
--- a/extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h
+++ /dev/null
@@ -1,240 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_CWISE_BINARY_OP_H
-#define EIGEN_CWISE_BINARY_OP_H
-
-/** \class CwiseBinaryOp
- * \ingroup Core_Module
- *
- * \brief Generic expression where a coefficient-wise binary operator is applied to two expressions
- *
- * \param BinaryOp template functor implementing the operator
- * \param Lhs the type of the left-hand side
- * \param Rhs the type of the right-hand side
- *
- * This class represents an expression where a coefficient-wise binary operator is applied to two expressions.
- * It is the return type of binary operators, by which we mean only those binary operators where
- * both the left-hand side and the right-hand side are Eigen expressions.
- * For example, the return type of matrix1+matrix2 is a CwiseBinaryOp.
- *
- * Most of the time, this is the only way that it is used, so you typically don't have to name
- * CwiseBinaryOp types explicitly.
- *
- * \sa MatrixBase::binaryExpr(const MatrixBase<OtherDerived> &,const CustomBinaryOp &) const, class CwiseUnaryOp, class CwiseNullaryOp
- */
-
-namespace internal {
-template<typename BinaryOp, typename Lhs, typename Rhs>
-struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
-{
- // we must not inherit from traits<Lhs> since it has
- // the potential to cause problems with MSVC
- typedef typename remove_all<Lhs>::type Ancestor;
- typedef typename traits<Ancestor>::XprKind XprKind;
- enum {
- RowsAtCompileTime = traits<Ancestor>::RowsAtCompileTime,
- ColsAtCompileTime = traits<Ancestor>::ColsAtCompileTime,
- MaxRowsAtCompileTime = traits<Ancestor>::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = traits<Ancestor>::MaxColsAtCompileTime
- };
-
- // even though we require Lhs and Rhs to have the same scalar type (see CwiseBinaryOp constructor),
- // we still want to handle the case when the result type is different.
- typedef typename result_of<
- BinaryOp(
- typename Lhs::Scalar,
- typename Rhs::Scalar
- )
- >::type Scalar;
- typedef typename promote_storage_type<typename traits<Lhs>::StorageKind,
- typename traits<Rhs>::StorageKind>::ret StorageKind;
- typedef typename promote_index_type<typename traits<Lhs>::Index,
- typename traits<Rhs>::Index>::type Index;
- typedef typename Lhs::Nested LhsNested;
- typedef typename Rhs::Nested RhsNested;
- typedef typename remove_reference<LhsNested>::type _LhsNested;
- typedef typename remove_reference<RhsNested>::type _RhsNested;
- enum {
- LhsCoeffReadCost = _LhsNested::CoeffReadCost,
- RhsCoeffReadCost = _RhsNested::CoeffReadCost,
- LhsFlags = _LhsNested::Flags,
- RhsFlags = _RhsNested::Flags,
- SameType = is_same<typename _LhsNested::Scalar,typename _RhsNested::Scalar>::value,
- StorageOrdersAgree = (int(Lhs::Flags)&RowMajorBit)==(int(Rhs::Flags)&RowMajorBit),
- Flags0 = (int(LhsFlags) | int(RhsFlags)) & (
- HereditaryBits
- | (int(LhsFlags) & int(RhsFlags) &
- ( AlignedBit
- | (StorageOrdersAgree ? LinearAccessBit : 0)
- | (functor_traits<BinaryOp>::PacketAccess && StorageOrdersAgree && SameType ? PacketAccessBit : 0)
- )
- )
- ),
- Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit),
- CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + functor_traits<BinaryOp>::Cost
- };
-};
-} // end namespace internal
-
-// we require Lhs and Rhs to have the same scalar type. Currently there is no example of a binary functor
-// that would take two operands of different types. If there were such an example, then this check should be
-// moved to the BinaryOp functors, on a per-case basis. This would however require a change in the BinaryOp functors, as
-// currently they take only one typename Scalar template parameter.
-// It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths.
-// So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to
-// add together a float matrix and a double matrix.
-#define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \
- EIGEN_STATIC_ASSERT((internal::functor_allows_mixing_real_and_complex<BINOP>::ret \
- ? int(internal::is_same<typename NumTraits<LHS>::Real, typename NumTraits<RHS>::Real>::value) \
- : int(internal::is_same<LHS, RHS>::value)), \
- YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
-
-template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind>
-class CwiseBinaryOpImpl;
-
-template<typename BinaryOp, typename Lhs, typename Rhs>
-class CwiseBinaryOp : internal::no_assignment_operator,
- public CwiseBinaryOpImpl<
- BinaryOp, Lhs, Rhs,
- typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind,
- typename internal::traits<Rhs>::StorageKind>::ret>
-{
- public:
-
- typedef typename CwiseBinaryOpImpl<
- BinaryOp, Lhs, Rhs,
- typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind,
- typename internal::traits<Rhs>::StorageKind>::ret>::Base Base;
- EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseBinaryOp)
-
- typedef typename internal::nested<Lhs>::type LhsNested;
- typedef typename internal::nested<Rhs>::type RhsNested;
- typedef typename internal::remove_reference<LhsNested>::type _LhsNested;
- typedef typename internal::remove_reference<RhsNested>::type _RhsNested;
-
- EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
- : m_lhs(lhs), m_rhs(rhs), m_functor(func)
- {
- EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar);
- // require the sizes to match
- EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs)
- eigen_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
- }
-
- EIGEN_STRONG_INLINE Index rows() const {
- // return the fixed size type if available to enable compile time optimizations
- if (internal::traits<typename internal::remove_all<LhsNested>::type>::RowsAtCompileTime==Dynamic)
- return m_rhs.rows();
- else
- return m_lhs.rows();
- }
- EIGEN_STRONG_INLINE Index cols() const {
- // return the fixed size type if available to enable compile time optimizations
- if (internal::traits<typename internal::remove_all<LhsNested>::type>::ColsAtCompileTime==Dynamic)
- return m_rhs.cols();
- else
- return m_lhs.cols();
- }
-
- /** \returns the left hand side nested expression */
- const _LhsNested& lhs() const { return m_lhs; }
- /** \returns the right hand side nested expression */
- const _RhsNested& rhs() const { return m_rhs; }
- /** \returns the functor representing the binary operation */
- const BinaryOp& functor() const { return m_functor; }
-
- protected:
- const LhsNested m_lhs;
- const RhsNested m_rhs;
- const BinaryOp m_functor;
-};
-
-template<typename BinaryOp, typename Lhs, typename Rhs>
-class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Dense>
- : public internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type
-{
- typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> Derived;
- public:
-
- typedef typename internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE( Derived )
-
- EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
- {
- return derived().functor()(derived().lhs().coeff(row, col),
- derived().rhs().coeff(row, col));
- }
-
- template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
- {
- return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(row, col),
- derived().rhs().template packet<LoadMode>(row, col));
- }
-
- EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
- {
- return derived().functor()(derived().lhs().coeff(index),
- derived().rhs().coeff(index));
- }
-
- template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet(Index index) const
- {
- return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(index),
- derived().rhs().template packet<LoadMode>(index));
- }
-};
-
-/** replaces \c *this by \c *this - \a other.
- *
- * \returns a reference to \c *this
- */
-template<typename Derived>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE Derived &
-MatrixBase<Derived>::operator-=(const MatrixBase<OtherDerived> &other)
-{
- SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, Derived, OtherDerived> tmp(derived());
- tmp = other.derived();
- return derived();
-}
-
-/** replaces \c *this by \c *this + \a other.
- *
- * \returns a reference to \c *this
- */
-template<typename Derived>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE Derived &
-MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other)
-{
- SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, Derived, OtherDerived> tmp(derived());
- tmp = other.derived();
- return derived();
-}
-
-#endif // EIGEN_CWISE_BINARY_OP_H
diff --git a/extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h b/extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h
deleted file mode 100644
index 958571d64bf..00000000000
--- a/extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h
+++ /dev/null
@@ -1,137 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_CWISE_UNARY_OP_H
-#define EIGEN_CWISE_UNARY_OP_H
-
-/** \class CwiseUnaryOp
- * \ingroup Core_Module
- *
- * \brief Generic expression where a coefficient-wise unary operator is applied to an expression
- *
- * \param UnaryOp template functor implementing the operator
- * \param XprType the type of the expression to which we are applying the unary operator
- *
- * This class represents an expression where a unary operator is applied to an expression.
- * It is the return type of all operations taking exactly 1 input expression, regardless of the
- * presence of other inputs such as scalars. For example, the operator* in the expression 3*matrix
- * is considered unary, because only the right-hand side is an expression, and its
- * return type is a specialization of CwiseUnaryOp.
- *
- * Most of the time, this is the only way that it is used, so you typically don't have to name
- * CwiseUnaryOp types explicitly.
- *
- * \sa MatrixBase::unaryExpr(const CustomUnaryOp &) const, class CwiseBinaryOp, class CwiseNullaryOp
- */
-
-namespace internal {
-template<typename UnaryOp, typename XprType>
-struct traits<CwiseUnaryOp<UnaryOp, XprType> >
- : traits<XprType>
-{
- typedef typename result_of<
- UnaryOp(typename XprType::Scalar)
- >::type Scalar;
- typedef typename XprType::Nested XprTypeNested;
- typedef typename remove_reference<XprTypeNested>::type _XprTypeNested;
- enum {
- Flags = _XprTypeNested::Flags & (
- HereditaryBits | LinearAccessBit | AlignedBit
- | (functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0)),
- CoeffReadCost = _XprTypeNested::CoeffReadCost + functor_traits<UnaryOp>::Cost
- };
-};
-}
-
-template<typename UnaryOp, typename XprType, typename StorageKind>
-class CwiseUnaryOpImpl;
-
-template<typename UnaryOp, typename XprType>
-class CwiseUnaryOp : internal::no_assignment_operator,
- public CwiseUnaryOpImpl<UnaryOp, XprType, typename internal::traits<XprType>::StorageKind>
-{
- public:
-
- typedef typename CwiseUnaryOpImpl<UnaryOp, XprType,typename internal::traits<XprType>::StorageKind>::Base Base;
- EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseUnaryOp)
-
- inline CwiseUnaryOp(const XprType& xpr, const UnaryOp& func = UnaryOp())
- : m_xpr(xpr), m_functor(func) {}
-
- EIGEN_STRONG_INLINE Index rows() const { return m_xpr.rows(); }
- EIGEN_STRONG_INLINE Index cols() const { return m_xpr.cols(); }
-
- /** \returns the functor representing the unary operation */
- const UnaryOp& functor() const { return m_functor; }
-
- /** \returns the nested expression */
- const typename internal::remove_all<typename XprType::Nested>::type&
- nestedExpression() const { return m_xpr; }
-
- /** \returns the nested expression */
- typename internal::remove_all<typename XprType::Nested>::type&
- nestedExpression() { return m_xpr.const_cast_derived(); }
-
- protected:
- const typename XprType::Nested m_xpr;
- const UnaryOp m_functor;
-};
-
-// This is the generic implementation for dense storage.
-// It can be used for any expression types implementing the dense concept.
-template<typename UnaryOp, typename XprType>
-class CwiseUnaryOpImpl<UnaryOp,XprType,Dense>
- : public internal::dense_xpr_base<CwiseUnaryOp<UnaryOp, XprType> >::type
-{
- public:
-
- typedef CwiseUnaryOp<UnaryOp, XprType> Derived;
- typedef typename internal::dense_xpr_base<CwiseUnaryOp<UnaryOp, XprType> >::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
-
- EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
- {
- return derived().functor()(derived().nestedExpression().coeff(row, col));
- }
-
- template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
- {
- return derived().functor().packetOp(derived().nestedExpression().template packet<LoadMode>(row, col));
- }
-
- EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
- {
- return derived().functor()(derived().nestedExpression().coeff(index));
- }
-
- template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet(Index index) const
- {
- return derived().functor().packetOp(derived().nestedExpression().template packet<LoadMode>(index));
- }
-};
-
-#endif // EIGEN_CWISE_UNARY_OP_H
diff --git a/extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h b/extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h
deleted file mode 100644
index d24ef037314..00000000000
--- a/extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_CWISE_UNARY_VIEW_H
-#define EIGEN_CWISE_UNARY_VIEW_H
-
-/** \class CwiseUnaryView
- * \ingroup Core_Module
- *
- * \brief Generic lvalue expression of a coefficient-wise unary operator of a matrix or a vector
- *
- * \param ViewOp template functor implementing the view
- * \param MatrixType the type of the matrix we are applying the unary operator
- *
- * This class represents a lvalue expression of a generic unary view operator of a matrix or a vector.
- * It is the return type of real() and imag(), and most of the time this is the only way it is used.
- *
- * \sa MatrixBase::unaryViewExpr(const CustomUnaryOp &) const, class CwiseUnaryOp
- */
-
-namespace internal {
-template<typename ViewOp, typename MatrixType>
-struct traits<CwiseUnaryView<ViewOp, MatrixType> >
- : traits<MatrixType>
-{
- typedef typename result_of<
- ViewOp(typename traits<MatrixType>::Scalar)
- >::type Scalar;
- typedef typename MatrixType::Nested MatrixTypeNested;
- typedef typename remove_all<MatrixTypeNested>::type _MatrixTypeNested;
- enum {
- Flags = (traits<_MatrixTypeNested>::Flags & (HereditaryBits | LvalueBit | LinearAccessBit | DirectAccessBit)),
- CoeffReadCost = traits<_MatrixTypeNested>::CoeffReadCost + functor_traits<ViewOp>::Cost,
- MatrixTypeInnerStride = inner_stride_at_compile_time<MatrixType>::ret,
- // need to cast the sizeof's from size_t to int explicitly, otherwise:
- // "error: no integral type can represent all of the enumerator values
- InnerStrideAtCompileTime = MatrixTypeInnerStride == Dynamic
- ? int(Dynamic)
- : int(MatrixTypeInnerStride)
- * int(sizeof(typename traits<MatrixType>::Scalar) / sizeof(Scalar)),
- OuterStrideAtCompileTime = outer_stride_at_compile_time<MatrixType>::ret
- };
-};
-}
-
-template<typename ViewOp, typename MatrixType, typename StorageKind>
-class CwiseUnaryViewImpl;
-
-template<typename ViewOp, typename MatrixType>
-class CwiseUnaryView : internal::no_assignment_operator,
- public CwiseUnaryViewImpl<ViewOp, MatrixType, typename internal::traits<MatrixType>::StorageKind>
-{
- public:
-
- typedef typename CwiseUnaryViewImpl<ViewOp, MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base;
- EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseUnaryView)
-
- inline CwiseUnaryView(const MatrixType& mat, const ViewOp& func = ViewOp())
- : m_matrix(mat), m_functor(func) {}
-
- EIGEN_INHERIT_ASSIGNMENT_OPERATORS(CwiseUnaryView)
-
- EIGEN_STRONG_INLINE Index rows() const { return m_matrix.rows(); }
- EIGEN_STRONG_INLINE Index cols() const { return m_matrix.cols(); }
-
- /** \returns the functor representing unary operation */
- const ViewOp& functor() const { return m_functor; }
-
- /** \returns the nested expression */
- const typename internal::remove_all<typename MatrixType::Nested>::type&
- nestedExpression() const { return m_matrix; }
-
- /** \returns the nested expression */
- typename internal::remove_all<typename MatrixType::Nested>::type&
- nestedExpression() { return m_matrix.const_cast_derived(); }
-
- protected:
- // FIXME changed from MatrixType::Nested because of a weird compilation error with sun CC
- const typename internal::nested<MatrixType>::type m_matrix;
- ViewOp m_functor;
-};
-
-template<typename ViewOp, typename MatrixType>
-class CwiseUnaryViewImpl<ViewOp,MatrixType,Dense>
- : public internal::dense_xpr_base< CwiseUnaryView<ViewOp, MatrixType> >::type
-{
- public:
-
- typedef CwiseUnaryView<ViewOp, MatrixType> Derived;
- typedef typename internal::dense_xpr_base< CwiseUnaryView<ViewOp, MatrixType> >::type Base;
-
- EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
-
- inline Index innerStride() const
- {
- return derived().nestedExpression().innerStride() * sizeof(typename internal::traits<MatrixType>::Scalar) / sizeof(Scalar);
- }
-
- inline Index outerStride() const
- {
- return derived().nestedExpression().outerStride();
- }
-
- EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const
- {
- return derived().functor()(derived().nestedExpression().coeff(row, col));
- }
-
- EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const
- {
- return derived().functor()(derived().nestedExpression().coeff(index));
- }
-
- EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
- {
- return derived().functor()(const_cast_derived().nestedExpression().coeffRef(row, col));
- }
-
- EIGEN_STRONG_INLINE Scalar& coeffRef(Index index)
- {
- return derived().functor()(const_cast_derived().nestedExpression().coeffRef(index));
- }
-};
-
-
-
-#endif // EIGEN_CWISE_UNARY_VIEW_H
diff --git a/extern/Eigen3/Eigen/src/Core/DenseBase.h b/extern/Eigen3/Eigen/src/Core/DenseBase.h
deleted file mode 100644
index 838fa40307a..00000000000
--- a/extern/Eigen3/Eigen/src/Core/DenseBase.h
+++ /dev/null
@@ -1,543 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2007-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_DENSEBASE_H
-#define EIGEN_DENSEBASE_H
-
-/** \class DenseBase
- * \ingroup Core_Module
- *
- * \brief Base class for all dense matrices, vectors, and arrays
- *
- * This class is the base that is inherited by all dense objects (matrix, vector, arrays,
- * and related expression types). The common Eigen API for dense objects is contained in this class.
- *
- * \tparam Derived is the derived type, e.g., a matrix type or an expression.
- *
- * 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_DENSEBASE_PLUGIN.
- *
- * \sa \ref TopicClassHierarchy
- */
-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>
-#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;
-
- typedef typename internal::traits<Derived>::StorageKind StorageKind;
-
- /** \brief The type of indices
- * \details To change this, \c \#define the preprocessor symbol \c EIGEN_DEFAULT_DENSE_INDEX_TYPE.
- * \sa \ref TopicPreprocessorDirectives.
- */
- typedef typename internal::traits<Derived>::Index Index;
-
- typedef typename internal::traits<Derived>::Scalar Scalar;
- typedef typename internal::packet_traits<Scalar>::type PacketScalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
- typedef DenseCoeffsBase<Derived> Base;
- using Base::derived;
- using Base::const_cast_derived;
- using Base::rows;
- using Base::cols;
- using Base::size;
- using Base::rowIndexByOuterInner;
- using Base::colIndexByOuterInner;
- using Base::coeff;
- using Base::coeffByOuterInner;
- using Base::packet;
- using Base::packetByOuterInner;
- using Base::writePacket;
- using Base::writePacketByOuterInner;
- using Base::coeffRef;
- using Base::coeffRefByOuterInner;
- using Base::copyCoeff;
- using Base::copyCoeffByOuterInner;
- using Base::copyPacket;
- using Base::copyPacketByOuterInner;
- using Base::operator();
- using Base::operator[];
- using Base::x;
- using Base::y;
- using Base::z;
- using Base::w;
- using Base::stride;
- using Base::innerStride;
- using Base::outerStride;
- using Base::rowStride;
- using Base::colStride;
- typedef typename Base::CoeffReturnType CoeffReturnType;
-
- enum {
-
- RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
- /**< The number of rows at compile-time. This is just a copy of the value provided
- * by the \a Derived type. If a value is not known at compile-time,
- * it is set to the \a Dynamic constant.
- * \sa MatrixBase::rows(), MatrixBase::cols(), ColsAtCompileTime, SizeAtCompileTime */
-
- ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
- /**< The number of columns at compile-time. This is just a copy of the value provided
- * by the \a Derived type. If a value is not known at compile-time,
- * it is set to the \a Dynamic constant.
- * \sa MatrixBase::rows(), MatrixBase::cols(), RowsAtCompileTime, SizeAtCompileTime */
-
-
- SizeAtCompileTime = (internal::size_at_compile_time<internal::traits<Derived>::RowsAtCompileTime,
- internal::traits<Derived>::ColsAtCompileTime>::ret),
- /**< This is equal to the number of coefficients, i.e. the number of
- * rows times the number of columns, or to \a Dynamic if this is not
- * known at compile-time. \sa RowsAtCompileTime, ColsAtCompileTime */
-
- MaxRowsAtCompileTime = internal::traits<Derived>::MaxRowsAtCompileTime,
- /**< This value is equal to the maximum possible number of rows that this expression
- * might have. If this expression might have an arbitrarily high number of rows,
- * this value is set to \a Dynamic.
- *
- * This value is useful to know when evaluating an expression, in order to determine
- * whether it is possible to avoid doing a dynamic memory allocation.
- *
- * \sa RowsAtCompileTime, MaxColsAtCompileTime, MaxSizeAtCompileTime
- */
-
- MaxColsAtCompileTime = internal::traits<Derived>::MaxColsAtCompileTime,
- /**< This value is equal to the maximum possible number of columns that this expression
- * might have. If this expression might have an arbitrarily high number of columns,
- * this value is set to \a Dynamic.
- *
- * This value is useful to know when evaluating an expression, in order to determine
- * whether it is possible to avoid doing a dynamic memory allocation.
- *
- * \sa ColsAtCompileTime, MaxRowsAtCompileTime, MaxSizeAtCompileTime
- */
-
- MaxSizeAtCompileTime = (internal::size_at_compile_time<internal::traits<Derived>::MaxRowsAtCompileTime,
- internal::traits<Derived>::MaxColsAtCompileTime>::ret),
- /**< This value is equal to the maximum possible number of coefficients that this expression
- * might have. If this expression might have an arbitrarily high number of coefficients,
- * this value is set to \a Dynamic.
- *
- * This value is useful to know when evaluating an expression, in order to determine
- * whether it is possible to avoid doing a dynamic memory allocation.
- *
- * \sa SizeAtCompileTime, MaxRowsAtCompileTime, MaxColsAtCompileTime
- */
-
- IsVectorAtCompileTime = internal::traits<Derived>::MaxRowsAtCompileTime == 1
- || internal::traits<Derived>::MaxColsAtCompileTime == 1,
- /**< This is set to true if either the number of rows or the number of
- * columns is known at compile-time to be equal to 1. Indeed, in that case,
- * we are dealing with a column-vector (if there is only one column) or with
- * a row-vector (if there is only one row). */
-
- Flags = internal::traits<Derived>::Flags,
- /**< This stores expression \ref flags flags which may or may not be inherited by new expressions
- * constructed from this one. See the \ref flags "list of flags".
- */
-
- IsRowMajor = int(Flags) & RowMajorBit, /**< True if this expression has row-major storage order. */
-
- InnerSizeAtCompileTime = int(IsVectorAtCompileTime) ? SizeAtCompileTime
- : int(IsRowMajor) ? ColsAtCompileTime : RowsAtCompileTime,
-
- CoeffReadCost = internal::traits<Derived>::CoeffReadCost,
- /**< This is a rough measure of how expensive it is to read one coefficient from
- * this expression.
- */
-
- InnerStrideAtCompileTime = internal::inner_stride_at_compile_time<Derived>::ret,
- OuterStrideAtCompileTime = internal::outer_stride_at_compile_time<Derived>::ret
- };
-
- enum { ThisConstantIsPrivateInPlainObjectBase };
-
- /** \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.
- *
- * \note For a vector, this returns just 1. For a matrix (non-vector), this is the major dimension
- * with respect to the \ref TopicStorageOrders "storage order", i.e., the number of columns for a
- * column-major matrix, and the number of rows for a row-major matrix. */
- Index outerSize() const
- {
- return IsVectorAtCompileTime ? 1
- : int(IsRowMajor) ? this->rows() : this->cols();
- }
-
- /** \returns the inner size.
- *
- * \note For a vector, this is just the size. For a matrix (non-vector), this is the minor dimension
- * with respect to the \ref TopicStorageOrders "storage order", i.e., the number of rows for a
- * column-major matrix, and the number of columns for a row-major matrix. */
- Index innerSize() const
- {
- return IsVectorAtCompileTime ? this->size()
- : int(IsRowMajor) ? this->cols() : this->rows();
- }
-
- /** Only plain matrices/arrays, not expressions, may be resized; therefore the only useful resize methods are
- * Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and does
- * nothing else.
- */
- void resize(Index size)
- {
- EIGEN_ONLY_USED_FOR_DEBUG(size);
- eigen_assert(size == this->size()
- && "DenseBase::resize() does not actually allow to resize.");
- }
- /** Only plain matrices/arrays, not expressions, may be resized; therefore the only useful resize methods are
- * Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and does
- * nothing else.
- */
- void resize(Index rows, Index cols)
- {
- EIGEN_ONLY_USED_FOR_DEBUG(rows);
- EIGEN_ONLY_USED_FOR_DEBUG(cols);
- eigen_assert(rows == this->rows() && cols == this->cols()
- && "DenseBase::resize() does not actually allow to resize.");
- }
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
-
- /** \internal Represents a matrix with all coefficients equal to one another*/
- typedef CwiseNullaryOp<internal::scalar_constant_op<Scalar>,Derived> ConstantReturnType;
- /** \internal Represents a vector with linearly spaced coefficients that allows sequential access only. */
- typedef CwiseNullaryOp<internal::linspaced_op<Scalar,false>,Derived> SequentialLinSpacedReturnType;
- /** \internal Represents a vector with linearly spaced coefficients that allows random access. */
- typedef CwiseNullaryOp<internal::linspaced_op<Scalar,true>,Derived> RandomAccessLinSpacedReturnType;
- /** \internal the return type of MatrixBase::eigenvalues() */
- typedef Matrix<typename NumTraits<typename internal::traits<Derived>::Scalar>::Real, internal::traits<Derived>::ColsAtCompileTime, 1> EigenvaluesReturnType;
-
-#endif // not EIGEN_PARSED_BY_DOXYGEN
-
- /** Copies \a other into *this. \returns a reference to *this. */
- template<typename OtherDerived>
- Derived& operator=(const DenseBase<OtherDerived>& other);
-
- /** Special case of the template operator=, in order to prevent the compiler
- * from generating a default operator= (issue hit with g++ 4.1)
- */
- Derived& operator=(const DenseBase& other);
-
- template<typename OtherDerived>
- Derived& operator=(const EigenBase<OtherDerived> &other);
-
- template<typename OtherDerived>
- Derived& operator+=(const EigenBase<OtherDerived> &other);
-
- template<typename OtherDerived>
- Derived& operator-=(const EigenBase<OtherDerived> &other);
-
- 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. */
- template<typename OtherDerived>
- Derived& lazyAssign(const DenseBase<OtherDerived>& other);
-#endif // not EIGEN_PARSED_BY_DOXYGEN
-
- CommaInitializer<Derived> operator<< (const Scalar& s);
-
- template<unsigned int Added,unsigned int Removed>
- const Flagged<Derived, Added, Removed> flagged() const;
-
- template<typename OtherDerived>
- CommaInitializer<Derived> operator<< (const DenseBase<OtherDerived>& other);
-
- Eigen::Transpose<Derived> transpose();
- typedef const Transpose<const Derived> ConstTransposeReturnType;
- ConstTransposeReturnType transpose() const;
- void transposeInPlace();
-#ifndef EIGEN_NO_DEBUG
- protected:
- template<typename OtherDerived>
- void checkTransposeAliasing(const OtherDerived& other) const;
- public:
-#endif
-
- typedef VectorBlock<Derived> SegmentReturnType;
- typedef const VectorBlock<const Derived> ConstSegmentReturnType;
- template<int Size> struct FixedSegmentReturnType { typedef VectorBlock<Derived, Size> Type; };
- template<int Size> struct ConstFixedSegmentReturnType { typedef const VectorBlock<const Derived, Size> Type; };
-
- // Note: The "DenseBase::" prefixes are added to help MSVC9 to match these declarations with the later implementations.
- SegmentReturnType segment(Index start, Index size);
- typename DenseBase::ConstSegmentReturnType segment(Index start, Index size) const;
-
- SegmentReturnType head(Index size);
- typename DenseBase::ConstSegmentReturnType head(Index size) const;
-
- SegmentReturnType tail(Index size);
- typename DenseBase::ConstSegmentReturnType tail(Index size) const;
-
- template<int Size> typename FixedSegmentReturnType<Size>::Type head();
- template<int Size> typename ConstFixedSegmentReturnType<Size>::Type head() const;
-
- template<int Size> typename FixedSegmentReturnType<Size>::Type tail();
- template<int Size> typename ConstFixedSegmentReturnType<Size>::Type tail() const;
-
- template<int Size> typename FixedSegmentReturnType<Size>::Type segment(Index start);
- template<int Size> typename ConstFixedSegmentReturnType<Size>::Type segment(Index start) const;
-
- static const ConstantReturnType
- Constant(Index rows, Index cols, const Scalar& value);
- static const ConstantReturnType
- Constant(Index size, const Scalar& value);
- static const ConstantReturnType
- Constant(const Scalar& value);
-
- static const SequentialLinSpacedReturnType
- LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high);
- static const RandomAccessLinSpacedReturnType
- LinSpaced(Index size, const Scalar& low, const Scalar& high);
- static const SequentialLinSpacedReturnType
- LinSpaced(Sequential_t, const Scalar& low, const Scalar& high);
- static const RandomAccessLinSpacedReturnType
- LinSpaced(const Scalar& low, const Scalar& high);
-
- template<typename CustomNullaryOp>
- static const CwiseNullaryOp<CustomNullaryOp, Derived>
- NullaryExpr(Index rows, Index cols, const CustomNullaryOp& func);
- template<typename CustomNullaryOp>
- static const CwiseNullaryOp<CustomNullaryOp, Derived>
- NullaryExpr(Index size, const CustomNullaryOp& func);
- template<typename CustomNullaryOp>
- static const CwiseNullaryOp<CustomNullaryOp, Derived>
- NullaryExpr(const CustomNullaryOp& func);
-
- static const ConstantReturnType Zero(Index rows, Index cols);
- static const ConstantReturnType Zero(Index size);
- static const ConstantReturnType Zero();
- static const ConstantReturnType Ones(Index rows, Index cols);
- static const ConstantReturnType Ones(Index size);
- static const ConstantReturnType Ones();
-
- void fill(const Scalar& value);
- Derived& setConstant(const Scalar& value);
- Derived& setLinSpaced(Index size, const Scalar& low, const Scalar& high);
- Derived& setLinSpaced(const Scalar& low, const Scalar& high);
- Derived& setZero();
- Derived& setOnes();
- Derived& setRandom();
-
- template<typename OtherDerived>
- bool isApprox(const DenseBase<OtherDerived>& other,
- RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isMuchSmallerThan(const RealScalar& other,
- RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- template<typename OtherDerived>
- bool isMuchSmallerThan(const DenseBase<OtherDerived>& other,
- RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
-
- bool isApproxToConstant(const Scalar& value, RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isConstant(const Scalar& value, RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isZero(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isOnes(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
-
- inline Derived& operator*=(const Scalar& other);
- inline Derived& operator/=(const Scalar& other);
-
- /** \returns the matrix or vector obtained by evaluating this expression.
- *
- * Notice that in the case of a plain matrix or vector (not an expression) this function just returns
- * a const reference, in order to avoid a useless copy.
- */
- EIGEN_STRONG_INLINE const typename internal::eval<Derived>::type eval() const
- {
- // Even though MSVC does not honor strong inlining when the return type
- // is a dynamic matrix, we desperately need strong inlining for fixed
- // size types on MSVC.
- return typename internal::eval<Derived>::type(derived());
- }
-
- /** swaps *this with the expression \a other.
- *
- */
- template<typename OtherDerived>
- void swap(const DenseBase<OtherDerived>& other,
- int = OtherDerived::ThisConstantIsPrivateInPlainObjectBase)
- {
- SwapWrapper<Derived>(derived()).lazyAssign(other.derived());
- }
-
- /** swaps *this with the matrix or array \a other.
- *
- */
- template<typename OtherDerived>
- void swap(PlainObjectBase<OtherDerived>& other)
- {
- SwapWrapper<Derived>(derived()).lazyAssign(other.derived());
- }
-
-
- inline const NestByValue<Derived> nestByValue() const;
- inline const ForceAlignedAccess<Derived> forceAlignedAccess() const;
- inline ForceAlignedAccess<Derived> forceAlignedAccess();
- template<bool Enable> inline const typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type forceAlignedAccessIf() const;
- template<bool Enable> inline typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type forceAlignedAccessIf();
-
- Scalar sum() const;
- Scalar mean() const;
- Scalar trace() const;
-
- Scalar prod() const;
-
- typename internal::traits<Derived>::Scalar minCoeff() const;
- typename internal::traits<Derived>::Scalar maxCoeff() const;
-
- template<typename IndexType>
- typename internal::traits<Derived>::Scalar minCoeff(IndexType* row, IndexType* col) const;
- template<typename IndexType>
- typename internal::traits<Derived>::Scalar maxCoeff(IndexType* row, IndexType* col) const;
- template<typename IndexType>
- typename internal::traits<Derived>::Scalar minCoeff(IndexType* index) const;
- template<typename IndexType>
- typename internal::traits<Derived>::Scalar maxCoeff(IndexType* index) const;
-
- template<typename BinaryOp>
- typename internal::result_of<BinaryOp(typename internal::traits<Derived>::Scalar)>::type
- redux(const BinaryOp& func) const;
-
- template<typename Visitor>
- void visit(Visitor& func) const;
-
- inline const WithFormat<Derived> format(const IOFormat& fmt) const;
-
- /** \returns the unique coefficient of a 1x1 expression */
- CoeffReturnType value() const
- {
- EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
- eigen_assert(this->rows() == 1 && this->cols() == 1);
- return derived().coeff(0,0);
- }
-
-/////////// Array module ///////////
-
- bool all(void) const;
- bool any(void) const;
- Index count() const;
-
- typedef VectorwiseOp<Derived, Horizontal> RowwiseReturnType;
- typedef const VectorwiseOp<const Derived, Horizontal> ConstRowwiseReturnType;
- typedef VectorwiseOp<Derived, Vertical> ColwiseReturnType;
- typedef const VectorwiseOp<const Derived, Vertical> ConstColwiseReturnType;
-
- ConstRowwiseReturnType rowwise() const;
- RowwiseReturnType rowwise();
- ConstColwiseReturnType colwise() const;
- ColwiseReturnType colwise();
-
- static const CwiseNullaryOp<internal::scalar_random_op<Scalar>,Derived> Random(Index rows, Index cols);
- static const CwiseNullaryOp<internal::scalar_random_op<Scalar>,Derived> Random(Index size);
- static const CwiseNullaryOp<internal::scalar_random_op<Scalar>,Derived> Random();
-
- template<typename ThenDerived,typename ElseDerived>
- const Select<Derived,ThenDerived,ElseDerived>
- select(const DenseBase<ThenDerived>& thenMatrix,
- const DenseBase<ElseDerived>& elseMatrix) const;
-
- template<typename ThenDerived>
- inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType>
- select(const DenseBase<ThenDerived>& thenMatrix, typename ThenDerived::Scalar elseScalar) const;
-
- template<typename ElseDerived>
- inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived >
- select(typename ElseDerived::Scalar thenScalar, const DenseBase<ElseDerived>& elseMatrix) const;
-
- 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;
-
- typedef Reverse<Derived, BothDirections> ReverseReturnType;
- typedef const Reverse<const Derived, BothDirections> ConstReverseReturnType;
- ReverseReturnType reverse();
- ConstReverseReturnType reverse() const;
- void reverseInPlace();
-
-#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::DenseBase
-# include "../plugins/BlockMethods.h"
-# ifdef EIGEN_DENSEBASE_PLUGIN
-# include EIGEN_DENSEBASE_PLUGIN
-# endif
-#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
-
-#ifdef EIGEN2_SUPPORT
-
- Block<Derived> corner(CornerType type, Index cRows, Index cCols);
- const Block<Derived> corner(CornerType type, Index cRows, Index cCols) const;
- template<int CRows, int CCols>
- Block<Derived, CRows, CCols> corner(CornerType type);
- template<int CRows, int CCols>
- const Block<Derived, CRows, CCols> corner(CornerType type) const;
-
-#endif // EIGEN2_SUPPORT
-
-
- // disable the use of evalTo for dense objects with a nice compilation error
- template<typename Dest> inline void evalTo(Dest& ) const
- {
- EIGEN_STATIC_ASSERT((internal::is_same<Dest,void>::value),THE_EVAL_EVALTO_FUNCTION_SHOULD_NEVER_BE_CALLED_FOR_DENSE_OBJECTS);
- }
-
- protected:
- /** Default constructor. Do nothing. */
- DenseBase()
- {
- /* Just checks for self-consistency of the flags.
- * Only do it when debugging Eigen, as this borders on paranoiac and could slow compilation down
- */
-#ifdef EIGEN_INTERNAL_DEBUGGING
- EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, int(IsRowMajor))
- && EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, int(!IsRowMajor))),
- INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION)
-#endif
- }
-
- private:
- explicit DenseBase(int);
- DenseBase(int,int);
- template<typename OtherDerived> explicit DenseBase(const DenseBase<OtherDerived>&);
-};
-
-#endif // EIGEN_DENSEBASE_H
diff --git a/extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h b/extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h
deleted file mode 100644
index e45238fb584..00000000000
--- a/extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h
+++ /dev/null
@@ -1,765 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_DENSECOEFFSBASE_H
-#define EIGEN_DENSECOEFFSBASE_H
-
-namespace internal {
-template<typename T> struct add_const_on_value_type_if_arithmetic
-{
- typedef typename conditional<is_arithmetic<T>::value, T, typename add_const_on_value_type<T>::type>::type type;
-};
-}
-
-/** \brief Base class providing read-only coefficient access to matrices and arrays.
- * \ingroup Core_Module
- * \tparam Derived Type of the derived class
- * \tparam #ReadOnlyAccessors Constant indicating read-only access
- *
- * This class defines the \c operator() \c const function and friends, which can be used to read specific
- * entries of a matrix or array.
- *
- * \sa DenseCoeffsBase<Derived, WriteAccessors>, DenseCoeffsBase<Derived, DirectAccessors>,
- * \ref TopicClassHierarchy
- */
-template<typename Derived>
-class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
-{
- public:
- typedef typename internal::traits<Derived>::StorageKind StorageKind;
- typedef typename internal::traits<Derived>::Index Index;
- typedef typename internal::traits<Derived>::Scalar Scalar;
- typedef typename internal::packet_traits<Scalar>::type PacketScalar;
-
- // Explanation for this CoeffReturnType typedef.
- // - This is the return type of the coeff() method.
- // - The LvalueBit means exactly that we can offer a coeffRef() method, which means exactly that we can get references
- // to coeffs, which means exactly that we can have coeff() return a const reference (as opposed to returning a value).
- // - The is_artihmetic check is required since "const int", "const double", etc. will cause warnings on some systems
- // while the declaration of "const T", where T is a non arithmetic type does not. Always returning "const Scalar&" is
- // not possible, since the underlying expressions might not offer a valid address the reference could be referring to.
- typedef typename internal::conditional<bool(internal::traits<Derived>::Flags&LvalueBit),
- const Scalar&,
- typename internal::conditional<internal::is_arithmetic<Scalar>::value, Scalar, const Scalar>::type
- >::type CoeffReturnType;
-
- typedef typename internal::add_const_on_value_type_if_arithmetic<
- typename internal::packet_traits<Scalar>::type
- >::type PacketReturnType;
-
- typedef EigenBase<Derived> Base;
- using Base::rows;
- using Base::cols;
- using Base::size;
- using Base::derived;
-
- EIGEN_STRONG_INLINE Index rowIndexByOuterInner(Index outer, Index inner) const
- {
- return int(Derived::RowsAtCompileTime) == 1 ? 0
- : int(Derived::ColsAtCompileTime) == 1 ? inner
- : int(Derived::Flags)&RowMajorBit ? outer
- : inner;
- }
-
- EIGEN_STRONG_INLINE Index colIndexByOuterInner(Index outer, Index inner) const
- {
- return int(Derived::ColsAtCompileTime) == 1 ? 0
- : int(Derived::RowsAtCompileTime) == 1 ? inner
- : int(Derived::Flags)&RowMajorBit ? inner
- : outer;
- }
-
- /** Short version: don't use this function, use
- * \link operator()(Index,Index) const \endlink instead.
- *
- * Long version: this function is similar to
- * \link operator()(Index,Index) const \endlink, but without the assertion.
- * Use this for limiting the performance cost of debugging code when doing
- * repeated coefficient access. Only use this when it is guaranteed that the
- * parameters \a row and \a col are in range.
- *
- * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this
- * function equivalent to \link operator()(Index,Index) const \endlink.
- *
- * \sa operator()(Index,Index) const, coeffRef(Index,Index), coeff(Index) const
- */
- EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const
- {
- eigen_internal_assert(row >= 0 && row < rows()
- && col >= 0 && col < cols());
- return derived().coeff(row, col);
- }
-
- EIGEN_STRONG_INLINE CoeffReturnType coeffByOuterInner(Index outer, Index inner) const
- {
- return coeff(rowIndexByOuterInner(outer, inner),
- colIndexByOuterInner(outer, inner));
- }
-
- /** \returns the coefficient at given the given row and column.
- *
- * \sa operator()(Index,Index), operator[](Index)
- */
- EIGEN_STRONG_INLINE CoeffReturnType operator()(Index row, Index col) const
- {
- eigen_assert(row >= 0 && row < rows()
- && col >= 0 && col < cols());
- return derived().coeff(row, col);
- }
-
- /** Short version: don't use this function, use
- * \link operator[](Index) const \endlink instead.
- *
- * Long version: this function is similar to
- * \link operator[](Index) const \endlink, but without the assertion.
- * Use this for limiting the performance cost of debugging code when doing
- * repeated coefficient access. Only use this when it is guaranteed that the
- * parameter \a index is in range.
- *
- * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this
- * function equivalent to \link operator[](Index) const \endlink.
- *
- * \sa operator[](Index) const, coeffRef(Index), coeff(Index,Index) const
- */
-
- EIGEN_STRONG_INLINE CoeffReturnType
- coeff(Index index) const
- {
- eigen_internal_assert(index >= 0 && index < size());
- return derived().coeff(index);
- }
-
-
- /** \returns the coefficient at given index.
- *
- * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit.
- *
- * \sa operator[](Index), operator()(Index,Index) const, x() const, y() const,
- * z() const, w() const
- */
-
- EIGEN_STRONG_INLINE CoeffReturnType
- operator[](Index index) const
- {
- #ifndef EIGEN2_SUPPORT
- EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
- THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
- #endif
- eigen_assert(index >= 0 && index < size());
- return derived().coeff(index);
- }
-
- /** \returns the coefficient at given index.
- *
- * This is synonymous to operator[](Index) const.
- *
- * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit.
- *
- * \sa operator[](Index), operator()(Index,Index) const, x() const, y() const,
- * z() const, w() const
- */
-
- EIGEN_STRONG_INLINE CoeffReturnType
- operator()(Index index) const
- {
- eigen_assert(index >= 0 && index < size());
- return derived().coeff(index);
- }
-
- /** equivalent to operator[](0). */
-
- EIGEN_STRONG_INLINE CoeffReturnType
- x() const { return (*this)[0]; }
-
- /** equivalent to operator[](1). */
-
- EIGEN_STRONG_INLINE CoeffReturnType
- y() const { return (*this)[1]; }
-
- /** equivalent to operator[](2). */
-
- EIGEN_STRONG_INLINE CoeffReturnType
- z() const { return (*this)[2]; }
-
- /** equivalent to operator[](3). */
-
- EIGEN_STRONG_INLINE CoeffReturnType
- w() const { return (*this)[3]; }
-
- /** \internal
- * \returns the packet of coefficients starting at the given row and column. It is your responsibility
- * to ensure that a packet really starts there. This method is only available on expressions having the
- * PacketAccessBit.
- *
- * The \a LoadMode parameter may have the value \a #Aligned or \a #Unaligned. Its effect is to select
- * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
- * starting at an address which is a multiple of the packet size.
- */
-
- template<int LoadMode>
- EIGEN_STRONG_INLINE PacketReturnType packet(Index row, Index col) const
- {
- eigen_internal_assert(row >= 0 && row < rows()
- && col >= 0 && col < cols());
- return derived().template packet<LoadMode>(row,col);
- }
-
-
- /** \internal */
- template<int LoadMode>
- EIGEN_STRONG_INLINE PacketReturnType packetByOuterInner(Index outer, Index inner) const
- {
- return packet<LoadMode>(rowIndexByOuterInner(outer, inner),
- colIndexByOuterInner(outer, inner));
- }
-
- /** \internal
- * \returns the packet of coefficients starting at the given index. It is your responsibility
- * to ensure that a packet really starts there. This method is only available on expressions having the
- * PacketAccessBit and the LinearAccessBit.
- *
- * The \a LoadMode parameter may have the value \a #Aligned or \a #Unaligned. Its effect is to select
- * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
- * starting at an address which is a multiple of the packet size.
- */
-
- template<int LoadMode>
- EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const
- {
- eigen_internal_assert(index >= 0 && index < size());
- return derived().template packet<LoadMode>(index);
- }
-
- protected:
- // explanation: DenseBase is doing "using ..." on the methods from DenseCoeffsBase.
- // But some methods are only available in the DirectAccess case.
- // So we add dummy methods here with these names, so that "using... " doesn't fail.
- // It's not private so that the child class DenseBase can access them, and it's not public
- // either since it's an implementation detail, so has to be protected.
- void coeffRef();
- void coeffRefByOuterInner();
- void writePacket();
- void writePacketByOuterInner();
- void copyCoeff();
- void copyCoeffByOuterInner();
- void copyPacket();
- void copyPacketByOuterInner();
- void stride();
- void innerStride();
- void outerStride();
- void rowStride();
- void colStride();
-};
-
-/** \brief Base class providing read/write coefficient access to matrices and arrays.
- * \ingroup Core_Module
- * \tparam Derived Type of the derived class
- * \tparam #WriteAccessors Constant indicating read/write access
- *
- * This class defines the non-const \c operator() function and friends, which can be used to write specific
- * entries of a matrix or array. This class inherits DenseCoeffsBase<Derived, ReadOnlyAccessors> which
- * defines the const variant for reading specific entries.
- *
- * \sa DenseCoeffsBase<Derived, DirectAccessors>, \ref TopicClassHierarchy
- */
-template<typename Derived>
-class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived, ReadOnlyAccessors>
-{
- public:
-
- typedef DenseCoeffsBase<Derived, ReadOnlyAccessors> Base;
-
- typedef typename internal::traits<Derived>::StorageKind StorageKind;
- typedef typename internal::traits<Derived>::Index Index;
- typedef typename internal::traits<Derived>::Scalar Scalar;
- typedef typename internal::packet_traits<Scalar>::type PacketScalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
- using Base::coeff;
- using Base::rows;
- using Base::cols;
- using Base::size;
- using Base::derived;
- using Base::rowIndexByOuterInner;
- using Base::colIndexByOuterInner;
- using Base::operator[];
- using Base::operator();
- using Base::x;
- using Base::y;
- using Base::z;
- using Base::w;
-
- /** Short version: don't use this function, use
- * \link operator()(Index,Index) \endlink instead.
- *
- * Long version: this function is similar to
- * \link operator()(Index,Index) \endlink, but without the assertion.
- * Use this for limiting the performance cost of debugging code when doing
- * repeated coefficient access. Only use this when it is guaranteed that the
- * parameters \a row and \a col are in range.
- *
- * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this
- * function equivalent to \link operator()(Index,Index) \endlink.
- *
- * \sa operator()(Index,Index), coeff(Index, Index) const, coeffRef(Index)
- */
- EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
- {
- eigen_internal_assert(row >= 0 && row < rows()
- && col >= 0 && col < cols());
- return derived().coeffRef(row, col);
- }
-
- EIGEN_STRONG_INLINE Scalar&
- coeffRefByOuterInner(Index outer, Index inner)
- {
- return coeffRef(rowIndexByOuterInner(outer, inner),
- colIndexByOuterInner(outer, inner));
- }
-
- /** \returns a reference to the coefficient at given the given row and column.
- *
- * \sa operator[](Index)
- */
-
- EIGEN_STRONG_INLINE Scalar&
- operator()(Index row, Index col)
- {
- eigen_assert(row >= 0 && row < rows()
- && col >= 0 && col < cols());
- return derived().coeffRef(row, col);
- }
-
-
- /** Short version: don't use this function, use
- * \link operator[](Index) \endlink instead.
- *
- * Long version: this function is similar to
- * \link operator[](Index) \endlink, but without the assertion.
- * Use this for limiting the performance cost of debugging code when doing
- * repeated coefficient access. Only use this when it is guaranteed that the
- * parameters \a row and \a col are in range.
- *
- * If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this
- * function equivalent to \link operator[](Index) \endlink.
- *
- * \sa operator[](Index), coeff(Index) const, coeffRef(Index,Index)
- */
-
- EIGEN_STRONG_INLINE Scalar&
- coeffRef(Index index)
- {
- eigen_internal_assert(index >= 0 && index < size());
- return derived().coeffRef(index);
- }
-
- /** \returns a reference to the coefficient at given index.
- *
- * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit.
- *
- * \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w()
- */
-
- EIGEN_STRONG_INLINE Scalar&
- operator[](Index index)
- {
- #ifndef EIGEN2_SUPPORT
- EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
- THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
- #endif
- eigen_assert(index >= 0 && index < size());
- return derived().coeffRef(index);
- }
-
- /** \returns a reference to the coefficient at given index.
- *
- * This is synonymous to operator[](Index).
- *
- * This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit.
- *
- * \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w()
- */
-
- EIGEN_STRONG_INLINE Scalar&
- operator()(Index index)
- {
- eigen_assert(index >= 0 && index < size());
- return derived().coeffRef(index);
- }
-
- /** equivalent to operator[](0). */
-
- EIGEN_STRONG_INLINE Scalar&
- x() { return (*this)[0]; }
-
- /** equivalent to operator[](1). */
-
- EIGEN_STRONG_INLINE Scalar&
- y() { return (*this)[1]; }
-
- /** equivalent to operator[](2). */
-
- EIGEN_STRONG_INLINE Scalar&
- z() { return (*this)[2]; }
-
- /** equivalent to operator[](3). */
-
- EIGEN_STRONG_INLINE Scalar&
- w() { return (*this)[3]; }
-
- /** \internal
- * Stores the given packet of coefficients, at the given row and column of this expression. It is your responsibility
- * to ensure that a packet really starts there. This method is only available on expressions having the
- * PacketAccessBit.
- *
- * The \a LoadMode parameter may have the value \a #Aligned or \a #Unaligned. Its effect is to select
- * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
- * starting at an address which is a multiple of the packet size.
- */
-
- template<int StoreMode>
- EIGEN_STRONG_INLINE void writePacket
- (Index row, Index col, const typename internal::packet_traits<Scalar>::type& x)
- {
- eigen_internal_assert(row >= 0 && row < rows()
- && col >= 0 && col < cols());
- derived().template writePacket<StoreMode>(row,col,x);
- }
-
-
- /** \internal */
- template<int StoreMode>
- EIGEN_STRONG_INLINE void writePacketByOuterInner
- (Index outer, Index inner, const typename internal::packet_traits<Scalar>::type& x)
- {
- writePacket<StoreMode>(rowIndexByOuterInner(outer, inner),
- colIndexByOuterInner(outer, inner),
- x);
- }
-
- /** \internal
- * Stores the given packet of coefficients, at the given index in this expression. It is your responsibility
- * to ensure that a packet really starts there. This method is only available on expressions having the
- * PacketAccessBit and the LinearAccessBit.
- *
- * The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select
- * the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets
- * starting at an address which is a multiple of the packet size.
- */
- template<int StoreMode>
- EIGEN_STRONG_INLINE void writePacket
- (Index index, const typename internal::packet_traits<Scalar>::type& x)
- {
- eigen_internal_assert(index >= 0 && index < size());
- derived().template writePacket<StoreMode>(index,x);
- }
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
-
- /** \internal Copies the coefficient at position (row,col) of other into *this.
- *
- * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code
- * with usual assignments.
- *
- * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox.
- */
-
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, const DenseBase<OtherDerived>& other)
- {
- eigen_internal_assert(row >= 0 && row < rows()
- && col >= 0 && col < cols());
- derived().coeffRef(row, col) = other.derived().coeff(row, col);
- }
-
- /** \internal Copies the coefficient at the given index of other into *this.
- *
- * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code
- * with usual assignments.
- *
- * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox.
- */
-
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE void copyCoeff(Index index, const DenseBase<OtherDerived>& other)
- {
- eigen_internal_assert(index >= 0 && index < size());
- derived().coeffRef(index) = other.derived().coeff(index);
- }
-
-
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE void copyCoeffByOuterInner(Index outer, Index inner, const DenseBase<OtherDerived>& other)
- {
- const Index row = rowIndexByOuterInner(outer,inner);
- const Index col = colIndexByOuterInner(outer,inner);
- // derived() is important here: copyCoeff() may be reimplemented in Derived!
- derived().copyCoeff(row, col, other);
- }
-
- /** \internal Copies the packet at position (row,col) of other into *this.
- *
- * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code
- * with usual assignments.
- *
- * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox.
- */
-
- template<typename OtherDerived, int StoreMode, int LoadMode>
- EIGEN_STRONG_INLINE void copyPacket(Index row, Index col, const DenseBase<OtherDerived>& other)
- {
- eigen_internal_assert(row >= 0 && row < rows()
- && col >= 0 && col < cols());
- derived().template writePacket<StoreMode>(row, col,
- other.derived().template packet<LoadMode>(row, col));
- }
-
- /** \internal Copies the packet at the given index of other into *this.
- *
- * This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code
- * with usual assignments.
- *
- * Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox.
- */
-
- template<typename OtherDerived, int StoreMode, int LoadMode>
- EIGEN_STRONG_INLINE void copyPacket(Index index, const DenseBase<OtherDerived>& other)
- {
- eigen_internal_assert(index >= 0 && index < size());
- derived().template writePacket<StoreMode>(index,
- other.derived().template packet<LoadMode>(index));
- }
-
- /** \internal */
- template<typename OtherDerived, int StoreMode, int LoadMode>
- EIGEN_STRONG_INLINE void copyPacketByOuterInner(Index outer, Index inner, const DenseBase<OtherDerived>& other)
- {
- const Index row = rowIndexByOuterInner(outer,inner);
- const Index col = colIndexByOuterInner(outer,inner);
- // derived() is important here: copyCoeff() may be reimplemented in Derived!
- derived().template copyPacket< OtherDerived, StoreMode, LoadMode>(row, col, other);
- }
-#endif
-
-};
-
-/** \brief Base class providing direct read-only coefficient access to matrices and arrays.
- * \ingroup Core_Module
- * \tparam Derived Type of the derived class
- * \tparam #DirectAccessors Constant indicating direct access
- *
- * This class defines functions to work with strides which can be used to access entries directly. This class
- * inherits DenseCoeffsBase<Derived, ReadOnlyAccessors> which defines functions to access entries read-only using
- * \c operator() .
- *
- * \sa \ref TopicClassHierarchy
- */
-template<typename Derived>
-class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived, ReadOnlyAccessors>
-{
- public:
-
- typedef DenseCoeffsBase<Derived, ReadOnlyAccessors> Base;
- typedef typename internal::traits<Derived>::Index Index;
- typedef typename internal::traits<Derived>::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
- using Base::rows;
- using Base::cols;
- using Base::size;
- using Base::derived;
-
- /** \returns the pointer increment between two consecutive elements within a slice in the inner direction.
- *
- * \sa outerStride(), rowStride(), colStride()
- */
- inline Index innerStride() const
- {
- return derived().innerStride();
- }
-
- /** \returns the pointer increment between two consecutive inner slices (for example, between two consecutive columns
- * in a column-major matrix).
- *
- * \sa innerStride(), rowStride(), colStride()
- */
- inline Index outerStride() const
- {
- return derived().outerStride();
- }
-
- // FIXME shall we remove it ?
- inline Index stride() const
- {
- return Derived::IsVectorAtCompileTime ? innerStride() : outerStride();
- }
-
- /** \returns the pointer increment between two consecutive rows.
- *
- * \sa innerStride(), outerStride(), colStride()
- */
- inline Index rowStride() const
- {
- return Derived::IsRowMajor ? outerStride() : innerStride();
- }
-
- /** \returns the pointer increment between two consecutive columns.
- *
- * \sa innerStride(), outerStride(), rowStride()
- */
- inline Index colStride() const
- {
- return Derived::IsRowMajor ? innerStride() : outerStride();
- }
-};
-
-/** \brief Base class providing direct read/write coefficient access to matrices and arrays.
- * \ingroup Core_Module
- * \tparam Derived Type of the derived class
- * \tparam #DirectWriteAccessors Constant indicating direct access
- *
- * This class defines functions to work with strides which can be used to access entries directly. This class
- * inherits DenseCoeffsBase<Derived, WriteAccessors> which defines functions to access entries read/write using
- * \c operator().
- *
- * \sa \ref TopicClassHierarchy
- */
-template<typename Derived>
-class DenseCoeffsBase<Derived, DirectWriteAccessors>
- : public DenseCoeffsBase<Derived, WriteAccessors>
-{
- public:
-
- typedef DenseCoeffsBase<Derived, WriteAccessors> Base;
- typedef typename internal::traits<Derived>::Index Index;
- typedef typename internal::traits<Derived>::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
- using Base::rows;
- using Base::cols;
- using Base::size;
- using Base::derived;
-
- /** \returns the pointer increment between two consecutive elements within a slice in the inner direction.
- *
- * \sa outerStride(), rowStride(), colStride()
- */
- inline Index innerStride() const
- {
- return derived().innerStride();
- }
-
- /** \returns the pointer increment between two consecutive inner slices (for example, between two consecutive columns
- * in a column-major matrix).
- *
- * \sa innerStride(), rowStride(), colStride()
- */
- inline Index outerStride() const
- {
- return derived().outerStride();
- }
-
- // FIXME shall we remove it ?
- inline Index stride() const
- {
- return Derived::IsVectorAtCompileTime ? innerStride() : outerStride();
- }
-
- /** \returns the pointer increment between two consecutive rows.
- *
- * \sa innerStride(), outerStride(), colStride()
- */
- inline Index rowStride() const
- {
- return Derived::IsRowMajor ? outerStride() : innerStride();
- }
-
- /** \returns the pointer increment between two consecutive columns.
- *
- * \sa innerStride(), outerStride(), rowStride()
- */
- inline Index colStride() const
- {
- return Derived::IsRowMajor ? innerStride() : outerStride();
- }
-};
-
-namespace internal {
-
-template<typename Derived, bool JustReturnZero>
-struct first_aligned_impl
-{
- inline static typename Derived::Index run(const Derived&)
- { return 0; }
-};
-
-template<typename Derived>
-struct first_aligned_impl<Derived, false>
-{
- inline static typename Derived::Index run(const Derived& m)
- {
- return first_aligned(&m.const_cast_derived().coeffRef(0,0), m.size());
- }
-};
-
-/** \internal \returns the index of the first element of the array that is well aligned for vectorization.
- *
- * There is also the variant first_aligned(const Scalar*, Integer) defined in Memory.h. See it for more
- * documentation.
- */
-template<typename Derived>
-inline static typename Derived::Index first_aligned(const Derived& m)
-{
- return first_aligned_impl
- <Derived, (Derived::Flags & AlignedBit) || !(Derived::Flags & DirectAccessBit)>
- ::run(m);
-}
-
-template<typename Derived, bool HasDirectAccess = has_direct_access<Derived>::ret>
-struct inner_stride_at_compile_time
-{
- enum { ret = traits<Derived>::InnerStrideAtCompileTime };
-};
-
-template<typename Derived>
-struct inner_stride_at_compile_time<Derived, false>
-{
- enum { ret = 0 };
-};
-
-template<typename Derived, bool HasDirectAccess = has_direct_access<Derived>::ret>
-struct outer_stride_at_compile_time
-{
- enum { ret = traits<Derived>::OuterStrideAtCompileTime };
-};
-
-template<typename Derived>
-struct outer_stride_at_compile_time<Derived, false>
-{
- enum { ret = 0 };
-};
-
-} // end namespace internal
-
-#endif // EIGEN_DENSECOEFFSBASE_H
diff --git a/extern/Eigen3/Eigen/src/Core/DenseStorage.h b/extern/Eigen3/Eigen/src/Core/DenseStorage.h
deleted file mode 100644
index 813053b00dd..00000000000
--- a/extern/Eigen3/Eigen/src/Core/DenseStorage.h
+++ /dev/null
@@ -1,304 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_MATRIXSTORAGE_H
-#define EIGEN_MATRIXSTORAGE_H
-
-#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN EIGEN_DENSE_STORAGE_CTOR_PLUGIN;
-#else
- #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
-#endif
-
-namespace internal {
-
-struct constructor_without_unaligned_array_assert {};
-
-/** \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.
- */
-template <typename T, int Size, int MatrixOrArrayOptions,
- int Alignment = (MatrixOrArrayOptions&DontAlign) ? 0
- : (((Size*sizeof(T))%16)==0) ? 16
- : 0 >
-struct plain_array
-{
- T array[Size];
- plain_array() {}
- plain_array(constructor_without_unaligned_array_assert) {}
-};
-
-#ifdef EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
- #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask)
-#else
- #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
- eigen_assert((reinterpret_cast<size_t>(array) & sizemask) == 0 \
- && "this assertion is explained here: " \
- "http://eigen.tuxfamily.org/dox-devel/TopicUnalignedArrayAssert.html" \
- " **** READ THIS WEB PAGE !!! ****");
-#endif
-
-template <typename T, int Size, int MatrixOrArrayOptions>
-struct plain_array<T, Size, MatrixOrArrayOptions, 16>
-{
- EIGEN_USER_ALIGN16 T array[Size];
- plain_array() { EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(0xf) }
- plain_array(constructor_without_unaligned_array_assert) {}
-};
-
-template <typename T, int MatrixOrArrayOptions, int Alignment>
-struct plain_array<T, 0, MatrixOrArrayOptions, Alignment>
-{
- EIGEN_USER_ALIGN16 T array[1];
- plain_array() {}
- plain_array(constructor_without_unaligned_array_assert) {}
-};
-
-} // end namespace internal
-
-/** \internal
- *
- * \class DenseStorage
- * \ingroup Core_Module
- *
- * \brief Stores the data of a matrix
- *
- * This class stores the data of fixed-size, dynamic-size or mixed matrices
- * in a way as compact as possible.
- *
- * \sa Matrix
- */
-template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseStorage;
-
-// purely fixed-size matrix
-template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseStorage
-{
- internal::plain_array<T,Size,_Options> m_data;
- public:
- inline explicit DenseStorage() {}
- inline 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); }
- inline static DenseIndex rows(void) {return _Rows;}
- inline static 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; }
-};
-
-// null matrix
-template<typename T, int _Rows, int _Cols, int _Options> class DenseStorage<T, 0, _Rows, _Cols, _Options>
-{
- public:
- inline explicit DenseStorage() {}
- inline DenseStorage(internal::constructor_without_unaligned_array_assert) {}
- inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
- inline void swap(DenseStorage& ) {}
- inline static DenseIndex rows(void) {return _Rows;}
- inline static 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; }
-};
-
-// dynamic-size matrix with fixed-size storage
-template<typename T, int Size, int _Options> class DenseStorage<T, Size, Dynamic, Dynamic, _Options>
-{
- internal::plain_array<T,Size,_Options> m_data;
- DenseIndex m_rows;
- DenseIndex m_cols;
- public:
- inline explicit DenseStorage() : m_rows(0), m_cols(0) {}
- inline 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 rows, DenseIndex cols) : m_rows(rows), m_cols(cols) {}
- inline 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, DenseIndex rows, DenseIndex cols) { m_rows = rows; m_cols = cols; }
- inline void resize(DenseIndex, DenseIndex rows, DenseIndex cols) { m_rows = rows; m_cols = cols; }
- inline const T *data() const { return m_data.array; }
- inline T *data() { return m_data.array; }
-};
-
-// dynamic-size matrix with fixed-size storage and fixed width
-template<typename T, int Size, int _Cols, int _Options> class DenseStorage<T, Size, Dynamic, _Cols, _Options>
-{
- internal::plain_array<T,Size,_Options> m_data;
- DenseIndex m_rows;
- public:
- inline explicit DenseStorage() : m_rows(0) {}
- inline DenseStorage(internal::constructor_without_unaligned_array_assert)
- : m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0) {}
- inline DenseStorage(DenseIndex, DenseIndex rows, DenseIndex) : m_rows(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;}
- inline DenseIndex cols(void) const {return _Cols;}
- inline void conservativeResize(DenseIndex, DenseIndex rows, DenseIndex) { m_rows = rows; }
- inline void resize(DenseIndex, DenseIndex rows, DenseIndex) { m_rows = rows; }
- inline const T *data() const { return m_data.array; }
- inline T *data() { return m_data.array; }
-};
-
-// dynamic-size matrix with fixed-size storage and fixed height
-template<typename T, int Size, int _Rows, int _Options> class DenseStorage<T, Size, _Rows, Dynamic, _Options>
-{
- internal::plain_array<T,Size,_Options> m_data;
- DenseIndex m_cols;
- public:
- inline explicit DenseStorage() : m_cols(0) {}
- inline DenseStorage(internal::constructor_without_unaligned_array_assert)
- : m_data(internal::constructor_without_unaligned_array_assert()), m_cols(0) {}
- inline DenseStorage(DenseIndex, DenseIndex, DenseIndex cols) : m_cols(cols) {}
- 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 cols) { m_cols = cols; }
- inline void resize(DenseIndex, DenseIndex, DenseIndex cols) { m_cols = cols; }
- inline const T *data() const { return m_data.array; }
- inline T *data() { return m_data.array; }
-};
-
-// purely dynamic matrix.
-template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynamic, _Options>
-{
- T *m_data;
- DenseIndex m_rows;
- DenseIndex m_cols;
- public:
- inline explicit DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
- inline DenseStorage(internal::constructor_without_unaligned_array_assert)
- : m_data(0), m_rows(0), m_cols(0) {}
- inline DenseStorage(DenseIndex size, DenseIndex rows, DenseIndex cols)
- : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(rows), m_cols(cols)
- { 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)
- { 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 rows, DenseIndex cols)
- {
- m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*m_cols);
- m_rows = rows;
- m_cols = cols;
- }
- void resize(DenseIndex size, DenseIndex rows, DenseIndex cols)
- {
- if(size != m_rows*m_cols)
- {
- internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols);
- if (size)
- m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
- else
- m_data = 0;
- EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
- }
- m_rows = rows;
- m_cols = cols;
- }
- inline const T *data() const { return m_data; }
- inline T *data() { return m_data; }
-};
-
-// matrix with dynamic width and fixed height (so that matrix has dynamic size).
-template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Rows, Dynamic, _Options>
-{
- T *m_data;
- DenseIndex m_cols;
- public:
- inline explicit 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 cols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(cols)
- { 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); }
- inline static DenseIndex rows(void) {return _Rows;}
- inline DenseIndex cols(void) const {return m_cols;}
- inline void conservativeResize(DenseIndex size, DenseIndex, DenseIndex cols)
- {
- m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, _Rows*m_cols);
- m_cols = cols;
- }
- EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex, DenseIndex cols)
- {
- if(size != _Rows*m_cols)
- {
- internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols);
- if (size)
- m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
- else
- m_data = 0;
- EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
- }
- m_cols = cols;
- }
- inline const T *data() const { return m_data; }
- inline T *data() { return m_data; }
-};
-
-// matrix with dynamic height and fixed width (so that matrix has dynamic size).
-template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dynamic, _Cols, _Options>
-{
- T *m_data;
- DenseIndex m_rows;
- public:
- inline explicit 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 rows, DenseIndex) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(rows)
- { 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;}
- inline static DenseIndex cols(void) {return _Cols;}
- inline void conservativeResize(DenseIndex size, DenseIndex rows, DenseIndex)
- {
- m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*_Cols);
- m_rows = rows;
- }
- EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex rows, DenseIndex)
- {
- if(size != m_rows*_Cols)
- {
- internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows);
- if (size)
- m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
- else
- m_data = 0;
- EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
- }
- m_rows = rows;
- }
- inline const T *data() const { return m_data; }
- inline T *data() { return m_data; }
-};
-
-#endif // EIGEN_MATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Core/Diagonal.h b/extern/Eigen3/Eigen/src/Core/Diagonal.h
deleted file mode 100644
index 61d3b063a44..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Diagonal.h
+++ /dev/null
@@ -1,227 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_DIAGONAL_H
-#define EIGEN_DIAGONAL_H
-
-/** \class Diagonal
- * \ingroup Core_Module
- *
- * \brief Expression of a diagonal/subdiagonal/superdiagonal in a matrix
- *
- * \param MatrixType the type of the object in which we are taking a sub/main/super diagonal
- * \param DiagIndex the index of the sub/super diagonal. The default is 0 and it means the main diagonal.
- * A positive value means a superdiagonal, a negative value means a subdiagonal.
- * You can also use Dynamic so the index can be set at runtime.
- *
- * The matrix is not required to be square.
- *
- * This class represents an expression of the main diagonal, or any sub/super diagonal
- * of a square matrix. It is the return type of MatrixBase::diagonal() and MatrixBase::diagonal(Index) and most of the
- * time this is the only way it is used.
- *
- * \sa MatrixBase::diagonal(), MatrixBase::diagonal(Index)
- */
-
-namespace internal {
-template<typename MatrixType, int DiagIndex>
-struct traits<Diagonal<MatrixType,DiagIndex> >
- : traits<MatrixType>
-{
- typedef typename nested<MatrixType>::type MatrixTypeNested;
- typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
- typedef typename MatrixType::StorageKind StorageKind;
- enum {
- AbsDiagIndex = DiagIndex<0 ? -DiagIndex : DiagIndex, // only used if DiagIndex != Dynamic
- // FIXME these computations are broken in the case where the matrix is rectangular and DiagIndex!=0
- RowsAtCompileTime = (int(DiagIndex) == Dynamic || int(MatrixType::SizeAtCompileTime) == Dynamic) ? Dynamic
- : (EIGEN_SIZE_MIN_PREFER_DYNAMIC(MatrixType::RowsAtCompileTime,
- MatrixType::ColsAtCompileTime) - AbsDiagIndex),
- ColsAtCompileTime = 1,
- MaxRowsAtCompileTime = int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic
- : DiagIndex == Dynamic ? EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::MaxRowsAtCompileTime,
- MatrixType::MaxColsAtCompileTime)
- : (EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::MaxRowsAtCompileTime, MatrixType::MaxColsAtCompileTime) - AbsDiagIndex),
- MaxColsAtCompileTime = 1,
- MaskLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
- Flags = (unsigned int)_MatrixTypeNested::Flags & (HereditaryBits | LinearAccessBit | MaskLvalueBit | DirectAccessBit) & ~RowMajorBit,
- CoeffReadCost = _MatrixTypeNested::CoeffReadCost,
- MatrixTypeOuterStride = outer_stride_at_compile_time<MatrixType>::ret,
- InnerStrideAtCompileTime = MatrixTypeOuterStride == Dynamic ? Dynamic : MatrixTypeOuterStride+1,
- OuterStrideAtCompileTime = 0
- };
-};
-}
-
-template<typename MatrixType, int DiagIndex> class Diagonal
- : public internal::dense_xpr_base< Diagonal<MatrixType,DiagIndex> >::type
-{
- public:
-
- typedef typename internal::dense_xpr_base<Diagonal>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Diagonal)
-
- inline Diagonal(MatrixType& matrix, Index index = DiagIndex) : m_matrix(matrix), m_index(index) {}
-
- EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal)
-
- inline Index rows() const
- { return m_index.value()<0 ? (std::min)(m_matrix.cols(),m_matrix.rows()+m_index.value()) : (std::min)(m_matrix.rows(),m_matrix.cols()-m_index.value()); }
-
- inline Index cols() const { return 1; }
-
- inline Index innerStride() const
- {
- return m_matrix.outerStride() + 1;
- }
-
- inline Index outerStride() const
- {
- return 0;
- }
-
- inline Scalar& coeffRef(Index row, Index)
- {
- EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
- return m_matrix.const_cast_derived().coeffRef(row+rowOffset(), row+colOffset());
- }
-
- inline const Scalar& coeffRef(Index row, Index) const
- {
- return m_matrix.const_cast_derived().coeffRef(row+rowOffset(), row+colOffset());
- }
-
- inline CoeffReturnType coeff(Index row, Index) const
- {
- return m_matrix.coeff(row+rowOffset(), row+colOffset());
- }
-
- inline Scalar& coeffRef(Index index)
- {
- EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
- return m_matrix.const_cast_derived().coeffRef(index+rowOffset(), index+colOffset());
- }
-
- inline const Scalar& coeffRef(Index index) const
- {
- return m_matrix.const_cast_derived().coeffRef(index+rowOffset(), index+colOffset());
- }
-
- inline CoeffReturnType coeff(Index index) const
- {
- return m_matrix.coeff(index+rowOffset(), index+colOffset());
- }
-
- protected:
- const typename MatrixType::Nested m_matrix;
- const internal::variable_if_dynamic<Index, DiagIndex> m_index;
-
- private:
- // some compilers may fail to optimize std::max etc in case of compile-time constants...
- EIGEN_STRONG_INLINE Index absDiagIndex() const { return m_index.value()>0 ? m_index.value() : -m_index.value(); }
- EIGEN_STRONG_INLINE Index rowOffset() const { return m_index.value()>0 ? 0 : -m_index.value(); }
- EIGEN_STRONG_INLINE Index colOffset() const { return m_index.value()>0 ? m_index.value() : 0; }
- // triger a compile time error is someone try to call packet
- template<int LoadMode> typename MatrixType::PacketReturnType packet(Index) const;
- template<int LoadMode> typename MatrixType::PacketReturnType packet(Index,Index) const;
-};
-
-/** \returns an expression of the main diagonal of the matrix \c *this
- *
- * \c *this is not required to be square.
- *
- * Example: \include MatrixBase_diagonal.cpp
- * Output: \verbinclude MatrixBase_diagonal.out
- *
- * \sa class Diagonal */
-template<typename Derived>
-inline typename MatrixBase<Derived>::DiagonalReturnType
-MatrixBase<Derived>::diagonal()
-{
- return derived();
-}
-
-/** This is the const version of diagonal(). */
-template<typename Derived>
-inline const typename MatrixBase<Derived>::ConstDiagonalReturnType
-MatrixBase<Derived>::diagonal() const
-{
- return ConstDiagonalReturnType(derived());
-}
-
-/** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this
- *
- * \c *this is not required to be square.
- *
- * The template parameter \a DiagIndex represent a super diagonal if \a DiagIndex > 0
- * and a sub diagonal otherwise. \a DiagIndex == 0 is equivalent to the main diagonal.
- *
- * Example: \include MatrixBase_diagonal_int.cpp
- * Output: \verbinclude MatrixBase_diagonal_int.out
- *
- * \sa MatrixBase::diagonal(), class Diagonal */
-template<typename Derived>
-inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<Dynamic>::Type
-MatrixBase<Derived>::diagonal(Index index)
-{
- return typename DiagonalIndexReturnType<Dynamic>::Type(derived(), index);
-}
-
-/** This is the const version of diagonal(Index). */
-template<typename Derived>
-inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<Dynamic>::Type
-MatrixBase<Derived>::diagonal(Index index) const
-{
- return typename ConstDiagonalIndexReturnType<Dynamic>::Type(derived(), index);
-}
-
-/** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this
- *
- * \c *this is not required to be square.
- *
- * The template parameter \a DiagIndex represent a super diagonal if \a DiagIndex > 0
- * and a sub diagonal otherwise. \a DiagIndex == 0 is equivalent to the main diagonal.
- *
- * Example: \include MatrixBase_diagonal_template_int.cpp
- * Output: \verbinclude MatrixBase_diagonal_template_int.out
- *
- * \sa MatrixBase::diagonal(), class Diagonal */
-template<typename Derived>
-template<int Index>
-inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<Index>::Type
-MatrixBase<Derived>::diagonal()
-{
- return derived();
-}
-
-/** This is the const version of diagonal<int>(). */
-template<typename Derived>
-template<int Index>
-inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<Index>::Type
-MatrixBase<Derived>::diagonal() const
-{
- return derived();
-}
-
-#endif // EIGEN_DIAGONAL_H
diff --git a/extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h b/extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h
deleted file mode 100644
index f41a74bfae7..00000000000
--- a/extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h
+++ /dev/null
@@ -1,306 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_DIAGONALMATRIX_H
-#define EIGEN_DIAGONALMATRIX_H
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
-template<typename Derived>
-class DiagonalBase : public EigenBase<Derived>
-{
- public:
- typedef typename internal::traits<Derived>::DiagonalVectorType DiagonalVectorType;
- typedef typename DiagonalVectorType::Scalar Scalar;
- typedef typename internal::traits<Derived>::StorageKind StorageKind;
- typedef typename internal::traits<Derived>::Index Index;
-
- enum {
- RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
- ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
- MaxRowsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
- MaxColsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime,
- IsVectorAtCompileTime = 0,
- Flags = 0
- };
-
- typedef Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime, 0, MaxRowsAtCompileTime, MaxColsAtCompileTime> DenseMatrixType;
- typedef DenseMatrixType DenseType;
- typedef DiagonalMatrix<Scalar,DiagonalVectorType::SizeAtCompileTime,DiagonalVectorType::MaxSizeAtCompileTime> PlainObject;
-
- inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
- inline Derived& derived() { return *static_cast<Derived*>(this); }
-
- DenseMatrixType toDenseMatrix() const { return derived(); }
- template<typename DenseDerived>
- void evalTo(MatrixBase<DenseDerived> &other) const;
- template<typename DenseDerived>
- void addTo(MatrixBase<DenseDerived> &other) const
- { other.diagonal() += diagonal(); }
- template<typename DenseDerived>
- void subTo(MatrixBase<DenseDerived> &other) const
- { other.diagonal() -= diagonal(); }
-
- inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
- inline DiagonalVectorType& diagonal() { return derived().diagonal(); }
-
- inline Index rows() const { return diagonal().size(); }
- inline Index cols() const { return diagonal().size(); }
-
- template<typename MatrixDerived>
- const DiagonalProduct<MatrixDerived, Derived, OnTheLeft>
- operator*(const MatrixBase<MatrixDerived> &matrix) const;
-
- inline const DiagonalWrapper<CwiseUnaryOp<internal::scalar_inverse_op<Scalar>, const DiagonalVectorType> >
- inverse() const
- {
- return diagonal().cwiseInverse();
- }
-
- #ifdef EIGEN2_SUPPORT
- template<typename OtherDerived>
- bool isApprox(const DiagonalBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
- {
- return diagonal().isApprox(other.diagonal(), precision);
- }
- template<typename OtherDerived>
- bool isApprox(const MatrixBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
- {
- return toDenseMatrix().isApprox(other, precision);
- }
- #endif
-};
-
-template<typename Derived>
-template<typename DenseDerived>
-void DiagonalBase<Derived>::evalTo(MatrixBase<DenseDerived> &other) const
-{
- other.setZero();
- other.diagonal() = diagonal();
-}
-#endif
-
-/** \class DiagonalMatrix
- * \ingroup Core_Module
- *
- * \brief Represents a diagonal matrix with its storage
- *
- * \param _Scalar the type of coefficients
- * \param SizeAtCompileTime the dimension of the matrix, or Dynamic
- * \param MaxSizeAtCompileTime the dimension of the matrix, or Dynamic. This parameter is optional and defaults
- * to SizeAtCompileTime. Most of the time, you do not need to specify it.
- *
- * \sa class DiagonalWrapper
- */
-
-namespace internal {
-template<typename _Scalar, int SizeAtCompileTime, int MaxSizeAtCompileTime>
-struct traits<DiagonalMatrix<_Scalar,SizeAtCompileTime,MaxSizeAtCompileTime> >
- : traits<Matrix<_Scalar,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> >
-{
- typedef Matrix<_Scalar,SizeAtCompileTime,1,0,MaxSizeAtCompileTime,1> DiagonalVectorType;
- typedef Dense StorageKind;
- typedef DenseIndex Index;
- enum {
- Flags = LvalueBit
- };
-};
-}
-template<typename _Scalar, int SizeAtCompileTime, int MaxSizeAtCompileTime>
-class DiagonalMatrix
- : public DiagonalBase<DiagonalMatrix<_Scalar,SizeAtCompileTime,MaxSizeAtCompileTime> >
-{
- public:
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- typedef typename internal::traits<DiagonalMatrix>::DiagonalVectorType DiagonalVectorType;
- typedef const DiagonalMatrix& Nested;
- typedef _Scalar Scalar;
- typedef typename internal::traits<DiagonalMatrix>::StorageKind StorageKind;
- typedef typename internal::traits<DiagonalMatrix>::Index Index;
- #endif
-
- protected:
-
- DiagonalVectorType m_diagonal;
-
- public:
-
- /** const version of diagonal(). */
- inline const DiagonalVectorType& diagonal() const { return m_diagonal; }
- /** \returns a reference to the stored vector of diagonal coefficients. */
- inline DiagonalVectorType& diagonal() { return m_diagonal; }
-
- /** Default constructor without initialization */
- inline DiagonalMatrix() {}
-
- /** Constructs a diagonal matrix with given dimension */
- inline DiagonalMatrix(Index dim) : m_diagonal(dim) {}
-
- /** 2D constructor. */
- inline DiagonalMatrix(const Scalar& x, const Scalar& y) : m_diagonal(x,y) {}
-
- /** 3D constructor. */
- inline DiagonalMatrix(const Scalar& x, const Scalar& y, const Scalar& z) : m_diagonal(x,y,z) {}
-
- /** Copy constructor. */
- template<typename OtherDerived>
- inline DiagonalMatrix(const DiagonalBase<OtherDerived>& other) : m_diagonal(other.diagonal()) {}
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- /** copy constructor. prevent a default copy constructor from hiding the other templated constructor */
- inline DiagonalMatrix(const DiagonalMatrix& other) : m_diagonal(other.diagonal()) {}
- #endif
-
- /** generic constructor from expression of the diagonal coefficients */
- template<typename OtherDerived>
- explicit inline DiagonalMatrix(const MatrixBase<OtherDerived>& other) : m_diagonal(other)
- {}
-
- /** Copy operator. */
- template<typename OtherDerived>
- DiagonalMatrix& operator=(const DiagonalBase<OtherDerived>& other)
- {
- m_diagonal = other.diagonal();
- return *this;
- }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- /** This is a special case of the templated operator=. Its purpose is to
- * prevent a default operator= from hiding the templated operator=.
- */
- DiagonalMatrix& operator=(const DiagonalMatrix& other)
- {
- m_diagonal = other.diagonal();
- return *this;
- }
- #endif
-
- /** Resizes to given size. */
- inline void resize(Index size) { m_diagonal.resize(size); }
- /** Sets all coefficients to zero. */
- inline void setZero() { m_diagonal.setZero(); }
- /** Resizes and sets all coefficients to zero. */
- inline void setZero(Index size) { m_diagonal.setZero(size); }
- /** Sets this matrix to be the identity matrix of the current size. */
- inline void setIdentity() { m_diagonal.setOnes(); }
- /** Sets this matrix to be the identity matrix of the given size. */
- inline void setIdentity(Index size) { m_diagonal.setOnes(size); }
-};
-
-/** \class DiagonalWrapper
- * \ingroup Core_Module
- *
- * \brief Expression of a diagonal matrix
- *
- * \param _DiagonalVectorType the type of the vector of diagonal coefficients
- *
- * This class is an expression of a diagonal matrix, but not storing its own vector of diagonal coefficients,
- * instead wrapping an existing vector expression. It is the return type of MatrixBase::asDiagonal()
- * and most of the time this is the only way that it is used.
- *
- * \sa class DiagonalMatrix, class DiagonalBase, MatrixBase::asDiagonal()
- */
-
-namespace internal {
-template<typename _DiagonalVectorType>
-struct traits<DiagonalWrapper<_DiagonalVectorType> >
-{
- typedef _DiagonalVectorType DiagonalVectorType;
- typedef typename DiagonalVectorType::Scalar Scalar;
- typedef typename DiagonalVectorType::Index Index;
- typedef typename DiagonalVectorType::StorageKind StorageKind;
- enum {
- RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
- ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
- MaxRowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
- MaxColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
- Flags = traits<DiagonalVectorType>::Flags & LvalueBit
- };
-};
-}
-
-template<typename _DiagonalVectorType>
-class DiagonalWrapper
- : public DiagonalBase<DiagonalWrapper<_DiagonalVectorType> >, internal::no_assignment_operator
-{
- public:
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- typedef _DiagonalVectorType DiagonalVectorType;
- typedef DiagonalWrapper Nested;
- #endif
-
- /** Constructor from expression of diagonal coefficients to wrap. */
- inline DiagonalWrapper(const DiagonalVectorType& diagonal) : m_diagonal(diagonal) {}
-
- /** \returns a const reference to the wrapped expression of diagonal coefficients. */
- const DiagonalVectorType& diagonal() const { return m_diagonal; }
-
- protected:
- const typename DiagonalVectorType::Nested m_diagonal;
-};
-
-/** \returns a pseudo-expression of a diagonal matrix with *this as vector of diagonal coefficients
- *
- * \only_for_vectors
- *
- * Example: \include MatrixBase_asDiagonal.cpp
- * Output: \verbinclude MatrixBase_asDiagonal.out
- *
- * \sa class DiagonalWrapper, class DiagonalMatrix, diagonal(), isDiagonal()
- **/
-template<typename Derived>
-inline const DiagonalWrapper<const Derived>
-MatrixBase<Derived>::asDiagonal() const
-{
- return derived();
-}
-
-/** \returns true if *this is approximately equal to a diagonal matrix,
- * within the precision given by \a prec.
- *
- * Example: \include MatrixBase_isDiagonal.cpp
- * Output: \verbinclude MatrixBase_isDiagonal.out
- *
- * \sa asDiagonal()
- */
-template<typename Derived>
-bool MatrixBase<Derived>::isDiagonal(RealScalar prec) const
-{
- if(cols() != rows()) return false;
- RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1);
- for(Index j = 0; j < cols(); ++j)
- {
- RealScalar absOnDiagonal = internal::abs(coeff(j,j));
- if(absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal;
- }
- for(Index j = 0; j < cols(); ++j)
- for(Index i = 0; i < j; ++i)
- {
- if(!internal::isMuchSmallerThan(coeff(i, j), maxAbsOnDiagonal, prec)) return false;
- if(!internal::isMuchSmallerThan(coeff(j, i), maxAbsOnDiagonal, prec)) return false;
- }
- return true;
-}
-
-#endif // EIGEN_DIAGONALMATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Core/DiagonalProduct.h b/extern/Eigen3/Eigen/src/Core/DiagonalProduct.h
deleted file mode 100644
index de0c6ed11b7..00000000000
--- a/extern/Eigen3/Eigen/src/Core/DiagonalProduct.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_DIAGONALPRODUCT_H
-#define EIGEN_DIAGONALPRODUCT_H
-
-namespace internal {
-template<typename MatrixType, typename DiagonalType, int ProductOrder>
-struct traits<DiagonalProduct<MatrixType, DiagonalType, ProductOrder> >
- : traits<MatrixType>
-{
- typedef typename scalar_product_traits<typename MatrixType::Scalar, typename DiagonalType::Scalar>::ReturnType Scalar;
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
-
- _StorageOrder = MatrixType::Flags & RowMajorBit ? RowMajor : ColMajor,
- _PacketOnDiag = !((int(_StorageOrder) == RowMajor && int(ProductOrder) == OnTheLeft)
- ||(int(_StorageOrder) == ColMajor && int(ProductOrder) == OnTheRight)),
- _SameTypes = is_same<typename MatrixType::Scalar, typename DiagonalType::Scalar>::value,
- // FIXME currently we need same types, but in the future the next rule should be the one
- //_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && ((!_PacketOnDiag) || (_SameTypes && bool(int(DiagonalType::Flags)&PacketAccessBit))),
- _Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && _SameTypes && ((!_PacketOnDiag) || (bool(int(DiagonalType::Flags)&PacketAccessBit))),
-
- Flags = (HereditaryBits & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0),
- CoeffReadCost = NumTraits<Scalar>::MulCost + MatrixType::CoeffReadCost + DiagonalType::DiagonalVectorType::CoeffReadCost
- };
-};
-}
-
-template<typename MatrixType, typename DiagonalType, int ProductOrder>
-class DiagonalProduct : internal::no_assignment_operator,
- public MatrixBase<DiagonalProduct<MatrixType, DiagonalType, ProductOrder> >
-{
- public:
-
- typedef MatrixBase<DiagonalProduct> Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(DiagonalProduct)
-
- inline DiagonalProduct(const MatrixType& matrix, const DiagonalType& diagonal)
- : m_matrix(matrix), m_diagonal(diagonal)
- {
- eigen_assert(diagonal.diagonal().size() == (ProductOrder == OnTheLeft ? matrix.rows() : matrix.cols()));
- }
-
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
-
- const Scalar coeff(Index row, Index col) const
- {
- return m_diagonal.diagonal().coeff(ProductOrder == OnTheLeft ? row : col) * m_matrix.coeff(row, col);
- }
-
- template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
- {
- enum {
- StorageOrder = Flags & RowMajorBit ? RowMajor : ColMajor
- };
- const Index indexInDiagonalVector = ProductOrder == OnTheLeft ? row : col;
-
- return packet_impl<LoadMode>(row,col,indexInDiagonalVector,typename internal::conditional<
- ((int(StorageOrder) == RowMajor && int(ProductOrder) == OnTheLeft)
- ||(int(StorageOrder) == ColMajor && int(ProductOrder) == OnTheRight)), internal::true_type, internal::false_type>::type());
- }
-
- protected:
- template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet_impl(Index row, Index col, Index id, internal::true_type) const
- {
- return internal::pmul(m_matrix.template packet<LoadMode>(row, col),
- internal::pset1<PacketScalar>(m_diagonal.diagonal().coeff(id)));
- }
-
- template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet_impl(Index row, Index col, Index id, internal::false_type) const
- {
- enum {
- InnerSize = (MatrixType::Flags & RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime,
- DiagonalVectorPacketLoadMode = (LoadMode == Aligned && ((InnerSize%16) == 0)) ? Aligned : Unaligned
- };
- return internal::pmul(m_matrix.template packet<LoadMode>(row, col),
- m_diagonal.diagonal().template packet<DiagonalVectorPacketLoadMode>(id));
- }
-
- const typename MatrixType::Nested m_matrix;
- const typename DiagonalType::Nested m_diagonal;
-};
-
-/** \returns the diagonal matrix product of \c *this by the diagonal matrix \a diagonal.
- */
-template<typename Derived>
-template<typename DiagonalDerived>
-inline const DiagonalProduct<Derived, DiagonalDerived, OnTheRight>
-MatrixBase<Derived>::operator*(const DiagonalBase<DiagonalDerived> &diagonal) const
-{
- return DiagonalProduct<Derived, DiagonalDerived, OnTheRight>(derived(), diagonal.derived());
-}
-
-/** \returns the diagonal matrix product of \c *this by the matrix \a matrix.
- */
-template<typename DiagonalDerived>
-template<typename MatrixDerived>
-inline const DiagonalProduct<MatrixDerived, DiagonalDerived, OnTheLeft>
-DiagonalBase<DiagonalDerived>::operator*(const MatrixBase<MatrixDerived> &matrix) const
-{
- return DiagonalProduct<MatrixDerived, DiagonalDerived, OnTheLeft>(matrix.derived(), derived());
-}
-
-
-#endif // EIGEN_DIAGONALPRODUCT_H
diff --git a/extern/Eigen3/Eigen/src/Core/Dot.h b/extern/Eigen3/Eigen/src/Core/Dot.h
deleted file mode 100644
index 42da7849896..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Dot.h
+++ /dev/null
@@ -1,272 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2006-2008, 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_DOT_H
-#define EIGEN_DOT_H
-
-namespace internal {
-
-// helper function for dot(). The problem is that if we put that in the body of dot(), then upon calling dot
-// with mismatched types, the compiler emits errors about failing to instantiate cwiseProduct BEFORE
-// looking at the static assertions. Thus this is a trick to get better compile errors.
-template<typename T, typename U,
-// the NeedToTranspose condition here is taken straight from Assign.h
- bool NeedToTranspose = T::IsVectorAtCompileTime
- && U::IsVectorAtCompileTime
- && ((int(T::RowsAtCompileTime) == 1 && int(U::ColsAtCompileTime) == 1)
- | // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
- // revert to || as soon as not needed anymore.
- (int(T::ColsAtCompileTime) == 1 && int(U::RowsAtCompileTime) == 1))
->
-struct dot_nocheck
-{
- typedef typename scalar_product_traits<typename traits<T>::Scalar,typename traits<U>::Scalar>::ReturnType ResScalar;
- static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
- {
- return a.template binaryExpr<scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> >(b).sum();
- }
-};
-
-template<typename T, typename U>
-struct dot_nocheck<T, U, true>
-{
- typedef typename scalar_product_traits<typename traits<T>::Scalar,typename traits<U>::Scalar>::ReturnType ResScalar;
- static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
- {
- return a.transpose().template binaryExpr<scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> >(b).sum();
- }
-};
-
-} // end namespace internal
-
-/** \returns the dot product of *this with other.
- *
- * \only_for_vectors
- *
- * \note If the scalar type is complex numbers, then this function returns the hermitian
- * (sesquilinear) dot product, conjugate-linear in the first variable and linear in the
- * second variable.
- *
- * \sa squaredNorm(), norm()
- */
-template<typename Derived>
-template<typename OtherDerived>
-typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
-MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
- EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
- typedef internal::scalar_conj_product_op<Scalar,typename OtherDerived::Scalar> func;
- EIGEN_CHECK_BINARY_COMPATIBILIY(func,Scalar,typename OtherDerived::Scalar);
-
- eigen_assert(size() == other.size());
-
- return internal::dot_nocheck<Derived,OtherDerived>::run(*this, other);
-}
-
-#ifdef EIGEN2_SUPPORT
-/** \returns the dot product of *this with other, with the Eigen2 convention that the dot product is linear in the first variable
- * (conjugating the second variable). Of course this only makes a difference in the complex case.
- *
- * This method is only available in EIGEN2_SUPPORT mode.
- *
- * \only_for_vectors
- *
- * \sa dot()
- */
-template<typename Derived>
-template<typename OtherDerived>
-typename internal::traits<Derived>::Scalar
-MatrixBase<Derived>::eigen2_dot(const MatrixBase<OtherDerived>& other) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
- EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
- EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
- YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
-
- eigen_assert(size() == other.size());
-
- return internal::dot_nocheck<OtherDerived,Derived>::run(other,*this);
-}
-#endif
-
-
-//---------- implementation of L2 norm and related functions ----------
-
-/** \returns, for vectors, the squared \em l2 norm of \c *this, and for matrices the Frobenius norm.
- * In both cases, it consists in the sum of the square of all the matrix entries.
- * For vectors, this is also equals to the dot product of \c *this with itself.
- *
- * \sa dot(), norm()
- */
-template<typename Derived>
-EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::squaredNorm() const
-{
- return internal::real((*this).cwiseAbs2().sum());
-}
-
-/** \returns, for vectors, the \em l2 norm of \c *this, and for matrices the Frobenius norm.
- * In both cases, it consists in the square root of the sum of the square of all the matrix entries.
- * For vectors, this is also equals to the square root of the dot product of \c *this with itself.
- *
- * \sa dot(), squaredNorm()
- */
-template<typename Derived>
-inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const
-{
- return internal::sqrt(squaredNorm());
-}
-
-/** \returns an expression of the quotient of *this by its own norm.
- *
- * \only_for_vectors
- *
- * \sa norm(), normalize()
- */
-template<typename Derived>
-inline const typename MatrixBase<Derived>::PlainObject
-MatrixBase<Derived>::normalized() const
-{
- typedef typename internal::nested<Derived>::type Nested;
- typedef typename internal::remove_reference<Nested>::type _Nested;
- _Nested n(derived());
- return n / n.norm();
-}
-
-/** Normalizes the vector, i.e. divides it by its own norm.
- *
- * \only_for_vectors
- *
- * \sa norm(), normalized()
- */
-template<typename Derived>
-inline void MatrixBase<Derived>::normalize()
-{
- *this /= norm();
-}
-
-//---------- implementation of other norms ----------
-
-namespace internal {
-
-template<typename Derived, int p>
-struct lpNorm_selector
-{
- typedef typename NumTraits<typename traits<Derived>::Scalar>::Real RealScalar;
- inline static RealScalar run(const MatrixBase<Derived>& m)
- {
- return pow(m.cwiseAbs().array().pow(p).sum(), RealScalar(1)/p);
- }
-};
-
-template<typename Derived>
-struct lpNorm_selector<Derived, 1>
-{
- inline static typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
- {
- return m.cwiseAbs().sum();
- }
-};
-
-template<typename Derived>
-struct lpNorm_selector<Derived, 2>
-{
- inline static typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
- {
- return m.norm();
- }
-};
-
-template<typename Derived>
-struct lpNorm_selector<Derived, Infinity>
-{
- inline static typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
- {
- return m.cwiseAbs().maxCoeff();
- }
-};
-
-} // end namespace internal
-
-/** \returns the \f$ \ell^p \f$ norm of *this, that is, returns the p-th root of the sum of the p-th powers of the absolute values
- * of the coefficients of *this. If \a p is the special value \a Eigen::Infinity, this function returns the \f$ \ell^\infty \f$
- * norm, that is the maximum of the absolute values of the coefficients of *this.
- *
- * \sa norm()
- */
-template<typename Derived>
-template<int p>
-inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
-MatrixBase<Derived>::lpNorm() const
-{
- return internal::lpNorm_selector<Derived, p>::run(*this);
-}
-
-//---------- implementation of isOrthogonal / isUnitary ----------
-
-/** \returns true if *this is approximately orthogonal to \a other,
- * within the precision given by \a prec.
- *
- * Example: \include MatrixBase_isOrthogonal.cpp
- * Output: \verbinclude MatrixBase_isOrthogonal.out
- */
-template<typename Derived>
-template<typename OtherDerived>
-bool MatrixBase<Derived>::isOrthogonal
-(const MatrixBase<OtherDerived>& other, RealScalar prec) const
-{
- typename internal::nested<Derived,2>::type nested(derived());
- typename internal::nested<OtherDerived,2>::type otherNested(other.derived());
- return internal::abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm();
-}
-
-/** \returns true if *this is approximately an unitary matrix,
- * within the precision given by \a prec. In the case where the \a Scalar
- * type is real numbers, a unitary matrix is an orthogonal matrix, whence the name.
- *
- * \note This can be used to check whether a family of vectors forms an orthonormal basis.
- * Indeed, \c m.isUnitary() returns true if and only if the columns (equivalently, the rows) of m form an
- * orthonormal basis.
- *
- * Example: \include MatrixBase_isUnitary.cpp
- * Output: \verbinclude MatrixBase_isUnitary.out
- */
-template<typename Derived>
-bool MatrixBase<Derived>::isUnitary(RealScalar prec) const
-{
- typename Derived::Nested nested(derived());
- for(Index i = 0; i < cols(); ++i)
- {
- if(!internal::isApprox(nested.col(i).squaredNorm(), static_cast<RealScalar>(1), prec))
- return false;
- for(Index j = 0; j < i; ++j)
- if(!internal::isMuchSmallerThan(nested.col(i).dot(nested.col(j)), static_cast<Scalar>(1), prec))
- return false;
- }
- return true;
-}
-
-#endif // EIGEN_DOT_H
diff --git a/extern/Eigen3/Eigen/src/Core/EigenBase.h b/extern/Eigen3/Eigen/src/Core/EigenBase.h
deleted file mode 100644
index 0472539af33..00000000000
--- a/extern/Eigen3/Eigen/src/Core/EigenBase.h
+++ /dev/null
@@ -1,172 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_EIGENBASE_H
-#define EIGEN_EIGENBASE_H
-
-
-/** Common base class for all classes T such that MatrixBase has an operator=(T) and a constructor MatrixBase(T).
- *
- * In other words, an EigenBase object is an object that can be copied into a MatrixBase.
- *
- * Besides MatrixBase-derived classes, this also includes special matrix classes such as diagonal matrices, etc.
- *
- * Notice that this class is trivial, it is only used to disambiguate overloaded functions.
- *
- * \sa \ref TopicClassHierarchy
- */
-template<typename Derived> struct EigenBase
-{
-// typedef typename internal::plain_matrix_type<Derived>::type PlainObject;
-
- typedef typename internal::traits<Derived>::StorageKind StorageKind;
- typedef typename internal::traits<Derived>::Index Index;
-
- /** \returns a reference to the derived object */
- Derived& derived() { return *static_cast<Derived*>(this); }
- /** \returns a const reference to the derived object */
- const Derived& derived() const { return *static_cast<const Derived*>(this); }
-
- inline Derived& const_cast_derived() const
- { return *static_cast<Derived*>(const_cast<EigenBase*>(this)); }
- inline const Derived& const_derived() const
- { return *static_cast<const Derived*>(this); }
-
- /** \returns the number of rows. \sa cols(), RowsAtCompileTime */
- inline Index rows() const { return derived().rows(); }
- /** \returns the number of columns. \sa rows(), ColsAtCompileTime*/
- inline Index cols() const { return derived().cols(); }
- /** \returns the number of coefficients, which is rows()*cols().
- * \sa rows(), cols(), SizeAtCompileTime. */
- inline Index size() const { return rows() * cols(); }
-
- /** \internal Don't use it, but do the equivalent: \code dst = *this; \endcode */
- template<typename Dest> inline void evalTo(Dest& dst) const
- { derived().evalTo(dst); }
-
- /** \internal Don't use it, but do the equivalent: \code dst += *this; \endcode */
- template<typename Dest> inline void addTo(Dest& dst) const
- {
- // This is the default implementation,
- // derived class can reimplement it in a more optimized way.
- typename Dest::PlainObject res(rows(),cols());
- evalTo(res);
- dst += res;
- }
-
- /** \internal Don't use it, but do the equivalent: \code dst -= *this; \endcode */
- template<typename Dest> inline void subTo(Dest& dst) const
- {
- // This is the default implementation,
- // derived class can reimplement it in a more optimized way.
- typename Dest::PlainObject res(rows(),cols());
- evalTo(res);
- dst -= res;
- }
-
- /** \internal Don't use it, but do the equivalent: \code dst.applyOnTheRight(*this); \endcode */
- template<typename Dest> inline void applyThisOnTheRight(Dest& dst) const
- {
- // This is the default implementation,
- // derived class can reimplement it in a more optimized way.
- dst = dst * this->derived();
- }
-
- /** \internal Don't use it, but do the equivalent: \code dst.applyOnTheLeft(*this); \endcode */
- template<typename Dest> inline void applyThisOnTheLeft(Dest& dst) const
- {
- // This is the default implementation,
- // derived class can reimplement it in a more optimized way.
- dst = this->derived() * dst;
- }
-
-};
-
-/***************************************************************************
-* Implementation of matrix base methods
-***************************************************************************/
-
-/** \brief Copies the generic expression \a other into *this.
- *
- * \details The expression must provide a (templated) evalTo(Derived& dst) const
- * function which does the actual job. In practice, this allows any user to write
- * its own special matrix without having to modify MatrixBase
- *
- * \returns a reference to *this.
- */
-template<typename Derived>
-template<typename OtherDerived>
-Derived& DenseBase<Derived>::operator=(const EigenBase<OtherDerived> &other)
-{
- other.derived().evalTo(derived());
- return derived();
-}
-
-template<typename Derived>
-template<typename OtherDerived>
-Derived& DenseBase<Derived>::operator+=(const EigenBase<OtherDerived> &other)
-{
- other.derived().addTo(derived());
- return derived();
-}
-
-template<typename Derived>
-template<typename OtherDerived>
-Derived& DenseBase<Derived>::operator-=(const EigenBase<OtherDerived> &other)
-{
- other.derived().subTo(derived());
- return derived();
-}
-
-/** replaces \c *this by \c *this * \a other.
- *
- * \returns a reference to \c *this
- */
-template<typename Derived>
-template<typename OtherDerived>
-inline Derived&
-MatrixBase<Derived>::operator*=(const EigenBase<OtherDerived> &other)
-{
- other.derived().applyThisOnTheRight(derived());
- return derived();
-}
-
-/** replaces \c *this by \c *this * \a other. It is equivalent to MatrixBase::operator*=() */
-template<typename Derived>
-template<typename OtherDerived>
-inline void MatrixBase<Derived>::applyOnTheRight(const EigenBase<OtherDerived> &other)
-{
- other.derived().applyThisOnTheRight(derived());
-}
-
-/** replaces \c *this by \c *this * \a other. */
-template<typename Derived>
-template<typename OtherDerived>
-inline void MatrixBase<Derived>::applyOnTheLeft(const EigenBase<OtherDerived> &other)
-{
- other.derived().applyThisOnTheLeft(derived());
-}
-
-#endif // EIGEN_EIGENBASE_H
diff --git a/extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h b/extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h
deleted file mode 100644
index 11c1f8f709a..00000000000
--- a/extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h
+++ /dev/null
@@ -1,157 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_FORCEALIGNEDACCESS_H
-#define EIGEN_FORCEALIGNEDACCESS_H
-
-/** \class ForceAlignedAccess
- * \ingroup Core_Module
- *
- * \brief Enforce aligned packet loads and stores regardless of what is requested
- *
- * \param ExpressionType the type of the object of which we are forcing aligned packet access
- *
- * This class is the return type of MatrixBase::forceAlignedAccess()
- * and most of the time this is the only way it is used.
- *
- * \sa MatrixBase::forceAlignedAccess()
- */
-
-namespace internal {
-template<typename ExpressionType>
-struct traits<ForceAlignedAccess<ExpressionType> > : public traits<ExpressionType>
-{};
-}
-
-template<typename ExpressionType> class ForceAlignedAccess
- : public internal::dense_xpr_base< ForceAlignedAccess<ExpressionType> >::type
-{
- public:
-
- typedef typename internal::dense_xpr_base<ForceAlignedAccess>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(ForceAlignedAccess)
-
- inline ForceAlignedAccess(const ExpressionType& matrix) : m_expression(matrix) {}
-
- inline Index rows() const { return m_expression.rows(); }
- inline Index cols() const { return m_expression.cols(); }
- inline Index outerStride() const { return m_expression.outerStride(); }
- inline Index innerStride() const { return m_expression.innerStride(); }
-
- inline const CoeffReturnType coeff(Index row, Index col) const
- {
- return m_expression.coeff(row, col);
- }
-
- inline Scalar& coeffRef(Index row, Index col)
- {
- return m_expression.const_cast_derived().coeffRef(row, col);
- }
-
- inline const CoeffReturnType coeff(Index index) const
- {
- return m_expression.coeff(index);
- }
-
- inline Scalar& coeffRef(Index index)
- {
- return m_expression.const_cast_derived().coeffRef(index);
- }
-
- template<int LoadMode>
- inline const PacketScalar packet(Index row, Index col) const
- {
- return m_expression.template packet<Aligned>(row, col);
- }
-
- template<int LoadMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
- {
- m_expression.const_cast_derived().template writePacket<Aligned>(row, col, x);
- }
-
- template<int LoadMode>
- inline const PacketScalar packet(Index index) const
- {
- return m_expression.template packet<Aligned>(index);
- }
-
- template<int LoadMode>
- inline void writePacket(Index index, const PacketScalar& x)
- {
- m_expression.const_cast_derived().template writePacket<Aligned>(index, x);
- }
-
- operator const ExpressionType&() const { return m_expression; }
-
- protected:
- const ExpressionType& m_expression;
-
- private:
- ForceAlignedAccess& operator=(const ForceAlignedAccess&);
-};
-
-/** \returns an expression of *this with forced aligned access
- * \sa forceAlignedAccessIf(),class ForceAlignedAccess
- */
-template<typename Derived>
-inline const ForceAlignedAccess<Derived>
-MatrixBase<Derived>::forceAlignedAccess() const
-{
- return ForceAlignedAccess<Derived>(derived());
-}
-
-/** \returns an expression of *this with forced aligned access
- * \sa forceAlignedAccessIf(), class ForceAlignedAccess
- */
-template<typename Derived>
-inline ForceAlignedAccess<Derived>
-MatrixBase<Derived>::forceAlignedAccess()
-{
- return ForceAlignedAccess<Derived>(derived());
-}
-
-/** \returns an expression of *this with forced aligned access if \a Enable is true.
- * \sa forceAlignedAccess(), class ForceAlignedAccess
- */
-template<typename Derived>
-template<bool Enable>
-inline typename internal::add_const_on_value_type<typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type>::type
-MatrixBase<Derived>::forceAlignedAccessIf() const
-{
- return derived();
-}
-
-/** \returns an expression of *this with forced aligned access if \a Enable is true.
- * \sa forceAlignedAccess(), class ForceAlignedAccess
- */
-template<typename Derived>
-template<bool Enable>
-inline typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type
-MatrixBase<Derived>::forceAlignedAccessIf()
-{
- return derived();
-}
-
-#endif // EIGEN_FORCEALIGNEDACCESS_H
diff --git a/extern/Eigen3/Eigen/src/Core/Functors.h b/extern/Eigen3/Eigen/src/Core/Functors.h
deleted file mode 100644
index 54636e0d459..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Functors.h
+++ /dev/null
@@ -1,942 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_FUNCTORS_H
-#define EIGEN_FUNCTORS_H
-
-namespace internal {
-
-// associative functors:
-
-/** \internal
- * \brief Template functor to compute the sum of two scalars
- *
- * \sa class CwiseBinaryOp, MatrixBase::operator+, class VectorwiseOp, MatrixBase::sum()
- */
-template<typename Scalar> struct scalar_sum_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op)
- EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a + b; }
- template<typename Packet>
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
- { return internal::padd(a,b); }
- template<typename Packet>
- EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
- { return internal::predux(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_sum_op<Scalar> > {
- enum {
- Cost = NumTraits<Scalar>::AddCost,
- PacketAccess = packet_traits<Scalar>::HasAdd
- };
-};
-
-/** \internal
- * \brief Template functor to compute the product of two scalars
- *
- * \sa class CwiseBinaryOp, Cwise::operator*(), class VectorwiseOp, MatrixBase::redux()
- */
-template<typename LhsScalar,typename RhsScalar> struct scalar_product_op {
- enum {
- // TODO vectorize mixed product
- Vectorizable = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasMul && packet_traits<RhsScalar>::HasMul
- };
- typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
- EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op)
- EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a * b; }
- template<typename Packet>
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
- { return internal::pmul(a,b); }
- template<typename Packet>
- EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
- { return internal::predux_mul(a); }
-};
-template<typename LhsScalar,typename RhsScalar>
-struct functor_traits<scalar_product_op<LhsScalar,RhsScalar> > {
- enum {
- Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost)/2, // rough estimate!
- PacketAccess = scalar_product_op<LhsScalar,RhsScalar>::Vectorizable
- };
-};
-
-/** \internal
- * \brief Template functor to compute the conjugate product of two scalars
- *
- * This is a short cut for conj(x) * y which is needed for optimization purpose; in Eigen2 support mode, this becomes x * conj(y)
- */
-template<typename LhsScalar,typename RhsScalar> struct scalar_conj_product_op {
-
- enum {
- Conj = NumTraits<LhsScalar>::IsComplex
- };
-
- typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
-
- EIGEN_EMPTY_STRUCT_CTOR(scalar_conj_product_op)
- EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const
- { return conj_helper<LhsScalar,RhsScalar,Conj,false>().pmul(a,b); }
-
- template<typename Packet>
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
- { return conj_helper<Packet,Packet,Conj,false>().pmul(a,b); }
-};
-template<typename LhsScalar,typename RhsScalar>
-struct functor_traits<scalar_conj_product_op<LhsScalar,RhsScalar> > {
- enum {
- Cost = NumTraits<LhsScalar>::MulCost,
- PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMul
- };
-};
-
-/** \internal
- * \brief Template functor to compute the min of two scalars
- *
- * \sa class CwiseBinaryOp, MatrixBase::cwiseMin, class VectorwiseOp, MatrixBase::minCoeff()
- */
-template<typename Scalar> struct scalar_min_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op)
- EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { using std::min; return (min)(a, b); }
- template<typename Packet>
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
- { return internal::pmin(a,b); }
- template<typename Packet>
- EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
- { return internal::predux_min(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_min_op<Scalar> > {
- enum {
- Cost = NumTraits<Scalar>::AddCost,
- PacketAccess = packet_traits<Scalar>::HasMin
- };
-};
-
-/** \internal
- * \brief Template functor to compute the max of two scalars
- *
- * \sa class CwiseBinaryOp, MatrixBase::cwiseMax, class VectorwiseOp, MatrixBase::maxCoeff()
- */
-template<typename Scalar> struct scalar_max_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op)
- EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { using std::max; return (max)(a, b); }
- template<typename Packet>
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
- { return internal::pmax(a,b); }
- template<typename Packet>
- EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
- { return internal::predux_max(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_max_op<Scalar> > {
- enum {
- Cost = NumTraits<Scalar>::AddCost,
- PacketAccess = packet_traits<Scalar>::HasMax
- };
-};
-
-/** \internal
- * \brief Template functor to compute the hypot of two scalars
- *
- * \sa MatrixBase::stableNorm(), class Redux
- */
-template<typename Scalar> struct scalar_hypot_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op)
-// typedef typename NumTraits<Scalar>::Real result_type;
- EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const
- {
- using std::max;
- using std::min;
- Scalar p = (max)(_x, _y);
- Scalar q = (min)(_x, _y);
- Scalar qp = q/p;
- return p * sqrt(Scalar(1) + qp*qp);
- }
-};
-template<typename Scalar>
-struct functor_traits<scalar_hypot_op<Scalar> > {
- enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess=0 };
-};
-
-// other binary functors:
-
-/** \internal
- * \brief Template functor to compute the difference of two scalars
- *
- * \sa class CwiseBinaryOp, MatrixBase::operator-
- */
-template<typename Scalar> struct scalar_difference_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op)
- EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a - b; }
- template<typename Packet>
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
- { return internal::psub(a,b); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_difference_op<Scalar> > {
- enum {
- Cost = NumTraits<Scalar>::AddCost,
- PacketAccess = packet_traits<Scalar>::HasSub
- };
-};
-
-/** \internal
- * \brief Template functor to compute the quotient of two scalars
- *
- * \sa class CwiseBinaryOp, Cwise::operator/()
- */
-template<typename Scalar> struct scalar_quotient_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
- EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a / b; }
- template<typename Packet>
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
- { return internal::pdiv(a,b); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_quotient_op<Scalar> > {
- enum {
- Cost = 2 * NumTraits<Scalar>::MulCost,
- PacketAccess = packet_traits<Scalar>::HasDiv
- };
-};
-
-// unary functors:
-
-/** \internal
- * \brief Template functor to compute the opposite of a scalar
- *
- * \sa class CwiseUnaryOp, MatrixBase::operator-
- */
-template<typename Scalar> struct scalar_opposite_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_opposite_op)
- EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return -a; }
- template<typename Packet>
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
- { return internal::pnegate(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_opposite_op<Scalar> >
-{ enum {
- Cost = NumTraits<Scalar>::AddCost,
- PacketAccess = packet_traits<Scalar>::HasNegate };
-};
-
-/** \internal
- * \brief Template functor to compute the absolute value of a scalar
- *
- * \sa class CwiseUnaryOp, Cwise::abs
- */
-template<typename Scalar> struct scalar_abs_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_abs_op)
- typedef typename NumTraits<Scalar>::Real result_type;
- EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return abs(a); }
- template<typename Packet>
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
- { return internal::pabs(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_abs_op<Scalar> >
-{
- enum {
- Cost = NumTraits<Scalar>::AddCost,
- PacketAccess = packet_traits<Scalar>::HasAbs
- };
-};
-
-/** \internal
- * \brief Template functor to compute the squared absolute value of a scalar
- *
- * \sa class CwiseUnaryOp, Cwise::abs2
- */
-template<typename Scalar> struct scalar_abs2_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op)
- typedef typename NumTraits<Scalar>::Real result_type;
- EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return abs2(a); }
- template<typename Packet>
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
- { return internal::pmul(a,a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_abs2_op<Scalar> >
-{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasAbs2 }; };
-
-/** \internal
- * \brief Template functor to compute the conjugate of a complex value
- *
- * \sa class CwiseUnaryOp, MatrixBase::conjugate()
- */
-template<typename Scalar> struct scalar_conjugate_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op)
- EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return conj(a); }
- template<typename Packet>
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_conjugate_op<Scalar> >
-{
- enum {
- Cost = NumTraits<Scalar>::IsComplex ? NumTraits<Scalar>::AddCost : 0,
- PacketAccess = packet_traits<Scalar>::HasConj
- };
-};
-
-/** \internal
- * \brief Template functor to cast a scalar to another type
- *
- * \sa class CwiseUnaryOp, MatrixBase::cast()
- */
-template<typename Scalar, typename NewType>
-struct scalar_cast_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_cast_op)
- typedef NewType result_type;
- EIGEN_STRONG_INLINE const NewType operator() (const Scalar& a) const { return cast<Scalar, NewType>(a); }
-};
-template<typename Scalar, typename NewType>
-struct functor_traits<scalar_cast_op<Scalar,NewType> >
-{ enum { Cost = is_same<Scalar, NewType>::value ? 0 : NumTraits<NewType>::AddCost, PacketAccess = false }; };
-
-/** \internal
- * \brief Template functor to extract the real part of a complex
- *
- * \sa class CwiseUnaryOp, MatrixBase::real()
- */
-template<typename Scalar>
-struct scalar_real_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op)
- typedef typename NumTraits<Scalar>::Real result_type;
- EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return real(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_real_op<Scalar> >
-{ enum { Cost = 0, PacketAccess = false }; };
-
-/** \internal
- * \brief Template functor to extract the imaginary part of a complex
- *
- * \sa class CwiseUnaryOp, MatrixBase::imag()
- */
-template<typename Scalar>
-struct scalar_imag_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op)
- typedef typename NumTraits<Scalar>::Real result_type;
- EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return imag(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_imag_op<Scalar> >
-{ enum { Cost = 0, PacketAccess = false }; };
-
-/** \internal
- * \brief Template functor to extract the real part of a complex as a reference
- *
- * \sa class CwiseUnaryOp, MatrixBase::real()
- */
-template<typename Scalar>
-struct scalar_real_ref_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op)
- typedef typename NumTraits<Scalar>::Real result_type;
- EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return real_ref(*const_cast<Scalar*>(&a)); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_real_ref_op<Scalar> >
-{ enum { Cost = 0, PacketAccess = false }; };
-
-/** \internal
- * \brief Template functor to extract the imaginary part of a complex as a reference
- *
- * \sa class CwiseUnaryOp, MatrixBase::imag()
- */
-template<typename Scalar>
-struct scalar_imag_ref_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op)
- typedef typename NumTraits<Scalar>::Real result_type;
- EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return imag_ref(*const_cast<Scalar*>(&a)); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_imag_ref_op<Scalar> >
-{ enum { Cost = 0, PacketAccess = false }; };
-
-/** \internal
- *
- * \brief Template functor to compute the exponential of a scalar
- *
- * \sa class CwiseUnaryOp, Cwise::exp()
- */
-template<typename Scalar> struct scalar_exp_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_exp_op)
- inline const Scalar operator() (const Scalar& a) const { return exp(a); }
- typedef typename packet_traits<Scalar>::type Packet;
- inline Packet packetOp(const Packet& a) const { return internal::pexp(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_exp_op<Scalar> >
-{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasExp }; };
-
-/** \internal
- *
- * \brief Template functor to compute the logarithm of a scalar
- *
- * \sa class CwiseUnaryOp, Cwise::log()
- */
-template<typename Scalar> struct scalar_log_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_log_op)
- inline const Scalar operator() (const Scalar& a) const { return log(a); }
- typedef typename packet_traits<Scalar>::type Packet;
- inline Packet packetOp(const Packet& a) const { return internal::plog(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_log_op<Scalar> >
-{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog }; };
-
-/** \internal
- * \brief Template functor to multiply a scalar by a fixed other one
- *
- * \sa class CwiseUnaryOp, MatrixBase::operator*, MatrixBase::operator/
- */
-/* NOTE why doing the pset1() in packetOp *is* an optimization ?
- * indeed it seems better to declare m_other as a Packet and do the pset1() once
- * in the constructor. However, in practice:
- * - GCC does not like m_other as a Packet and generate a load every time it needs it
- * - on the other hand GCC is able to moves the pset1() away the loop :)
- * - simpler code ;)
- * (ICC and gcc 4.4 seems to perform well in both cases, the issue is visible with y = a*x + b*y)
- */
-template<typename Scalar>
-struct scalar_multiple_op {
- typedef typename packet_traits<Scalar>::type Packet;
- // FIXME default copy constructors seems bugged with std::complex<>
- EIGEN_STRONG_INLINE scalar_multiple_op(const scalar_multiple_op& other) : m_other(other.m_other) { }
- EIGEN_STRONG_INLINE scalar_multiple_op(const Scalar& other) : m_other(other) { }
- EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
- { return internal::pmul(a, pset1<Packet>(m_other)); }
- typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
-};
-template<typename Scalar>
-struct functor_traits<scalar_multiple_op<Scalar> >
-{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
-
-template<typename Scalar1, typename Scalar2>
-struct scalar_multiple2_op {
- typedef typename scalar_product_traits<Scalar1,Scalar2>::ReturnType result_type;
- EIGEN_STRONG_INLINE scalar_multiple2_op(const scalar_multiple2_op& other) : m_other(other.m_other) { }
- EIGEN_STRONG_INLINE scalar_multiple2_op(const Scalar2& other) : m_other(other) { }
- EIGEN_STRONG_INLINE result_type operator() (const Scalar1& a) const { return a * m_other; }
- typename add_const_on_value_type<typename NumTraits<Scalar2>::Nested>::type m_other;
-};
-template<typename Scalar1,typename Scalar2>
-struct functor_traits<scalar_multiple2_op<Scalar1,Scalar2> >
-{ enum { Cost = NumTraits<Scalar1>::MulCost, PacketAccess = false }; };
-
-template<typename Scalar, bool IsInteger>
-struct scalar_quotient1_impl {
- typedef typename packet_traits<Scalar>::type Packet;
- // FIXME default copy constructors seems bugged with std::complex<>
- EIGEN_STRONG_INLINE scalar_quotient1_impl(const scalar_quotient1_impl& other) : m_other(other.m_other) { }
- EIGEN_STRONG_INLINE scalar_quotient1_impl(const Scalar& other) : m_other(static_cast<Scalar>(1) / other) {}
- EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
- EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
- { return internal::pmul(a, pset1<Packet>(m_other)); }
- const Scalar m_other;
-};
-template<typename Scalar>
-struct functor_traits<scalar_quotient1_impl<Scalar,false> >
-{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
-
-template<typename Scalar>
-struct scalar_quotient1_impl<Scalar,true> {
- // FIXME default copy constructors seems bugged with std::complex<>
- EIGEN_STRONG_INLINE scalar_quotient1_impl(const scalar_quotient1_impl& other) : m_other(other.m_other) { }
- EIGEN_STRONG_INLINE scalar_quotient1_impl(const Scalar& other) : m_other(other) {}
- EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; }
- typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
-};
-template<typename Scalar>
-struct functor_traits<scalar_quotient1_impl<Scalar,true> >
-{ enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
-
-/** \internal
- * \brief Template functor to divide a scalar by a fixed other one
- *
- * This functor is used to implement the quotient of a matrix by
- * a scalar where the scalar type is not necessarily a floating point type.
- *
- * \sa class CwiseUnaryOp, MatrixBase::operator/
- */
-template<typename Scalar>
-struct scalar_quotient1_op : scalar_quotient1_impl<Scalar, NumTraits<Scalar>::IsInteger > {
- EIGEN_STRONG_INLINE scalar_quotient1_op(const Scalar& other)
- : scalar_quotient1_impl<Scalar, NumTraits<Scalar>::IsInteger >(other) {}
-};
-template<typename Scalar>
-struct functor_traits<scalar_quotient1_op<Scalar> >
-: functor_traits<scalar_quotient1_impl<Scalar, NumTraits<Scalar>::IsInteger> >
-{};
-
-// nullary functors
-
-template<typename Scalar>
-struct scalar_constant_op {
- typedef typename packet_traits<Scalar>::type Packet;
- EIGEN_STRONG_INLINE scalar_constant_op(const scalar_constant_op& other) : m_other(other.m_other) { }
- EIGEN_STRONG_INLINE scalar_constant_op(const Scalar& other) : m_other(other) { }
- template<typename Index>
- EIGEN_STRONG_INLINE const Scalar operator() (Index, Index = 0) const { return m_other; }
- template<typename Index>
- EIGEN_STRONG_INLINE const Packet packetOp(Index, Index = 0) const { return internal::pset1<Packet>(m_other); }
- const Scalar m_other;
-};
-template<typename Scalar>
-struct functor_traits<scalar_constant_op<Scalar> >
-// FIXME replace this packet test by a safe one
-{ enum { Cost = 1, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = true }; };
-
-template<typename Scalar> struct scalar_identity_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_identity_op)
- template<typename Index>
- EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const { return row==col ? Scalar(1) : Scalar(0); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_identity_op<Scalar> >
-{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true }; };
-
-template <typename Scalar, bool RandomAccess> struct linspaced_op_impl;
-
-// linear access for packet ops:
-// 1) initialization
-// base = [low, ..., low] + ([step, ..., step] * [-size, ..., 0])
-// 2) each step
-// base += [size*step, ..., size*step]
-template <typename Scalar>
-struct linspaced_op_impl<Scalar,false>
-{
- typedef typename packet_traits<Scalar>::type Packet;
-
- linspaced_op_impl(Scalar low, Scalar step) :
- m_low(low), m_step(step),
- m_packetStep(pset1<Packet>(packet_traits<Scalar>::size*step)),
- m_base(padd(pset1<Packet>(low),pmul(pset1<Packet>(step),plset<Scalar>(-packet_traits<Scalar>::size)))) {}
-
- template<typename Index>
- EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; }
- template<typename Index>
- EIGEN_STRONG_INLINE const Packet packetOp(Index) const { return m_base = padd(m_base,m_packetStep); }
-
- const Scalar m_low;
- const Scalar m_step;
- const Packet m_packetStep;
- mutable Packet m_base;
-};
-
-// random access for packet ops:
-// 1) each step
-// [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) )
-template <typename Scalar>
-struct linspaced_op_impl<Scalar,true>
-{
- typedef typename packet_traits<Scalar>::type Packet;
-
- linspaced_op_impl(Scalar low, Scalar step) :
- m_low(low), m_step(step),
- m_lowPacket(pset1<Packet>(m_low)), m_stepPacket(pset1<Packet>(m_step)), m_interPacket(plset<Scalar>(0)) {}
-
- template<typename Index>
- EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; }
-
- 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))); }
-
- const Scalar m_low;
- const Scalar m_step;
- const Packet m_lowPacket;
- const Packet m_stepPacket;
- const Packet m_interPacket;
-};
-
-// ----- Linspace functor ----------------------------------------------------------------
-
-// Forward declaration (we default to random access which does not really give
-// us a speed gain when using packet access but it allows to use the functor in
-// nested expressions).
-template <typename Scalar, bool RandomAccess = true> struct linspaced_op;
-template <typename Scalar, bool RandomAccess> struct functor_traits< linspaced_op<Scalar,RandomAccess> >
-{ enum { Cost = 1, PacketAccess = packet_traits<Scalar>::HasSetLinear, IsRepeatable = true }; };
-template <typename Scalar, bool RandomAccess> struct linspaced_op
-{
- typedef typename packet_traits<Scalar>::type Packet;
- linspaced_op(Scalar low, Scalar high, int num_steps) : impl(low, (high-low)/(num_steps-1)) {}
-
- template<typename Index>
- EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); }
-
- // We need this function when assigning e.g. a RowVectorXd to a MatrixXd since
- // there row==0 and col is used for the actual iteration.
- template<typename Index>
- EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const
- {
- eigen_assert(col==0 || row==0);
- return impl(col + row);
- }
-
- template<typename Index>
- EIGEN_STRONG_INLINE const Packet packetOp(Index i) const { return impl.packetOp(i); }
-
- // We need this function when assigning e.g. a RowVectorXd to a MatrixXd since
- // there row==0 and col is used for the actual iteration.
- template<typename Index>
- EIGEN_STRONG_INLINE const Packet packetOp(Index row, Index col) const
- {
- eigen_assert(col==0 || row==0);
- return impl.packetOp(col + row);
- }
-
- // This proxy object handles the actual required temporaries, the different
- // implementations (random vs. sequential access) as well as the
- // correct piping to size 2/4 packet operations.
- const linspaced_op_impl<Scalar,RandomAccess> impl;
-};
-
-// all functors allow linear access, except scalar_identity_op. So we fix here a quick meta
-// to indicate whether a functor allows linear access, just always answering 'yes' except for
-// scalar_identity_op.
-// FIXME move this to functor_traits adding a functor_default
-template<typename Functor> struct functor_has_linear_access { enum { ret = 1 }; };
-template<typename Scalar> struct functor_has_linear_access<scalar_identity_op<Scalar> > { enum { ret = 0 }; };
-
-// in CwiseBinaryOp, we require the Lhs and Rhs to have the same scalar type, except for multiplication
-// where we only require them to have the same _real_ scalar type so one may multiply, say, float by complex<float>.
-// FIXME move this to functor_traits adding a functor_default
-template<typename Functor> struct functor_allows_mixing_real_and_complex { enum { ret = 0 }; };
-template<typename LhsScalar,typename RhsScalar> struct functor_allows_mixing_real_and_complex<scalar_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
-template<typename LhsScalar,typename RhsScalar> struct functor_allows_mixing_real_and_complex<scalar_conj_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
-
-
-/** \internal
- * \brief Template functor to add a scalar to a fixed other one
- * \sa class CwiseUnaryOp, Array::operator+
- */
-/* If you wonder why doing the pset1() in packetOp() is an optimization check scalar_multiple_op */
-template<typename Scalar>
-struct scalar_add_op {
- typedef typename packet_traits<Scalar>::type Packet;
- // FIXME default copy constructors seems bugged with std::complex<>
- inline scalar_add_op(const scalar_add_op& other) : m_other(other.m_other) { }
- inline scalar_add_op(const Scalar& other) : m_other(other) { }
- inline Scalar operator() (const Scalar& a) const { return a + m_other; }
- inline const Packet packetOp(const Packet& a) const
- { return internal::padd(a, pset1<Packet>(m_other)); }
- const Scalar m_other;
-};
-template<typename Scalar>
-struct functor_traits<scalar_add_op<Scalar> >
-{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
-
-/** \internal
- * \brief Template functor to compute the square root of a scalar
- * \sa class CwiseUnaryOp, Cwise::sqrt()
- */
-template<typename Scalar> struct scalar_sqrt_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op)
- inline const Scalar operator() (const Scalar& a) const { return sqrt(a); }
- typedef typename packet_traits<Scalar>::type Packet;
- inline Packet packetOp(const Packet& a) const { return internal::psqrt(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_sqrt_op<Scalar> >
-{ enum {
- Cost = 5 * NumTraits<Scalar>::MulCost,
- PacketAccess = packet_traits<Scalar>::HasSqrt
- };
-};
-
-/** \internal
- * \brief Template functor to compute the cosine of a scalar
- * \sa class CwiseUnaryOp, ArrayBase::cos()
- */
-template<typename Scalar> struct scalar_cos_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op)
- inline Scalar operator() (const Scalar& a) const { return cos(a); }
- typedef typename packet_traits<Scalar>::type Packet;
- inline Packet packetOp(const Packet& a) const { return internal::pcos(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_cos_op<Scalar> >
-{
- enum {
- Cost = 5 * NumTraits<Scalar>::MulCost,
- PacketAccess = packet_traits<Scalar>::HasCos
- };
-};
-
-/** \internal
- * \brief Template functor to compute the sine of a scalar
- * \sa class CwiseUnaryOp, ArrayBase::sin()
- */
-template<typename Scalar> struct scalar_sin_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op)
- inline const Scalar operator() (const Scalar& a) const { return sin(a); }
- typedef typename packet_traits<Scalar>::type Packet;
- inline Packet packetOp(const Packet& a) const { return internal::psin(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_sin_op<Scalar> >
-{
- enum {
- Cost = 5 * NumTraits<Scalar>::MulCost,
- PacketAccess = packet_traits<Scalar>::HasSin
- };
-};
-
-
-/** \internal
- * \brief Template functor to compute the tan of a scalar
- * \sa class CwiseUnaryOp, ArrayBase::tan()
- */
-template<typename Scalar> struct scalar_tan_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_tan_op)
- inline const Scalar operator() (const Scalar& a) const { return tan(a); }
- typedef typename packet_traits<Scalar>::type Packet;
- inline Packet packetOp(const Packet& a) const { return internal::ptan(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_tan_op<Scalar> >
-{
- enum {
- Cost = 5 * NumTraits<Scalar>::MulCost,
- PacketAccess = packet_traits<Scalar>::HasTan
- };
-};
-
-/** \internal
- * \brief Template functor to compute the arc cosine of a scalar
- * \sa class CwiseUnaryOp, ArrayBase::acos()
- */
-template<typename Scalar> struct scalar_acos_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_acos_op)
- inline const Scalar operator() (const Scalar& a) const { return acos(a); }
- typedef typename packet_traits<Scalar>::type Packet;
- inline Packet packetOp(const Packet& a) const { return internal::pacos(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_acos_op<Scalar> >
-{
- enum {
- Cost = 5 * NumTraits<Scalar>::MulCost,
- PacketAccess = packet_traits<Scalar>::HasACos
- };
-};
-
-/** \internal
- * \brief Template functor to compute the arc sine of a scalar
- * \sa class CwiseUnaryOp, ArrayBase::asin()
- */
-template<typename Scalar> struct scalar_asin_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op)
- inline const Scalar operator() (const Scalar& a) const { return asin(a); }
- typedef typename packet_traits<Scalar>::type Packet;
- inline Packet packetOp(const Packet& a) const { return internal::pasin(a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_asin_op<Scalar> >
-{
- enum {
- Cost = 5 * NumTraits<Scalar>::MulCost,
- PacketAccess = packet_traits<Scalar>::HasASin
- };
-};
-
-/** \internal
- * \brief Template functor to raise a scalar to a power
- * \sa class CwiseUnaryOp, Cwise::pow
- */
-template<typename Scalar>
-struct scalar_pow_op {
- // FIXME default copy constructors seems bugged with std::complex<>
- inline scalar_pow_op(const scalar_pow_op& other) : m_exponent(other.m_exponent) { }
- inline scalar_pow_op(const Scalar& exponent) : m_exponent(exponent) {}
- inline Scalar operator() (const Scalar& a) const { return internal::pow(a, m_exponent); }
- const Scalar m_exponent;
-};
-template<typename Scalar>
-struct functor_traits<scalar_pow_op<Scalar> >
-{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
-
-/** \internal
- * \brief Template functor to compute the inverse of a scalar
- * \sa class CwiseUnaryOp, Cwise::inverse()
- */
-template<typename Scalar>
-struct scalar_inverse_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_inverse_op)
- inline Scalar operator() (const Scalar& a) const { return Scalar(1)/a; }
- template<typename Packet>
- inline const Packet packetOp(const Packet& a) const
- { return internal::pdiv(pset1<Packet>(Scalar(1)),a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_inverse_op<Scalar> >
-{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; };
-
-/** \internal
- * \brief Template functor to compute the square of a scalar
- * \sa class CwiseUnaryOp, Cwise::square()
- */
-template<typename Scalar>
-struct scalar_square_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_square_op)
- inline Scalar operator() (const Scalar& a) const { return a*a; }
- template<typename Packet>
- inline const Packet packetOp(const Packet& a) const
- { return internal::pmul(a,a); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_square_op<Scalar> >
-{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
-
-/** \internal
- * \brief Template functor to compute the cube of a scalar
- * \sa class CwiseUnaryOp, Cwise::cube()
- */
-template<typename Scalar>
-struct scalar_cube_op {
- EIGEN_EMPTY_STRUCT_CTOR(scalar_cube_op)
- inline Scalar operator() (const Scalar& a) const { return a*a*a; }
- template<typename Packet>
- inline const Packet packetOp(const Packet& a) const
- { return internal::pmul(a,pmul(a,a)); }
-};
-template<typename Scalar>
-struct functor_traits<scalar_cube_op<Scalar> >
-{ enum { Cost = 2*NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
-
-// default functor traits for STL functors:
-
-template<typename T>
-struct functor_traits<std::multiplies<T> >
-{ enum { Cost = NumTraits<T>::MulCost, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::divides<T> >
-{ enum { Cost = NumTraits<T>::MulCost, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::plus<T> >
-{ enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::minus<T> >
-{ enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::negate<T> >
-{ enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::logical_or<T> >
-{ enum { Cost = 1, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::logical_and<T> >
-{ enum { Cost = 1, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::logical_not<T> >
-{ enum { Cost = 1, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::greater<T> >
-{ enum { Cost = 1, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::less<T> >
-{ enum { Cost = 1, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::greater_equal<T> >
-{ enum { Cost = 1, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::less_equal<T> >
-{ enum { Cost = 1, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::equal_to<T> >
-{ enum { Cost = 1, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::not_equal_to<T> >
-{ enum { Cost = 1, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::binder2nd<T> >
-{ enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::binder1st<T> >
-{ enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::unary_negate<T> >
-{ enum { Cost = 1 + functor_traits<T>::Cost, PacketAccess = false }; };
-
-template<typename T>
-struct functor_traits<std::binary_negate<T> >
-{ enum { Cost = 1 + functor_traits<T>::Cost, PacketAccess = false }; };
-
-#ifdef EIGEN_STDEXT_SUPPORT
-
-template<typename T0,typename T1>
-struct functor_traits<std::project1st<T0,T1> >
-{ enum { Cost = 0, PacketAccess = false }; };
-
-template<typename T0,typename T1>
-struct functor_traits<std::project2nd<T0,T1> >
-{ enum { Cost = 0, PacketAccess = false }; };
-
-template<typename T0,typename T1>
-struct functor_traits<std::select2nd<std::pair<T0,T1> > >
-{ enum { Cost = 0, PacketAccess = false }; };
-
-template<typename T0,typename T1>
-struct functor_traits<std::select1st<std::pair<T0,T1> > >
-{ enum { Cost = 0, PacketAccess = false }; };
-
-template<typename T0,typename T1>
-struct functor_traits<std::unary_compose<T0,T1> >
-{ enum { Cost = functor_traits<T0>::Cost + functor_traits<T1>::Cost, PacketAccess = false }; };
-
-template<typename T0,typename T1,typename T2>
-struct functor_traits<std::binary_compose<T0,T1,T2> >
-{ enum { Cost = functor_traits<T0>::Cost + functor_traits<T1>::Cost + functor_traits<T2>::Cost, PacketAccess = false }; };
-
-#endif // EIGEN_STDEXT_SUPPORT
-
-// allow to add new functors and specializations of functor_traits from outside Eigen.
-// this macro is really needed because functor_traits must be specialized after it is declared but before it is used...
-#ifdef EIGEN_FUNCTORS_PLUGIN
-#include EIGEN_FUNCTORS_PLUGIN
-#endif
-
-} // end namespace internal
-
-#endif // EIGEN_FUNCTORS_H
diff --git a/extern/Eigen3/Eigen/src/Core/Fuzzy.h b/extern/Eigen3/Eigen/src/Core/Fuzzy.h
deleted file mode 100644
index d266eed0ac6..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Fuzzy.h
+++ /dev/null
@@ -1,161 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_FUZZY_H
-#define EIGEN_FUZZY_H
-
-namespace internal
-{
-
-template<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger>
-struct isApprox_selector
-{
- static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec)
- {
- using std::min;
- const typename internal::nested<Derived,2>::type nested(x);
- const typename internal::nested<OtherDerived,2>::type otherNested(y);
- return (nested - otherNested).cwiseAbs2().sum() <= prec * prec * (min)(nested.cwiseAbs2().sum(), otherNested.cwiseAbs2().sum());
- }
-};
-
-template<typename Derived, typename OtherDerived>
-struct isApprox_selector<Derived, OtherDerived, true>
-{
- static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar)
- {
- return x.matrix() == y.matrix();
- }
-};
-
-template<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger>
-struct isMuchSmallerThan_object_selector
-{
- static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec)
- {
- return x.cwiseAbs2().sum() <= abs2(prec) * y.cwiseAbs2().sum();
- }
-};
-
-template<typename Derived, typename OtherDerived>
-struct isMuchSmallerThan_object_selector<Derived, OtherDerived, true>
-{
- static bool run(const Derived& x, const OtherDerived&, typename Derived::RealScalar)
- {
- return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix();
- }
-};
-
-template<typename Derived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger>
-struct isMuchSmallerThan_scalar_selector
-{
- static bool run(const Derived& x, const typename Derived::RealScalar& y, typename Derived::RealScalar prec)
- {
- return x.cwiseAbs2().sum() <= abs2(prec * y);
- }
-};
-
-template<typename Derived>
-struct isMuchSmallerThan_scalar_selector<Derived, true>
-{
- static bool run(const Derived& x, const typename Derived::RealScalar&, typename Derived::RealScalar)
- {
- return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix();
- }
-};
-
-} // end namespace internal
-
-
-/** \returns \c true if \c *this is approximately equal to \a other, within the precision
- * determined by \a prec.
- *
- * \note The fuzzy compares are done multiplicatively. Two vectors \f$ v \f$ and \f$ w \f$
- * are considered to be approximately equal within precision \f$ p \f$ if
- * \f[ \Vert v - w \Vert \leqslant p\,\min(\Vert v\Vert, \Vert w\Vert). \f]
- * For matrices, the comparison is done using the Hilbert-Schmidt norm (aka Frobenius norm
- * L2 norm).
- *
- * \note Because of the multiplicativeness of this comparison, one can't use this function
- * to check whether \c *this is approximately equal to the zero matrix or vector.
- * Indeed, \c isApprox(zero) returns false unless \c *this itself is exactly the zero matrix
- * or vector. If you want to test whether \c *this is zero, use internal::isMuchSmallerThan(const
- * RealScalar&, RealScalar) instead.
- *
- * \sa internal::isMuchSmallerThan(const RealScalar&, RealScalar) const
- */
-template<typename Derived>
-template<typename OtherDerived>
-bool DenseBase<Derived>::isApprox(
- const DenseBase<OtherDerived>& other,
- RealScalar prec
-) const
-{
- return internal::isApprox_selector<Derived, OtherDerived>::run(derived(), other.derived(), prec);
-}
-
-/** \returns \c true if the norm of \c *this is much smaller than \a other,
- * within the precision determined by \a prec.
- *
- * \note The fuzzy compares are done multiplicatively. A vector \f$ v \f$ is
- * considered to be much smaller than \f$ x \f$ within precision \f$ p \f$ if
- * \f[ \Vert v \Vert \leqslant p\,\vert x\vert. \f]
- *
- * For matrices, the comparison is done using the Hilbert-Schmidt norm. For this reason,
- * the value of the reference scalar \a other should come from the Hilbert-Schmidt norm
- * of a reference matrix of same dimensions.
- *
- * \sa isApprox(), isMuchSmallerThan(const DenseBase<OtherDerived>&, RealScalar) const
- */
-template<typename Derived>
-bool DenseBase<Derived>::isMuchSmallerThan(
- const typename NumTraits<Scalar>::Real& other,
- RealScalar prec
-) const
-{
- return internal::isMuchSmallerThan_scalar_selector<Derived>::run(derived(), other, prec);
-}
-
-/** \returns \c true if the norm of \c *this is much smaller than the norm of \a other,
- * within the precision determined by \a prec.
- *
- * \note The fuzzy compares are done multiplicatively. A vector \f$ v \f$ is
- * considered to be much smaller than a vector \f$ w \f$ within precision \f$ p \f$ if
- * \f[ \Vert v \Vert \leqslant p\,\Vert w\Vert. \f]
- * For matrices, the comparison is done using the Hilbert-Schmidt norm.
- *
- * \sa isApprox(), isMuchSmallerThan(const RealScalar&, RealScalar) const
- */
-template<typename Derived>
-template<typename OtherDerived>
-bool DenseBase<Derived>::isMuchSmallerThan(
- const DenseBase<OtherDerived>& other,
- RealScalar prec
-) const
-{
- return internal::isMuchSmallerThan_object_selector<Derived, OtherDerived>::run(derived(), other.derived(), prec);
-}
-
-#endif // EIGEN_FUZZY_H
diff --git a/extern/Eigen3/Eigen/src/Core/GenericPacketMath.h b/extern/Eigen3/Eigen/src/Core/GenericPacketMath.h
deleted file mode 100644
index 8ed83532712..00000000000
--- a/extern/Eigen3/Eigen/src/Core/GenericPacketMath.h
+++ /dev/null
@@ -1,339 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_GENERIC_PACKET_MATH_H
-#define EIGEN_GENERIC_PACKET_MATH_H
-
-namespace internal {
-
-/** \internal
- * \file GenericPacketMath.h
- *
- * Default implementation for types not supported by the vectorization.
- * In practice these functions are provided to make easier the writing
- * of generic vectorized code.
- */
-
-#ifndef EIGEN_DEBUG_ALIGNED_LOAD
-#define EIGEN_DEBUG_ALIGNED_LOAD
-#endif
-
-#ifndef EIGEN_DEBUG_UNALIGNED_LOAD
-#define EIGEN_DEBUG_UNALIGNED_LOAD
-#endif
-
-#ifndef EIGEN_DEBUG_ALIGNED_STORE
-#define EIGEN_DEBUG_ALIGNED_STORE
-#endif
-
-#ifndef EIGEN_DEBUG_UNALIGNED_STORE
-#define EIGEN_DEBUG_UNALIGNED_STORE
-#endif
-
-struct default_packet_traits
-{
- enum {
- HasAdd = 1,
- HasSub = 1,
- HasMul = 1,
- HasNegate = 1,
- HasAbs = 1,
- HasAbs2 = 1,
- HasMin = 1,
- HasMax = 1,
- HasConj = 1,
- HasSetLinear = 1,
-
- HasDiv = 0,
- HasSqrt = 0,
- HasExp = 0,
- HasLog = 0,
- HasPow = 0,
-
- HasSin = 0,
- HasCos = 0,
- HasTan = 0,
- HasASin = 0,
- HasACos = 0,
- HasATan = 0
- };
-};
-
-template<typename T> struct packet_traits : default_packet_traits
-{
- typedef T type;
- enum {
- Vectorizable = 0,
- size = 1,
- AlignedOnScalar = 0
- };
- enum {
- HasAdd = 0,
- HasSub = 0,
- HasMul = 0,
- HasNegate = 0,
- HasAbs = 0,
- HasAbs2 = 0,
- HasMin = 0,
- HasMax = 0,
- HasConj = 0,
- HasSetLinear = 0
- };
-};
-
-/** \internal \returns a + b (coeff-wise) */
-template<typename Packet> inline Packet
-padd(const Packet& a,
- const Packet& b) { return a+b; }
-
-/** \internal \returns a - b (coeff-wise) */
-template<typename Packet> inline Packet
-psub(const Packet& a,
- const Packet& b) { return a-b; }
-
-/** \internal \returns -a (coeff-wise) */
-template<typename Packet> inline Packet
-pnegate(const Packet& a) { return -a; }
-
-/** \internal \returns conj(a) (coeff-wise) */
-template<typename Packet> inline Packet
-pconj(const Packet& a) { return conj(a); }
-
-/** \internal \returns a * b (coeff-wise) */
-template<typename Packet> inline Packet
-pmul(const Packet& a,
- const Packet& b) { return a*b; }
-
-/** \internal \returns a / b (coeff-wise) */
-template<typename Packet> inline Packet
-pdiv(const Packet& a,
- const Packet& b) { return a/b; }
-
-/** \internal \returns the min of \a a and \a b (coeff-wise) */
-template<typename Packet> inline Packet
-pmin(const Packet& a,
- const Packet& b) { using std::min; return (min)(a, b); }
-
-/** \internal \returns the max of \a a and \a b (coeff-wise) */
-template<typename Packet> inline Packet
-pmax(const Packet& a,
- const Packet& b) { using std::max; return (max)(a, b); }
-
-/** \internal \returns the absolute value of \a a */
-template<typename Packet> inline Packet
-pabs(const Packet& a) { return abs(a); }
-
-/** \internal \returns the bitwise and of \a a and \a b */
-template<typename Packet> inline Packet
-pand(const Packet& a, const Packet& b) { return a & b; }
-
-/** \internal \returns the bitwise or of \a a and \a b */
-template<typename Packet> inline Packet
-por(const Packet& a, const Packet& b) { return a | b; }
-
-/** \internal \returns the bitwise xor of \a a and \a b */
-template<typename Packet> inline Packet
-pxor(const Packet& a, const Packet& b) { return a ^ b; }
-
-/** \internal \returns the bitwise andnot of \a a and \a b */
-template<typename Packet> inline Packet
-pandnot(const Packet& a, const Packet& b) { return a & (!b); }
-
-/** \internal \returns a packet version of \a *from, from must be 16 bytes aligned */
-template<typename Packet> inline Packet
-pload(const typename unpacket_traits<Packet>::type* from) { return *from; }
-
-/** \internal \returns a packet version of \a *from, (un-aligned load) */
-template<typename Packet> inline Packet
-ploadu(const typename unpacket_traits<Packet>::type* from) { return *from; }
-
-/** \internal \returns a packet with elements of \a *from duplicated, e.g.: (from[0],from[0],from[1],from[1]) */
-template<typename Packet> inline Packet
-ploaddup(const typename unpacket_traits<Packet>::type* from) { return *from; }
-
-/** \internal \returns a packet with constant coefficients \a a, e.g.: (a,a,a,a) */
-template<typename Packet> inline Packet
-pset1(const typename unpacket_traits<Packet>::type& a) { return a; }
-
-/** \internal \brief Returns a packet with coefficients (a,a+1,...,a+packet_size-1). */
-template<typename Scalar> inline typename packet_traits<Scalar>::type
-plset(const Scalar& a) { return a; }
-
-/** \internal copy the packet \a from to \a *to, \a to must be 16 bytes aligned */
-template<typename Scalar, typename Packet> inline void pstore(Scalar* to, const Packet& from)
-{ (*to) = from; }
-
-/** \internal copy the packet \a from to \a *to, (un-aligned store) */
-template<typename Scalar, typename Packet> inline void pstoreu(Scalar* to, const Packet& from)
-{ (*to) = from; }
-
-/** \internal tries to do cache prefetching of \a addr */
-template<typename Scalar> inline void prefetch(const Scalar* addr)
-{
-#if !defined(_MSC_VER)
-__builtin_prefetch(addr);
-#endif
-}
-
-/** \internal \returns the first element of a packet */
-template<typename Packet> inline typename unpacket_traits<Packet>::type pfirst(const Packet& a)
-{ return a; }
-
-/** \internal \returns a packet where the element i contains the sum of the packet of \a vec[i] */
-template<typename Packet> inline Packet
-preduxp(const Packet* vecs) { return vecs[0]; }
-
-/** \internal \returns the sum of the elements of \a a*/
-template<typename Packet> inline typename unpacket_traits<Packet>::type predux(const Packet& a)
-{ return a; }
-
-/** \internal \returns the product of the elements of \a a*/
-template<typename Packet> inline typename unpacket_traits<Packet>::type predux_mul(const Packet& a)
-{ return a; }
-
-/** \internal \returns the min of the elements of \a a*/
-template<typename Packet> inline typename unpacket_traits<Packet>::type predux_min(const Packet& a)
-{ return a; }
-
-/** \internal \returns the max of the elements of \a a*/
-template<typename Packet> inline typename unpacket_traits<Packet>::type predux_max(const Packet& a)
-{ return a; }
-
-/** \internal \returns the reversed elements of \a a*/
-template<typename Packet> inline Packet preverse(const Packet& a)
-{ return a; }
-
-
-/** \internal \returns \a a with real and imaginary part flipped (for complex type only) */
-template<typename Packet> inline Packet pcplxflip(const Packet& a)
-{ return Packet(imag(a),real(a)); }
-
-/**************************
-* Special math functions
-***************************/
-
-/** \internal \returns the sine of \a a (coeff-wise) */
-template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet psin(const Packet& a) { return sin(a); }
-
-/** \internal \returns the cosine of \a a (coeff-wise) */
-template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet pcos(const Packet& a) { return cos(a); }
-
-/** \internal \returns the tan of \a a (coeff-wise) */
-template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet ptan(const Packet& a) { return tan(a); }
-
-/** \internal \returns the arc sine of \a a (coeff-wise) */
-template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet pasin(const Packet& a) { return asin(a); }
-
-/** \internal \returns the arc cosine of \a a (coeff-wise) */
-template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet pacos(const Packet& a) { return acos(a); }
-
-/** \internal \returns the exp of \a a (coeff-wise) */
-template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet pexp(const Packet& a) { return exp(a); }
-
-/** \internal \returns the log of \a a (coeff-wise) */
-template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet plog(const Packet& a) { return log(a); }
-
-/** \internal \returns the square-root of \a a (coeff-wise) */
-template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-Packet psqrt(const Packet& a) { return sqrt(a); }
-
-/***************************************************************************
-* The following functions might not have to be overwritten for vectorized types
-***************************************************************************/
-
-/** \internal copy a packet with constant coeficient \a a (e.g., [a,a,a,a]) to \a *to. \a to must be 16 bytes aligned */
-// NOTE: this function must really be templated on the packet type (think about different packet types for the same scalar type)
-template<typename Packet>
-inline void pstore1(typename unpacket_traits<Packet>::type* to, const typename unpacket_traits<Packet>::type& a)
-{
- pstore(to, pset1<Packet>(a));
-}
-
-/** \internal \returns a * b + c (coeff-wise) */
-template<typename Packet> inline Packet
-pmadd(const Packet& a,
- const Packet& b,
- const Packet& c)
-{ return padd(pmul(a, b),c); }
-
-/** \internal \returns a packet version of \a *from.
- * If LoadMode equals #Aligned, \a from must be 16 bytes aligned */
-template<typename Packet, int LoadMode>
-inline Packet ploadt(const typename unpacket_traits<Packet>::type* from)
-{
- if(LoadMode == Aligned)
- return pload<Packet>(from);
- else
- return ploadu<Packet>(from);
-}
-
-/** \internal copy the packet \a from to \a *to.
- * If StoreMode equals #Aligned, \a to must be 16 bytes aligned */
-template<typename Scalar, typename Packet, int LoadMode>
-inline void pstoret(Scalar* to, const Packet& from)
-{
- if(LoadMode == Aligned)
- pstore(to, from);
- else
- pstoreu(to, from);
-}
-
-/** \internal default implementation of palign() allowing partial specialization */
-template<int Offset,typename PacketType>
-struct palign_impl
-{
- // by default data are aligned, so there is nothing to be done :)
- inline static void run(PacketType&, const PacketType&) {}
-};
-
-/** \internal update \a first using the concatenation of the \a Offset last elements
- * of \a first and packet_size minus \a Offset first elements of \a second */
-template<int Offset,typename PacketType>
-inline void palign(PacketType& first, const PacketType& second)
-{
- palign_impl<Offset,PacketType>::run(first,second);
-}
-
-/***************************************************************************
-* Fast complex products (GCC generates a function call which is very slow)
-***************************************************************************/
-
-template<> inline std::complex<float> pmul(const std::complex<float>& a, const std::complex<float>& b)
-{ return std::complex<float>(real(a)*real(b) - imag(a)*imag(b), imag(a)*real(b) + real(a)*imag(b)); }
-
-template<> inline std::complex<double> pmul(const std::complex<double>& a, const std::complex<double>& b)
-{ return std::complex<double>(real(a)*real(b) - imag(a)*imag(b), imag(a)*real(b) + real(a)*imag(b)); }
-
-} // end namespace internal
-
-#endif // EIGEN_GENERIC_PACKET_MATH_H
-
diff --git a/extern/Eigen3/Eigen/src/Core/GlobalFunctions.h b/extern/Eigen3/Eigen/src/Core/GlobalFunctions.h
deleted file mode 100644
index 144145a955c..00000000000
--- a/extern/Eigen3/Eigen/src/Core/GlobalFunctions.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_GLOBAL_FUNCTIONS_H
-#define EIGEN_GLOBAL_FUNCTIONS_H
-
-#define EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(NAME,FUNCTOR) \
- template<typename Derived> \
- inline const Eigen::CwiseUnaryOp<Eigen::internal::FUNCTOR<typename Derived::Scalar>, const Derived> \
- NAME(const Eigen::ArrayBase<Derived>& x) { \
- return x.derived(); \
- }
-
-#define EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(NAME,FUNCTOR) \
- \
- template<typename Derived> \
- struct NAME##_retval<ArrayBase<Derived> > \
- { \
- typedef const Eigen::CwiseUnaryOp<Eigen::internal::FUNCTOR<typename Derived::Scalar>, const Derived> type; \
- }; \
- template<typename Derived> \
- struct NAME##_impl<ArrayBase<Derived> > \
- { \
- static inline typename NAME##_retval<ArrayBase<Derived> >::type run(const Eigen::ArrayBase<Derived>& x) \
- { \
- return x.derived(); \
- } \
- };
-
-
-namespace std
-{
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(real,scalar_real_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(imag,scalar_imag_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(sin,scalar_sin_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(cos,scalar_cos_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(asin,scalar_asin_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(acos,scalar_acos_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(tan,scalar_tan_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(exp,scalar_exp_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(log,scalar_log_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(abs,scalar_abs_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_STD_UNARY(sqrt,scalar_sqrt_op)
-
- template<typename Derived>
- inline const Eigen::CwiseUnaryOp<Eigen::internal::scalar_pow_op<typename Derived::Scalar>, const Derived>
- pow(const Eigen::ArrayBase<Derived>& x, const typename Derived::Scalar& exponent) { \
- return x.derived().pow(exponent); \
- }
-}
-
-namespace Eigen
-{
- namespace internal
- {
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(real,scalar_real_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(imag,scalar_imag_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(sin,scalar_sin_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(cos,scalar_cos_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(asin,scalar_asin_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(acos,scalar_acos_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(tan,scalar_tan_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(exp,scalar_exp_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(log,scalar_log_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(abs,scalar_abs_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(abs2,scalar_abs2_op)
- EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(sqrt,scalar_sqrt_op)
- }
-}
-
-// TODO: cleanly disable those functions that are not supported on Array (internal::real_ref, internal::random, internal::isApprox...)
-
-#endif // EIGEN_GLOBAL_FUNCTIONS_H
diff --git a/extern/Eigen3/Eigen/src/Core/Map.h b/extern/Eigen3/Eigen/src/Core/Map.h
deleted file mode 100644
index dd0673609c5..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Map.h
+++ /dev/null
@@ -1,205 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2007-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_MAP_H
-#define EIGEN_MAP_H
-
-/** \class Map
- * \ingroup Core_Module
- *
- * \brief A matrix or vector expression mapping an existing array of data.
- *
- * \tparam PlainObjectType the equivalent matrix type of the mapped data
- * \tparam MapOptions specifies whether the pointer is \c #Aligned, or \c #Unaligned.
- * The default is \c #Unaligned.
- * \tparam StrideType optionally specifies strides. By default, Map assumes the memory layout
- * of an ordinary, contiguous array. This can be overridden by specifying strides.
- * The type passed here must be a specialization of the Stride template, see examples below.
- *
- * This class represents a matrix or vector expression mapping an existing array of data.
- * It can be used to let Eigen interface without any overhead with non-Eigen data structures,
- * such as plain C arrays or structures from other libraries. By default, it assumes that the
- * data is laid out contiguously in memory. You can however override this by explicitly specifying
- * inner and outer strides.
- *
- * Here's an example of simply mapping a contiguous array as a \ref TopicStorageOrders "column-major" matrix:
- * \include Map_simple.cpp
- * Output: \verbinclude Map_simple.out
- *
- * If you need to map non-contiguous arrays, you can do so by specifying strides:
- *
- * Here's an example of mapping an array as a vector, specifying an inner stride, that is, the pointer
- * increment between two consecutive coefficients. Here, we're specifying the inner stride as a compile-time
- * fixed value.
- * \include Map_inner_stride.cpp
- * Output: \verbinclude Map_inner_stride.out
- *
- * Here's an example of mapping an array while specifying an outer stride. Here, since we're mapping
- * as a column-major matrix, 'outer stride' means the pointer increment between two consecutive columns.
- * Here, we're specifying the outer stride as a runtime parameter. Note that here \c OuterStride<> is
- * a short version of \c OuterStride<Dynamic> because the default template parameter of OuterStride
- * is \c Dynamic
- * \include Map_outer_stride.cpp
- * Output: \verbinclude Map_outer_stride.out
- *
- * For more details and for an example of specifying both an inner and an outer stride, see class Stride.
- *
- * \b Tip: to change the array of data mapped by a Map object, you can use the C++
- * placement new syntax:
- *
- * Example: \include Map_placement_new.cpp
- * Output: \verbinclude Map_placement_new.out
- *
- * This class is the return type of PlainObjectBase::Map() but can also be used directly.
- *
- * \sa PlainObjectBase::Map(), \ref TopicStorageOrders
- */
-
-namespace internal {
-template<typename PlainObjectType, int MapOptions, typename StrideType>
-struct traits<Map<PlainObjectType, MapOptions, StrideType> >
- : public traits<PlainObjectType>
-{
- typedef traits<PlainObjectType> TraitsBase;
- typedef typename PlainObjectType::Index Index;
- typedef typename PlainObjectType::Scalar Scalar;
- enum {
- InnerStrideAtCompileTime = StrideType::InnerStrideAtCompileTime == 0
- ? int(PlainObjectType::InnerStrideAtCompileTime)
- : int(StrideType::InnerStrideAtCompileTime),
- OuterStrideAtCompileTime = StrideType::OuterStrideAtCompileTime == 0
- ? int(PlainObjectType::OuterStrideAtCompileTime)
- : int(StrideType::OuterStrideAtCompileTime),
- HasNoInnerStride = InnerStrideAtCompileTime == 1,
- HasNoOuterStride = StrideType::OuterStrideAtCompileTime == 0,
- HasNoStride = HasNoInnerStride && HasNoOuterStride,
- IsAligned = bool(EIGEN_ALIGN) && ((int(MapOptions)&Aligned)==Aligned),
- IsDynamicSize = PlainObjectType::SizeAtCompileTime==Dynamic,
- KeepsPacketAccess = bool(HasNoInnerStride)
- && ( bool(IsDynamicSize)
- || HasNoOuterStride
- || ( OuterStrideAtCompileTime!=Dynamic
- && ((static_cast<int>(sizeof(Scalar))*OuterStrideAtCompileTime)%16)==0 ) ),
- Flags0 = TraitsBase::Flags,
- Flags1 = IsAligned ? (int(Flags0) | AlignedBit) : (int(Flags0) & ~AlignedBit),
- Flags2 = (bool(HasNoStride) || bool(PlainObjectType::IsVectorAtCompileTime))
- ? int(Flags1) : int(Flags1 & ~LinearAccessBit),
- Flags3 = is_lvalue<PlainObjectType>::value ? int(Flags2) : (int(Flags2) & ~LvalueBit),
- Flags = KeepsPacketAccess ? int(Flags3) : (int(Flags3) & ~PacketAccessBit)
- };
-private:
- enum { Options }; // Expressions don't have Options
-};
-}
-
-template<typename PlainObjectType, int MapOptions, typename StrideType> class Map
- : public MapBase<Map<PlainObjectType, MapOptions, StrideType> >
-{
- public:
-
- typedef MapBase<Map> Base;
-
- EIGEN_DENSE_PUBLIC_INTERFACE(Map)
-
- typedef typename Base::PointerType PointerType;
-#if EIGEN2_SUPPORT_STAGE <= STAGE30_FULL_EIGEN3_API
- typedef const Scalar* PointerArgType;
- inline PointerType cast_to_pointer_type(PointerArgType ptr) { return const_cast<PointerType>(ptr); }
-#else
- typedef PointerType PointerArgType;
- inline PointerType cast_to_pointer_type(PointerArgType ptr) { return ptr; }
-#endif
-
- inline Index innerStride() const
- {
- return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1;
- }
-
- inline Index outerStride() const
- {
- return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer()
- : IsVectorAtCompileTime ? this->size()
- : int(Flags)&RowMajorBit ? this->cols()
- : this->rows();
- }
-
- /** Constructor in the fixed-size case.
- *
- * \param data pointer to the array to map
- * \param stride optional Stride object, passing the strides.
- */
- inline Map(PointerArgType data, const StrideType& stride = StrideType())
- : Base(cast_to_pointer_type(data)), m_stride(stride)
- {
- PlainObjectType::Base::_check_template_params();
- }
-
- /** Constructor in the dynamic-size vector case.
- *
- * \param data pointer to the array to map
- * \param size the size of the vector expression
- * \param stride optional Stride object, passing the strides.
- */
- inline Map(PointerArgType data, Index size, const StrideType& stride = StrideType())
- : Base(cast_to_pointer_type(data), size), m_stride(stride)
- {
- PlainObjectType::Base::_check_template_params();
- }
-
- /** Constructor in the dynamic-size matrix case.
- *
- * \param data pointer to the array to map
- * \param rows the number of rows of the matrix expression
- * \param cols the number of columns of the matrix expression
- * \param stride optional Stride object, passing the strides.
- */
- inline Map(PointerArgType data, Index rows, Index cols, const StrideType& stride = StrideType())
- : Base(cast_to_pointer_type(data), rows, cols), m_stride(stride)
- {
- PlainObjectType::Base::_check_template_params();
- }
-
-
- EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
-
- protected:
- StrideType m_stride;
-};
-
-template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
-inline Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>
- ::Array(const Scalar *data)
-{
- this->_set_noalias(Eigen::Map<const Array>(data));
-}
-
-template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
-inline Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>
- ::Matrix(const Scalar *data)
-{
- this->_set_noalias(Eigen::Map<const Matrix>(data));
-}
-
-#endif // EIGEN_MAP_H
diff --git a/extern/Eigen3/Eigen/src/Core/MapBase.h b/extern/Eigen3/Eigen/src/Core/MapBase.h
deleted file mode 100644
index c23bcbfdcca..00000000000
--- a/extern/Eigen3/Eigen/src/Core/MapBase.h
+++ /dev/null
@@ -1,255 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2007-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_MAPBASE_H
-#define EIGEN_MAPBASE_H
-
-#define EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) \
- EIGEN_STATIC_ASSERT((int(internal::traits<Derived>::Flags) & LinearAccessBit) || Derived::IsVectorAtCompileTime, \
- YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT)
-
-
-/** \class MapBase
- * \ingroup Core_Module
- *
- * \brief Base class for Map and Block expression with direct access
- *
- * \sa class Map, class Block
- */
-template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
- : public internal::dense_xpr_base<Derived>::type
-{
- public:
-
- typedef typename internal::dense_xpr_base<Derived>::type Base;
- enum {
- RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
- ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
- SizeAtCompileTime = Base::SizeAtCompileTime
- };
-
- typedef typename internal::traits<Derived>::StorageKind StorageKind;
- typedef typename internal::traits<Derived>::Index Index;
- typedef typename internal::traits<Derived>::Scalar Scalar;
- typedef typename internal::packet_traits<Scalar>::type PacketScalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef typename internal::conditional<
- bool(internal::is_lvalue<Derived>::value),
- Scalar *,
- const Scalar *>::type
- PointerType;
-
- using Base::derived;
-// using Base::RowsAtCompileTime;
-// using Base::ColsAtCompileTime;
-// using Base::SizeAtCompileTime;
- using Base::MaxRowsAtCompileTime;
- using Base::MaxColsAtCompileTime;
- using Base::MaxSizeAtCompileTime;
- using Base::IsVectorAtCompileTime;
- using Base::Flags;
- using Base::IsRowMajor;
-
- using Base::rows;
- using Base::cols;
- using Base::size;
- using Base::coeff;
- using Base::coeffRef;
- using Base::lazyAssign;
- using Base::eval;
-
- using Base::innerStride;
- using Base::outerStride;
- using Base::rowStride;
- using Base::colStride;
-
- // bug 217 - compile error on ICC 11.1
- using Base::operator=;
-
- typedef typename Base::CoeffReturnType CoeffReturnType;
-
- inline Index rows() const { return m_rows.value(); }
- inline Index cols() const { return m_cols.value(); }
-
- /** Returns a pointer to the first coefficient of the matrix or vector.
- *
- * \note When addressing this data, make sure to honor the strides returned by innerStride() and outerStride().
- *
- * \sa innerStride(), outerStride()
- */
- inline const Scalar* data() const { return m_data; }
-
- inline const Scalar& coeff(Index row, Index col) const
- {
- return m_data[col * colStride() + row * rowStride()];
- }
-
- inline const Scalar& coeff(Index index) const
- {
- EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
- return m_data[index * innerStride()];
- }
-
- inline const Scalar& coeffRef(Index row, Index col) const
- {
- return this->m_data[col * colStride() + row * rowStride()];
- }
-
- inline const Scalar& coeffRef(Index index) const
- {
- EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
- return this->m_data[index * innerStride()];
- }
-
- template<int LoadMode>
- inline PacketScalar packet(Index row, Index col) const
- {
- return internal::ploadt<PacketScalar, LoadMode>
- (m_data + (col * colStride() + row * rowStride()));
- }
-
- template<int LoadMode>
- inline PacketScalar packet(Index index) const
- {
- EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
- return internal::ploadt<PacketScalar, LoadMode>(m_data + index * innerStride());
- }
-
- inline MapBase(PointerType data) : m_data(data), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
- {
- EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
- checkSanity();
- }
-
- inline MapBase(PointerType data, Index size)
- : m_data(data),
- m_rows(RowsAtCompileTime == Dynamic ? size : Index(RowsAtCompileTime)),
- m_cols(ColsAtCompileTime == Dynamic ? size : Index(ColsAtCompileTime))
- {
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- eigen_assert(size >= 0);
- eigen_assert(data == 0 || SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
- checkSanity();
- }
-
- inline MapBase(PointerType data, Index rows, Index cols)
- : m_data(data), m_rows(rows), m_cols(cols)
- {
- eigen_assert( (data == 0)
- || ( rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
- && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)));
- checkSanity();
- }
-
- protected:
-
- void checkSanity() const
- {
- EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(internal::traits<Derived>::Flags&PacketAccessBit,
- 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) % (sizeof(Scalar)*internal::packet_traits<Scalar>::size)) == 0)
- && "data is not aligned");
- }
-
- PointerType m_data;
- const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_rows;
- const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_cols;
-};
-
-template<typename Derived> class MapBase<Derived, WriteAccessors>
- : public MapBase<Derived, ReadOnlyAccessors>
-{
- public:
-
- typedef MapBase<Derived, ReadOnlyAccessors> Base;
-
- typedef typename Base::Scalar Scalar;
- typedef typename Base::PacketScalar PacketScalar;
- typedef typename Base::Index Index;
- typedef typename Base::PointerType PointerType;
-
- using Base::derived;
- using Base::rows;
- using Base::cols;
- using Base::size;
- using Base::coeff;
- using Base::coeffRef;
-
- using Base::innerStride;
- using Base::outerStride;
- using Base::rowStride;
- using Base::colStride;
-
- typedef typename internal::conditional<
- internal::is_lvalue<Derived>::value,
- Scalar,
- const Scalar
- >::type ScalarWithConstIfNotLvalue;
-
- inline const Scalar* data() const { return this->m_data; }
- inline ScalarWithConstIfNotLvalue* data() { return this->m_data; } // no const-cast here so non-const-correct code will give a compile error
-
- inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col)
- {
- return this->m_data[col * colStride() + row * rowStride()];
- }
-
- inline ScalarWithConstIfNotLvalue& coeffRef(Index index)
- {
- EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
- return this->m_data[index * innerStride()];
- }
-
- template<int StoreMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
- {
- internal::pstoret<Scalar, PacketScalar, StoreMode>
- (this->m_data + (col * colStride() + row * rowStride()), x);
- }
-
- template<int StoreMode>
- inline void writePacket(Index index, const PacketScalar& x)
- {
- EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
- internal::pstoret<Scalar, PacketScalar, StoreMode>
- (this->m_data + index * innerStride(), x);
- }
-
- explicit inline MapBase(PointerType data) : Base(data) {}
- inline MapBase(PointerType data, Index size) : Base(data, size) {}
- inline MapBase(PointerType data, Index rows, Index cols) : Base(data, rows, cols) {}
-
- Derived& operator=(const MapBase& other)
- {
- Base::Base::operator=(other);
- return derived();
- }
-
- using Base::Base::operator=;
-};
-
-
-#endif // EIGEN_MAPBASE_H
diff --git a/extern/Eigen3/Eigen/src/Core/MathFunctions.h b/extern/Eigen3/Eigen/src/Core/MathFunctions.h
deleted file mode 100644
index 2b454db21e9..00000000000
--- a/extern/Eigen3/Eigen/src/Core/MathFunctions.h
+++ /dev/null
@@ -1,843 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_MATHFUNCTIONS_H
-#define EIGEN_MATHFUNCTIONS_H
-
-namespace internal {
-
-/** \internal \struct global_math_functions_filtering_base
- *
- * What it does:
- * Defines a typedef 'type' as follows:
- * - if type T has a member typedef Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl, then
- * global_math_functions_filtering_base<T>::type is a typedef for it.
- * - otherwise, global_math_functions_filtering_base<T>::type is a typedef for T.
- *
- * How it's used:
- * To allow to defined the global math functions (like sin...) in certain cases, like the Array expressions.
- * When you do sin(array1+array2), the object array1+array2 has a complicated expression type, all what you want to know
- * is that it inherits ArrayBase. So we implement a partial specialization of sin_impl for ArrayBase<Derived>.
- * So we must make sure to use sin_impl<ArrayBase<Derived> > and not sin_impl<Derived>, otherwise our partial specialization
- * won't be used. How does sin know that? That's exactly what global_math_functions_filtering_base tells it.
- *
- * How it's implemented:
- * SFINAE in the style of enable_if. Highly susceptible of breaking compilers. With GCC, it sure does work, but if you replace
- * the typename dummy by an integer template parameter, it doesn't work anymore!
- */
-
-template<typename T, typename dummy = void>
-struct global_math_functions_filtering_base
-{
- typedef T type;
-};
-
-template<typename T> struct always_void { typedef void type; };
-
-template<typename T>
-struct global_math_functions_filtering_base
- <T,
- typename always_void<typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl>::type
- >
-{
- typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type;
-};
-
-#define EIGEN_MATHFUNC_IMPL(func, scalar) func##_impl<typename global_math_functions_filtering_base<scalar>::type>
-#define EIGEN_MATHFUNC_RETVAL(func, scalar) typename func##_retval<typename global_math_functions_filtering_base<scalar>::type>::type
-
-
-/****************************************************************************
-* Implementation of real *
-****************************************************************************/
-
-template<typename Scalar>
-struct real_impl
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- static inline RealScalar run(const Scalar& x)
- {
- return x;
- }
-};
-
-template<typename RealScalar>
-struct real_impl<std::complex<RealScalar> >
-{
- static inline RealScalar run(const std::complex<RealScalar>& x)
- {
- using std::real;
- return real(x);
- }
-};
-
-template<typename Scalar>
-struct real_retval
-{
- typedef typename NumTraits<Scalar>::Real type;
-};
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x);
-}
-
-/****************************************************************************
-* Implementation of imag *
-****************************************************************************/
-
-template<typename Scalar>
-struct imag_impl
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- static inline RealScalar run(const Scalar&)
- {
- return RealScalar(0);
- }
-};
-
-template<typename RealScalar>
-struct imag_impl<std::complex<RealScalar> >
-{
- static inline RealScalar run(const std::complex<RealScalar>& x)
- {
- using std::imag;
- return imag(x);
- }
-};
-
-template<typename Scalar>
-struct imag_retval
-{
- typedef typename NumTraits<Scalar>::Real type;
-};
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x);
-}
-
-/****************************************************************************
-* Implementation of real_ref *
-****************************************************************************/
-
-template<typename Scalar>
-struct real_ref_impl
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- static inline RealScalar& run(Scalar& x)
- {
- return reinterpret_cast<RealScalar*>(&x)[0];
- }
- static inline const RealScalar& run(const Scalar& x)
- {
- return reinterpret_cast<const RealScalar*>(&x)[0];
- }
-};
-
-template<typename Scalar>
-struct real_ref_retval
-{
- typedef typename NumTraits<Scalar>::Real & type;
-};
-
-template<typename Scalar>
-inline typename add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) >::type real_ref(const Scalar& x)
-{
- return real_ref_impl<Scalar>::run(x);
-}
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x);
-}
-
-/****************************************************************************
-* Implementation of imag_ref *
-****************************************************************************/
-
-template<typename Scalar, bool IsComplex>
-struct imag_ref_default_impl
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- static inline RealScalar& run(Scalar& x)
- {
- return reinterpret_cast<RealScalar*>(&x)[1];
- }
- static inline const RealScalar& run(const Scalar& x)
- {
- return reinterpret_cast<RealScalar*>(&x)[1];
- }
-};
-
-template<typename Scalar>
-struct imag_ref_default_impl<Scalar, false>
-{
- static inline Scalar run(Scalar&)
- {
- return Scalar(0);
- }
- static inline const Scalar run(const Scalar&)
- {
- return Scalar(0);
- }
-};
-
-template<typename Scalar>
-struct imag_ref_impl : imag_ref_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {};
-
-template<typename Scalar>
-struct imag_ref_retval
-{
- typedef typename NumTraits<Scalar>::Real & type;
-};
-
-template<typename Scalar>
-inline typename add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x)
-{
- return imag_ref_impl<Scalar>::run(x);
-}
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x);
-}
-
-/****************************************************************************
-* Implementation of conj *
-****************************************************************************/
-
-template<typename Scalar>
-struct conj_impl
-{
- static inline Scalar run(const Scalar& x)
- {
- return x;
- }
-};
-
-template<typename RealScalar>
-struct conj_impl<std::complex<RealScalar> >
-{
- static inline std::complex<RealScalar> run(const std::complex<RealScalar>& x)
- {
- using std::conj;
- return conj(x);
- }
-};
-
-template<typename Scalar>
-struct conj_retval
-{
- typedef Scalar type;
-};
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x);
-}
-
-/****************************************************************************
-* Implementation of abs *
-****************************************************************************/
-
-template<typename Scalar>
-struct abs_impl
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- static inline RealScalar run(const Scalar& x)
- {
- using std::abs;
- return abs(x);
- }
-};
-
-template<typename Scalar>
-struct abs_retval
-{
- typedef typename NumTraits<Scalar>::Real type;
-};
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(abs, Scalar) abs(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(abs, Scalar)::run(x);
-}
-
-/****************************************************************************
-* Implementation of abs2 *
-****************************************************************************/
-
-template<typename Scalar>
-struct abs2_impl
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- static inline RealScalar run(const Scalar& x)
- {
- return x*x;
- }
-};
-
-template<typename RealScalar>
-struct abs2_impl<std::complex<RealScalar> >
-{
- static inline RealScalar run(const std::complex<RealScalar>& x)
- {
- using std::norm;
- return norm(x);
- }
-};
-
-template<typename Scalar>
-struct abs2_retval
-{
- typedef typename NumTraits<Scalar>::Real type;
-};
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x);
-}
-
-/****************************************************************************
-* Implementation of norm1 *
-****************************************************************************/
-
-template<typename Scalar, bool IsComplex>
-struct norm1_default_impl
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- static inline RealScalar run(const Scalar& x)
- {
- return abs(real(x)) + abs(imag(x));
- }
-};
-
-template<typename Scalar>
-struct norm1_default_impl<Scalar, false>
-{
- static inline Scalar run(const Scalar& x)
- {
- return abs(x);
- }
-};
-
-template<typename Scalar>
-struct norm1_impl : norm1_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {};
-
-template<typename Scalar>
-struct norm1_retval
-{
- typedef typename NumTraits<Scalar>::Real type;
-};
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x);
-}
-
-/****************************************************************************
-* Implementation of hypot *
-****************************************************************************/
-
-template<typename Scalar>
-struct hypot_impl
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- static inline RealScalar run(const Scalar& x, const Scalar& y)
- {
- using std::max;
- using std::min;
- RealScalar _x = abs(x);
- RealScalar _y = abs(y);
- RealScalar p = (max)(_x, _y);
- RealScalar q = (min)(_x, _y);
- RealScalar qp = q/p;
- return p * sqrt(RealScalar(1) + qp*qp);
- }
-};
-
-template<typename Scalar>
-struct hypot_retval
-{
- typedef typename NumTraits<Scalar>::Real type;
-};
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y)
-{
- return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y);
-}
-
-/****************************************************************************
-* Implementation of cast *
-****************************************************************************/
-
-template<typename OldType, typename NewType>
-struct cast_impl
-{
- static inline NewType run(const OldType& x)
- {
- return static_cast<NewType>(x);
- }
-};
-
-// here, for once, we're plainly returning NewType: we don't want cast to do weird things.
-
-template<typename OldType, typename NewType>
-inline NewType cast(const OldType& x)
-{
- return cast_impl<OldType, NewType>::run(x);
-}
-
-/****************************************************************************
-* Implementation of sqrt *
-****************************************************************************/
-
-template<typename Scalar, bool IsInteger>
-struct sqrt_default_impl
-{
- static inline Scalar run(const Scalar& x)
- {
- using std::sqrt;
- return sqrt(x);
- }
-};
-
-template<typename Scalar>
-struct sqrt_default_impl<Scalar, true>
-{
- static inline Scalar run(const Scalar&)
- {
-#ifdef EIGEN2_SUPPORT
- eigen_assert(!NumTraits<Scalar>::IsInteger);
-#else
- EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
-#endif
- return Scalar(0);
- }
-};
-
-template<typename Scalar>
-struct sqrt_impl : sqrt_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
-
-template<typename Scalar>
-struct sqrt_retval
-{
- typedef Scalar type;
-};
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(sqrt, Scalar) sqrt(const Scalar& x)
-{
- return EIGEN_MATHFUNC_IMPL(sqrt, Scalar)::run(x);
-}
-
-/****************************************************************************
-* Implementation of standard unary real functions (exp, log, sin, cos, ... *
-****************************************************************************/
-
-// This macro instanciate all the necessary template mechanism which is common to all unary real functions.
-#define EIGEN_MATHFUNC_STANDARD_REAL_UNARY(NAME) \
- template<typename Scalar, bool IsInteger> struct NAME##_default_impl { \
- static inline Scalar run(const Scalar& x) { using std::NAME; return NAME(x); } \
- }; \
- template<typename Scalar> struct NAME##_default_impl<Scalar, true> { \
- static inline Scalar run(const Scalar&) { \
- EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) \
- return Scalar(0); \
- } \
- }; \
- template<typename Scalar> struct NAME##_impl \
- : NAME##_default_impl<Scalar, NumTraits<Scalar>::IsInteger> \
- {}; \
- template<typename Scalar> struct NAME##_retval { typedef Scalar type; }; \
- template<typename Scalar> \
- inline EIGEN_MATHFUNC_RETVAL(NAME, Scalar) NAME(const Scalar& x) { \
- return EIGEN_MATHFUNC_IMPL(NAME, Scalar)::run(x); \
- }
-
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(exp)
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(log)
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(sin)
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(cos)
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(tan)
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(asin)
-EIGEN_MATHFUNC_STANDARD_REAL_UNARY(acos)
-
-/****************************************************************************
-* Implementation of atan2 *
-****************************************************************************/
-
-template<typename Scalar, bool IsInteger>
-struct atan2_default_impl
-{
- typedef Scalar retval;
- static inline Scalar run(const Scalar& x, const Scalar& y)
- {
- using std::atan2;
- return atan2(x, y);
- }
-};
-
-template<typename Scalar>
-struct atan2_default_impl<Scalar, true>
-{
- static inline Scalar run(const Scalar&, const Scalar&)
- {
- EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
- return Scalar(0);
- }
-};
-
-template<typename Scalar>
-struct atan2_impl : atan2_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
-
-template<typename Scalar>
-struct atan2_retval
-{
- typedef Scalar type;
-};
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(atan2, Scalar) atan2(const Scalar& x, const Scalar& y)
-{
- return EIGEN_MATHFUNC_IMPL(atan2, Scalar)::run(x, y);
-}
-
-/****************************************************************************
-* Implementation of pow *
-****************************************************************************/
-
-template<typename Scalar, bool IsInteger>
-struct pow_default_impl
-{
- typedef Scalar retval;
- static inline Scalar run(const Scalar& x, const Scalar& y)
- {
- using std::pow;
- return pow(x, y);
- }
-};
-
-template<typename Scalar>
-struct pow_default_impl<Scalar, true>
-{
- static inline Scalar run(Scalar x, Scalar y)
- {
- Scalar res = 1;
- eigen_assert(!NumTraits<Scalar>::IsSigned || y >= 0);
- if(y & 1) res *= x;
- y >>= 1;
- while(y)
- {
- x *= x;
- if(y&1) res *= x;
- y >>= 1;
- }
- return res;
- }
-};
-
-template<typename Scalar>
-struct pow_impl : pow_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
-
-template<typename Scalar>
-struct pow_retval
-{
- typedef Scalar type;
-};
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(pow, Scalar) pow(const Scalar& x, const Scalar& y)
-{
- return EIGEN_MATHFUNC_IMPL(pow, Scalar)::run(x, y);
-}
-
-/****************************************************************************
-* Implementation of random *
-****************************************************************************/
-
-template<typename Scalar,
- bool IsComplex,
- bool IsInteger>
-struct random_default_impl {};
-
-template<typename Scalar>
-struct random_impl : random_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {};
-
-template<typename Scalar>
-struct random_retval
-{
- typedef Scalar type;
-};
-
-template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y);
-template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random();
-
-template<typename Scalar>
-struct random_default_impl<Scalar, false, false>
-{
- static inline Scalar run(const Scalar& x, const Scalar& y)
- {
- return x + (y-x) * Scalar(std::rand()) / Scalar(RAND_MAX);
- }
- static inline Scalar run()
- {
- return run(Scalar(NumTraits<Scalar>::IsSigned ? -1 : 0), Scalar(1));
- }
-};
-
-enum {
- floor_log2_terminate,
- floor_log2_move_up,
- floor_log2_move_down,
- floor_log2_bogus
-};
-
-template<unsigned int n, int lower, int upper> struct floor_log2_selector
-{
- enum { middle = (lower + upper) / 2,
- value = (upper <= lower + 1) ? int(floor_log2_terminate)
- : (n < (1 << middle)) ? int(floor_log2_move_down)
- : (n==0) ? int(floor_log2_bogus)
- : int(floor_log2_move_up)
- };
-};
-
-template<unsigned int n,
- int lower = 0,
- int upper = sizeof(unsigned int) * CHAR_BIT - 1,
- int selector = floor_log2_selector<n, lower, upper>::value>
-struct floor_log2 {};
-
-template<unsigned int n, int lower, int upper>
-struct floor_log2<n, lower, upper, floor_log2_move_down>
-{
- enum { value = floor_log2<n, lower, floor_log2_selector<n, lower, upper>::middle>::value };
-};
-
-template<unsigned int n, int lower, int upper>
-struct floor_log2<n, lower, upper, floor_log2_move_up>
-{
- enum { value = floor_log2<n, floor_log2_selector<n, lower, upper>::middle, upper>::value };
-};
-
-template<unsigned int n, int lower, int upper>
-struct floor_log2<n, lower, upper, floor_log2_terminate>
-{
- enum { value = (n >= ((unsigned int)(1) << (lower+1))) ? lower+1 : lower };
-};
-
-template<unsigned int n, int lower, int upper>
-struct floor_log2<n, lower, upper, floor_log2_bogus>
-{
- // no value, error at compile time
-};
-
-template<typename Scalar>
-struct random_default_impl<Scalar, false, true>
-{
- typedef typename NumTraits<Scalar>::NonInteger NonInteger;
-
- static inline Scalar run(const Scalar& x, const Scalar& y)
- {
- return x + Scalar((NonInteger(y)-x+1) * std::rand() / (RAND_MAX + NonInteger(1)));
- }
-
- static inline Scalar run()
- {
-#ifdef EIGEN_MAKING_DOCS
- return run(Scalar(NumTraits<Scalar>::IsSigned ? -10 : 0), Scalar(10));
-#else
- enum { rand_bits = floor_log2<(unsigned int)(RAND_MAX)+1>::value,
- scalar_bits = sizeof(Scalar) * CHAR_BIT,
- shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits))
- };
- Scalar x = Scalar(std::rand() >> shift);
- Scalar offset = NumTraits<Scalar>::IsSigned ? Scalar(1 << (rand_bits-1)) : Scalar(0);
- return x - offset;
-#endif
- }
-};
-
-template<typename Scalar>
-struct random_default_impl<Scalar, true, false>
-{
- static inline Scalar run(const Scalar& x, const Scalar& y)
- {
- return Scalar(random(real(x), real(y)),
- random(imag(x), imag(y)));
- }
- static inline Scalar run()
- {
- typedef typename NumTraits<Scalar>::Real RealScalar;
- return Scalar(random<RealScalar>(), random<RealScalar>());
- }
-};
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y)
-{
- return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(x, y);
-}
-
-template<typename Scalar>
-inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random()
-{
- return EIGEN_MATHFUNC_IMPL(random, Scalar)::run();
-}
-
-/****************************************************************************
-* Implementation of fuzzy comparisons *
-****************************************************************************/
-
-template<typename Scalar,
- bool IsComplex,
- bool IsInteger>
-struct scalar_fuzzy_default_impl {};
-
-template<typename Scalar>
-struct scalar_fuzzy_default_impl<Scalar, false, false>
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- template<typename OtherScalar>
- static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
- {
- return abs(x) <= abs(y) * prec;
- }
- static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
- {
- using std::min;
- return abs(x - y) <= (min)(abs(x), abs(y)) * prec;
- }
- static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec)
- {
- return x <= y || isApprox(x, y, prec);
- }
-};
-
-template<typename Scalar>
-struct scalar_fuzzy_default_impl<Scalar, false, true>
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- template<typename OtherScalar>
- static inline bool isMuchSmallerThan(const Scalar& x, const Scalar&, const RealScalar&)
- {
- return x == Scalar(0);
- }
- static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar&)
- {
- return x == y;
- }
- static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar&)
- {
- return x <= y;
- }
-};
-
-template<typename Scalar>
-struct scalar_fuzzy_default_impl<Scalar, true, false>
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- template<typename OtherScalar>
- static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
- {
- return abs2(x) <= abs2(y) * prec * prec;
- }
- static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
- {
- using std::min;
- return abs2(x - y) <= (min)(abs2(x), abs2(y)) * prec * prec;
- }
-};
-
-template<typename Scalar>
-struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {};
-
-template<typename Scalar, typename OtherScalar>
-inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y,
- typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
-{
- return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision);
-}
-
-template<typename Scalar>
-inline bool isApprox(const Scalar& x, const Scalar& y,
- typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
-{
- return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision);
-}
-
-template<typename Scalar>
-inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y,
- typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
-{
- return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision);
-}
-
-/******************************************
-*** The special case of the bool type ***
-******************************************/
-
-template<> struct random_impl<bool>
-{
- static inline bool run()
- {
- return random<int>(0,1)==0 ? false : true;
- }
-};
-
-template<> struct scalar_fuzzy_impl<bool>
-{
- typedef bool RealScalar;
-
- template<typename OtherScalar>
- static inline bool isMuchSmallerThan(const bool& x, const bool&, const bool&)
- {
- return !x;
- }
-
- static inline bool isApprox(bool x, bool y, bool)
- {
- return x == y;
- }
-
- static inline bool isApproxOrLessThan(const bool& x, const bool& y, const bool&)
- {
- return (!x) || y;
- }
-
-};
-
-} // end namespace internal
-
-#endif // EIGEN_MATHFUNCTIONS_H
diff --git a/extern/Eigen3/Eigen/src/Core/Matrix.h b/extern/Eigen3/Eigen/src/Core/Matrix.h
deleted file mode 100644
index 44de22cb4d5..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Matrix.h
+++ /dev/null
@@ -1,439 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_MATRIX_H
-#define EIGEN_MATRIX_H
-
-/** \class Matrix
- * \ingroup Core_Module
- *
- * \brief The matrix class, also used for vectors and row-vectors
- *
- * The %Matrix class is the work-horse for all \em dense (\ref dense "note") matrices and vectors within Eigen.
- * Vectors are matrices with one column, and row-vectors are matrices with one row.
- *
- * The %Matrix class encompasses \em both fixed-size and dynamic-size objects (\ref fixedsize "note").
- *
- * The first three template parameters are required:
- * \tparam _Scalar \anchor matrix_tparam_scalar Numeric type, e.g. float, double, int or std::complex<float>.
- * User defined sclar types are supported as well (see \ref user_defined_scalars "here").
- * \tparam _Rows Number of rows, or \b Dynamic
- * \tparam _Cols Number of columns, or \b Dynamic
- *
- * The remaining template parameters are optional -- in most cases you don't have to worry about them.
- * \tparam _Options \anchor matrix_tparam_options A combination of either \b #RowMajor or \b #ColMajor, and of either
- * \b #AutoAlign or \b #DontAlign.
- * The former controls \ref TopicStorageOrders "storage order", and defaults to column-major. The latter controls alignment, which is required
- * for vectorization. It defaults to aligning matrices except for fixed sizes that aren't a multiple of the packet size.
- * \tparam _MaxRows Maximum number of rows. Defaults to \a _Rows (\ref maxrows "note").
- * \tparam _MaxCols Maximum number of columns. Defaults to \a _Cols (\ref maxrows "note").
- *
- * Eigen provides a number of typedefs covering the usual cases. Here are some examples:
- *
- * \li \c Matrix2d is a 2x2 square matrix of doubles (\c Matrix<double, 2, 2>)
- * \li \c Vector4f is a vector of 4 floats (\c Matrix<float, 4, 1>)
- * \li \c RowVector3i is a row-vector of 3 ints (\c Matrix<int, 1, 3>)
- *
- * \li \c MatrixXf is a dynamic-size matrix of floats (\c Matrix<float, Dynamic, Dynamic>)
- * \li \c VectorXf is a dynamic-size vector of floats (\c Matrix<float, Dynamic, 1>)
- *
- * \li \c Matrix2Xf is a partially fixed-size (dynamic-size) matrix of floats (\c Matrix<float, 2, Dynamic>)
- * \li \c MatrixX3d is a partially dynamic-size (fixed-size) matrix of double (\c Matrix<double, Dynamic, 3>)
- *
- * See \link matrixtypedefs this page \endlink for a complete list of predefined \em %Matrix and \em Vector typedefs.
- *
- * You can access elements of vectors and matrices using normal subscripting:
- *
- * \code
- * Eigen::VectorXd v(10);
- * v[0] = 0.1;
- * v[1] = 0.2;
- * v(0) = 0.3;
- * v(1) = 0.4;
- *
- * Eigen::MatrixXi m(10, 10);
- * m(0, 1) = 1;
- * m(0, 2) = 2;
- * m(0, 3) = 3;
- * \endcode
- *
- * 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_MATRIX_PLUGIN.
- *
- * <i><b>Some notes:</b></i>
- *
- * <dl>
- * <dt><b>\anchor dense Dense versus sparse:</b></dt>
- * <dd>This %Matrix class handles dense, not sparse matrices and vectors. For sparse matrices and vectors, see the Sparse module.
- *
- * Dense matrices and vectors are plain usual arrays of coefficients. All the coefficients are stored, in an ordinary contiguous array.
- * This is unlike Sparse matrices and vectors where the coefficients are stored as a list of nonzero coefficients.</dd>
- *
- * <dt><b>\anchor fixedsize Fixed-size versus dynamic-size:</b></dt>
- * <dd>Fixed-size means that the numbers of rows and columns are known are compile-time. In this case, Eigen allocates the array
- * of coefficients as a fixed-size array, as a class member. This makes sense for very small matrices, typically up to 4x4, sometimes up
- * to 16x16. Larger matrices should be declared as dynamic-size even if one happens to know their size at compile-time.
- *
- * Dynamic-size means that the numbers of rows or columns are not necessarily known at compile-time. In this case they are runtime
- * variables, and the array of coefficients is allocated dynamically on the heap.
- *
- * Note that \em dense matrices, be they Fixed-size or Dynamic-size, <em>do not</em> expand dynamically in the sense of a std::map.
- * If you want this behavior, see the Sparse module.</dd>
- *
- * <dt><b>\anchor maxrows _MaxRows and _MaxCols:</b></dt>
- * <dd>In most cases, one just leaves these parameters to the default values.
- * These parameters mean the maximum size of rows and columns that the matrix may have. They are useful in cases
- * when the exact numbers of rows and columns are not known are compile-time, but it is known at compile-time that they cannot
- * exceed a certain value. This happens when taking dynamic-size blocks inside fixed-size matrices: in this case _MaxRows and _MaxCols
- * are the dimensions of the original matrix, while _Rows and _Cols are Dynamic.</dd>
- * </dl>
- *
- * \see MatrixBase for the majority of the API methods for matrices, \ref TopicClassHierarchy,
- * \ref TopicStorageOrders
- */
-
-namespace internal {
-template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
-struct traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
-{
- typedef _Scalar Scalar;
- typedef Dense StorageKind;
- typedef DenseIndex Index;
- typedef MatrixXpr XprKind;
- enum {
- RowsAtCompileTime = _Rows,
- ColsAtCompileTime = _Cols,
- MaxRowsAtCompileTime = _MaxRows,
- MaxColsAtCompileTime = _MaxCols,
- Flags = compute_matrix_flags<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::ret,
- CoeffReadCost = NumTraits<Scalar>::ReadCost,
- Options = _Options,
- InnerStrideAtCompileTime = 1,
- OuterStrideAtCompileTime = (Options&RowMajor) ? ColsAtCompileTime : RowsAtCompileTime
- };
-};
-}
-
-template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
-class Matrix
- : public PlainObjectBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
-{
- public:
-
- /** \brief Base class typedef.
- * \sa PlainObjectBase
- */
- typedef PlainObjectBase<Matrix> Base;
-
- enum { Options = _Options };
-
- EIGEN_DENSE_PUBLIC_INTERFACE(Matrix)
-
- typedef typename Base::PlainObject PlainObject;
-
- enum { NeedsToAlign = (!(Options&DontAlign))
- && SizeAtCompileTime!=Dynamic && ((static_cast<int>(sizeof(Scalar))*SizeAtCompileTime)%16)==0 };
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
-
- using Base::base;
- using Base::coeffRef;
-
- /**
- * \brief Assigns matrices to each other.
- *
- * \note This is a special case of the templated operator=. Its purpose is
- * to prevent a default operator= from hiding the templated operator=.
- *
- * \callgraph
- */
- EIGEN_STRONG_INLINE Matrix& operator=(const Matrix& other)
- {
- return Base::_set(other);
- }
-
- /** \internal
- * \brief Copies the value of the expression \a other into \c *this with automatic resizing.
- *
- * *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized),
- * it will be initialized.
- *
- * Note that copying a row-vector into a vector (and conversely) is allowed.
- * The resizing, if any, is then done in the appropriate way so that row-vectors
- * remain row-vectors and vectors remain vectors.
- */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Matrix& operator=(const MatrixBase<OtherDerived>& other)
- {
- return Base::_set(other);
- }
-
- /* Here, doxygen failed to copy the brief information when using \copydoc */
-
- /**
- * \brief Copies the generic expression \a other into *this.
- * \copydetails DenseBase::operator=(const EigenBase<OtherDerived> &other)
- */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Matrix& operator=(const EigenBase<OtherDerived> &other)
- {
- return Base::operator=(other);
- }
-
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Matrix& operator=(const ReturnByValue<OtherDerived>& func)
- {
- return Base::operator=(func);
- }
-
- /** \brief Default constructor.
- *
- * For fixed-size matrices, does nothing.
- *
- * For dynamic-size matrices, creates an empty matrix of size 0. Does not allocate any array. Such a matrix
- * is called a null matrix. This constructor is the unique way to create null matrices: resizing
- * a matrix to 0 is not supported.
- *
- * \sa resize(Index,Index)
- */
- EIGEN_STRONG_INLINE explicit Matrix() : Base()
- {
- Base::_check_template_params();
- EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
- }
-
- // FIXME is it still needed
- Matrix(internal::constructor_without_unaligned_array_assert)
- : Base(internal::constructor_without_unaligned_array_assert())
- { Base::_check_template_params(); EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED }
-
- /** \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,
- * it is redundant to pass the dimension here, so it makes more sense to use the default
- * constructor Matrix() instead.
- */
- EIGEN_STRONG_INLINE explicit Matrix(Index dim)
- : Base(dim, RowsAtCompileTime == 1 ? 1 : dim, ColsAtCompileTime == 1 ? 1 : dim)
- {
- Base::_check_template_params();
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
- eigen_assert(dim >= 0);
- eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == dim);
- EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
- }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- template<typename T0, typename T1>
- EIGEN_STRONG_INLINE Matrix(const T0& x, const T1& y)
- {
- Base::_check_template_params();
- Base::template _init2<T0,T1>(x, y);
- }
- #else
- /** \brief Constructs an uninitialized matrix with \a rows rows and \a cols columns.
- *
- * This is useful for dynamic-size matrices. For fixed-size matrices,
- * it is redundant to pass these parameters, so one should use the default constructor
- * Matrix() instead. */
- Matrix(Index rows, Index cols);
- /** \brief Constructs an initialized 2D vector with given coefficients */
- Matrix(const Scalar& x, const Scalar& y);
- #endif
-
- /** \brief Constructs an initialized 3D vector with given coefficients */
- EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z)
- {
- Base::_check_template_params();
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 3)
- m_storage.data()[0] = x;
- m_storage.data()[1] = y;
- m_storage.data()[2] = z;
- }
- /** \brief Constructs an initialized 4D vector with given coefficients */
- EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w)
- {
- Base::_check_template_params();
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 4)
- m_storage.data()[0] = x;
- m_storage.data()[1] = y;
- m_storage.data()[2] = z;
- m_storage.data()[3] = w;
- }
-
- explicit Matrix(const Scalar *data);
-
- /** \brief Constructor copying the value of the expression \a other */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Matrix(const MatrixBase<OtherDerived>& other)
- : Base(other.rows() * other.cols(), other.rows(), other.cols())
- {
- // This test resides here, to bring the error messages closer to the user. Normally, these checks
- // are performed deeply within the library, thus causing long and scary error traces.
- EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
- YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
-
- Base::_check_template_params();
- Base::_set_noalias(other);
- }
- /** \brief Copy constructor */
- EIGEN_STRONG_INLINE Matrix(const Matrix& other)
- : Base(other.rows() * other.cols(), other.rows(), other.cols())
- {
- Base::_check_template_params();
- Base::_set_noalias(other);
- }
- /** \brief Copy constructor with in-place evaluation */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Matrix(const ReturnByValue<OtherDerived>& other)
- {
- Base::_check_template_params();
- Base::resize(other.rows(), other.cols());
- other.evalTo(*this);
- }
-
- /** \brief Copy constructor for generic expressions.
- * \sa MatrixBase::operator=(const EigenBase<OtherDerived>&)
- */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Matrix(const EigenBase<OtherDerived> &other)
- : Base(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
- {
- Base::_check_template_params();
- Base::resize(other.rows(), other.cols());
- // FIXME/CHECK: isn't *this = other.derived() more efficient. it allows to
- // go for pure _set() implementations, right?
- *this = other;
- }
-
- /** \internal
- * \brief Override MatrixBase::swap() since for dynamic-sized matrices
- * of same type it is enough to swap the data pointers.
- */
- template<typename OtherDerived>
- void swap(MatrixBase<OtherDerived> const & other)
- { this->_swap(other.derived()); }
-
- inline Index innerStride() const { return 1; }
- inline Index outerStride() const { return this->innerSize(); }
-
- /////////// Geometry module ///////////
-
- template<typename OtherDerived>
- explicit Matrix(const RotationBase<OtherDerived,ColsAtCompileTime>& r);
- template<typename OtherDerived>
- Matrix& operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r);
-
- #ifdef EIGEN2_SUPPORT
- template<typename OtherDerived>
- explicit Matrix(const eigen2_RotationBase<OtherDerived,ColsAtCompileTime>& r);
- template<typename OtherDerived>
- Matrix& operator=(const eigen2_RotationBase<OtherDerived,ColsAtCompileTime>& r);
- #endif
-
- // allow to extend Matrix outside Eigen
- #ifdef EIGEN_MATRIX_PLUGIN
- #include EIGEN_MATRIX_PLUGIN
- #endif
-
- protected:
- template <typename Derived, typename OtherDerived, bool IsVector>
- friend struct internal::conservative_resize_like_impl;
-
- using Base::m_storage;
-};
-
-/** \defgroup matrixtypedefs Global matrix typedefs
- *
- * \ingroup Core_Module
- *
- * Eigen defines several typedef shortcuts for most common matrix and vector types.
- *
- * The general patterns are the following:
- *
- * \c MatrixSizeType where \c Size can be \c 2,\c 3,\c 4 for fixed size square matrices or \c X for dynamic size,
- * and where \c Type can be \c i for integer, \c f for float, \c d for double, \c cf for complex float, \c cd
- * for complex double.
- *
- * For example, \c Matrix3d is a fixed-size 3x3 matrix type of doubles, and \c MatrixXf is a dynamic-size matrix of floats.
- *
- * There are also \c VectorSizeType and \c RowVectorSizeType which are self-explanatory. For example, \c Vector4cf is
- * a fixed-size vector of 4 complex floats.
- *
- * \sa class Matrix
- */
-
-#define EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \
-/** \ingroup matrixtypedefs */ \
-typedef Matrix<Type, Size, Size> Matrix##SizeSuffix##TypeSuffix; \
-/** \ingroup matrixtypedefs */ \
-typedef Matrix<Type, Size, 1> Vector##SizeSuffix##TypeSuffix; \
-/** \ingroup matrixtypedefs */ \
-typedef Matrix<Type, 1, Size> RowVector##SizeSuffix##TypeSuffix;
-
-#define EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, Size) \
-/** \ingroup matrixtypedefs */ \
-typedef Matrix<Type, Size, Dynamic> Matrix##Size##X##TypeSuffix; \
-/** \ingroup matrixtypedefs */ \
-typedef Matrix<Type, Dynamic, Size> Matrix##X##Size##TypeSuffix;
-
-#define EIGEN_MAKE_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \
-EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 2, 2) \
-EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 3, 3) \
-EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 4, 4) \
-EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Dynamic, X) \
-EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 2) \
-EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 3) \
-EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 4)
-
-EIGEN_MAKE_TYPEDEFS_ALL_SIZES(int, i)
-EIGEN_MAKE_TYPEDEFS_ALL_SIZES(float, f)
-EIGEN_MAKE_TYPEDEFS_ALL_SIZES(double, d)
-EIGEN_MAKE_TYPEDEFS_ALL_SIZES(std::complex<float>, cf)
-EIGEN_MAKE_TYPEDEFS_ALL_SIZES(std::complex<double>, cd)
-
-#undef EIGEN_MAKE_TYPEDEFS_ALL_SIZES
-#undef EIGEN_MAKE_TYPEDEFS
-
-#undef EIGEN_MAKE_TYPEDEFS_LARGE
-
-#define EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, SizeSuffix) \
-using Eigen::Matrix##SizeSuffix##TypeSuffix; \
-using Eigen::Vector##SizeSuffix##TypeSuffix; \
-using Eigen::RowVector##SizeSuffix##TypeSuffix;
-
-#define EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(TypeSuffix) \
-EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 2) \
-EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 3) \
-EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 4) \
-EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, X) \
-
-#define EIGEN_USING_MATRIX_TYPEDEFS \
-EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(i) \
-EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(f) \
-EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(d) \
-EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cf) \
-EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cd)
-
-#endif // EIGEN_MATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Core/MatrixBase.h b/extern/Eigen3/Eigen/src/Core/MatrixBase.h
deleted file mode 100644
index db156f6e9d0..00000000000
--- a/extern/Eigen3/Eigen/src/Core/MatrixBase.h
+++ /dev/null
@@ -1,520 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_MATRIXBASE_H
-#define EIGEN_MATRIXBASE_H
-
-/** \class MatrixBase
- * \ingroup Core_Module
- *
- * \brief Base class for all dense matrices, vectors, and expressions
- *
- * This class is the base that is inherited by all matrix, vector, and related expression
- * types. Most of the Eigen API is contained in this class, and its base classes. Other important
- * classes for the Eigen API are Matrix, and VectorwiseOp.
- *
- * Note that some methods are defined in other modules such as the \ref LU_Module LU module
- * for all functions related to matrix inversions.
- *
- * \tparam Derived is the derived type, e.g. a matrix type, or an expression, etc.
- *
- * When writing a function taking Eigen objects as argument, if you want your function
- * to take as argument any matrix, vector, or expression, just let it take a
- * MatrixBase argument. As an example, here is a function printFirstRow which, given
- * a matrix, vector, or expression \a x, prints the first row of \a x.
- *
- * \code
- template<typename Derived>
- void printFirstRow(const Eigen::MatrixBase<Derived>& x)
- {
- cout << x.row(0) << endl;
- }
- * \endcode
- *
- * 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_MATRIXBASE_PLUGIN.
- *
- * \sa \ref TopicClassHierarchy
- */
-template<typename Derived> class MatrixBase
- : public DenseBase<Derived>
-{
- public:
-#ifndef EIGEN_PARSED_BY_DOXYGEN
- typedef MatrixBase StorageBaseType;
- typedef typename internal::traits<Derived>::StorageKind StorageKind;
- typedef typename internal::traits<Derived>::Index Index;
- typedef typename internal::traits<Derived>::Scalar Scalar;
- typedef typename internal::packet_traits<Scalar>::type PacketScalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
- typedef DenseBase<Derived> Base;
- using Base::RowsAtCompileTime;
- using Base::ColsAtCompileTime;
- using Base::SizeAtCompileTime;
- using Base::MaxRowsAtCompileTime;
- using Base::MaxColsAtCompileTime;
- using Base::MaxSizeAtCompileTime;
- using Base::IsVectorAtCompileTime;
- using Base::Flags;
- using Base::CoeffReadCost;
-
- using Base::derived;
- using Base::const_cast_derived;
- using Base::rows;
- using Base::cols;
- using Base::size;
- using Base::coeff;
- using Base::coeffRef;
- using Base::lazyAssign;
- using Base::eval;
- using Base::operator+=;
- using Base::operator-=;
- using Base::operator*=;
- using Base::operator/=;
-
- typedef typename Base::CoeffReturnType CoeffReturnType;
- typedef typename Base::ConstTransposeReturnType ConstTransposeReturnType;
- typedef typename Base::RowXpr RowXpr;
- typedef typename Base::ColXpr ColXpr;
-#endif // not EIGEN_PARSED_BY_DOXYGEN
-
-
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
- /** type of the equivalent square matrix */
- typedef Matrix<Scalar,EIGEN_SIZE_MAX(RowsAtCompileTime,ColsAtCompileTime),
- EIGEN_SIZE_MAX(RowsAtCompileTime,ColsAtCompileTime)> SquareMatrixType;
-#endif // not EIGEN_PARSED_BY_DOXYGEN
-
- /** \returns the size of the main diagonal, which is min(rows(),cols()).
- * \sa rows(), cols(), SizeAtCompileTime. */
- inline Index diagonalSize() const { return (std::min)(rows(),cols()); }
-
- /** \brief The plain matrix type corresponding to this expression.
- *
- * This is not necessarily exactly the return type of eval(). In the case of plain matrices,
- * the return type of eval() is a const reference to a matrix, not a matrix! It is however guaranteed
- * that the return type of eval() is either PlainObject or const PlainObject&.
- */
- typedef Matrix<typename internal::traits<Derived>::Scalar,
- internal::traits<Derived>::RowsAtCompileTime,
- internal::traits<Derived>::ColsAtCompileTime,
- AutoAlign | (internal::traits<Derived>::Flags&RowMajorBit ? RowMajor : ColMajor),
- internal::traits<Derived>::MaxRowsAtCompileTime,
- internal::traits<Derived>::MaxColsAtCompileTime
- > PlainObject;
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
- /** \internal Represents a matrix with all coefficients equal to one another*/
- typedef CwiseNullaryOp<internal::scalar_constant_op<Scalar>,Derived> ConstantReturnType;
- /** \internal the return type of MatrixBase::adjoint() */
- typedef typename internal::conditional<NumTraits<Scalar>::IsComplex,
- CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, ConstTransposeReturnType>,
- ConstTransposeReturnType
- >::type AdjointReturnType;
- /** \internal Return type of eigenvalues() */
- typedef Matrix<std::complex<RealScalar>, internal::traits<Derived>::ColsAtCompileTime, 1, ColMajor> EigenvaluesReturnType;
- /** \internal the return type of identity */
- typedef CwiseNullaryOp<internal::scalar_identity_op<Scalar>,Derived> IdentityReturnType;
- /** \internal the return type of unit vectors */
- typedef Block<const CwiseNullaryOp<internal::scalar_identity_op<Scalar>, SquareMatrixType>,
- internal::traits<Derived>::RowsAtCompileTime,
- internal::traits<Derived>::ColsAtCompileTime> BasisReturnType;
-#endif // not EIGEN_PARSED_BY_DOXYGEN
-
-#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::MatrixBase
-# include "../plugins/CommonCwiseUnaryOps.h"
-# include "../plugins/CommonCwiseBinaryOps.h"
-# include "../plugins/MatrixCwiseUnaryOps.h"
-# include "../plugins/MatrixCwiseBinaryOps.h"
-# ifdef EIGEN_MATRIXBASE_PLUGIN
-# include EIGEN_MATRIXBASE_PLUGIN
-# endif
-#undef EIGEN_CURRENT_STORAGE_BASE_CLASS
-
- /** Special case of the template operator=, in order to prevent the compiler
- * from generating a default operator= (issue hit with g++ 4.1)
- */
- Derived& operator=(const MatrixBase& other);
-
- // We cannot inherit here via Base::operator= since it is causing
- // trouble with MSVC.
-
- template <typename OtherDerived>
- Derived& operator=(const DenseBase<OtherDerived>& other);
-
- template <typename OtherDerived>
- Derived& operator=(const EigenBase<OtherDerived>& other);
-
- 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);
-#endif // not EIGEN_PARSED_BY_DOXYGEN
-
- template<typename OtherDerived>
- Derived& operator+=(const MatrixBase<OtherDerived>& other);
- template<typename OtherDerived>
- Derived& operator-=(const MatrixBase<OtherDerived>& other);
-
- template<typename OtherDerived>
- const typename ProductReturnType<Derived,OtherDerived>::Type
- operator*(const MatrixBase<OtherDerived> &other) const;
-
- template<typename OtherDerived>
- const typename LazyProductReturnType<Derived,OtherDerived>::Type
- lazyProduct(const MatrixBase<OtherDerived> &other) const;
-
- template<typename OtherDerived>
- Derived& operator*=(const EigenBase<OtherDerived>& other);
-
- template<typename OtherDerived>
- void applyOnTheLeft(const EigenBase<OtherDerived>& other);
-
- template<typename OtherDerived>
- void applyOnTheRight(const EigenBase<OtherDerived>& other);
-
- template<typename DiagonalDerived>
- const DiagonalProduct<Derived, DiagonalDerived, OnTheRight>
- operator*(const DiagonalBase<DiagonalDerived> &diagonal) const;
-
- template<typename OtherDerived>
- typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
- dot(const MatrixBase<OtherDerived>& other) const;
-
- #ifdef EIGEN2_SUPPORT
- template<typename OtherDerived>
- Scalar eigen2_dot(const MatrixBase<OtherDerived>& other) const;
- #endif
-
- RealScalar squaredNorm() const;
- RealScalar norm() const;
- RealScalar stableNorm() const;
- RealScalar blueNorm() const;
- RealScalar hypotNorm() const;
- const PlainObject normalized() const;
- void normalize();
-
- const AdjointReturnType adjoint() const;
- void adjointInPlace();
-
- typedef Diagonal<Derived> DiagonalReturnType;
- DiagonalReturnType diagonal();
- typedef const Diagonal<const Derived> ConstDiagonalReturnType;
- const ConstDiagonalReturnType diagonal() const;
-
- template<int Index> struct DiagonalIndexReturnType { typedef Diagonal<Derived,Index> Type; };
- template<int Index> struct ConstDiagonalIndexReturnType { typedef const Diagonal<const Derived,Index> Type; };
-
- template<int Index> typename DiagonalIndexReturnType<Index>::Type diagonal();
- template<int Index> typename ConstDiagonalIndexReturnType<Index>::Type diagonal() const;
-
- // 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<Dynamic>::Type diagonal(Index index);
- typename MatrixBase::template ConstDiagonalIndexReturnType<Dynamic>::Type diagonal(Index index) const;
- #else
- typename DiagonalIndexReturnType<Dynamic>::Type diagonal(Index index);
- typename ConstDiagonalIndexReturnType<Dynamic>::Type diagonal(Index index) const;
- #endif
-
- #ifdef EIGEN2_SUPPORT
- template<unsigned int Mode> typename internal::eigen2_part_return_type<Derived, Mode>::type part();
- template<unsigned int Mode> const typename internal::eigen2_part_return_type<Derived, Mode>::type part() const;
-
- // huuuge hack. make Eigen2's matrix.part<Diagonal>() work in eigen3. Problem: Diagonal is now a class template instead
- // of an integer constant. Solution: overload the part() method template wrt template parameters list.
- template<template<typename T, int n> class U>
- const DiagonalWrapper<ConstDiagonalReturnType> part() const
- { return diagonal().asDiagonal(); }
- #endif // EIGEN2_SUPPORT
-
- template<unsigned int Mode> struct TriangularViewReturnType { typedef TriangularView<Derived, Mode> Type; };
- template<unsigned int Mode> struct ConstTriangularViewReturnType { typedef const TriangularView<const Derived, Mode> Type; };
-
- template<unsigned int Mode> typename TriangularViewReturnType<Mode>::Type triangularView();
- template<unsigned int Mode> typename ConstTriangularViewReturnType<Mode>::Type triangularView() const;
-
- template<unsigned int UpLo> struct SelfAdjointViewReturnType { typedef SelfAdjointView<Derived, UpLo> Type; };
- template<unsigned int UpLo> struct ConstSelfAdjointViewReturnType { typedef const SelfAdjointView<const Derived, UpLo> Type; };
-
- template<unsigned int UpLo> typename SelfAdjointViewReturnType<UpLo>::Type selfadjointView();
- template<unsigned int UpLo> typename ConstSelfAdjointViewReturnType<UpLo>::Type selfadjointView() const;
-
- const SparseView<Derived> sparseView(const Scalar& m_reference = Scalar(0),
- typename NumTraits<Scalar>::Real m_epsilon = NumTraits<Scalar>::dummy_precision()) const;
- static const IdentityReturnType Identity();
- static const IdentityReturnType Identity(Index rows, Index cols);
- static const BasisReturnType Unit(Index size, Index i);
- static const BasisReturnType Unit(Index i);
- static const BasisReturnType UnitX();
- static const BasisReturnType UnitY();
- static const BasisReturnType UnitZ();
- static const BasisReturnType UnitW();
-
- const DiagonalWrapper<const Derived> asDiagonal() const;
- const PermutationWrapper<const Derived> asPermutation() const;
-
- Derived& setIdentity();
- Derived& setIdentity(Index rows, Index cols);
-
- bool isIdentity(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isDiagonal(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
-
- bool isUpperTriangular(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isLowerTriangular(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
-
- template<typename OtherDerived>
- bool isOrthogonal(const MatrixBase<OtherDerived>& other,
- RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
- bool isUnitary(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const;
-
- /** \returns true if each coefficients of \c *this and \a other are all exactly equal.
- * \warning When using floating point scalar values you probably should rather use a
- * fuzzy comparison such as isApprox()
- * \sa isApprox(), operator!= */
- template<typename OtherDerived>
- inline bool operator==(const MatrixBase<OtherDerived>& other) const
- { return cwiseEqual(other).all(); }
-
- /** \returns true if at least one pair of coefficients of \c *this and \a other are not exactly equal to each other.
- * \warning When using floating point scalar values you probably should rather use a
- * fuzzy comparison such as isApprox()
- * \sa isApprox(), operator== */
- template<typename OtherDerived>
- inline bool operator!=(const MatrixBase<OtherDerived>& other) const
- { return cwiseNotEqual(other).any(); }
-
- NoAlias<Derived,Eigen::MatrixBase > noalias();
-
- inline const ForceAlignedAccess<Derived> forceAlignedAccess() const;
- inline ForceAlignedAccess<Derived> forceAlignedAccess();
- template<bool Enable> inline typename internal::add_const_on_value_type<typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type>::type forceAlignedAccessIf() const;
- template<bool Enable> inline typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type forceAlignedAccessIf();
-
- Scalar trace() const;
-
-/////////// Array module ///////////
-
- template<int p> RealScalar lpNorm() const;
-
- MatrixBase<Derived>& matrix() { return *this; }
- const MatrixBase<Derived>& matrix() const { return *this; }
-
- /** \returns an \link ArrayBase Array \endlink expression of this matrix
- * \sa ArrayBase::matrix() */
- ArrayWrapper<Derived> array() { return derived(); }
- const ArrayWrapper<Derived> array() const { return derived(); }
-
-/////////// LU module ///////////
-
- const FullPivLU<PlainObject> fullPivLu() const;
- const PartialPivLU<PlainObject> partialPivLu() const;
-
- #if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS
- const LU<PlainObject> lu() const;
- #endif
-
- #ifdef EIGEN2_SUPPORT
- const LU<PlainObject> eigen2_lu() const;
- #endif
-
- #if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
- const PartialPivLU<PlainObject> lu() const;
- #endif
-
- #ifdef EIGEN2_SUPPORT
- template<typename ResultType>
- void computeInverse(MatrixBase<ResultType> *result) const {
- *result = this->inverse();
- }
- #endif
-
- const internal::inverse_impl<Derived> inverse() const;
- template<typename ResultType>
- void computeInverseAndDetWithCheck(
- ResultType& inverse,
- typename ResultType::Scalar& determinant,
- bool& invertible,
- const RealScalar& absDeterminantThreshold = NumTraits<Scalar>::dummy_precision()
- ) const;
- template<typename ResultType>
- void computeInverseWithCheck(
- ResultType& inverse,
- bool& invertible,
- const RealScalar& absDeterminantThreshold = NumTraits<Scalar>::dummy_precision()
- ) const;
- Scalar determinant() const;
-
-/////////// Cholesky module ///////////
-
- const LLT<PlainObject> llt() const;
- const LDLT<PlainObject> ldlt() const;
-
-/////////// QR module ///////////
-
- const HouseholderQR<PlainObject> householderQr() const;
- const ColPivHouseholderQR<PlainObject> colPivHouseholderQr() const;
- const FullPivHouseholderQR<PlainObject> fullPivHouseholderQr() const;
-
- #ifdef EIGEN2_SUPPORT
- const QR<PlainObject> qr() const;
- #endif
-
- EigenvaluesReturnType eigenvalues() const;
- RealScalar operatorNorm() const;
-
-/////////// SVD module ///////////
-
- JacobiSVD<PlainObject> jacobiSvd(unsigned int computationOptions = 0) const;
-
- #ifdef EIGEN2_SUPPORT
- SVD<PlainObject> svd() const;
- #endif
-
-/////////// Geometry module ///////////
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- /// \internal helper struct to form the return type of the cross product
- template<typename OtherDerived> struct cross_product_return_type {
- typedef typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType Scalar;
- typedef Matrix<Scalar,MatrixBase::RowsAtCompileTime,MatrixBase::ColsAtCompileTime> type;
- };
- #endif // EIGEN_PARSED_BY_DOXYGEN
- template<typename OtherDerived>
- typename cross_product_return_type<OtherDerived>::type
- cross(const MatrixBase<OtherDerived>& other) const;
- template<typename OtherDerived>
- PlainObject cross3(const MatrixBase<OtherDerived>& other) const;
- PlainObject unitOrthogonal(void) const;
- Matrix<Scalar,3,1> eulerAngles(Index a0, Index a1, Index a2) const;
-
- #if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
- ScalarMultipleReturnType operator*(const UniformScaling<Scalar>& s) const;
- // put this as separate enum value to work around possible GCC 4.3 bug (?)
- enum { HomogeneousReturnTypeDirection = ColsAtCompileTime==1?Vertical:Horizontal };
- typedef Homogeneous<Derived, HomogeneousReturnTypeDirection> HomogeneousReturnType;
- HomogeneousReturnType homogeneous() const;
- #endif
-
- enum {
- SizeMinusOne = SizeAtCompileTime==Dynamic ? Dynamic : SizeAtCompileTime-1
- };
- typedef Block<const Derived,
- internal::traits<Derived>::ColsAtCompileTime==1 ? SizeMinusOne : 1,
- internal::traits<Derived>::ColsAtCompileTime==1 ? 1 : SizeMinusOne> ConstStartMinusOne;
- typedef CwiseUnaryOp<internal::scalar_quotient1_op<typename internal::traits<Derived>::Scalar>,
- const ConstStartMinusOne > HNormalizedReturnType;
-
- const HNormalizedReturnType hnormalized() const;
-
-////////// Householder module ///////////
-
- void makeHouseholderInPlace(Scalar& tau, RealScalar& beta);
- template<typename EssentialPart>
- void makeHouseholder(EssentialPart& essential,
- Scalar& tau, RealScalar& beta) const;
- template<typename EssentialPart>
- void applyHouseholderOnTheLeft(const EssentialPart& essential,
- const Scalar& tau,
- Scalar* workspace);
- template<typename EssentialPart>
- void applyHouseholderOnTheRight(const EssentialPart& essential,
- const Scalar& tau,
- Scalar* workspace);
-
-///////// Jacobi module /////////
-
- template<typename OtherScalar>
- void applyOnTheLeft(Index p, Index q, const JacobiRotation<OtherScalar>& j);
- template<typename OtherScalar>
- void applyOnTheRight(Index p, Index q, const JacobiRotation<OtherScalar>& j);
-
-///////// MatrixFunctions module /////////
-
- typedef typename internal::stem_function<Scalar>::type StemFunction;
- const MatrixExponentialReturnValue<Derived> exp() const;
- const MatrixFunctionReturnValue<Derived> matrixFunction(StemFunction f) const;
- const MatrixFunctionReturnValue<Derived> cosh() const;
- const MatrixFunctionReturnValue<Derived> sinh() const;
- const MatrixFunctionReturnValue<Derived> cos() const;
- const MatrixFunctionReturnValue<Derived> sin() const;
-
-#ifdef EIGEN2_SUPPORT
- template<typename ProductDerived, typename Lhs, typename Rhs>
- Derived& operator+=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0,
- EvalBeforeAssigningBit>& other);
-
- template<typename ProductDerived, typename Lhs, typename Rhs>
- Derived& operator-=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0,
- EvalBeforeAssigningBit>& other);
-
- /** \deprecated because .lazy() is deprecated
- * Overloaded for cache friendly product evaluation */
- template<typename OtherDerived>
- Derived& lazyAssign(const Flagged<OtherDerived, 0, EvalBeforeAssigningBit>& other)
- { return lazyAssign(other._expression()); }
-
- template<unsigned int Added>
- const Flagged<Derived, Added, 0> marked() const;
- const Flagged<Derived, 0, EvalBeforeAssigningBit> lazy() const;
-
- inline const Cwise<Derived> cwise() const;
- inline Cwise<Derived> cwise();
-
- VectorBlock<Derived> start(Index size);
- const VectorBlock<const Derived> start(Index size) const;
- VectorBlock<Derived> end(Index size);
- const VectorBlock<const Derived> end(Index size) const;
- template<int Size> VectorBlock<Derived,Size> start();
- template<int Size> const VectorBlock<const Derived,Size> start() const;
- template<int Size> VectorBlock<Derived,Size> end();
- template<int Size> const VectorBlock<const Derived,Size> end() const;
-
- Minor<Derived> minor(Index row, Index col);
- const Minor<Derived> minor(Index row, Index col) const;
-#endif
-
- protected:
- MatrixBase() : Base() {}
-
- private:
- explicit MatrixBase(int);
- MatrixBase(int,int);
- template<typename OtherDerived> explicit MatrixBase(const MatrixBase<OtherDerived>&);
- protected:
- // mixing arrays and matrices is not legal
- template<typename OtherDerived> Derived& operator+=(const ArrayBase<OtherDerived>& )
- {EIGEN_STATIC_ASSERT(sizeof(typename OtherDerived::Scalar)==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES);}
- // mixing arrays and matrices is not legal
- template<typename OtherDerived> Derived& operator-=(const ArrayBase<OtherDerived>& )
- {EIGEN_STATIC_ASSERT(sizeof(typename OtherDerived::Scalar)==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES);}
-};
-
-#endif // EIGEN_MATRIXBASE_H
diff --git a/extern/Eigen3/Eigen/src/Core/NoAlias.h b/extern/Eigen3/Eigen/src/Core/NoAlias.h
deleted file mode 100644
index da64affcf9a..00000000000
--- a/extern/Eigen3/Eigen/src/Core/NoAlias.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_NOALIAS_H
-#define EIGEN_NOALIAS_H
-
-/** \class NoAlias
- * \ingroup Core_Module
- *
- * \brief Pseudo expression providing an operator = assuming no aliasing
- *
- * \param ExpressionType the type of the object on which to do the lazy assignment
- *
- * This class represents an expression with special assignment operators
- * assuming no aliasing between the target expression and the source expression.
- * More precisely it alloas to bypass the EvalBeforeAssignBit flag of the source expression.
- * It is the return type of MatrixBase::noalias()
- * and most of the time this is the only way it is used.
- *
- * \sa MatrixBase::noalias()
- */
-template<typename ExpressionType, template <typename> class StorageBase>
-class NoAlias
-{
- typedef typename ExpressionType::Scalar Scalar;
- public:
- NoAlias(ExpressionType& expression) : m_expression(expression) {}
-
- /** Behaves like MatrixBase::lazyAssign(other)
- * \sa MatrixBase::lazyAssign() */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE ExpressionType& operator=(const StorageBase<OtherDerived>& other)
- { return internal::assign_selector<ExpressionType,OtherDerived,false>::run(m_expression,other.derived()); }
-
- /** \sa MatrixBase::operator+= */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE ExpressionType& operator+=(const StorageBase<OtherDerived>& other)
- {
- typedef SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, ExpressionType, OtherDerived> SelfAdder;
- SelfAdder tmp(m_expression);
- typedef typename internal::nested<OtherDerived>::type OtherDerivedNested;
- typedef typename internal::remove_all<OtherDerivedNested>::type _OtherDerivedNested;
- internal::assign_selector<SelfAdder,_OtherDerivedNested,false>::run(tmp,OtherDerivedNested(other.derived()));
- return m_expression;
- }
-
- /** \sa MatrixBase::operator-= */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE ExpressionType& operator-=(const StorageBase<OtherDerived>& other)
- {
- typedef SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, ExpressionType, OtherDerived> SelfAdder;
- SelfAdder tmp(m_expression);
- typedef typename internal::nested<OtherDerived>::type OtherDerivedNested;
- typedef typename internal::remove_all<OtherDerivedNested>::type _OtherDerivedNested;
- internal::assign_selector<SelfAdder,_OtherDerivedNested,false>::run(tmp,OtherDerivedNested(other.derived()));
- return m_expression;
- }
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
- template<typename ProductDerived, typename Lhs, typename Rhs>
- EIGEN_STRONG_INLINE ExpressionType& operator+=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
- { other.derived().addTo(m_expression); return m_expression; }
-
- template<typename ProductDerived, typename Lhs, typename Rhs>
- EIGEN_STRONG_INLINE ExpressionType& operator-=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
- { other.derived().subTo(m_expression); return m_expression; }
-
- template<typename Lhs, typename Rhs, int NestingFlags>
- EIGEN_STRONG_INLINE ExpressionType& operator+=(const CoeffBasedProduct<Lhs,Rhs,NestingFlags>& other)
- { return m_expression.derived() += CoeffBasedProduct<Lhs,Rhs,NestByRefBit>(other.lhs(), other.rhs()); }
-
- template<typename Lhs, typename Rhs, int NestingFlags>
- EIGEN_STRONG_INLINE ExpressionType& operator-=(const CoeffBasedProduct<Lhs,Rhs,NestingFlags>& other)
- { return m_expression.derived() -= CoeffBasedProduct<Lhs,Rhs,NestByRefBit>(other.lhs(), other.rhs()); }
-#endif
-
- protected:
- ExpressionType& m_expression;
-};
-
-/** \returns a pseudo expression of \c *this with an operator= assuming
- * no aliasing between \c *this and the source expression.
- *
- * More precisely, noalias() allows to bypass the EvalBeforeAssignBit flag.
- * Currently, even though several expressions may alias, only product
- * expressions have this flag. Therefore, noalias() is only usefull when
- * the source expression contains a matrix product.
- *
- * Here are some examples where noalias is usefull:
- * \code
- * D.noalias() = A * B;
- * D.noalias() += A.transpose() * B;
- * D.noalias() -= 2 * A * B.adjoint();
- * \endcode
- *
- * On the other hand the following example will lead to a \b wrong result:
- * \code
- * A.noalias() = A * B;
- * \endcode
- * because the result matrix A is also an operand of the matrix product. Therefore,
- * there is no alternative than evaluating A * B in a temporary, that is the default
- * behavior when you write:
- * \code
- * A = A * B;
- * \endcode
- *
- * \sa class NoAlias
- */
-template<typename Derived>
-NoAlias<Derived,MatrixBase> MatrixBase<Derived>::noalias()
-{
- return derived();
-}
-
-#endif // EIGEN_NOALIAS_H
diff --git a/extern/Eigen3/Eigen/src/Core/NumTraits.h b/extern/Eigen3/Eigen/src/Core/NumTraits.h
deleted file mode 100644
index 73ef05dfe7a..00000000000
--- a/extern/Eigen3/Eigen/src/Core/NumTraits.h
+++ /dev/null
@@ -1,160 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_NUMTRAITS_H
-#define EIGEN_NUMTRAITS_H
-
-/** \class NumTraits
- * \ingroup Core_Module
- *
- * \brief Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
- *
- * \param T the numeric type at hand
- *
- * This class stores enums, typedefs and static methods giving information about a numeric type.
- *
- * The provided data consists of:
- * \li A typedef \a Real, giving the "real part" type of \a T. If \a T is already real,
- * then \a Real is just a typedef to \a T. If \a T is \c std::complex<U> then \a Real
- * is a typedef to \a U.
- * \li A typedef \a NonInteger, giving the type that should be used for operations producing non-integral values,
- * such as quotients, square roots, etc. If \a T is a floating-point type, then this typedef just gives
- * \a T again. Note however that many Eigen functions such as internal::sqrt simply refuse to
- * take integers. Outside of a few cases, Eigen doesn't do automatic type promotion. Thus, this typedef is
- * only intended as a helper for code that needs to explicitly promote types.
- * \li A typedef \a Nested giving the type to use to nest a value inside of the expression tree. If you don't know what
- * this means, just use \a T here.
- * \li An enum value \a IsComplex. It is equal to 1 if \a T is a \c std::complex
- * type, and to 0 otherwise.
- * \li An enum value \a IsInteger. It is equal to \c 1 if \a T is an integer type such as \c int,
- * and to \c 0 otherwise.
- * \li Enum values ReadCost, AddCost and MulCost representing a rough estimate of the number of CPU cycles needed
- * to by move / add / mul instructions respectively, assuming the data is already stored in CPU registers.
- * Stay vague here. No need to do architecture-specific stuff.
- * \li An enum value \a IsSigned. It is equal to \c 1 if \a T is a signed type and to 0 if \a T is unsigned.
- * \li An enum value \a RequireInitialization. It is equal to \c 1 if the constructor of the numeric type \a T must
- * be called, and to 0 if it is safe not to call it. Default is 0 if \a T is an arithmetic type, and 1 otherwise.
- * \li An epsilon() function which, unlike std::numeric_limits::epsilon(), returns a \a Real instead of a \a T.
- * \li A dummy_precision() function returning a weak epsilon value. It is mainly used as a default
- * value by the fuzzy comparison operators.
- * \li highest() and lowest() functions returning the highest and lowest possible values respectively.
- */
-
-template<typename T> struct GenericNumTraits
-{
- enum {
- IsInteger = std::numeric_limits<T>::is_integer,
- IsSigned = std::numeric_limits<T>::is_signed,
- IsComplex = 0,
- RequireInitialization = internal::is_arithmetic<T>::value ? 0 : 1,
- ReadCost = 1,
- AddCost = 1,
- MulCost = 1
- };
-
- typedef T Real;
- typedef typename internal::conditional<
- IsInteger,
- typename internal::conditional<sizeof(T)<=2, float, double>::type,
- T
- >::type NonInteger;
- typedef T Nested;
-
- inline static Real epsilon() { return std::numeric_limits<T>::epsilon(); }
- inline static Real dummy_precision()
- {
- // make sure to override this for floating-point types
- return Real(0);
- }
- inline static T highest() { return (std::numeric_limits<T>::max)(); }
- inline static T lowest() { return IsInteger ? (std::numeric_limits<T>::min)() : (-(std::numeric_limits<T>::max)()); }
-
-#ifdef EIGEN2_SUPPORT
- enum {
- HasFloatingPoint = !IsInteger
- };
- typedef NonInteger FloatingPoint;
-#endif
-};
-
-template<typename T> struct NumTraits : GenericNumTraits<T>
-{};
-
-template<> struct NumTraits<float>
- : GenericNumTraits<float>
-{
- inline static float dummy_precision() { return 1e-5f; }
-};
-
-template<> struct NumTraits<double> : GenericNumTraits<double>
-{
- inline static double dummy_precision() { return 1e-12; }
-};
-
-template<> struct NumTraits<long double>
- : GenericNumTraits<long double>
-{
- static inline long double dummy_precision() { return 1e-15l; }
-};
-
-template<typename _Real> struct NumTraits<std::complex<_Real> >
- : GenericNumTraits<std::complex<_Real> >
-{
- typedef _Real Real;
- enum {
- IsComplex = 1,
- RequireInitialization = NumTraits<_Real>::RequireInitialization,
- ReadCost = 2 * NumTraits<_Real>::ReadCost,
- AddCost = 2 * NumTraits<Real>::AddCost,
- MulCost = 4 * NumTraits<Real>::MulCost + 2 * NumTraits<Real>::AddCost
- };
-
- inline static Real epsilon() { return NumTraits<Real>::epsilon(); }
- inline static Real dummy_precision() { return NumTraits<Real>::dummy_precision(); }
-};
-
-template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
-struct NumTraits<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
-{
- typedef Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> ArrayType;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Array<RealScalar, Rows, Cols, Options, MaxRows, MaxCols> Real;
- typedef typename NumTraits<Scalar>::NonInteger NonIntegerScalar;
- typedef Array<NonIntegerScalar, Rows, Cols, Options, MaxRows, MaxCols> NonInteger;
- typedef ArrayType & Nested;
-
- enum {
- IsComplex = NumTraits<Scalar>::IsComplex,
- IsInteger = NumTraits<Scalar>::IsInteger,
- IsSigned = NumTraits<Scalar>::IsSigned,
- RequireInitialization = 1,
- ReadCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::ReadCost,
- AddCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::AddCost,
- MulCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::MulCost
- };
-};
-
-
-
-#endif // EIGEN_NUMTRAITS_H
diff --git a/extern/Eigen3/Eigen/src/Core/PermutationMatrix.h b/extern/Eigen3/Eigen/src/Core/PermutationMatrix.h
deleted file mode 100644
index a064e053e51..00000000000
--- a/extern/Eigen3/Eigen/src/Core/PermutationMatrix.h
+++ /dev/null
@@ -1,696 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2009-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_PERMUTATIONMATRIX_H
-#define EIGEN_PERMUTATIONMATRIX_H
-
-template<int RowCol,typename IndicesType,typename MatrixType, typename StorageKind> class PermutedImpl;
-
-/** \class PermutationBase
- * \ingroup Core_Module
- *
- * \brief Base class for permutations
- *
- * \param Derived the derived class
- *
- * This class is the base class for all expressions representing a permutation matrix,
- * internally stored as a vector of integers.
- * The convention followed here is that if \f$ \sigma \f$ is a permutation, the corresponding permutation matrix
- * \f$ P_\sigma \f$ is such that if \f$ (e_1,\ldots,e_p) \f$ is the canonical basis, we have:
- * \f[ P_\sigma(e_i) = e_{\sigma(i)}. \f]
- * This convention ensures that for any two permutations \f$ \sigma, \tau \f$, we have:
- * \f[ P_{\sigma\circ\tau} = P_\sigma P_\tau. \f]
- *
- * Permutation matrices are square and invertible.
- *
- * Notice that in addition to the member functions and operators listed here, there also are non-member
- * operator* to multiply any kind of permutation object with any kind of matrix expression (MatrixBase)
- * on either side.
- *
- * \sa class PermutationMatrix, class PermutationWrapper
- */
-
-namespace internal {
-
-template<typename PermutationType, typename MatrixType, int Side, bool Transposed=false>
-struct permut_matrix_product_retval;
-enum PermPermProduct_t {PermPermProduct};
-
-} // end namespace internal
-
-template<typename Derived>
-class PermutationBase : public EigenBase<Derived>
-{
- typedef internal::traits<Derived> Traits;
- typedef EigenBase<Derived> Base;
- public:
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- typedef typename Traits::IndicesType IndicesType;
- enum {
- Flags = Traits::Flags,
- CoeffReadCost = Traits::CoeffReadCost,
- RowsAtCompileTime = Traits::RowsAtCompileTime,
- ColsAtCompileTime = Traits::ColsAtCompileTime,
- MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = Traits::MaxColsAtCompileTime
- };
- typedef typename Traits::Scalar Scalar;
- typedef typename Traits::Index Index;
- typedef Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime,0,MaxRowsAtCompileTime,MaxColsAtCompileTime>
- DenseMatrixType;
- typedef PermutationMatrix<IndicesType::SizeAtCompileTime,IndicesType::MaxSizeAtCompileTime,Index>
- PlainPermutationType;
- using Base::derived;
- #endif
-
- /** Copies the other permutation into *this */
- template<typename OtherDerived>
- Derived& operator=(const PermutationBase<OtherDerived>& other)
- {
- indices() = other.indices();
- return derived();
- }
-
- /** Assignment from the Transpositions \a tr */
- template<typename OtherDerived>
- Derived& operator=(const TranspositionsBase<OtherDerived>& tr)
- {
- setIdentity(tr.size());
- for(Index k=size()-1; k>=0; --k)
- applyTranspositionOnTheRight(k,tr.coeff(k));
- return derived();
- }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- /** This is a special case of the templated operator=. Its purpose is to
- * prevent a default operator= from hiding the templated operator=.
- */
- Derived& operator=(const PermutationBase& other)
- {
- indices() = other.indices();
- return derived();
- }
- #endif
-
- /** \returns the number of rows */
- inline Index rows() const { return indices().size(); }
-
- /** \returns the number of columns */
- inline Index cols() const { return indices().size(); }
-
- /** \returns the size of a side of the respective square matrix, i.e., the number of indices */
- inline Index size() const { return indices().size(); }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- template<typename DenseDerived>
- void evalTo(MatrixBase<DenseDerived>& other) const
- {
- other.setZero();
- for (int i=0; i<rows();++i)
- other.coeffRef(indices().coeff(i),i) = typename DenseDerived::Scalar(1);
- }
- #endif
-
- /** \returns a Matrix object initialized from this permutation matrix. Notice that it
- * is inefficient to return this Matrix object by value. For efficiency, favor using
- * the Matrix constructor taking EigenBase objects.
- */
- DenseMatrixType toDenseMatrix() const
- {
- return derived();
- }
-
- /** const version of indices(). */
- const IndicesType& indices() const { return derived().indices(); }
- /** \returns a reference to the stored array representing the permutation. */
- IndicesType& indices() { return derived().indices(); }
-
- /** Resizes to given size.
- */
- inline void resize(Index size)
- {
- indices().resize(size);
- }
-
- /** Sets *this to be the identity permutation matrix */
- void setIdentity()
- {
- for(Index i = 0; i < size(); ++i)
- indices().coeffRef(i) = i;
- }
-
- /** Sets *this to be the identity permutation matrix of given size.
- */
- void setIdentity(Index size)
- {
- resize(size);
- setIdentity();
- }
-
- /** Multiplies *this by the transposition \f$(ij)\f$ on the left.
- *
- * \returns a reference to *this.
- *
- * \warning This is much slower than applyTranspositionOnTheRight(int,int):
- * this has linear complexity and requires a lot of branching.
- *
- * \sa applyTranspositionOnTheRight(int,int)
- */
- Derived& applyTranspositionOnTheLeft(Index i, Index j)
- {
- eigen_assert(i>=0 && j>=0 && i<size() && j<size());
- for(Index k = 0; k < size(); ++k)
- {
- if(indices().coeff(k) == i) indices().coeffRef(k) = j;
- else if(indices().coeff(k) == j) indices().coeffRef(k) = i;
- }
- return derived();
- }
-
- /** Multiplies *this by the transposition \f$(ij)\f$ on the right.
- *
- * \returns a reference to *this.
- *
- * This is a fast operation, it only consists in swapping two indices.
- *
- * \sa applyTranspositionOnTheLeft(int,int)
- */
- Derived& applyTranspositionOnTheRight(Index i, Index j)
- {
- eigen_assert(i>=0 && j>=0 && i<size() && j<size());
- std::swap(indices().coeffRef(i), indices().coeffRef(j));
- return derived();
- }
-
- /** \returns the inverse permutation matrix.
- *
- * \note \note_try_to_help_rvo
- */
- inline Transpose<PermutationBase> inverse() const
- { return derived(); }
- /** \returns the tranpose permutation matrix.
- *
- * \note \note_try_to_help_rvo
- */
- inline Transpose<PermutationBase> transpose() const
- { return derived(); }
-
- /**** multiplication helpers to hopefully get RVO ****/
-
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
- protected:
- template<typename OtherDerived>
- void assignTranspose(const PermutationBase<OtherDerived>& other)
- {
- for (int i=0; i<rows();++i) indices().coeffRef(other.indices().coeff(i)) = i;
- }
- template<typename Lhs,typename Rhs>
- void assignProduct(const Lhs& lhs, const Rhs& rhs)
- {
- eigen_assert(lhs.cols() == rhs.rows());
- for (int i=0; i<rows();++i) indices().coeffRef(i) = lhs.indices().coeff(rhs.indices().coeff(i));
- }
-#endif
-
- public:
-
- /** \returns the product permutation matrix.
- *
- * \note \note_try_to_help_rvo
- */
- template<typename Other>
- inline PlainPermutationType operator*(const PermutationBase<Other>& other) const
- { return PlainPermutationType(internal::PermPermProduct, derived(), other.derived()); }
-
- /** \returns the product of a permutation with another inverse permutation.
- *
- * \note \note_try_to_help_rvo
- */
- template<typename Other>
- inline PlainPermutationType operator*(const Transpose<PermutationBase<Other> >& other) const
- { return PlainPermutationType(internal::PermPermProduct, *this, other.eval()); }
-
- /** \returns the product of an inverse permutation with another permutation.
- *
- * \note \note_try_to_help_rvo
- */
- template<typename Other> friend
- inline PlainPermutationType operator*(const Transpose<PermutationBase<Other> >& other, const PermutationBase& perm)
- { return PlainPermutationType(internal::PermPermProduct, other.eval(), perm); }
-
- protected:
-
-};
-
-/** \class PermutationMatrix
- * \ingroup Core_Module
- *
- * \brief Permutation matrix
- *
- * \param SizeAtCompileTime the number of rows/cols, or Dynamic
- * \param MaxSizeAtCompileTime the maximum number of rows/cols, or Dynamic. This optional parameter defaults to SizeAtCompileTime. Most of the time, you should not have to specify it.
- * \param IndexType the interger type of the indices
- *
- * This class represents a permutation matrix, internally stored as a vector of integers.
- *
- * \sa class PermutationBase, class PermutationWrapper, class DiagonalMatrix
- */
-
-namespace internal {
-template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType>
-struct traits<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType> >
- : traits<Matrix<IndexType,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> >
-{
- typedef IndexType Index;
- typedef Matrix<IndexType, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1> IndicesType;
-};
-}
-
-template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType>
-class PermutationMatrix : public PermutationBase<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType> >
-{
- typedef PermutationBase<PermutationMatrix> Base;
- typedef internal::traits<PermutationMatrix> Traits;
- public:
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- typedef typename Traits::IndicesType IndicesType;
- #endif
-
- inline PermutationMatrix()
- {}
-
- /** Constructs an uninitialized permutation matrix of given size.
- */
- inline PermutationMatrix(int size) : m_indices(size)
- {}
-
- /** Copy constructor. */
- template<typename OtherDerived>
- inline PermutationMatrix(const PermutationBase<OtherDerived>& other)
- : m_indices(other.indices()) {}
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- /** Standard copy constructor. Defined only to prevent a default copy constructor
- * from hiding the other templated constructor */
- inline PermutationMatrix(const PermutationMatrix& other) : m_indices(other.indices()) {}
- #endif
-
- /** Generic constructor from expression of the indices. The indices
- * array has the meaning that the permutations sends each integer i to indices[i].
- *
- * \warning It is your responsibility to check that the indices array that you passes actually
- * describes a permutation, i.e., each value between 0 and n-1 occurs exactly once, where n is the
- * array's size.
- */
- template<typename Other>
- explicit inline PermutationMatrix(const MatrixBase<Other>& indices) : m_indices(indices)
- {}
-
- /** Convert the Transpositions \a tr to a permutation matrix */
- template<typename Other>
- explicit PermutationMatrix(const TranspositionsBase<Other>& tr)
- : m_indices(tr.size())
- {
- *this = tr;
- }
-
- /** Copies the other permutation into *this */
- template<typename Other>
- PermutationMatrix& operator=(const PermutationBase<Other>& other)
- {
- m_indices = other.indices();
- return *this;
- }
-
- /** Assignment from the Transpositions \a tr */
- template<typename Other>
- PermutationMatrix& operator=(const TranspositionsBase<Other>& tr)
- {
- return Base::operator=(tr.derived());
- }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- /** This is a special case of the templated operator=. Its purpose is to
- * prevent a default operator= from hiding the templated operator=.
- */
- PermutationMatrix& operator=(const PermutationMatrix& other)
- {
- m_indices = other.m_indices;
- return *this;
- }
- #endif
-
- /** const version of indices(). */
- const IndicesType& indices() const { return m_indices; }
- /** \returns a reference to the stored array representing the permutation. */
- IndicesType& indices() { return m_indices; }
-
-
- /**** multiplication helpers to hopefully get RVO ****/
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
- template<typename Other>
- PermutationMatrix(const Transpose<PermutationBase<Other> >& other)
- : m_indices(other.nestedPermutation().size())
- {
- for (int i=0; i<m_indices.size();++i) m_indices.coeffRef(other.nestedPermutation().indices().coeff(i)) = i;
- }
- template<typename Lhs,typename Rhs>
- PermutationMatrix(internal::PermPermProduct_t, const Lhs& lhs, const Rhs& rhs)
- : m_indices(lhs.indices().size())
- {
- Base::assignProduct(lhs,rhs);
- }
-#endif
-
- protected:
-
- IndicesType m_indices;
-};
-
-
-namespace internal {
-template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int _PacketAccess>
-struct traits<Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType>,_PacketAccess> >
- : traits<Matrix<IndexType,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> >
-{
- typedef IndexType Index;
- typedef Map<const Matrix<IndexType, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1>, _PacketAccess> IndicesType;
-};
-}
-
-template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int _PacketAccess>
-class Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType>,_PacketAccess>
- : public PermutationBase<Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType>,_PacketAccess> >
-{
- typedef PermutationBase<Map> Base;
- typedef internal::traits<Map> Traits;
- public:
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- typedef typename Traits::IndicesType IndicesType;
- typedef typename IndicesType::Scalar Index;
- #endif
-
- inline Map(const Index* indices)
- : m_indices(indices)
- {}
-
- inline Map(const Index* indices, Index size)
- : m_indices(indices,size)
- {}
-
- /** Copies the other permutation into *this */
- template<typename Other>
- Map& operator=(const PermutationBase<Other>& other)
- { return Base::operator=(other.derived()); }
-
- /** Assignment from the Transpositions \a tr */
- template<typename Other>
- Map& operator=(const TranspositionsBase<Other>& tr)
- { return Base::operator=(tr.derived()); }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- /** This is a special case of the templated operator=. Its purpose is to
- * prevent a default operator= from hiding the templated operator=.
- */
- Map& operator=(const Map& other)
- {
- m_indices = other.m_indices;
- return *this;
- }
- #endif
-
- /** const version of indices(). */
- const IndicesType& indices() const { return m_indices; }
- /** \returns a reference to the stored array representing the permutation. */
- IndicesType& indices() { return m_indices; }
-
- protected:
-
- IndicesType m_indices;
-};
-
-/** \class PermutationWrapper
- * \ingroup Core_Module
- *
- * \brief Class to view a vector of integers as a permutation matrix
- *
- * \param _IndicesType the type of the vector of integer (can be any compatible expression)
- *
- * This class allows to view any vector expression of integers as a permutation matrix.
- *
- * \sa class PermutationBase, class PermutationMatrix
- */
-
-struct PermutationStorage {};
-
-template<typename _IndicesType> class TranspositionsWrapper;
-namespace internal {
-template<typename _IndicesType>
-struct traits<PermutationWrapper<_IndicesType> >
-{
- typedef PermutationStorage StorageKind;
- typedef typename _IndicesType::Scalar Scalar;
- typedef typename _IndicesType::Scalar Index;
- typedef _IndicesType IndicesType;
- enum {
- RowsAtCompileTime = _IndicesType::SizeAtCompileTime,
- ColsAtCompileTime = _IndicesType::SizeAtCompileTime,
- MaxRowsAtCompileTime = IndicesType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = IndicesType::MaxColsAtCompileTime,
- Flags = 0,
- CoeffReadCost = _IndicesType::CoeffReadCost
- };
-};
-}
-
-template<typename _IndicesType>
-class PermutationWrapper : public PermutationBase<PermutationWrapper<_IndicesType> >
-{
- typedef PermutationBase<PermutationWrapper> Base;
- typedef internal::traits<PermutationWrapper> Traits;
- public:
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- typedef typename Traits::IndicesType IndicesType;
- #endif
-
- inline PermutationWrapper(const IndicesType& indices)
- : m_indices(indices)
- {}
-
- /** const version of indices(). */
- const typename internal::remove_all<typename IndicesType::Nested>::type&
- indices() const { return m_indices; }
-
- protected:
-
- const typename IndicesType::Nested m_indices;
-};
-
-/** \returns the matrix with the permutation applied to the columns.
- */
-template<typename Derived, typename PermutationDerived>
-inline const internal::permut_matrix_product_retval<PermutationDerived, Derived, OnTheRight>
-operator*(const MatrixBase<Derived>& matrix,
- const PermutationBase<PermutationDerived> &permutation)
-{
- return internal::permut_matrix_product_retval
- <PermutationDerived, Derived, OnTheRight>
- (permutation.derived(), matrix.derived());
-}
-
-/** \returns the matrix with the permutation applied to the rows.
- */
-template<typename Derived, typename PermutationDerived>
-inline const internal::permut_matrix_product_retval
- <PermutationDerived, Derived, OnTheLeft>
-operator*(const PermutationBase<PermutationDerived> &permutation,
- const MatrixBase<Derived>& matrix)
-{
- return internal::permut_matrix_product_retval
- <PermutationDerived, Derived, OnTheLeft>
- (permutation.derived(), matrix.derived());
-}
-
-namespace internal {
-
-template<typename PermutationType, typename MatrixType, int Side, bool Transposed>
-struct traits<permut_matrix_product_retval<PermutationType, MatrixType, Side, Transposed> >
-{
- typedef typename MatrixType::PlainObject ReturnType;
-};
-
-template<typename PermutationType, typename MatrixType, int Side, bool Transposed>
-struct permut_matrix_product_retval
- : public ReturnByValue<permut_matrix_product_retval<PermutationType, MatrixType, Side, Transposed> >
-{
- typedef typename remove_all<typename MatrixType::Nested>::type MatrixTypeNestedCleaned;
-
- permut_matrix_product_retval(const PermutationType& perm, const MatrixType& matrix)
- : m_permutation(perm), m_matrix(matrix)
- {}
-
- inline int rows() const { return m_matrix.rows(); }
- inline int cols() const { return m_matrix.cols(); }
-
- template<typename Dest> inline void evalTo(Dest& dst) const
- {
- const int n = Side==OnTheLeft ? rows() : cols();
-
- if(is_same<MatrixTypeNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_matrix))
- {
- // apply the permutation inplace
- Matrix<bool,PermutationType::RowsAtCompileTime,1,0,PermutationType::MaxRowsAtCompileTime> mask(m_permutation.size());
- mask.fill(false);
- int r = 0;
- while(r < m_permutation.size())
- {
- // search for the next seed
- while(r<m_permutation.size() && mask[r]) r++;
- if(r>=m_permutation.size())
- break;
- // we got one, let's follow it until we are back to the seed
- int k0 = r++;
- int kPrev = k0;
- mask.coeffRef(k0) = true;
- for(int k=m_permutation.indices().coeff(k0); k!=k0; k=m_permutation.indices().coeff(k))
- {
- Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>(dst, k)
- .swap(Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>
- (dst,((Side==OnTheLeft) ^ Transposed) ? k0 : kPrev));
-
- mask.coeffRef(k) = true;
- kPrev = k;
- }
- }
- }
- else
- {
- for(int i = 0; i < n; ++i)
- {
- Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>
- (dst, ((Side==OnTheLeft) ^ Transposed) ? m_permutation.indices().coeff(i) : i)
-
- =
-
- Block<const MatrixTypeNestedCleaned,Side==OnTheLeft ? 1 : MatrixType::RowsAtCompileTime,Side==OnTheRight ? 1 : MatrixType::ColsAtCompileTime>
- (m_matrix, ((Side==OnTheRight) ^ Transposed) ? m_permutation.indices().coeff(i) : i);
- }
- }
- }
-
- protected:
- const PermutationType& m_permutation;
- const typename MatrixType::Nested m_matrix;
-};
-
-/* Template partial specialization for transposed/inverse permutations */
-
-template<typename Derived>
-struct traits<Transpose<PermutationBase<Derived> > >
- : traits<Derived>
-{};
-
-} // end namespace internal
-
-template<typename Derived>
-class Transpose<PermutationBase<Derived> >
- : public EigenBase<Transpose<PermutationBase<Derived> > >
-{
- typedef Derived PermutationType;
- typedef typename PermutationType::IndicesType IndicesType;
- typedef typename PermutationType::PlainPermutationType PlainPermutationType;
- public:
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- typedef internal::traits<PermutationType> Traits;
- typedef typename Derived::DenseMatrixType DenseMatrixType;
- enum {
- Flags = Traits::Flags,
- CoeffReadCost = Traits::CoeffReadCost,
- RowsAtCompileTime = Traits::RowsAtCompileTime,
- ColsAtCompileTime = Traits::ColsAtCompileTime,
- MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = Traits::MaxColsAtCompileTime
- };
- typedef typename Traits::Scalar Scalar;
- #endif
-
- Transpose(const PermutationType& p) : m_permutation(p) {}
-
- inline int rows() const { return m_permutation.rows(); }
- inline int cols() const { return m_permutation.cols(); }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- template<typename DenseDerived>
- void evalTo(MatrixBase<DenseDerived>& other) const
- {
- other.setZero();
- for (int i=0; i<rows();++i)
- other.coeffRef(i, m_permutation.indices().coeff(i)) = typename DenseDerived::Scalar(1);
- }
- #endif
-
- /** \return the equivalent permutation matrix */
- PlainPermutationType eval() const { return *this; }
-
- DenseMatrixType toDenseMatrix() const { return *this; }
-
- /** \returns the matrix with the inverse permutation applied to the columns.
- */
- template<typename OtherDerived> friend
- inline const internal::permut_matrix_product_retval<PermutationType, OtherDerived, OnTheRight, true>
- operator*(const MatrixBase<OtherDerived>& matrix, const Transpose& trPerm)
- {
- return internal::permut_matrix_product_retval<PermutationType, OtherDerived, OnTheRight, true>(trPerm.m_permutation, matrix.derived());
- }
-
- /** \returns the matrix with the inverse permutation applied to the rows.
- */
- template<typename OtherDerived>
- inline const internal::permut_matrix_product_retval<PermutationType, OtherDerived, OnTheLeft, true>
- operator*(const MatrixBase<OtherDerived>& matrix) const
- {
- return internal::permut_matrix_product_retval<PermutationType, OtherDerived, OnTheLeft, true>(m_permutation, matrix.derived());
- }
-
- const PermutationType& nestedPermutation() const { return m_permutation; }
-
- protected:
- const PermutationType& m_permutation;
-};
-
-template<typename Derived>
-const PermutationWrapper<const Derived> MatrixBase<Derived>::asPermutation() const
-{
- return derived();
-}
-
-#endif // EIGEN_PERMUTATIONMATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Core/PlainObjectBase.h b/extern/Eigen3/Eigen/src/Core/PlainObjectBase.h
deleted file mode 100644
index c70db92479a..00000000000
--- a/extern/Eigen3/Eigen/src/Core/PlainObjectBase.h
+++ /dev/null
@@ -1,737 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_DENSESTORAGEBASE_H
-#define EIGEN_DENSESTORAGEBASE_H
-
-#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
-# define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0);
-#else
-# define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
-#endif
-
-namespace internal {
-
-template <typename Derived, typename OtherDerived = Derived, bool IsVector = static_cast<bool>(Derived::IsVectorAtCompileTime)> struct conservative_resize_like_impl;
-
-template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct matrix_swap_impl;
-
-} // end namespace internal
-
-/**
- * \brief %Dense storage base class for matrices and arrays.
- *
- * 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_PLAINOBJECTBASE_PLUGIN.
- *
- * \sa \ref TopicClassHierarchy
- */
-template<typename Derived>
-class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
-{
- public:
- enum { Options = internal::traits<Derived>::Options };
- typedef typename internal::dense_xpr_base<Derived>::type Base;
-
- typedef typename internal::traits<Derived>::StorageKind StorageKind;
- typedef typename internal::traits<Derived>::Index Index;
- typedef typename internal::traits<Derived>::Scalar Scalar;
- typedef typename internal::packet_traits<Scalar>::type PacketScalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef Derived DenseType;
-
- using Base::RowsAtCompileTime;
- using Base::ColsAtCompileTime;
- using Base::SizeAtCompileTime;
- using Base::MaxRowsAtCompileTime;
- using Base::MaxColsAtCompileTime;
- using Base::MaxSizeAtCompileTime;
- using Base::IsVectorAtCompileTime;
- using Base::Flags;
-
- template<typename PlainObjectType, int MapOptions, typename StrideType> friend class Eigen::Map;
- friend class Eigen::Map<Derived, Unaligned>;
- typedef Eigen::Map<Derived, Unaligned> MapType;
- friend class Eigen::Map<const Derived, Unaligned>;
- typedef const Eigen::Map<const Derived, Unaligned> ConstMapType;
- friend class Eigen::Map<Derived, Aligned>;
- typedef Eigen::Map<Derived, Aligned> AlignedMapType;
- friend class Eigen::Map<const Derived, Aligned>;
- typedef const Eigen::Map<const Derived, Aligned> ConstAlignedMapType;
- template<typename StrideType> struct StridedMapType { typedef Eigen::Map<Derived, Unaligned, StrideType> type; };
- template<typename StrideType> struct StridedConstMapType { typedef Eigen::Map<const Derived, Unaligned, StrideType> type; };
- template<typename StrideType> struct StridedAlignedMapType { typedef Eigen::Map<Derived, Aligned, StrideType> type; };
- template<typename StrideType> struct StridedConstAlignedMapType { typedef Eigen::Map<const Derived, Aligned, StrideType> type; };
-
-
- protected:
- DenseStorage<Scalar, Base::MaxSizeAtCompileTime, Base::RowsAtCompileTime, Base::ColsAtCompileTime, Options> m_storage;
-
- public:
- enum { NeedsToAlign = (!(Options&DontAlign))
- && SizeAtCompileTime!=Dynamic && ((static_cast<int>(sizeof(Scalar))*SizeAtCompileTime)%16)==0 };
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
-
- Base& base() { return *static_cast<Base*>(this); }
- const Base& base() const { return *static_cast<const Base*>(this); }
-
- EIGEN_STRONG_INLINE Index rows() const { return m_storage.rows(); }
- EIGEN_STRONG_INLINE Index cols() const { return m_storage.cols(); }
-
- EIGEN_STRONG_INLINE const Scalar& coeff(Index row, Index col) const
- {
- if(Flags & RowMajorBit)
- return m_storage.data()[col + row * m_storage.cols()];
- else // column-major
- return m_storage.data()[row + col * m_storage.rows()];
- }
-
- EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const
- {
- return m_storage.data()[index];
- }
-
- EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
- {
- if(Flags & RowMajorBit)
- return m_storage.data()[col + row * m_storage.cols()];
- else // column-major
- return m_storage.data()[row + col * m_storage.rows()];
- }
-
- EIGEN_STRONG_INLINE Scalar& coeffRef(Index index)
- {
- return m_storage.data()[index];
- }
-
- EIGEN_STRONG_INLINE const Scalar& coeffRef(Index row, Index col) const
- {
- if(Flags & RowMajorBit)
- return m_storage.data()[col + row * m_storage.cols()];
- else // column-major
- return m_storage.data()[row + col * m_storage.rows()];
- }
-
- EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const
- {
- return m_storage.data()[index];
- }
-
- /** \internal */
- template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
- {
- return internal::ploadt<PacketScalar, LoadMode>
- (m_storage.data() + (Flags & RowMajorBit
- ? col + row * m_storage.cols()
- : row + col * m_storage.rows()));
- }
-
- /** \internal */
- template<int LoadMode>
- EIGEN_STRONG_INLINE PacketScalar packet(Index index) const
- {
- return internal::ploadt<PacketScalar, LoadMode>(m_storage.data() + index);
- }
-
- /** \internal */
- template<int StoreMode>
- EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketScalar& x)
- {
- internal::pstoret<Scalar, PacketScalar, StoreMode>
- (m_storage.data() + (Flags & RowMajorBit
- ? col + row * m_storage.cols()
- : row + col * m_storage.rows()), x);
- }
-
- /** \internal */
- template<int StoreMode>
- EIGEN_STRONG_INLINE void writePacket(Index index, const PacketScalar& x)
- {
- internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, x);
- }
-
- /** \returns a const pointer to the data array of this matrix */
- EIGEN_STRONG_INLINE const Scalar *data() const
- { return m_storage.data(); }
-
- /** \returns a pointer to the data array of this matrix */
- EIGEN_STRONG_INLINE Scalar *data()
- { return m_storage.data(); }
-
- /** Resizes \c *this to a \a rows x \a cols matrix.
- *
- * This method is intended for dynamic-size matrices, although it is legal to call it on any
- * matrix as long as fixed dimensions are left unchanged. If you only want to change the number
- * of rows and/or of columns, you can use resize(NoChange_t, Index), resize(Index, NoChange_t).
- *
- * If the current number of coefficients of \c *this exactly matches the
- * product \a rows * \a cols, then no memory allocation is performed and
- * the current values are left unchanged. In all other cases, including
- * shrinking, the data is reallocated and all previous values are lost.
- *
- * Example: \include Matrix_resize_int_int.cpp
- * Output: \verbinclude Matrix_resize_int_int.out
- *
- * \sa resize(Index) for vectors, resize(NoChange_t, Index), resize(Index, NoChange_t)
- */
- EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
- {
- #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
- Index size = rows*cols;
- bool size_changed = size != this->size();
- m_storage.resize(size, rows, cols);
- if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
- #else
- m_storage.resize(rows*cols, rows, cols);
- #endif
- }
-
- /** Resizes \c *this to a vector of length \a size
- *
- * \only_for_vectors. This method does not work for
- * partially dynamic matrices when the static dimension is anything other
- * than 1. For example it will not work with Matrix<double, 2, Dynamic>.
- *
- * Example: \include Matrix_resize_int.cpp
- * Output: \verbinclude Matrix_resize_int.out
- *
- * \sa resize(Index,Index), resize(NoChange_t, Index), resize(Index, NoChange_t)
- */
- inline void resize(Index size)
- {
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(PlainObjectBase)
- eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
- #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
- bool size_changed = size != this->size();
- #endif
- if(RowsAtCompileTime == 1)
- m_storage.resize(size, 1, size);
- else
- m_storage.resize(size, size, 1);
- #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
- if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
- #endif
- }
-
- /** Resizes the matrix, changing only the number of columns. For the parameter of type NoChange_t, just pass the special value \c NoChange
- * as in the example below.
- *
- * Example: \include Matrix_resize_NoChange_int.cpp
- * Output: \verbinclude Matrix_resize_NoChange_int.out
- *
- * \sa resize(Index,Index)
- */
- inline void resize(NoChange_t, Index cols)
- {
- resize(rows(), cols);
- }
-
- /** Resizes the matrix, changing only the number of rows. For the parameter of type NoChange_t, just pass the special value \c NoChange
- * as in the example below.
- *
- * Example: \include Matrix_resize_int_NoChange.cpp
- * Output: \verbinclude Matrix_resize_int_NoChange.out
- *
- * \sa resize(Index,Index)
- */
- inline void resize(Index rows, NoChange_t)
- {
- resize(rows, cols());
- }
-
- /** Resizes \c *this to have the same dimensions as \a other.
- * Takes care of doing all the checking that's needed.
- *
- * Note that copying a row-vector into a vector (and conversely) is allowed.
- * The resizing, if any, is then done in the appropriate way so that row-vectors
- * remain row-vectors and vectors remain vectors.
- */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other)
- {
- const OtherDerived& other = _other.derived();
- const Index othersize = other.rows()*other.cols();
- if(RowsAtCompileTime == 1)
- {
- eigen_assert(other.rows() == 1 || other.cols() == 1);
- resize(1, othersize);
- }
- else if(ColsAtCompileTime == 1)
- {
- eigen_assert(other.rows() == 1 || other.cols() == 1);
- resize(othersize, 1);
- }
- else resize(other.rows(), other.cols());
- }
-
- /** Resizes the matrix to \a rows x \a cols while leaving old values untouched.
- *
- * The method is intended for matrices of dynamic size. If you only want to change the number
- * of rows and/or of columns, you can use conservativeResize(NoChange_t, Index) or
- * conservativeResize(Index, NoChange_t).
- *
- * Matrices are resized relative to the top-left element. In case values need to be
- * appended to the matrix they will be uninitialized.
- */
- EIGEN_STRONG_INLINE void conservativeResize(Index rows, Index cols)
- {
- internal::conservative_resize_like_impl<Derived>::run(*this, rows, cols);
- }
-
- /** Resizes the matrix to \a rows x \a cols while leaving old values untouched.
- *
- * As opposed to conservativeResize(Index rows, Index cols), this version leaves
- * the number of columns unchanged.
- *
- * In case the matrix is growing, new rows will be uninitialized.
- */
- EIGEN_STRONG_INLINE void conservativeResize(Index rows, NoChange_t)
- {
- // Note: see the comment in conservativeResize(Index,Index)
- conservativeResize(rows, cols());
- }
-
- /** Resizes the matrix to \a rows x \a cols while leaving old values untouched.
- *
- * As opposed to conservativeResize(Index rows, Index cols), this version leaves
- * the number of rows unchanged.
- *
- * In case the matrix is growing, new columns will be uninitialized.
- */
- EIGEN_STRONG_INLINE void conservativeResize(NoChange_t, Index cols)
- {
- // Note: see the comment in conservativeResize(Index,Index)
- conservativeResize(rows(), cols);
- }
-
- /** Resizes the vector to \a size while retaining old values.
- *
- * \only_for_vectors. This method does not work for
- * partially dynamic matrices when the static dimension is anything other
- * than 1. For example it will not work with Matrix<double, 2, Dynamic>.
- *
- * When values are appended, they will be uninitialized.
- */
- EIGEN_STRONG_INLINE void conservativeResize(Index size)
- {
- internal::conservative_resize_like_impl<Derived>::run(*this, size);
- }
-
- /** Resizes the matrix to \a rows x \a cols of \c other, while leaving old values untouched.
- *
- * The method is intended for matrices of dynamic size. If you only want to change the number
- * of rows and/or of columns, you can use conservativeResize(NoChange_t, Index) or
- * conservativeResize(Index, NoChange_t).
- *
- * Matrices are resized relative to the top-left element. In case values need to be
- * appended to the matrix they will copied from \c other.
- */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE void conservativeResizeLike(const DenseBase<OtherDerived>& other)
- {
- internal::conservative_resize_like_impl<Derived,OtherDerived>::run(*this, other);
- }
-
- /** This is a special case of the templated operator=. Its purpose is to
- * prevent a default operator= from hiding the templated operator=.
- */
- EIGEN_STRONG_INLINE Derived& operator=(const PlainObjectBase& other)
- {
- return _set(other);
- }
-
- /** \sa MatrixBase::lazyAssign() */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Derived& lazyAssign(const DenseBase<OtherDerived>& other)
- {
- _resize_to_match(other);
- return Base::lazyAssign(other.derived());
- }
-
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Derived& operator=(const ReturnByValue<OtherDerived>& func)
- {
- resize(func.rows(), func.cols());
- return Base::operator=(func);
- }
-
- EIGEN_STRONG_INLINE explicit PlainObjectBase() : m_storage()
- {
-// _check_template_params();
-// EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
- }
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
- // FIXME is it still needed ?
- /** \internal */
- PlainObjectBase(internal::constructor_without_unaligned_array_assert)
- : m_storage(internal::constructor_without_unaligned_array_assert())
- {
-// _check_template_params(); EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
- }
-#endif
-
- EIGEN_STRONG_INLINE PlainObjectBase(Index size, Index rows, Index cols)
- : m_storage(size, rows, cols)
- {
-// _check_template_params();
-// EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
- }
-
- /** \copydoc MatrixBase::operator=(const EigenBase<OtherDerived>&)
- */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Derived& operator=(const EigenBase<OtherDerived> &other)
- {
- _resize_to_match(other);
- Base::operator=(other.derived());
- return this->derived();
- }
-
- /** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived> &other)
- : m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
- {
- _check_template_params();
- Base::operator=(other.derived());
- }
-
- /** \name Map
- * These are convenience functions returning Map objects. The Map() static functions return unaligned Map objects,
- * while the AlignedMap() functions return aligned Map objects and thus should be called only with 16-byte-aligned
- * \a data pointers.
- *
- * \see class Map
- */
- //@{
- inline static ConstMapType Map(const Scalar* data)
- { return ConstMapType(data); }
- inline static MapType Map(Scalar* data)
- { return MapType(data); }
- inline static ConstMapType Map(const Scalar* data, Index size)
- { return ConstMapType(data, size); }
- inline static MapType Map(Scalar* data, Index size)
- { return MapType(data, size); }
- inline static ConstMapType Map(const Scalar* data, Index rows, Index cols)
- { return ConstMapType(data, rows, cols); }
- inline static MapType Map(Scalar* data, Index rows, Index cols)
- { return MapType(data, rows, cols); }
-
- inline static ConstAlignedMapType MapAligned(const Scalar* data)
- { return ConstAlignedMapType(data); }
- inline static AlignedMapType MapAligned(Scalar* data)
- { return AlignedMapType(data); }
- inline static ConstAlignedMapType MapAligned(const Scalar* data, Index size)
- { return ConstAlignedMapType(data, size); }
- inline static AlignedMapType MapAligned(Scalar* data, Index size)
- { return AlignedMapType(data, size); }
- inline static ConstAlignedMapType MapAligned(const Scalar* data, Index rows, Index cols)
- { return ConstAlignedMapType(data, rows, cols); }
- inline static AlignedMapType MapAligned(Scalar* data, Index rows, Index cols)
- { return AlignedMapType(data, rows, cols); }
-
- template<int Outer, int Inner>
- inline static typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, const Stride<Outer, Inner>& stride)
- { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, stride); }
- template<int Outer, int Inner>
- inline static typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, const Stride<Outer, Inner>& stride)
- { return typename StridedMapType<Stride<Outer, Inner> >::type(data, stride); }
- template<int Outer, int Inner>
- inline static typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index size, const Stride<Outer, Inner>& stride)
- { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, size, stride); }
- template<int Outer, int Inner>
- inline static typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index size, const Stride<Outer, Inner>& stride)
- { return typename StridedMapType<Stride<Outer, Inner> >::type(data, size, stride); }
- template<int Outer, int Inner>
- inline static typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
- { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
- template<int Outer, int Inner>
- inline static typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
- { return typename StridedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
-
- template<int Outer, int Inner>
- inline static typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, const Stride<Outer, Inner>& stride)
- { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, stride); }
- template<int Outer, int Inner>
- inline static typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, const Stride<Outer, Inner>& stride)
- { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, stride); }
- template<int Outer, int Inner>
- inline static typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index size, const Stride<Outer, Inner>& stride)
- { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); }
- template<int Outer, int Inner>
- inline static typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index size, const Stride<Outer, Inner>& stride)
- { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); }
- template<int Outer, int Inner>
- inline static typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
- { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
- template<int Outer, int Inner>
- inline static typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
- { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
- //@}
-
- using Base::setConstant;
- Derived& setConstant(Index size, const Scalar& value);
- Derived& setConstant(Index rows, Index cols, const Scalar& value);
-
- using Base::setZero;
- Derived& setZero(Index size);
- Derived& setZero(Index rows, Index cols);
-
- using Base::setOnes;
- Derived& setOnes(Index size);
- Derived& setOnes(Index rows, Index cols);
-
- using Base::setRandom;
- Derived& setRandom(Index size);
- Derived& setRandom(Index rows, Index cols);
-
- #ifdef EIGEN_PLAINOBJECTBASE_PLUGIN
- #include EIGEN_PLAINOBJECTBASE_PLUGIN
- #endif
-
- protected:
- /** \internal Resizes *this in preparation for assigning \a other to it.
- * Takes care of doing all the checking that's needed.
- *
- * Note that copying a row-vector into a vector (and conversely) is allowed.
- * The resizing, if any, is then done in the appropriate way so that row-vectors
- * remain row-vectors and vectors remain vectors.
- */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE void _resize_to_match(const EigenBase<OtherDerived>& other)
- {
- #ifdef EIGEN_NO_AUTOMATIC_RESIZING
- eigen_assert((this->size()==0 || (IsVectorAtCompileTime ? (this->size() == other.size())
- : (rows() == other.rows() && cols() == other.cols())))
- && "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
- #else
- resizeLike(other);
- #endif
- }
-
- /**
- * \brief Copies the value of the expression \a other into \c *this with automatic resizing.
- *
- * *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized),
- * it will be initialized.
- *
- * Note that copying a row-vector into a vector (and conversely) is allowed.
- * The resizing, if any, is then done in the appropriate way so that row-vectors
- * remain row-vectors and vectors remain vectors.
- *
- * \sa operator=(const MatrixBase<OtherDerived>&), _set_noalias()
- *
- * \internal
- */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Derived& _set(const DenseBase<OtherDerived>& other)
- {
- _set_selector(other.derived(), typename internal::conditional<static_cast<bool>(int(OtherDerived::Flags) & EvalBeforeAssigningBit), internal::true_type, internal::false_type>::type());
- return this->derived();
- }
-
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::true_type&) { _set_noalias(other.eval()); }
-
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::false_type&) { _set_noalias(other); }
-
- /** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which
- * is the case when creating a new matrix) so one can enforce lazy evaluation.
- *
- * \sa operator=(const MatrixBase<OtherDerived>&), _set()
- */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE Derived& _set_noalias(const DenseBase<OtherDerived>& other)
- {
- // I don't think we need this resize call since the lazyAssign will anyways resize
- // and lazyAssign will be called by the assign selector.
- //_resize_to_match(other);
- // the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because
- // it wouldn't allow to copy a row-vector into a column-vector.
- return internal::assign_selector<Derived,OtherDerived,false>::run(this->derived(), other.derived());
- }
-
- template<typename T0, typename T1>
- EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0)
- {
- eigen_assert(rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
- && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
- m_storage.resize(rows*cols,rows,cols);
- EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
- }
- template<typename T0, typename T1>
- EIGEN_STRONG_INLINE void _init2(const Scalar& x, const Scalar& y, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0)
- {
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2)
- m_storage.data()[0] = x;
- m_storage.data()[1] = y;
- }
-
- template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
- friend struct internal::matrix_swap_impl;
-
- /** \internal generic implementation of swap for dense storage since for dynamic-sized matrices of same type it is enough to swap the
- * data pointers.
- */
- template<typename OtherDerived>
- void _swap(DenseBase<OtherDerived> const & other)
- {
- enum { SwapPointers = internal::is_same<Derived, OtherDerived>::value && Base::SizeAtCompileTime==Dynamic };
- internal::matrix_swap_impl<Derived, OtherDerived, bool(SwapPointers)>::run(this->derived(), other.const_cast_derived());
- }
-
- public:
-#ifndef EIGEN_PARSED_BY_DOXYGEN
- EIGEN_STRONG_INLINE static void _check_template_params()
- {
- EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
- && EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0)
- && ((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0))
- && ((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0))
- && ((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0))
- && ((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0))
- && (MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime==Dynamic)
- && (MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime==Dynamic)
- && (Options & (DontAlign|RowMajor)) == Options),
- INVALID_MATRIX_TEMPLATE_PARAMETERS)
- }
-#endif
-
-private:
- enum { ThisConstantIsPrivateInPlainObjectBase };
-};
-
-template <typename Derived, typename OtherDerived, bool IsVector>
-struct internal::conservative_resize_like_impl
-{
- typedef typename Derived::Index Index;
- static void run(DenseBase<Derived>& _this, Index rows, Index cols)
- {
- if (_this.rows() == rows && _this.cols() == cols) return;
- EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived)
-
- if ( ( Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows
- (!Derived::IsRowMajor && _this.rows() == rows) ) // column-major and we change only the number of columns
- {
- _this.derived().m_storage.conservativeResize(rows*cols,rows,cols);
- }
- else
- {
- // The storage order does not allow us to use reallocation.
- typename Derived::PlainObject tmp(rows,cols);
- const Index common_rows = (std::min)(rows, _this.rows());
- const Index common_cols = (std::min)(cols, _this.cols());
- tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
- _this.derived().swap(tmp);
- }
- }
-
- static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other)
- {
- if (_this.rows() == other.rows() && _this.cols() == other.cols()) return;
-
- // Note: Here is space for improvement. Basically, for conservativeResize(Index,Index),
- // neither RowsAtCompileTime or ColsAtCompileTime must be Dynamic. If only one of the
- // dimensions is dynamic, one could use either conservativeResize(Index rows, NoChange_t) or
- // conservativeResize(NoChange_t, Index cols). For these methods new static asserts like
- // EIGEN_STATIC_ASSERT_DYNAMIC_ROWS and EIGEN_STATIC_ASSERT_DYNAMIC_COLS would be good.
- EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived)
- EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(OtherDerived)
-
- if ( ( Derived::IsRowMajor && _this.cols() == other.cols()) || // row-major and we change only the number of rows
- (!Derived::IsRowMajor && _this.rows() == other.rows()) ) // column-major and we change only the number of columns
- {
- const Index new_rows = other.rows() - _this.rows();
- const Index new_cols = other.cols() - _this.cols();
- _this.derived().m_storage.conservativeResize(other.size(),other.rows(),other.cols());
- if (new_rows>0)
- _this.bottomRightCorner(new_rows, other.cols()) = other.bottomRows(new_rows);
- else if (new_cols>0)
- _this.bottomRightCorner(other.rows(), new_cols) = other.rightCols(new_cols);
- }
- else
- {
- // The storage order does not allow us to use reallocation.
- typename Derived::PlainObject tmp(other);
- const Index common_rows = (std::min)(tmp.rows(), _this.rows());
- const Index common_cols = (std::min)(tmp.cols(), _this.cols());
- tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
- _this.derived().swap(tmp);
- }
- }
-};
-
-namespace internal {
-
-template <typename Derived, typename OtherDerived>
-struct conservative_resize_like_impl<Derived,OtherDerived,true>
-{
- typedef typename Derived::Index Index;
- static void run(DenseBase<Derived>& _this, Index size)
- {
- const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : size;
- const Index new_cols = Derived::RowsAtCompileTime==1 ? size : 1;
- _this.derived().m_storage.conservativeResize(size,new_rows,new_cols);
- }
-
- static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other)
- {
- if (_this.rows() == other.rows() && _this.cols() == other.cols()) return;
-
- const Index num_new_elements = other.size() - _this.size();
-
- const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : other.rows();
- const Index new_cols = Derived::RowsAtCompileTime==1 ? other.cols() : 1;
- _this.derived().m_storage.conservativeResize(other.size(),new_rows,new_cols);
-
- if (num_new_elements > 0)
- _this.tail(num_new_elements) = other.tail(num_new_elements);
- }
-};
-
-template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
-struct matrix_swap_impl
-{
- static inline void run(MatrixTypeA& a, MatrixTypeB& b)
- {
- a.base().swap(b);
- }
-};
-
-template<typename MatrixTypeA, typename MatrixTypeB>
-struct matrix_swap_impl<MatrixTypeA, MatrixTypeB, true>
-{
- static inline void run(MatrixTypeA& a, MatrixTypeB& b)
- {
- static_cast<typename MatrixTypeA::Base&>(a).m_storage.swap(static_cast<typename MatrixTypeB::Base&>(b).m_storage);
- }
-};
-
-} // end namespace internal
-
-#endif // EIGEN_DENSESTORAGEBASE_H
diff --git a/extern/Eigen3/Eigen/src/Core/Product.h b/extern/Eigen3/Eigen/src/Core/Product.h
deleted file mode 100644
index e2035b242b1..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Product.h
+++ /dev/null
@@ -1,625 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_PRODUCT_H
-#define EIGEN_PRODUCT_H
-
-/** \class GeneralProduct
- * \ingroup Core_Module
- *
- * \brief Expression of the product of two general matrices or vectors
- *
- * \param LhsNested the type used to store the left-hand side
- * \param RhsNested the type used to store the right-hand side
- * \param ProductMode the type of the product
- *
- * This class represents an expression of the product of two general matrices.
- * We call a general matrix, a dense matrix with full storage. For instance,
- * This excludes triangular, selfadjoint, and sparse matrices.
- * It is the return type of the operator* between general matrices. Its template
- * arguments are determined automatically by ProductReturnType. Therefore,
- * GeneralProduct should never be used direclty. To determine the result type of a
- * function which involves a matrix product, use ProductReturnType::Type.
- *
- * \sa ProductReturnType, MatrixBase::operator*(const MatrixBase<OtherDerived>&)
- */
-template<typename Lhs, typename Rhs, int ProductType = internal::product_type<Lhs,Rhs>::value>
-class GeneralProduct;
-
-enum {
- Large = 2,
- Small = 3
-};
-
-namespace internal {
-
-template<int Rows, int Cols, int Depth> struct product_type_selector;
-
-template<int Size, int MaxSize> struct product_size_category
-{
- enum { is_large = MaxSize == Dynamic ||
- Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD,
- value = is_large ? Large
- : Size == 1 ? 1
- : Small
- };
-};
-
-template<typename Lhs, typename Rhs> struct product_type
-{
- typedef typename remove_all<Lhs>::type _Lhs;
- typedef typename remove_all<Rhs>::type _Rhs;
- enum {
- MaxRows = _Lhs::MaxRowsAtCompileTime,
- Rows = _Lhs::RowsAtCompileTime,
- MaxCols = _Rhs::MaxColsAtCompileTime,
- Cols = _Rhs::ColsAtCompileTime,
- MaxDepth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::MaxColsAtCompileTime,
- _Rhs::MaxRowsAtCompileTime),
- Depth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::ColsAtCompileTime,
- _Rhs::RowsAtCompileTime),
- LargeThreshold = EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
- };
-
- // the splitting into different lines of code here, introducing the _select enums and the typedef below,
- // is to work around an internal compiler error with gcc 4.1 and 4.2.
-private:
- enum {
- rows_select = product_size_category<Rows,MaxRows>::value,
- cols_select = product_size_category<Cols,MaxCols>::value,
- depth_select = product_size_category<Depth,MaxDepth>::value
- };
- typedef product_type_selector<rows_select, cols_select, depth_select> selector;
-
-public:
- enum {
- value = selector::ret
- };
-#ifdef EIGEN_DEBUG_PRODUCT
- static void debug()
- {
- EIGEN_DEBUG_VAR(Rows);
- EIGEN_DEBUG_VAR(Cols);
- EIGEN_DEBUG_VAR(Depth);
- EIGEN_DEBUG_VAR(rows_select);
- EIGEN_DEBUG_VAR(cols_select);
- EIGEN_DEBUG_VAR(depth_select);
- EIGEN_DEBUG_VAR(value);
- }
-#endif
-};
-
-
-/* The following allows to select the kind of product at compile time
- * based on the three dimensions of the product.
- * This is a compile time mapping from {1,Small,Large}^3 -> {product types} */
-// FIXME I'm not sure the current mapping is the ideal one.
-template<int M, int N> struct product_type_selector<M,N,1> { enum { ret = OuterProduct }; };
-template<int Depth> struct product_type_selector<1, 1, Depth> { enum { ret = InnerProduct }; };
-template<> struct product_type_selector<1, 1, 1> { enum { ret = InnerProduct }; };
-template<> struct product_type_selector<Small,1, Small> { enum { ret = CoeffBasedProductMode }; };
-template<> struct product_type_selector<1, Small,Small> { enum { ret = CoeffBasedProductMode }; };
-template<> struct product_type_selector<Small,Small,Small> { enum { ret = CoeffBasedProductMode }; };
-template<> struct product_type_selector<Small, Small, 1> { enum { ret = LazyCoeffBasedProductMode }; };
-template<> struct product_type_selector<Small, Large, 1> { enum { ret = LazyCoeffBasedProductMode }; };
-template<> struct product_type_selector<Large, Small, 1> { enum { ret = LazyCoeffBasedProductMode }; };
-template<> struct product_type_selector<1, Large,Small> { enum { ret = CoeffBasedProductMode }; };
-template<> struct product_type_selector<1, Large,Large> { enum { ret = GemvProduct }; };
-template<> struct product_type_selector<1, Small,Large> { enum { ret = CoeffBasedProductMode }; };
-template<> struct product_type_selector<Large,1, Small> { enum { ret = CoeffBasedProductMode }; };
-template<> struct product_type_selector<Large,1, Large> { enum { ret = GemvProduct }; };
-template<> struct product_type_selector<Small,1, Large> { enum { ret = CoeffBasedProductMode }; };
-template<> struct product_type_selector<Small,Small,Large> { enum { ret = GemmProduct }; };
-template<> struct product_type_selector<Large,Small,Large> { enum { ret = GemmProduct }; };
-template<> struct product_type_selector<Small,Large,Large> { enum { ret = GemmProduct }; };
-template<> struct product_type_selector<Large,Large,Large> { enum { ret = GemmProduct }; };
-template<> struct product_type_selector<Large,Small,Small> { enum { ret = GemmProduct }; };
-template<> struct product_type_selector<Small,Large,Small> { enum { ret = GemmProduct }; };
-template<> struct product_type_selector<Large,Large,Small> { enum { ret = GemmProduct }; };
-
-} // end namespace internal
-
-/** \class ProductReturnType
- * \ingroup Core_Module
- *
- * \brief Helper class to get the correct and optimized returned type of operator*
- *
- * \param Lhs the type of the left-hand side
- * \param Rhs the type of the right-hand side
- * \param ProductMode the type of the product (determined automatically by internal::product_mode)
- *
- * This class defines the typename Type representing the optimized product expression
- * between two matrix expressions. In practice, using ProductReturnType<Lhs,Rhs>::Type
- * is the recommended way to define the result type of a function returning an expression
- * which involve a matrix product. The class Product should never be
- * used directly.
- *
- * \sa class Product, MatrixBase::operator*(const MatrixBase<OtherDerived>&)
- */
-template<typename Lhs, typename Rhs, int ProductType>
-struct ProductReturnType
-{
- // TODO use the nested type to reduce instanciations ????
-// typedef typename internal::nested<Lhs,Rhs::ColsAtCompileTime>::type LhsNested;
-// typedef typename internal::nested<Rhs,Lhs::RowsAtCompileTime>::type RhsNested;
-
- typedef GeneralProduct<Lhs/*Nested*/, Rhs/*Nested*/, ProductType> Type;
-};
-
-template<typename Lhs, typename Rhs>
-struct ProductReturnType<Lhs,Rhs,CoeffBasedProductMode>
-{
- typedef typename internal::nested<Lhs, Rhs::ColsAtCompileTime, typename internal::plain_matrix_type<Lhs>::type >::type LhsNested;
- typedef typename internal::nested<Rhs, Lhs::RowsAtCompileTime, typename internal::plain_matrix_type<Rhs>::type >::type RhsNested;
- typedef CoeffBasedProduct<LhsNested, RhsNested, EvalBeforeAssigningBit | EvalBeforeNestingBit> Type;
-};
-
-template<typename Lhs, typename Rhs>
-struct ProductReturnType<Lhs,Rhs,LazyCoeffBasedProductMode>
-{
- typedef typename internal::nested<Lhs, Rhs::ColsAtCompileTime, typename internal::plain_matrix_type<Lhs>::type >::type LhsNested;
- typedef typename internal::nested<Rhs, Lhs::RowsAtCompileTime, typename internal::plain_matrix_type<Rhs>::type >::type RhsNested;
- typedef CoeffBasedProduct<LhsNested, RhsNested, NestByRefBit> Type;
-};
-
-// this is a workaround for sun CC
-template<typename Lhs, typename Rhs>
-struct LazyProductReturnType : public ProductReturnType<Lhs,Rhs,LazyCoeffBasedProductMode>
-{};
-
-/***********************************************************************
-* Implementation of Inner Vector Vector Product
-***********************************************************************/
-
-// FIXME : maybe the "inner product" could return a Scalar
-// instead of a 1x1 matrix ??
-// Pro: more natural for the user
-// Cons: this could be a problem if in a meta unrolled algorithm a matrix-matrix
-// product ends up to a row-vector times col-vector product... To tackle this use
-// case, we could have a specialization for Block<MatrixType,1,1> with: operator=(Scalar x);
-
-namespace internal {
-
-template<typename Lhs, typename Rhs>
-struct traits<GeneralProduct<Lhs,Rhs,InnerProduct> >
- : traits<Matrix<typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1> >
-{};
-
-}
-
-template<typename Lhs, typename Rhs>
-class GeneralProduct<Lhs, Rhs, InnerProduct>
- : internal::no_assignment_operator,
- public Matrix<typename internal::scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1>
-{
- typedef Matrix<typename internal::scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1> Base;
- public:
- GeneralProduct(const Lhs& lhs, const Rhs& rhs)
- {
- EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
- YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
-
- Base::coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum();
- }
-
- /** Convertion to scalar */
- operator const typename Base::Scalar() const {
- return Base::coeff(0,0);
- }
-};
-
-/***********************************************************************
-* Implementation of Outer Vector Vector Product
-***********************************************************************/
-
-namespace internal {
-template<int StorageOrder> struct outer_product_selector;
-
-template<typename Lhs, typename Rhs>
-struct traits<GeneralProduct<Lhs,Rhs,OuterProduct> >
- : traits<ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs> >
-{};
-
-}
-
-template<typename Lhs, typename Rhs>
-class GeneralProduct<Lhs, Rhs, OuterProduct>
- : public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs>
-{
- public:
- EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
-
- GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
- {
- EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
- YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
- }
-
- template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
- {
- internal::outer_product_selector<(int(Dest::Flags)&RowMajorBit) ? RowMajor : ColMajor>::run(*this, dest, alpha);
- }
-};
-
-namespace internal {
-
-template<> struct outer_product_selector<ColMajor> {
- template<typename ProductType, typename Dest>
- static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) {
- typedef typename Dest::Index Index;
- // FIXME make sure lhs is sequentially stored
- // 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)
- dest.col(j) += (alpha * prod.rhs().coeff(j)) * prod.lhs();
- }
-};
-
-template<> struct outer_product_selector<RowMajor> {
- template<typename ProductType, typename Dest>
- static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) {
- typedef typename Dest::Index Index;
- // FIXME make sure rhs is sequentially stored
- // 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)
- dest.row(i) += (alpha * prod.lhs().coeff(i)) * prod.rhs();
- }
-};
-
-} // end namespace internal
-
-/***********************************************************************
-* Implementation of General Matrix Vector Product
-***********************************************************************/
-
-/* According to the shape/flags of the matrix we have to distinghish 3 different cases:
- * 1 - the matrix is col-major, BLAS compatible and M is large => call fast BLAS-like colmajor routine
- * 2 - the matrix is row-major, BLAS compatible and N is large => call fast BLAS-like rowmajor routine
- * 3 - all other cases are handled using a simple loop along the outer-storage direction.
- * Therefore we need a lower level meta selector.
- * Furthermore, if the matrix is the rhs, then the product has to be transposed.
- */
-namespace internal {
-
-template<typename Lhs, typename Rhs>
-struct traits<GeneralProduct<Lhs,Rhs,GemvProduct> >
- : traits<ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs> >
-{};
-
-template<int Side, int StorageOrder, bool BlasCompatible>
-struct gemv_selector;
-
-} // end namespace internal
-
-template<typename Lhs, typename Rhs>
-class GeneralProduct<Lhs, Rhs, GemvProduct>
- : public ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs>
-{
- public:
- EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
-
- typedef typename Lhs::Scalar LhsScalar;
- typedef typename Rhs::Scalar RhsScalar;
-
- GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
- {
-// EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::Scalar, typename Rhs::Scalar>::value),
-// YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
- }
-
- enum { Side = Lhs::IsVectorAtCompileTime ? OnTheLeft : OnTheRight };
- typedef typename internal::conditional<int(Side)==OnTheRight,_LhsNested,_RhsNested>::type MatrixType;
-
- template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
- {
- eigen_assert(m_lhs.rows() == dst.rows() && m_rhs.cols() == dst.cols());
- internal::gemv_selector<Side,(int(MatrixType::Flags)&RowMajorBit) ? RowMajor : ColMajor,
- bool(internal::blas_traits<MatrixType>::HasUsableDirectAccess)>::run(*this, dst, alpha);
- }
-};
-
-namespace internal {
-
-// The vector is on the left => transposition
-template<int StorageOrder, bool BlasCompatible>
-struct gemv_selector<OnTheLeft,StorageOrder,BlasCompatible>
-{
- template<typename ProductType, typename Dest>
- static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
- {
- Transpose<Dest> destT(dest);
- enum { OtherStorageOrder = StorageOrder == RowMajor ? ColMajor : RowMajor };
- gemv_selector<OnTheRight,OtherStorageOrder,BlasCompatible>
- ::run(GeneralProduct<Transpose<const typename ProductType::_RhsNested>,Transpose<const typename ProductType::_LhsNested>, GemvProduct>
- (prod.rhs().transpose(), prod.lhs().transpose()), destT, alpha);
- }
-};
-
-template<typename Scalar,int Size,int MaxSize,bool Cond> struct gemv_static_vector_if;
-
-template<typename Scalar,int Size,int MaxSize>
-struct gemv_static_vector_if<Scalar,Size,MaxSize,false>
-{
- EIGEN_STRONG_INLINE Scalar* data() { eigen_internal_assert(false && "should never be called"); return 0; }
-};
-
-template<typename Scalar,int Size>
-struct gemv_static_vector_if<Scalar,Size,Dynamic,true>
-{
- EIGEN_STRONG_INLINE Scalar* data() { return 0; }
-};
-
-template<typename Scalar,int Size,int MaxSize>
-struct gemv_static_vector_if<Scalar,Size,MaxSize,true>
-{
- #if EIGEN_ALIGN_STATICALLY
- internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize),0> m_data;
- EIGEN_STRONG_INLINE Scalar* data() { return m_data.array; }
- #else
- // Some architectures cannot align on the stack,
- // => let's manually enforce alignment by allocating more data and return the address of the first aligned element.
- enum {
- ForceAlignment = internal::packet_traits<Scalar>::Vectorizable,
- PacketSize = internal::packet_traits<Scalar>::size
- };
- internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize)+(ForceAlignment?PacketSize:0),0> m_data;
- EIGEN_STRONG_INLINE Scalar* data() {
- return ForceAlignment
- ? reinterpret_cast<Scalar*>((reinterpret_cast<size_t>(m_data.array) & ~(size_t(15))) + 16)
- : m_data.array;
- }
- #endif
-};
-
-template<> struct gemv_selector<OnTheRight,ColMajor,true>
-{
- template<typename ProductType, typename Dest>
- static inline void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
- {
- typedef typename ProductType::Index Index;
- typedef typename ProductType::LhsScalar LhsScalar;
- typedef typename ProductType::RhsScalar RhsScalar;
- typedef typename ProductType::Scalar ResScalar;
- typedef typename ProductType::RealScalar RealScalar;
- typedef typename ProductType::ActualLhsType ActualLhsType;
- typedef typename ProductType::ActualRhsType ActualRhsType;
- typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
- typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
- typedef Map<Matrix<ResScalar,Dynamic,1>, Aligned> MappedDest;
-
- const ActualLhsType actualLhs = LhsBlasTraits::extract(prod.lhs());
- const ActualRhsType actualRhs = RhsBlasTraits::extract(prod.rhs());
-
- ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
- * RhsBlasTraits::extractScalarFactor(prod.rhs());
-
- enum {
- // FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1
- // on, the other hand it is good for the cache to pack the vector anyways...
- EvalToDestAtCompileTime = Dest::InnerStrideAtCompileTime==1,
- ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
- MightCannotUseDest = (Dest::InnerStrideAtCompileTime!=1) || ComplexByReal
- };
-
- gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
-
- // this is written like this (i.e., with a ?:) to workaround an ICE with ICC 12
- bool alphaIsCompatible = (!ComplexByReal) ? true : (imag(actualAlpha)==RealScalar(0));
- bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
-
- RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
-
- ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(),
- evalToDest ? dest.data() : static_dest.data());
-
- if(!evalToDest)
- {
- #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- int size = dest.size();
- EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- #endif
- if(!alphaIsCompatible)
- {
- MappedDest(actualDestPtr, dest.size()).setZero();
- compatibleAlpha = RhsScalar(1);
- }
- else
- MappedDest(actualDestPtr, dest.size()) = dest;
- }
-
- general_matrix_vector_product
- <Index,LhsScalar,ColMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run(
- actualLhs.rows(), actualLhs.cols(),
- &actualLhs.coeffRef(0,0), actualLhs.outerStride(),
- actualRhs.data(), actualRhs.innerStride(),
- actualDestPtr, 1,
- compatibleAlpha);
-
- if (!evalToDest)
- {
- if(!alphaIsCompatible)
- dest += actualAlpha * MappedDest(actualDestPtr, dest.size());
- else
- dest = MappedDest(actualDestPtr, dest.size());
- }
- }
-};
-
-template<> struct gemv_selector<OnTheRight,RowMajor,true>
-{
- template<typename ProductType, typename Dest>
- static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
- {
- typedef typename ProductType::LhsScalar LhsScalar;
- typedef typename ProductType::RhsScalar RhsScalar;
- typedef typename ProductType::Scalar ResScalar;
- typedef typename ProductType::Index Index;
- typedef typename ProductType::ActualLhsType ActualLhsType;
- typedef typename ProductType::ActualRhsType ActualRhsType;
- typedef typename ProductType::_ActualRhsType _ActualRhsType;
- typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
- typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
-
- typename add_const<ActualLhsType>::type actualLhs = LhsBlasTraits::extract(prod.lhs());
- typename add_const<ActualRhsType>::type actualRhs = RhsBlasTraits::extract(prod.rhs());
-
- ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
- * RhsBlasTraits::extractScalarFactor(prod.rhs());
-
- enum {
- // FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1
- // on, the other hand it is good for the cache to pack the vector anyways...
- DirectlyUseRhs = _ActualRhsType::InnerStrideAtCompileTime==1
- };
-
- gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs;
-
- ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,actualRhs.size(),
- DirectlyUseRhs ? const_cast<RhsScalar*>(actualRhs.data()) : static_rhs.data());
-
- if(!DirectlyUseRhs)
- {
- #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- int size = actualRhs.size();
- EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- #endif
- Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
- }
-
- general_matrix_vector_product
- <Index,LhsScalar,RowMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run(
- actualLhs.rows(), actualLhs.cols(),
- &actualLhs.coeffRef(0,0), actualLhs.outerStride(),
- actualRhsPtr, 1,
- &dest.coeffRef(0,0), dest.innerStride(),
- actualAlpha);
- }
-};
-
-template<> struct gemv_selector<OnTheRight,ColMajor,false>
-{
- template<typename ProductType, typename Dest>
- static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
- {
- typedef typename Dest::Index Index;
- // TODO makes sure dest is sequentially stored in memory, otherwise use a temp
- const Index size = prod.rhs().rows();
- for(Index k=0; k<size; ++k)
- dest += (alpha*prod.rhs().coeff(k)) * prod.lhs().col(k);
- }
-};
-
-template<> struct gemv_selector<OnTheRight,RowMajor,false>
-{
- template<typename ProductType, typename Dest>
- static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha)
- {
- typedef typename Dest::Index Index;
- // TODO makes sure rhs is sequentially stored in memory, otherwise use a temp
- const Index rows = prod.rows();
- for(Index i=0; i<rows; ++i)
- dest.coeffRef(i) += alpha * (prod.lhs().row(i).cwiseProduct(prod.rhs().transpose())).sum();
- }
-};
-
-} // end namespace internal
-
-/***************************************************************************
-* Implementation of matrix base methods
-***************************************************************************/
-
-/** \returns the matrix product of \c *this and \a other.
- *
- * \note If instead of the matrix product you want the coefficient-wise product, see Cwise::operator*().
- *
- * \sa lazyProduct(), operator*=(const MatrixBase&), Cwise::operator*()
- */
-template<typename Derived>
-template<typename OtherDerived>
-inline const typename ProductReturnType<Derived,OtherDerived>::Type
-MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
-{
- // A note regarding the function declaration: In MSVC, this function will sometimes
- // not be inlined since DenseStorage is an unwindable object for dynamic
- // matrices and product types are holding a member to store the result.
- // Thus it does not help tagging this function with EIGEN_STRONG_INLINE.
- enum {
- ProductIsValid = Derived::ColsAtCompileTime==Dynamic
- || OtherDerived::RowsAtCompileTime==Dynamic
- || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime),
- AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
- SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived)
- };
- // note to the lost user:
- // * for a dot product use: v1.dot(v2)
- // * for a coeff-wise product use: v1.cwiseProduct(v2)
- EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
- INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
- EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
- INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
- EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
-#ifdef EIGEN_DEBUG_PRODUCT
- internal::product_type<Derived,OtherDerived>::debug();
-#endif
- return typename ProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
-}
-
-/** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation.
- *
- * The returned product will behave like any other expressions: the coefficients of the product will be
- * computed once at a time as requested. This might be useful in some extremely rare cases when only
- * a small and no coherent fraction of the result's coefficients have to be computed.
- *
- * \warning This version of the matrix product can be much much slower. So use it only if you know
- * what you are doing and that you measured a true speed improvement.
- *
- * \sa operator*(const MatrixBase&)
- */
-template<typename Derived>
-template<typename OtherDerived>
-const typename LazyProductReturnType<Derived,OtherDerived>::Type
-MatrixBase<Derived>::lazyProduct(const MatrixBase<OtherDerived> &other) const
-{
- enum {
- ProductIsValid = Derived::ColsAtCompileTime==Dynamic
- || OtherDerived::RowsAtCompileTime==Dynamic
- || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime),
- AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime,
- SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived)
- };
- // note to the lost user:
- // * for a dot product use: v1.dot(v2)
- // * for a coeff-wise product use: v1.cwiseProduct(v2)
- EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
- INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
- EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
- INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
- EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
-
- return typename LazyProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
-}
-
-#endif // EIGEN_PRODUCT_H
diff --git a/extern/Eigen3/Eigen/src/Core/ProductBase.h b/extern/Eigen3/Eigen/src/Core/ProductBase.h
deleted file mode 100644
index 3bd3487d6a2..00000000000
--- a/extern/Eigen3/Eigen/src/Core/ProductBase.h
+++ /dev/null
@@ -1,288 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_PRODUCTBASE_H
-#define EIGEN_PRODUCTBASE_H
-
-/** \class ProductBase
- * \ingroup Core_Module
- *
- */
-
-namespace internal {
-template<typename Derived, typename _Lhs, typename _Rhs>
-struct traits<ProductBase<Derived,_Lhs,_Rhs> >
-{
- typedef MatrixXpr XprKind;
- typedef typename remove_all<_Lhs>::type Lhs;
- typedef typename remove_all<_Rhs>::type Rhs;
- typedef typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType Scalar;
- typedef typename promote_storage_type<typename traits<Lhs>::StorageKind,
- typename traits<Rhs>::StorageKind>::ret StorageKind;
- typedef typename promote_index_type<typename traits<Lhs>::Index,
- typename traits<Rhs>::Index>::type Index;
- enum {
- RowsAtCompileTime = traits<Lhs>::RowsAtCompileTime,
- ColsAtCompileTime = traits<Rhs>::ColsAtCompileTime,
- MaxRowsAtCompileTime = traits<Lhs>::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = traits<Rhs>::MaxColsAtCompileTime,
- Flags = (MaxRowsAtCompileTime==1 ? RowMajorBit : 0)
- | EvalBeforeNestingBit | EvalBeforeAssigningBit | NestByRefBit,
- // Note that EvalBeforeNestingBit and NestByRefBit
- // are not used in practice because nested is overloaded for products
- CoeffReadCost = 0 // FIXME why is it needed ?
- };
-};
-}
-
-#define EIGEN_PRODUCT_PUBLIC_INTERFACE(Derived) \
- typedef ProductBase<Derived, Lhs, Rhs > Base; \
- EIGEN_DENSE_PUBLIC_INTERFACE(Derived) \
- typedef typename Base::LhsNested LhsNested; \
- typedef typename Base::_LhsNested _LhsNested; \
- typedef typename Base::LhsBlasTraits LhsBlasTraits; \
- typedef typename Base::ActualLhsType ActualLhsType; \
- typedef typename Base::_ActualLhsType _ActualLhsType; \
- typedef typename Base::RhsNested RhsNested; \
- typedef typename Base::_RhsNested _RhsNested; \
- typedef typename Base::RhsBlasTraits RhsBlasTraits; \
- typedef typename Base::ActualRhsType ActualRhsType; \
- typedef typename Base::_ActualRhsType _ActualRhsType; \
- using Base::m_lhs; \
- using Base::m_rhs;
-
-template<typename Derived, typename Lhs, typename Rhs>
-class ProductBase : public MatrixBase<Derived>
-{
- public:
- typedef MatrixBase<Derived> Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(ProductBase)
-
- typedef typename Lhs::Nested LhsNested;
- typedef typename internal::remove_all<LhsNested>::type _LhsNested;
- typedef internal::blas_traits<_LhsNested> LhsBlasTraits;
- typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType;
- typedef typename internal::remove_all<ActualLhsType>::type _ActualLhsType;
- typedef typename internal::traits<Lhs>::Scalar LhsScalar;
-
- typedef typename Rhs::Nested RhsNested;
- typedef typename internal::remove_all<RhsNested>::type _RhsNested;
- typedef internal::blas_traits<_RhsNested> RhsBlasTraits;
- typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType;
- typedef typename internal::remove_all<ActualRhsType>::type _ActualRhsType;
- typedef typename internal::traits<Rhs>::Scalar RhsScalar;
-
- // Diagonal of a product: no need to evaluate the arguments because they are going to be evaluated only once
- typedef CoeffBasedProduct<LhsNested, RhsNested, 0> FullyLazyCoeffBaseProductType;
-
- public:
-
- typedef typename Base::PlainObject PlainObject;
-
- ProductBase(const Lhs& lhs, const Rhs& rhs)
- : m_lhs(lhs), m_rhs(rhs)
- {
- eigen_assert(lhs.cols() == rhs.rows()
- && "invalid matrix product"
- && "if you wanted a coeff-wise or a dot product use the respective explicit functions");
- }
-
- inline Index rows() const { return m_lhs.rows(); }
- inline Index cols() const { return m_rhs.cols(); }
-
- template<typename Dest>
- inline void evalTo(Dest& dst) const { dst.setZero(); scaleAndAddTo(dst,Scalar(1)); }
-
- template<typename Dest>
- inline void addTo(Dest& dst) const { scaleAndAddTo(dst,1); }
-
- template<typename Dest>
- inline void subTo(Dest& dst) const { scaleAndAddTo(dst,-1); }
-
- template<typename Dest>
- inline void scaleAndAddTo(Dest& dst,Scalar alpha) const { derived().scaleAndAddTo(dst,alpha); }
-
- const _LhsNested& lhs() const { return m_lhs; }
- const _RhsNested& rhs() const { return m_rhs; }
-
- // Implicit conversion to the nested type (trigger the evaluation of the product)
- operator const PlainObject& () const
- {
- m_result.resize(m_lhs.rows(), m_rhs.cols());
- derived().evalTo(m_result);
- return m_result;
- }
-
- const Diagonal<const FullyLazyCoeffBaseProductType,0> diagonal() const
- { return FullyLazyCoeffBaseProductType(m_lhs, m_rhs); }
-
- template<int Index>
- const Diagonal<FullyLazyCoeffBaseProductType,Index> diagonal() const
- { return FullyLazyCoeffBaseProductType(m_lhs, m_rhs); }
-
- const Diagonal<FullyLazyCoeffBaseProductType,Dynamic> diagonal(Index index) const
- { return FullyLazyCoeffBaseProductType(m_lhs, m_rhs).diagonal(index); }
-
- // restrict coeff accessors to 1x1 expressions. No need to care about mutators here since this isnt a Lvalue expression
- typename Base::CoeffReturnType coeff(Index row, Index col) const
- {
-#ifdef EIGEN2_SUPPORT
- return lhs().row(row).cwiseProduct(rhs().col(col).transpose()).sum();
-#else
- EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
- eigen_assert(this->rows() == 1 && this->cols() == 1);
- return derived().coeff(row,col);
-#endif
- }
-
- typename Base::CoeffReturnType coeff(Index i) const
- {
- EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
- eigen_assert(this->rows() == 1 && this->cols() == 1);
- return derived().coeff(i);
- }
-
- const Scalar& coeffRef(Index row, Index col) const
- {
- EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
- eigen_assert(this->rows() == 1 && this->cols() == 1);
- return derived().coeffRef(row,col);
- }
-
- const Scalar& coeffRef(Index i) const
- {
- EIGEN_STATIC_ASSERT_SIZE_1x1(Derived)
- eigen_assert(this->rows() == 1 && this->cols() == 1);
- return derived().coeffRef(i);
- }
-
- protected:
-
- const LhsNested m_lhs;
- const RhsNested m_rhs;
-
- mutable PlainObject m_result;
-};
-
-// here we need to overload the nested rule for products
-// such that the nested type is a const reference to a plain matrix
-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;
-};
-}
-
-template<typename NestedProduct>
-class ScaledProduct;
-
-// Note that these two operator* functions are not defined as member
-// functions of ProductBase, because, otherwise we would have to
-// define all overloads defined in MatrixBase. Furthermore, Using
-// "using Base::operator*" would not work with MSVC.
-//
-// Also note that here we accept any compatible scalar types
-template<typename Derived,typename Lhs,typename Rhs>
-const ScaledProduct<Derived>
-operator*(const ProductBase<Derived,Lhs,Rhs>& prod, typename Derived::Scalar x)
-{ return ScaledProduct<Derived>(prod.derived(), x); }
-
-template<typename Derived,typename Lhs,typename Rhs>
-typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value,
- const ScaledProduct<Derived> >::type
-operator*(const ProductBase<Derived,Lhs,Rhs>& prod, typename Derived::RealScalar x)
-{ return ScaledProduct<Derived>(prod.derived(), x); }
-
-
-template<typename Derived,typename Lhs,typename Rhs>
-const ScaledProduct<Derived>
-operator*(typename Derived::Scalar x,const ProductBase<Derived,Lhs,Rhs>& prod)
-{ return ScaledProduct<Derived>(prod.derived(), x); }
-
-template<typename Derived,typename Lhs,typename Rhs>
-typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value,
- const ScaledProduct<Derived> >::type
-operator*(typename Derived::RealScalar x,const ProductBase<Derived,Lhs,Rhs>& prod)
-{ return ScaledProduct<Derived>(prod.derived(), x); }
-
-namespace internal {
-template<typename NestedProduct>
-struct traits<ScaledProduct<NestedProduct> >
- : traits<ProductBase<ScaledProduct<NestedProduct>,
- typename NestedProduct::_LhsNested,
- typename NestedProduct::_RhsNested> >
-{
- typedef typename traits<NestedProduct>::StorageKind StorageKind;
-};
-}
-
-template<typename NestedProduct>
-class ScaledProduct
- : public ProductBase<ScaledProduct<NestedProduct>,
- typename NestedProduct::_LhsNested,
- typename NestedProduct::_RhsNested>
-{
- public:
- typedef ProductBase<ScaledProduct<NestedProduct>,
- typename NestedProduct::_LhsNested,
- typename NestedProduct::_RhsNested> Base;
- typedef typename Base::Scalar Scalar;
- typedef typename Base::PlainObject PlainObject;
-// EIGEN_PRODUCT_PUBLIC_INTERFACE(ScaledProduct)
-
- ScaledProduct(const NestedProduct& prod, Scalar x)
- : Base(prod.lhs(),prod.rhs()), m_prod(prod), m_alpha(x) {}
-
- template<typename Dest>
- inline void evalTo(Dest& dst) const { dst.setZero(); scaleAndAddTo(dst,m_alpha); }
-
- template<typename Dest>
- inline void addTo(Dest& dst) const { scaleAndAddTo(dst,m_alpha); }
-
- template<typename Dest>
- inline void subTo(Dest& dst) const { scaleAndAddTo(dst,-m_alpha); }
-
- template<typename Dest>
- inline void scaleAndAddTo(Dest& dst,Scalar alpha) const { m_prod.derived().scaleAndAddTo(dst,alpha); }
-
- const Scalar& alpha() const { return m_alpha; }
-
- protected:
- const NestedProduct& m_prod;
- Scalar m_alpha;
-};
-
-/** \internal
- * Overloaded to perform an efficient C = (A*B).lazy() */
-template<typename Derived>
-template<typename ProductDerived, typename Lhs, typename Rhs>
-Derived& MatrixBase<Derived>::lazyAssign(const ProductBase<ProductDerived, Lhs,Rhs>& other)
-{
- other.derived().evalTo(derived());
- return derived();
-}
-
-
-#endif // EIGEN_PRODUCTBASE_H
diff --git a/extern/Eigen3/Eigen/src/Core/Redux.h b/extern/Eigen3/Eigen/src/Core/Redux.h
deleted file mode 100644
index f9f5a95d546..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Redux.h
+++ /dev/null
@@ -1,404 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_REDUX_H
-#define EIGEN_REDUX_H
-
-namespace internal {
-
-// TODO
-// * implement other kind of vectorization
-// * factorize code
-
-/***************************************************************************
-* Part 1 : the logic deciding a strategy for vectorization and unrolling
-***************************************************************************/
-
-template<typename Func, typename Derived>
-struct redux_traits
-{
-public:
- enum {
- PacketSize = packet_traits<typename Derived::Scalar>::size,
- InnerMaxSize = int(Derived::IsRowMajor)
- ? Derived::MaxColsAtCompileTime
- : Derived::MaxRowsAtCompileTime
- };
-
- enum {
- MightVectorize = (int(Derived::Flags)&ActualPacketAccessBit)
- && (functor_traits<Func>::PacketAccess),
- MayLinearVectorize = MightVectorize && (int(Derived::Flags)&LinearAccessBit),
- MaySliceVectorize = MightVectorize && int(InnerMaxSize)>=3*PacketSize
- };
-
-public:
- enum {
- Traversal = int(MayLinearVectorize) ? int(LinearVectorizedTraversal)
- : int(MaySliceVectorize) ? int(SliceVectorizedTraversal)
- : int(DefaultTraversal)
- };
-
-public:
- enum {
- Cost = ( Derived::SizeAtCompileTime == Dynamic
- || Derived::CoeffReadCost == Dynamic
- || (Derived::SizeAtCompileTime!=1 && functor_traits<Func>::Cost == Dynamic)
- ) ? Dynamic
- : Derived::SizeAtCompileTime * Derived::CoeffReadCost
- + (Derived::SizeAtCompileTime-1) * functor_traits<Func>::Cost,
- UnrollingLimit = EIGEN_UNROLLING_LIMIT * (int(Traversal) == int(DefaultTraversal) ? 1 : int(PacketSize))
- };
-
-public:
- enum {
- Unrolling = Cost != Dynamic && Cost <= UnrollingLimit
- ? CompleteUnrolling
- : NoUnrolling
- };
-};
-
-/***************************************************************************
-* Part 2 : unrollers
-***************************************************************************/
-
-/*** no vectorization ***/
-
-template<typename Func, typename Derived, int Start, int Length>
-struct redux_novec_unroller
-{
- enum {
- HalfLength = Length/2
- };
-
- typedef typename Derived::Scalar Scalar;
-
- EIGEN_STRONG_INLINE static Scalar run(const Derived &mat, const Func& func)
- {
- return func(redux_novec_unroller<Func, Derived, Start, HalfLength>::run(mat,func),
- redux_novec_unroller<Func, Derived, Start+HalfLength, Length-HalfLength>::run(mat,func));
- }
-};
-
-template<typename Func, typename Derived, int Start>
-struct redux_novec_unroller<Func, Derived, Start, 1>
-{
- enum {
- outer = Start / Derived::InnerSizeAtCompileTime,
- inner = Start % Derived::InnerSizeAtCompileTime
- };
-
- typedef typename Derived::Scalar Scalar;
-
- EIGEN_STRONG_INLINE static Scalar run(const Derived &mat, const Func&)
- {
- return mat.coeffByOuterInner(outer, inner);
- }
-};
-
-// This is actually dead code and will never be called. It is required
-// to prevent false warnings regarding failed inlining though
-// for 0 length run() will never be called at all.
-template<typename Func, typename Derived, int Start>
-struct redux_novec_unroller<Func, Derived, Start, 0>
-{
- typedef typename Derived::Scalar Scalar;
- EIGEN_STRONG_INLINE static Scalar run(const Derived&, const Func&) { return Scalar(); }
-};
-
-/*** vectorization ***/
-
-template<typename Func, typename Derived, int Start, int Length>
-struct redux_vec_unroller
-{
- enum {
- PacketSize = packet_traits<typename Derived::Scalar>::size,
- HalfLength = Length/2
- };
-
- typedef typename Derived::Scalar Scalar;
- typedef typename packet_traits<Scalar>::type PacketScalar;
-
- EIGEN_STRONG_INLINE static PacketScalar run(const Derived &mat, const Func& func)
- {
- return func.packetOp(
- redux_vec_unroller<Func, Derived, Start, HalfLength>::run(mat,func),
- redux_vec_unroller<Func, Derived, Start+HalfLength, Length-HalfLength>::run(mat,func) );
- }
-};
-
-template<typename Func, typename Derived, int Start>
-struct redux_vec_unroller<Func, Derived, Start, 1>
-{
- enum {
- index = Start * packet_traits<typename Derived::Scalar>::size,
- outer = index / int(Derived::InnerSizeAtCompileTime),
- inner = index % int(Derived::InnerSizeAtCompileTime),
- alignment = (Derived::Flags & AlignedBit) ? Aligned : Unaligned
- };
-
- typedef typename Derived::Scalar Scalar;
- typedef typename packet_traits<Scalar>::type PacketScalar;
-
- EIGEN_STRONG_INLINE static PacketScalar run(const Derived &mat, const Func&)
- {
- return mat.template packetByOuterInner<alignment>(outer, inner);
- }
-};
-
-/***************************************************************************
-* Part 3 : implementation of all cases
-***************************************************************************/
-
-template<typename Func, typename Derived,
- int Traversal = redux_traits<Func, Derived>::Traversal,
- int Unrolling = redux_traits<Func, Derived>::Unrolling
->
-struct redux_impl;
-
-template<typename Func, typename Derived>
-struct redux_impl<Func, Derived, DefaultTraversal, NoUnrolling>
-{
- typedef typename Derived::Scalar Scalar;
- typedef typename Derived::Index Index;
- static EIGEN_STRONG_INLINE Scalar run(const Derived& mat, const Func& func)
- {
- eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix");
- Scalar res;
- res = mat.coeffByOuterInner(0, 0);
- for(Index i = 1; i < mat.innerSize(); ++i)
- res = func(res, mat.coeffByOuterInner(0, i));
- for(Index i = 1; i < mat.outerSize(); ++i)
- for(Index j = 0; j < mat.innerSize(); ++j)
- res = func(res, mat.coeffByOuterInner(i, j));
- return res;
- }
-};
-
-template<typename Func, typename Derived>
-struct redux_impl<Func,Derived, DefaultTraversal, CompleteUnrolling>
- : public redux_novec_unroller<Func,Derived, 0, Derived::SizeAtCompileTime>
-{};
-
-template<typename Func, typename Derived>
-struct redux_impl<Func, Derived, LinearVectorizedTraversal, NoUnrolling>
-{
- typedef typename Derived::Scalar Scalar;
- typedef typename packet_traits<Scalar>::type PacketScalar;
- typedef typename Derived::Index Index;
-
- static Scalar run(const Derived& mat, const Func& func)
- {
- const Index size = mat.size();
- eigen_assert(size && "you are using an empty matrix");
- const Index packetSize = packet_traits<Scalar>::size;
- const Index alignedStart = first_aligned(mat);
- enum {
- alignment = bool(Derived::Flags & DirectAccessBit) || bool(Derived::Flags & AlignedBit)
- ? Aligned : Unaligned
- };
- const Index alignedSize = ((size-alignedStart)/packetSize)*packetSize;
- const Index alignedEnd = alignedStart + alignedSize;
- Scalar res;
- if(alignedSize)
- {
- PacketScalar packet_res = mat.template packet<alignment>(alignedStart);
- for(Index index = alignedStart + packetSize; index < alignedEnd; index += packetSize)
- packet_res = func.packetOp(packet_res, mat.template packet<alignment>(index));
- res = func.predux(packet_res);
-
- for(Index index = 0; index < alignedStart; ++index)
- res = func(res,mat.coeff(index));
-
- for(Index index = alignedEnd; index < size; ++index)
- res = func(res,mat.coeff(index));
- }
- else // too small to vectorize anything.
- // since this is dynamic-size hence inefficient anyway for such small sizes, don't try to optimize.
- {
- res = mat.coeff(0);
- for(Index index = 1; index < size; ++index)
- res = func(res,mat.coeff(index));
- }
-
- return res;
- }
-};
-
-template<typename Func, typename Derived>
-struct redux_impl<Func, Derived, SliceVectorizedTraversal, NoUnrolling>
-{
- typedef typename Derived::Scalar Scalar;
- typedef typename packet_traits<Scalar>::type PacketScalar;
- typedef typename Derived::Index Index;
-
- static Scalar run(const Derived& mat, const Func& func)
- {
- eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix");
- const Index innerSize = mat.innerSize();
- const Index outerSize = mat.outerSize();
- enum {
- packetSize = packet_traits<Scalar>::size
- };
- const Index packetedInnerSize = ((innerSize)/packetSize)*packetSize;
- Scalar res;
- if(packetedInnerSize)
- {
- PacketScalar packet_res = mat.template packet<Unaligned>(0,0);
- for(Index j=0; j<outerSize; ++j)
- for(Index i=(j==0?packetSize:0); i<packetedInnerSize; i+=Index(packetSize))
- packet_res = func.packetOp(packet_res, mat.template packetByOuterInner<Unaligned>(j,i));
-
- res = func.predux(packet_res);
- for(Index j=0; j<outerSize; ++j)
- for(Index i=packetedInnerSize; i<innerSize; ++i)
- res = func(res, mat.coeffByOuterInner(j,i));
- }
- else // too small to vectorize anything.
- // since this is dynamic-size hence inefficient anyway for such small sizes, don't try to optimize.
- {
- res = redux_impl<Func, Derived, DefaultTraversal, NoUnrolling>::run(mat, func);
- }
-
- return res;
- }
-};
-
-template<typename Func, typename Derived>
-struct redux_impl<Func, Derived, LinearVectorizedTraversal, CompleteUnrolling>
-{
- typedef typename Derived::Scalar Scalar;
- typedef typename packet_traits<Scalar>::type PacketScalar;
- enum {
- PacketSize = packet_traits<Scalar>::size,
- Size = Derived::SizeAtCompileTime,
- VectorizedSize = (Size / PacketSize) * PacketSize
- };
- EIGEN_STRONG_INLINE static Scalar run(const Derived& mat, const Func& func)
- {
- eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix");
- Scalar res = func.predux(redux_vec_unroller<Func, Derived, 0, Size / PacketSize>::run(mat,func));
- if (VectorizedSize != Size)
- res = func(res,redux_novec_unroller<Func, Derived, VectorizedSize, Size-VectorizedSize>::run(mat,func));
- return res;
- }
-};
-
-} // end namespace internal
-
-/***************************************************************************
-* Part 4 : public API
-***************************************************************************/
-
-
-/** \returns the result of a full redux operation on the whole matrix or vector using \a func
- *
- * The template parameter \a BinaryOp is the type of the functor \a func which must be
- * an associative operator. Both current STL and TR1 functor styles are handled.
- *
- * \sa DenseBase::sum(), DenseBase::minCoeff(), DenseBase::maxCoeff(), MatrixBase::colwise(), MatrixBase::rowwise()
- */
-template<typename Derived>
-template<typename Func>
-EIGEN_STRONG_INLINE typename internal::result_of<Func(typename internal::traits<Derived>::Scalar)>::type
-DenseBase<Derived>::redux(const Func& func) const
-{
- typedef typename internal::remove_all<typename Derived::Nested>::type ThisNested;
- return internal::redux_impl<Func, ThisNested>
- ::run(derived(), func);
-}
-
-/** \returns the minimum of all coefficients of *this
- */
-template<typename Derived>
-EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
-DenseBase<Derived>::minCoeff() const
-{
- return this->redux(Eigen::internal::scalar_min_op<Scalar>());
-}
-
-/** \returns the maximum of all coefficients of *this
- */
-template<typename Derived>
-EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
-DenseBase<Derived>::maxCoeff() const
-{
- return this->redux(Eigen::internal::scalar_max_op<Scalar>());
-}
-
-/** \returns the sum of all coefficients of *this
- *
- * \sa trace(), prod(), mean()
- */
-template<typename Derived>
-EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
-DenseBase<Derived>::sum() const
-{
- if(SizeAtCompileTime==0 || (SizeAtCompileTime==Dynamic && size()==0))
- return Scalar(0);
- return this->redux(Eigen::internal::scalar_sum_op<Scalar>());
-}
-
-/** \returns the mean of all coefficients of *this
-*
-* \sa trace(), prod(), sum()
-*/
-template<typename Derived>
-EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
-DenseBase<Derived>::mean() const
-{
- return Scalar(this->redux(Eigen::internal::scalar_sum_op<Scalar>())) / Scalar(this->size());
-}
-
-/** \returns the product of all coefficients of *this
- *
- * Example: \include MatrixBase_prod.cpp
- * Output: \verbinclude MatrixBase_prod.out
- *
- * \sa sum(), mean(), trace()
- */
-template<typename Derived>
-EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
-DenseBase<Derived>::prod() const
-{
- if(SizeAtCompileTime==0 || (SizeAtCompileTime==Dynamic && size()==0))
- return Scalar(1);
- return this->redux(Eigen::internal::scalar_product_op<Scalar>());
-}
-
-/** \returns the trace of \c *this, i.e. the sum of the coefficients on the main diagonal.
- *
- * \c *this can be any matrix, not necessarily square.
- *
- * \sa diagonal(), sum()
- */
-template<typename Derived>
-EIGEN_STRONG_INLINE typename internal::traits<Derived>::Scalar
-MatrixBase<Derived>::trace() const
-{
- return derived().diagonal().sum();
-}
-
-#endif // EIGEN_REDUX_H
diff --git a/extern/Eigen3/Eigen/src/Core/Replicate.h b/extern/Eigen3/Eigen/src/Core/Replicate.h
deleted file mode 100644
index d2f9712db0f..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Replicate.h
+++ /dev/null
@@ -1,179 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_REPLICATE_H
-#define EIGEN_REPLICATE_H
-
-/**
- * \class Replicate
- * \ingroup Core_Module
- *
- * \brief Expression of the multiple replication of a matrix or vector
- *
- * \param MatrixType the type of the object we are replicating
- *
- * This class represents an expression of the multiple replication of a matrix or vector.
- * It is the return type of DenseBase::replicate() and most of the time
- * this is the only way it is used.
- *
- * \sa DenseBase::replicate()
- */
-
-namespace internal {
-template<typename MatrixType,int RowFactor,int ColFactor>
-struct traits<Replicate<MatrixType,RowFactor,ColFactor> >
- : traits<MatrixType>
-{
- typedef typename MatrixType::Scalar Scalar;
- typedef typename traits<MatrixType>::StorageKind StorageKind;
- typedef typename traits<MatrixType>::XprKind XprKind;
- typedef typename nested<MatrixType>::type MatrixTypeNested;
- typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
- enum {
- RowsAtCompileTime = RowFactor==Dynamic || int(MatrixType::RowsAtCompileTime)==Dynamic
- ? Dynamic
- : RowFactor * MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = ColFactor==Dynamic || int(MatrixType::ColsAtCompileTime)==Dynamic
- ? Dynamic
- : ColFactor * MatrixType::ColsAtCompileTime,
- //FIXME we don't propagate the max sizes !!!
- MaxRowsAtCompileTime = RowsAtCompileTime,
- MaxColsAtCompileTime = ColsAtCompileTime,
- IsRowMajor = MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1 ? 1
- : MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1 ? 0
- : (MatrixType::Flags & RowMajorBit) ? 1 : 0,
- Flags = (_MatrixTypeNested::Flags & HereditaryBits & ~RowMajorBit) | (IsRowMajor ? RowMajorBit : 0),
- CoeffReadCost = _MatrixTypeNested::CoeffReadCost
- };
-};
-}
-
-template<typename MatrixType,int RowFactor,int ColFactor> class Replicate
- : public internal::dense_xpr_base< Replicate<MatrixType,RowFactor,ColFactor> >::type
-{
- public:
-
- typedef typename internal::dense_xpr_base<Replicate>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Replicate)
-
- template<typename OriginalMatrixType>
- inline explicit Replicate(const OriginalMatrixType& matrix)
- : m_matrix(matrix), m_rowFactor(RowFactor), m_colFactor(ColFactor)
- {
- EIGEN_STATIC_ASSERT((internal::is_same<typename internal::remove_const<MatrixType>::type,OriginalMatrixType>::value),
- THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE)
- eigen_assert(RowFactor!=Dynamic && ColFactor!=Dynamic);
- }
-
- template<typename OriginalMatrixType>
- inline Replicate(const OriginalMatrixType& matrix, int rowFactor, int colFactor)
- : m_matrix(matrix), m_rowFactor(rowFactor), m_colFactor(colFactor)
- {
- EIGEN_STATIC_ASSERT((internal::is_same<typename internal::remove_const<MatrixType>::type,OriginalMatrixType>::value),
- THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE)
- }
-
- inline Index rows() const { return m_matrix.rows() * m_rowFactor.value(); }
- inline Index cols() const { return m_matrix.cols() * m_colFactor.value(); }
-
- inline Scalar coeff(Index row, Index col) const
- {
- // try to avoid using modulo; this is a pure optimization strategy
- const Index actual_row = internal::traits<MatrixType>::RowsAtCompileTime==1 ? 0
- : RowFactor==1 ? row
- : row%m_matrix.rows();
- const Index actual_col = internal::traits<MatrixType>::ColsAtCompileTime==1 ? 0
- : ColFactor==1 ? col
- : col%m_matrix.cols();
-
- return m_matrix.coeff(actual_row, actual_col);
- }
- template<int LoadMode>
- inline PacketScalar packet(Index row, Index col) const
- {
- const Index actual_row = internal::traits<MatrixType>::RowsAtCompileTime==1 ? 0
- : RowFactor==1 ? row
- : row%m_matrix.rows();
- const Index actual_col = internal::traits<MatrixType>::ColsAtCompileTime==1 ? 0
- : ColFactor==1 ? col
- : col%m_matrix.cols();
-
- return m_matrix.template packet<LoadMode>(actual_row, actual_col);
- }
-
-
- protected:
- const typename MatrixType::Nested m_matrix;
- const internal::variable_if_dynamic<Index, RowFactor> m_rowFactor;
- const internal::variable_if_dynamic<Index, ColFactor> m_colFactor;
-};
-
-/**
- * \return an expression of the replication of \c *this
- *
- * Example: \include MatrixBase_replicate.cpp
- * Output: \verbinclude MatrixBase_replicate.out
- *
- * \sa VectorwiseOp::replicate(), DenseBase::replicate(Index,Index), class Replicate
- */
-template<typename Derived>
-template<int RowFactor, int ColFactor>
-inline const Replicate<Derived,RowFactor,ColFactor>
-DenseBase<Derived>::replicate() const
-{
- return Replicate<Derived,RowFactor,ColFactor>(derived());
-}
-
-/**
- * \return an expression of the replication of \c *this
- *
- * Example: \include MatrixBase_replicate_int_int.cpp
- * Output: \verbinclude MatrixBase_replicate_int_int.out
- *
- * \sa VectorwiseOp::replicate(), DenseBase::replicate<int,int>(), class Replicate
- */
-template<typename Derived>
-inline const Replicate<Derived,Dynamic,Dynamic>
-DenseBase<Derived>::replicate(Index rowFactor,Index colFactor) const
-{
- return Replicate<Derived,Dynamic,Dynamic>(derived(),rowFactor,colFactor);
-}
-
-/**
- * \return an expression of the replication of each column (or row) of \c *this
- *
- * Example: \include DirectionWise_replicate_int.cpp
- * Output: \verbinclude DirectionWise_replicate_int.out
- *
- * \sa VectorwiseOp::replicate(), DenseBase::replicate(), class Replicate
- */
-template<typename ExpressionType, int Direction>
-const typename VectorwiseOp<ExpressionType,Direction>::ReplicateReturnType
-VectorwiseOp<ExpressionType,Direction>::replicate(Index factor) const
-{
- return typename VectorwiseOp<ExpressionType,Direction>::ReplicateReturnType
- (_expression(),Direction==Vertical?factor:1,Direction==Horizontal?factor:1);
-}
-
-#endif // EIGEN_REPLICATE_H
diff --git a/extern/Eigen3/Eigen/src/Core/ReturnByValue.h b/extern/Eigen3/Eigen/src/Core/ReturnByValue.h
deleted file mode 100644
index 24c5a4e215d..00000000000
--- a/extern/Eigen3/Eigen/src/Core/ReturnByValue.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2009-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_RETURNBYVALUE_H
-#define EIGEN_RETURNBYVALUE_H
-
-/** \class ReturnByValue
- * \ingroup Core_Module
- *
- */
-
-namespace internal {
-
-template<typename Derived>
-struct traits<ReturnByValue<Derived> >
- : public traits<typename traits<Derived>::ReturnType>
-{
- enum {
- // We're disabling the DirectAccess because e.g. the constructor of
- // the Block-with-DirectAccess expression requires to have a coeffRef method.
- // Also, we don't want to have to implement the stride stuff.
- Flags = (traits<typename traits<Derived>::ReturnType>::Flags
- | EvalBeforeNestingBit) & ~DirectAccessBit
- };
-};
-
-/* The ReturnByValue object doesn't even have a coeff() method.
- * So the only way that nesting it in an expression can work, is by evaluating it into a plain matrix.
- * So internal::nested always gives the plain return matrix type.
- *
- * FIXME: I don't understand why we need this specialization: isn't this taken care of by the EvalBeforeNestingBit ??
- */
-template<typename Derived,int n,typename PlainObject>
-struct nested<ReturnByValue<Derived>, n, PlainObject>
-{
- typedef typename traits<Derived>::ReturnType type;
-};
-
-} // end namespace internal
-
-template<typename Derived> class ReturnByValue
- : public internal::dense_xpr_base< ReturnByValue<Derived> >::type
-{
- public:
- typedef typename internal::traits<Derived>::ReturnType ReturnType;
-
- typedef typename internal::dense_xpr_base<ReturnByValue>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(ReturnByValue)
-
- template<typename Dest>
- inline void evalTo(Dest& dst) const
- { static_cast<const Derived*>(this)->evalTo(dst); }
- inline Index rows() const { return static_cast<const Derived*>(this)->rows(); }
- inline Index cols() const { return static_cast<const Derived*>(this)->cols(); }
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
-#define Unusable YOU_ARE_TRYING_TO_ACCESS_A_SINGLE_COEFFICIENT_IN_A_SPECIAL_EXPRESSION_WHERE_THAT_IS_NOT_ALLOWED_BECAUSE_THAT_WOULD_BE_INEFFICIENT
- class Unusable{
- Unusable(const Unusable&) {}
- Unusable& operator=(const Unusable&) {return *this;}
- };
- const Unusable& coeff(Index) const { return *reinterpret_cast<const Unusable*>(this); }
- 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); }
-#endif
-};
-
-template<typename Derived>
-template<typename OtherDerived>
-Derived& DenseBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
-{
- other.evalTo(derived());
- return derived();
-}
-
-#endif // EIGEN_RETURNBYVALUE_H
diff --git a/extern/Eigen3/Eigen/src/Core/Reverse.h b/extern/Eigen3/Eigen/src/Core/Reverse.h
deleted file mode 100644
index 600744ae758..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Reverse.h
+++ /dev/null
@@ -1,230 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2009 Ricard Marxer <email@ricardmarxer.com>
-// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_REVERSE_H
-#define EIGEN_REVERSE_H
-
-/** \class Reverse
- * \ingroup Core_Module
- *
- * \brief Expression of the reverse of a vector or matrix
- *
- * \param MatrixType the type of the object of which we are taking the reverse
- *
- * This class represents an expression of the reverse of a vector.
- * It is the return type of MatrixBase::reverse() and VectorwiseOp::reverse()
- * and most of the time this is the only way it is used.
- *
- * \sa MatrixBase::reverse(), VectorwiseOp::reverse()
- */
-
-namespace internal {
-
-template<typename MatrixType, int Direction>
-struct traits<Reverse<MatrixType, Direction> >
- : traits<MatrixType>
-{
- typedef typename MatrixType::Scalar Scalar;
- typedef typename traits<MatrixType>::StorageKind StorageKind;
- typedef typename traits<MatrixType>::XprKind XprKind;
- typedef typename nested<MatrixType>::type MatrixTypeNested;
- typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
-
- // let's enable LinearAccess only with vectorization because of the product overhead
- LinearAccess = ( (Direction==BothDirections) && (int(_MatrixTypeNested::Flags)&PacketAccessBit) )
- ? LinearAccessBit : 0,
-
- Flags = int(_MatrixTypeNested::Flags) & (HereditaryBits | LvalueBit | PacketAccessBit | LinearAccess),
-
- CoeffReadCost = _MatrixTypeNested::CoeffReadCost
- };
-};
-
-template<typename PacketScalar, bool ReversePacket> struct reverse_packet_cond
-{
- static inline PacketScalar run(const PacketScalar& x) { return preverse(x); }
-};
-
-template<typename PacketScalar> struct reverse_packet_cond<PacketScalar,false>
-{
- static inline PacketScalar run(const PacketScalar& x) { return x; }
-};
-
-} // end namespace internal
-
-template<typename MatrixType, int Direction> class Reverse
- : public internal::dense_xpr_base< Reverse<MatrixType, Direction> >::type
-{
- public:
-
- typedef typename internal::dense_xpr_base<Reverse>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Reverse)
- using Base::IsRowMajor;
-
- // next line is necessary because otherwise const version of operator()
- // is hidden by non-const version defined in this file
- using Base::operator();
-
- protected:
- enum {
- PacketSize = internal::packet_traits<Scalar>::size,
- IsColMajor = !IsRowMajor,
- ReverseRow = (Direction == Vertical) || (Direction == BothDirections),
- ReverseCol = (Direction == Horizontal) || (Direction == BothDirections),
- OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1,
- OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1,
- ReversePacket = (Direction == BothDirections)
- || ((Direction == Vertical) && IsColMajor)
- || ((Direction == Horizontal) && IsRowMajor)
- };
- typedef internal::reverse_packet_cond<PacketScalar,ReversePacket> reverse_packet;
- public:
-
- inline Reverse(const MatrixType& matrix) : m_matrix(matrix) { }
-
- EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Reverse)
-
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
-
- inline Index innerStride() const
- {
- return -m_matrix.innerStride();
- }
-
- inline Scalar& operator()(Index row, Index col)
- {
- eigen_assert(row >= 0 && row < rows() && col >= 0 && col < cols());
- return coeffRef(row, col);
- }
-
- inline Scalar& coeffRef(Index row, Index col)
- {
- return m_matrix.const_cast_derived().coeffRef(ReverseRow ? m_matrix.rows() - row - 1 : row,
- ReverseCol ? m_matrix.cols() - col - 1 : col);
- }
-
- inline CoeffReturnType coeff(Index row, Index col) const
- {
- return m_matrix.coeff(ReverseRow ? m_matrix.rows() - row - 1 : row,
- ReverseCol ? m_matrix.cols() - col - 1 : col);
- }
-
- inline CoeffReturnType coeff(Index index) const
- {
- return m_matrix.coeff(m_matrix.size() - index - 1);
- }
-
- inline Scalar& coeffRef(Index index)
- {
- return m_matrix.const_cast_derived().coeffRef(m_matrix.size() - index - 1);
- }
-
- inline Scalar& operator()(Index index)
- {
- eigen_assert(index >= 0 && index < m_matrix.size());
- return coeffRef(index);
- }
-
- template<int LoadMode>
- inline const PacketScalar packet(Index row, Index col) const
- {
- return reverse_packet::run(m_matrix.template packet<LoadMode>(
- ReverseRow ? m_matrix.rows() - row - OffsetRow : row,
- ReverseCol ? m_matrix.cols() - col - OffsetCol : col));
- }
-
- template<int LoadMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
- {
- m_matrix.const_cast_derived().template writePacket<LoadMode>(
- ReverseRow ? m_matrix.rows() - row - OffsetRow : row,
- ReverseCol ? m_matrix.cols() - col - OffsetCol : col,
- reverse_packet::run(x));
- }
-
- template<int LoadMode>
- inline const PacketScalar packet(Index index) const
- {
- return internal::preverse(m_matrix.template packet<LoadMode>( m_matrix.size() - index - PacketSize ));
- }
-
- template<int LoadMode>
- inline void writePacket(Index index, const PacketScalar& x)
- {
- m_matrix.const_cast_derived().template writePacket<LoadMode>(m_matrix.size() - index - PacketSize, internal::preverse(x));
- }
-
- protected:
- const typename MatrixType::Nested m_matrix;
-};
-
-/** \returns an expression of the reverse of *this.
- *
- * Example: \include MatrixBase_reverse.cpp
- * Output: \verbinclude MatrixBase_reverse.out
- *
- */
-template<typename Derived>
-inline typename DenseBase<Derived>::ReverseReturnType
-DenseBase<Derived>::reverse()
-{
- return derived();
-}
-
-/** This is the const version of reverse(). */
-template<typename Derived>
-inline const typename DenseBase<Derived>::ConstReverseReturnType
-DenseBase<Derived>::reverse() const
-{
- return derived();
-}
-
-/** This is the "in place" version of reverse: it reverses \c *this.
- *
- * In most cases it is probably better to simply use the reversed expression
- * of a matrix. However, when reversing the matrix data itself is really needed,
- * then this "in-place" version is probably the right choice because it provides
- * the following additional features:
- * - less error prone: doing the same operation with .reverse() requires special care:
- * \code m = m.reverse().eval(); \endcode
- * - this API allows to avoid creating a temporary (the current implementation creates a temporary, but that could be avoided using swap)
- * - it allows future optimizations (cache friendliness, etc.)
- *
- * \sa reverse() */
-template<typename Derived>
-inline void DenseBase<Derived>::reverseInPlace()
-{
- derived() = derived().reverse().eval();
-}
-
-
-#endif // EIGEN_REVERSE_H
diff --git a/extern/Eigen3/Eigen/src/Core/SelfAdjointView.h b/extern/Eigen3/Eigen/src/Core/SelfAdjointView.h
deleted file mode 100644
index 4bb68755eee..00000000000
--- a/extern/Eigen3/Eigen/src/Core/SelfAdjointView.h
+++ /dev/null
@@ -1,325 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SELFADJOINTMATRIX_H
-#define EIGEN_SELFADJOINTMATRIX_H
-
-/** \class SelfAdjointView
- * \ingroup Core_Module
- *
- *
- * \brief Expression of a selfadjoint matrix from a triangular part of a dense matrix
- *
- * \param MatrixType the type of the dense matrix storing the coefficients
- * \param TriangularPart can be either \c #Lower or \c #Upper
- *
- * This class is an expression of a sefladjoint matrix from a triangular part of a matrix
- * with given dense storage of the coefficients. It is the return type of MatrixBase::selfadjointView()
- * and most of the time this is the only way that it is used.
- *
- * \sa class TriangularBase, MatrixBase::selfadjointView()
- */
-
-namespace internal {
-template<typename MatrixType, unsigned int UpLo>
-struct traits<SelfAdjointView<MatrixType, UpLo> > : traits<MatrixType>
-{
- typedef typename nested<MatrixType>::type MatrixTypeNested;
- typedef typename remove_all<MatrixTypeNested>::type MatrixTypeNestedCleaned;
- typedef MatrixType ExpressionType;
- typedef typename MatrixType::PlainObject DenseMatrixType;
- enum {
- Mode = UpLo | SelfAdjoint,
- Flags = MatrixTypeNestedCleaned::Flags & (HereditaryBits)
- & (~(PacketAccessBit | DirectAccessBit | LinearAccessBit)), // FIXME these flags should be preserved
- CoeffReadCost = MatrixTypeNestedCleaned::CoeffReadCost
- };
-};
-}
-
-template <typename Lhs, int LhsMode, bool LhsIsVector,
- typename Rhs, int RhsMode, bool RhsIsVector>
-struct SelfadjointProductMatrix;
-
-// FIXME could also be called SelfAdjointWrapper to be consistent with DiagonalWrapper ??
-template<typename MatrixType, unsigned int UpLo> class SelfAdjointView
- : public TriangularBase<SelfAdjointView<MatrixType, UpLo> >
-{
- public:
-
- typedef TriangularBase<SelfAdjointView> Base;
- typedef typename internal::traits<SelfAdjointView>::MatrixTypeNested MatrixTypeNested;
- typedef typename internal::traits<SelfAdjointView>::MatrixTypeNestedCleaned MatrixTypeNestedCleaned;
-
- /** \brief The type of coefficients in this matrix */
- typedef typename internal::traits<SelfAdjointView>::Scalar Scalar;
-
- typedef typename MatrixType::Index Index;
-
- enum {
- Mode = internal::traits<SelfAdjointView>::Mode
- };
- typedef typename MatrixType::PlainObject PlainObject;
-
- inline SelfAdjointView(const MatrixType& matrix) : m_matrix(matrix)
- {}
-
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
- inline Index outerStride() const { return m_matrix.outerStride(); }
- inline Index innerStride() const { return m_matrix.innerStride(); }
-
- /** \sa MatrixBase::coeff()
- * \warning the coordinates must fit into the referenced triangular part
- */
- inline Scalar coeff(Index row, Index col) const
- {
- Base::check_coordinates_internal(row, col);
- return m_matrix.coeff(row, col);
- }
-
- /** \sa MatrixBase::coeffRef()
- * \warning the coordinates must fit into the referenced triangular part
- */
- inline Scalar& coeffRef(Index row, Index col)
- {
- Base::check_coordinates_internal(row, col);
- return m_matrix.const_cast_derived().coeffRef(row, col);
- }
-
- /** \internal */
- const MatrixTypeNestedCleaned& _expression() const { return m_matrix; }
-
- const MatrixTypeNestedCleaned& nestedExpression() const { return m_matrix; }
- MatrixTypeNestedCleaned& nestedExpression() { return *const_cast<MatrixTypeNestedCleaned*>(&m_matrix); }
-
- /** Efficient self-adjoint matrix times vector/matrix product */
- template<typename OtherDerived>
- SelfadjointProductMatrix<MatrixType,Mode,false,OtherDerived,0,OtherDerived::IsVectorAtCompileTime>
- operator*(const MatrixBase<OtherDerived>& rhs) const
- {
- return SelfadjointProductMatrix
- <MatrixType,Mode,false,OtherDerived,0,OtherDerived::IsVectorAtCompileTime>
- (m_matrix, rhs.derived());
- }
-
- /** Efficient vector/matrix times self-adjoint matrix product */
- template<typename OtherDerived> friend
- SelfadjointProductMatrix<OtherDerived,0,OtherDerived::IsVectorAtCompileTime,MatrixType,Mode,false>
- operator*(const MatrixBase<OtherDerived>& lhs, const SelfAdjointView& rhs)
- {
- return SelfadjointProductMatrix
- <OtherDerived,0,OtherDerived::IsVectorAtCompileTime,MatrixType,Mode,false>
- (lhs.derived(),rhs.m_matrix);
- }
-
- /** Perform a symmetric rank 2 update of the selfadjoint matrix \c *this:
- * \f$ this = this + \alpha u v^* + conj(\alpha) v u^* \f$
- * \returns a reference to \c *this
- *
- * The vectors \a u and \c v \b must be column vectors, however they can be
- * a adjoint expression without any overhead. Only the meaningful triangular
- * part of the matrix is updated, the rest is left unchanged.
- *
- * \sa rankUpdate(const MatrixBase<DerivedU>&, Scalar)
- */
- template<typename DerivedU, typename DerivedV>
- SelfAdjointView& rankUpdate(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, Scalar alpha = Scalar(1));
-
- /** Perform a symmetric rank K update of the selfadjoint matrix \c *this:
- * \f$ this = this + \alpha ( u u^* ) \f$ where \a u is a vector or matrix.
- *
- * \returns a reference to \c *this
- *
- * Note that to perform \f$ this = this + \alpha ( u^* u ) \f$ you can simply
- * call this function with u.adjoint().
- *
- * \sa rankUpdate(const MatrixBase<DerivedU>&, const MatrixBase<DerivedV>&, Scalar)
- */
- template<typename DerivedU>
- SelfAdjointView& rankUpdate(const MatrixBase<DerivedU>& u, Scalar alpha = Scalar(1));
-
-/////////// Cholesky module ///////////
-
- const LLT<PlainObject, UpLo> llt() const;
- const LDLT<PlainObject, UpLo> ldlt() const;
-
-/////////// Eigenvalue module ///////////
-
- /** Real part of #Scalar */
- typedef typename NumTraits<Scalar>::Real RealScalar;
- /** Return type of eigenvalues() */
- typedef Matrix<RealScalar, internal::traits<MatrixType>::ColsAtCompileTime, 1> EigenvaluesReturnType;
-
- EigenvaluesReturnType eigenvalues() const;
- RealScalar operatorNorm() const;
-
- #ifdef EIGEN2_SUPPORT
- template<typename OtherDerived>
- SelfAdjointView& operator=(const MatrixBase<OtherDerived>& other)
- {
- enum {
- OtherPart = UpLo == Upper ? StrictlyLower : StrictlyUpper
- };
- m_matrix.const_cast_derived().template triangularView<UpLo>() = other;
- m_matrix.const_cast_derived().template triangularView<OtherPart>() = other.adjoint();
- return *this;
- }
- template<typename OtherMatrixType, unsigned int OtherMode>
- SelfAdjointView& operator=(const TriangularView<OtherMatrixType, OtherMode>& other)
- {
- enum {
- OtherPart = UpLo == Upper ? StrictlyLower : StrictlyUpper
- };
- m_matrix.const_cast_derived().template triangularView<UpLo>() = other.toDenseMatrix();
- m_matrix.const_cast_derived().template triangularView<OtherPart>() = other.toDenseMatrix().adjoint();
- return *this;
- }
- #endif
-
- protected:
- const MatrixTypeNested m_matrix;
-};
-
-
-// template<typename OtherDerived, typename MatrixType, unsigned int UpLo>
-// internal::selfadjoint_matrix_product_returntype<OtherDerived,SelfAdjointView<MatrixType,UpLo> >
-// operator*(const MatrixBase<OtherDerived>& lhs, const SelfAdjointView<MatrixType,UpLo>& rhs)
-// {
-// return internal::matrix_selfadjoint_product_returntype<OtherDerived,SelfAdjointView<MatrixType,UpLo> >(lhs.derived(),rhs);
-// }
-
-// selfadjoint to dense matrix
-
-namespace internal {
-
-template<typename Derived1, typename Derived2, int UnrollCount, bool ClearOpposite>
-struct triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Upper), UnrollCount, ClearOpposite>
-{
- enum {
- col = (UnrollCount-1) / Derived1::RowsAtCompileTime,
- row = (UnrollCount-1) % Derived1::RowsAtCompileTime
- };
-
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Upper), UnrollCount-1, ClearOpposite>::run(dst, src);
-
- if(row == col)
- dst.coeffRef(row, col) = real(src.coeff(row, col));
- else if(row < col)
- dst.coeffRef(col, row) = conj(dst.coeffRef(row, col) = src.coeff(row, col));
- }
-};
-
-template<typename Derived1, typename Derived2, bool ClearOpposite>
-struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Upper, 0, ClearOpposite>
-{
- inline static void run(Derived1 &, const Derived2 &) {}
-};
-
-template<typename Derived1, typename Derived2, int UnrollCount, bool ClearOpposite>
-struct triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Lower), UnrollCount, ClearOpposite>
-{
- enum {
- col = (UnrollCount-1) / Derived1::RowsAtCompileTime,
- row = (UnrollCount-1) % Derived1::RowsAtCompileTime
- };
-
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- triangular_assignment_selector<Derived1, Derived2, (SelfAdjoint|Lower), UnrollCount-1, ClearOpposite>::run(dst, src);
-
- if(row == col)
- dst.coeffRef(row, col) = real(src.coeff(row, col));
- else if(row > col)
- dst.coeffRef(col, row) = conj(dst.coeffRef(row, col) = src.coeff(row, col));
- }
-};
-
-template<typename Derived1, typename Derived2, bool ClearOpposite>
-struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Lower, 0, ClearOpposite>
-{
- inline static void run(Derived1 &, const Derived2 &) {}
-};
-
-template<typename Derived1, typename Derived2, bool ClearOpposite>
-struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Upper, Dynamic, ClearOpposite>
-{
- typedef typename Derived1::Index Index;
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- for(Index j = 0; j < dst.cols(); ++j)
- {
- for(Index i = 0; i < j; ++i)
- {
- dst.copyCoeff(i, j, src);
- dst.coeffRef(j,i) = conj(dst.coeff(i,j));
- }
- dst.copyCoeff(j, j, src);
- }
- }
-};
-
-template<typename Derived1, typename Derived2, bool ClearOpposite>
-struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Lower, Dynamic, ClearOpposite>
-{
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- typedef typename Derived1::Index Index;
- for(Index i = 0; i < dst.rows(); ++i)
- {
- for(Index j = 0; j < i; ++j)
- {
- dst.copyCoeff(i, j, src);
- dst.coeffRef(j,i) = conj(dst.coeff(i,j));
- }
- dst.copyCoeff(i, i, src);
- }
- }
-};
-
-} // end namespace internal
-
-/***************************************************************************
-* Implementation of MatrixBase methods
-***************************************************************************/
-
-template<typename Derived>
-template<unsigned int UpLo>
-typename MatrixBase<Derived>::template ConstSelfAdjointViewReturnType<UpLo>::Type
-MatrixBase<Derived>::selfadjointView() const
-{
- return derived();
-}
-
-template<typename Derived>
-template<unsigned int UpLo>
-typename MatrixBase<Derived>::template SelfAdjointViewReturnType<UpLo>::Type
-MatrixBase<Derived>::selfadjointView()
-{
- return derived();
-}
-
-#endif // EIGEN_SELFADJOINTMATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h b/extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h
deleted file mode 100644
index 4e9ca88745d..00000000000
--- a/extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h
+++ /dev/null
@@ -1,195 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SELFCWISEBINARYOP_H
-#define EIGEN_SELFCWISEBINARYOP_H
-
-/** \class SelfCwiseBinaryOp
- * \ingroup Core_Module
- *
- * \internal
- *
- * \brief Internal helper class for optimizing operators like +=, -=
- *
- * This is a pseudo expression class re-implementing the copyCoeff/copyPacket
- * method to directly performs a +=/-= operations in an optimal way. In particular,
- * this allows to make sure that the input/output data are loaded only once using
- * aligned packet loads.
- *
- * \sa class SwapWrapper for a similar trick.
- */
-
-namespace internal {
-template<typename BinaryOp, typename Lhs, typename Rhs>
-struct traits<SelfCwiseBinaryOp<BinaryOp,Lhs,Rhs> >
- : traits<CwiseBinaryOp<BinaryOp,Lhs,Rhs> >
-{
- enum {
- // Note that it is still a good idea to preserve the DirectAccessBit
- // so that assign can correctly align the data.
- Flags = traits<CwiseBinaryOp<BinaryOp,Lhs,Rhs> >::Flags | (Lhs::Flags&DirectAccessBit) | (Lhs::Flags&LvalueBit),
- OuterStrideAtCompileTime = Lhs::OuterStrideAtCompileTime,
- InnerStrideAtCompileTime = Lhs::InnerStrideAtCompileTime
- };
-};
-}
-
-template<typename BinaryOp, typename Lhs, typename Rhs> class SelfCwiseBinaryOp
- : public internal::dense_xpr_base< SelfCwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type
-{
- public:
-
- typedef typename internal::dense_xpr_base<SelfCwiseBinaryOp>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(SelfCwiseBinaryOp)
-
- typedef typename internal::packet_traits<Scalar>::type Packet;
-
- inline SelfCwiseBinaryOp(Lhs& xpr, const BinaryOp& func = BinaryOp()) : m_matrix(xpr), m_functor(func) {}
-
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
- inline Index outerStride() const { return m_matrix.outerStride(); }
- inline Index innerStride() const { return m_matrix.innerStride(); }
- inline const Scalar* data() const { return m_matrix.data(); }
-
- // note that this function is needed by assign to correctly align loads/stores
- // TODO make Assign use .data()
- inline Scalar& coeffRef(Index row, Index col)
- {
- EIGEN_STATIC_ASSERT_LVALUE(Lhs)
- return m_matrix.const_cast_derived().coeffRef(row, col);
- }
- inline const Scalar& coeffRef(Index row, Index col) const
- {
- return m_matrix.coeffRef(row, col);
- }
-
- // note that this function is needed by assign to correctly align loads/stores
- // TODO make Assign use .data()
- inline Scalar& coeffRef(Index index)
- {
- EIGEN_STATIC_ASSERT_LVALUE(Lhs)
- return m_matrix.const_cast_derived().coeffRef(index);
- }
- inline const Scalar& coeffRef(Index index) const
- {
- return m_matrix.const_cast_derived().coeffRef(index);
- }
-
- template<typename OtherDerived>
- void copyCoeff(Index row, Index col, const DenseBase<OtherDerived>& other)
- {
- OtherDerived& _other = other.const_cast_derived();
- eigen_internal_assert(row >= 0 && row < rows()
- && col >= 0 && col < cols());
- Scalar& tmp = m_matrix.coeffRef(row,col);
- tmp = m_functor(tmp, _other.coeff(row,col));
- }
-
- template<typename OtherDerived>
- void copyCoeff(Index index, const DenseBase<OtherDerived>& other)
- {
- OtherDerived& _other = other.const_cast_derived();
- eigen_internal_assert(index >= 0 && index < m_matrix.size());
- Scalar& tmp = m_matrix.coeffRef(index);
- tmp = m_functor(tmp, _other.coeff(index));
- }
-
- template<typename OtherDerived, int StoreMode, int LoadMode>
- void copyPacket(Index row, Index col, const DenseBase<OtherDerived>& other)
- {
- OtherDerived& _other = other.const_cast_derived();
- eigen_internal_assert(row >= 0 && row < rows()
- && col >= 0 && col < cols());
- m_matrix.template writePacket<StoreMode>(row, col,
- m_functor.packetOp(m_matrix.template packet<StoreMode>(row, col),_other.template packet<LoadMode>(row, col)) );
- }
-
- template<typename OtherDerived, int StoreMode, int LoadMode>
- void copyPacket(Index index, const DenseBase<OtherDerived>& other)
- {
- OtherDerived& _other = other.const_cast_derived();
- eigen_internal_assert(index >= 0 && index < m_matrix.size());
- m_matrix.template writePacket<StoreMode>(index,
- m_functor.packetOp(m_matrix.template packet<StoreMode>(index),_other.template packet<LoadMode>(index)) );
- }
-
- // reimplement lazyAssign to handle complex *= real
- // see CwiseBinaryOp ctor for details
- template<typename RhsDerived>
- EIGEN_STRONG_INLINE SelfCwiseBinaryOp& lazyAssign(const DenseBase<RhsDerived>& rhs)
- {
- EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs,RhsDerived)
- EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename RhsDerived::Scalar);
-
- #ifdef EIGEN_DEBUG_ASSIGN
- internal::assign_traits<SelfCwiseBinaryOp, RhsDerived>::debug();
- #endif
- eigen_assert(rows() == rhs.rows() && cols() == rhs.cols());
- internal::assign_impl<SelfCwiseBinaryOp, RhsDerived>::run(*this,rhs.derived());
- #ifndef EIGEN_NO_DEBUG
- this->checkTransposeAliasing(rhs.derived());
- #endif
- return *this;
- }
-
- // overloaded to honor evaluation of special matrices
- // maybe another solution would be to not use SelfCwiseBinaryOp
- // at first...
- SelfCwiseBinaryOp& operator=(const Rhs& _rhs)
- {
- typename internal::nested<Rhs>::type rhs(_rhs);
- return Base::operator=(rhs);
- }
-
- protected:
- Lhs& m_matrix;
- const BinaryOp& m_functor;
-
- private:
- SelfCwiseBinaryOp& operator=(const SelfCwiseBinaryOp&);
-};
-
-template<typename Derived>
-inline Derived& DenseBase<Derived>::operator*=(const Scalar& other)
-{
- typedef typename Derived::PlainObject PlainObject;
- SelfCwiseBinaryOp<internal::scalar_product_op<Scalar>, Derived, typename PlainObject::ConstantReturnType> tmp(derived());
- tmp = PlainObject::Constant(rows(),cols(),other);
- return derived();
-}
-
-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());
- tmp = PlainObject::Constant(rows(),cols(), NumTraits<Scalar>::IsInteger ? other : Scalar(1)/other);
- return derived();
-}
-
-#endif // EIGEN_SELFCWISEBINARYOP_H
diff --git a/extern/Eigen3/Eigen/src/Core/SolveTriangular.h b/extern/Eigen3/Eigen/src/Core/SolveTriangular.h
deleted file mode 100644
index 71e129c7f12..00000000000
--- a/extern/Eigen3/Eigen/src/Core/SolveTriangular.h
+++ /dev/null
@@ -1,263 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SOLVETRIANGULAR_H
-#define EIGEN_SOLVETRIANGULAR_H
-
-namespace internal {
-
-// Forward declarations:
-// The following two routines are implemented in the products/TriangularSolver*.h files
-template<typename LhsScalar, typename RhsScalar, typename Index, int Side, int Mode, bool Conjugate, int StorageOrder>
-struct triangular_solve_vector;
-
-template <typename Scalar, typename Index, int Side, int Mode, bool Conjugate, int TriStorageOrder, int OtherStorageOrder>
-struct triangular_solve_matrix;
-
-// small helper struct extracting some traits on the underlying solver operation
-template<typename Lhs, typename Rhs, int Side>
-class trsolve_traits
-{
- private:
- enum {
- RhsIsVectorAtCompileTime = (Side==OnTheLeft ? Rhs::ColsAtCompileTime : Rhs::RowsAtCompileTime)==1
- };
- public:
- enum {
- Unrolling = (RhsIsVectorAtCompileTime && Rhs::SizeAtCompileTime != Dynamic && Rhs::SizeAtCompileTime <= 8)
- ? CompleteUnrolling : NoUnrolling,
- RhsVectors = RhsIsVectorAtCompileTime ? 1 : Dynamic
- };
-};
-
-template<typename Lhs, typename Rhs,
- int Side, // can be OnTheLeft/OnTheRight
- int Mode, // can be Upper/Lower | UnitDiag
- int Unrolling = trsolve_traits<Lhs,Rhs,Side>::Unrolling,
- int RhsVectors = trsolve_traits<Lhs,Rhs,Side>::RhsVectors
- >
-struct triangular_solver_selector;
-
-template<typename Lhs, typename Rhs, int Side, int Mode>
-struct triangular_solver_selector<Lhs,Rhs,Side,Mode,NoUnrolling,1>
-{
- typedef typename Lhs::Scalar LhsScalar;
- typedef typename Rhs::Scalar RhsScalar;
- typedef blas_traits<Lhs> LhsProductTraits;
- typedef typename LhsProductTraits::ExtractType ActualLhsType;
- typedef Map<Matrix<RhsScalar,Dynamic,1>, Aligned> MappedRhs;
- static void run(const Lhs& lhs, Rhs& rhs)
- {
- ActualLhsType actualLhs = LhsProductTraits::extract(lhs);
-
- // FIXME find a way to allow an inner stride if packet_traits<Scalar>::size==1
-
- bool useRhsDirectly = Rhs::InnerStrideAtCompileTime==1 || rhs.innerStride()==1;
-
- ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhs,rhs.size(),
- (useRhsDirectly ? rhs.data() : 0));
-
- if(!useRhsDirectly)
- MappedRhs(actualRhs,rhs.size()) = rhs;
-
- triangular_solve_vector<LhsScalar, RhsScalar, typename Lhs::Index, Side, Mode, LhsProductTraits::NeedToConjugate,
- (int(Lhs::Flags) & RowMajorBit) ? RowMajor : ColMajor>
- ::run(actualLhs.cols(), actualLhs.data(), actualLhs.outerStride(), actualRhs);
-
- if(!useRhsDirectly)
- rhs = MappedRhs(actualRhs, rhs.size());
- }
-};
-
-// the rhs is a matrix
-template<typename Lhs, typename Rhs, int Side, int Mode>
-struct triangular_solver_selector<Lhs,Rhs,Side,Mode,NoUnrolling,Dynamic>
-{
- typedef typename Rhs::Scalar Scalar;
- typedef typename Rhs::Index Index;
- typedef blas_traits<Lhs> LhsProductTraits;
- typedef typename LhsProductTraits::DirectLinearAccessType ActualLhsType;
- static void run(const Lhs& lhs, Rhs& rhs)
- {
- const ActualLhsType actualLhs = LhsProductTraits::extract(lhs);
- triangular_solve_matrix<Scalar,Index,Side,Mode,LhsProductTraits::NeedToConjugate,(int(Lhs::Flags) & RowMajorBit) ? RowMajor : ColMajor,
- (Rhs::Flags&RowMajorBit) ? RowMajor : ColMajor>
- ::run(lhs.rows(), Side==OnTheLeft? rhs.cols() : rhs.rows(), &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &rhs.coeffRef(0,0), rhs.outerStride());
- }
-};
-
-/***************************************************************************
-* meta-unrolling implementation
-***************************************************************************/
-
-template<typename Lhs, typename Rhs, int Mode, int Index, int Size,
- bool Stop = Index==Size>
-struct triangular_solver_unroller;
-
-template<typename Lhs, typename Rhs, int Mode, int Index, int Size>
-struct triangular_solver_unroller<Lhs,Rhs,Mode,Index,Size,false> {
- enum {
- IsLower = ((Mode&Lower)==Lower),
- I = IsLower ? Index : Size - Index - 1,
- S = IsLower ? 0 : I+1
- };
- static void run(const Lhs& lhs, Rhs& rhs)
- {
- if (Index>0)
- rhs.coeffRef(I) -= lhs.row(I).template segment<Index>(S).transpose()
- .cwiseProduct(rhs.template segment<Index>(S)).sum();
-
- if(!(Mode & UnitDiag))
- rhs.coeffRef(I) /= lhs.coeff(I,I);
-
- triangular_solver_unroller<Lhs,Rhs,Mode,Index+1,Size>::run(lhs,rhs);
- }
-};
-
-template<typename Lhs, typename Rhs, int Mode, int Index, int Size>
-struct triangular_solver_unroller<Lhs,Rhs,Mode,Index,Size,true> {
- static void run(const Lhs&, Rhs&) {}
-};
-
-template<typename Lhs, typename Rhs, int Mode>
-struct triangular_solver_selector<Lhs,Rhs,OnTheLeft,Mode,CompleteUnrolling,1> {
- static void run(const Lhs& lhs, Rhs& rhs)
- { triangular_solver_unroller<Lhs,Rhs,Mode,0,Rhs::SizeAtCompileTime>::run(lhs,rhs); }
-};
-
-template<typename Lhs, typename Rhs, int Mode>
-struct triangular_solver_selector<Lhs,Rhs,OnTheRight,Mode,CompleteUnrolling,1> {
- static void run(const Lhs& lhs, Rhs& rhs)
- {
- Transpose<const Lhs> trLhs(lhs);
- Transpose<Rhs> trRhs(rhs);
-
- triangular_solver_unroller<Transpose<const Lhs>,Transpose<Rhs>,
- ((Mode&Upper)==Upper ? Lower : Upper) | (Mode&UnitDiag),
- 0,Rhs::SizeAtCompileTime>::run(trLhs,trRhs);
- }
-};
-
-} // end namespace internal
-
-/***************************************************************************
-* TriangularView methods
-***************************************************************************/
-
-/** "in-place" version of TriangularView::solve() where the result is written in \a other
- *
- * \warning The parameter is only marked 'const' to make the C++ compiler accept a temporary expression here.
- * This function will const_cast it, so constness isn't honored here.
- *
- * See TriangularView:solve() for the details.
- */
-template<typename MatrixType, unsigned int Mode>
-template<int Side, typename OtherDerived>
-void TriangularView<MatrixType,Mode>::solveInPlace(const MatrixBase<OtherDerived>& _other) const
-{
- OtherDerived& other = _other.const_cast_derived();
- eigen_assert(cols() == rows());
- eigen_assert( (Side==OnTheLeft && cols() == other.rows()) || (Side==OnTheRight && cols() == other.cols()) );
- eigen_assert(!(Mode & ZeroDiag));
- eigen_assert(Mode & (Upper|Lower));
-
- enum { copy = internal::traits<OtherDerived>::Flags & RowMajorBit && OtherDerived::IsVectorAtCompileTime };
- typedef typename internal::conditional<copy,
- typename internal::plain_matrix_type_column_major<OtherDerived>::type, OtherDerived&>::type OtherCopy;
- OtherCopy otherCopy(other);
-
- internal::triangular_solver_selector<MatrixType, typename internal::remove_reference<OtherCopy>::type,
- Side, Mode>::run(nestedExpression(), otherCopy);
-
- if (copy)
- other = otherCopy;
-}
-
-/** \returns the product of the inverse of \c *this with \a other, \a *this being triangular.
- *
- * This function computes the inverse-matrix matrix product inverse(\c *this) * \a other if
- * \a Side==OnTheLeft (the default), or the right-inverse-multiply \a other * inverse(\c *this) if
- * \a Side==OnTheRight.
- *
- * The matrix \c *this must be triangular and invertible (i.e., all the coefficients of the
- * diagonal must be non zero). It works as a forward (resp. backward) substitution if \c *this
- * is an upper (resp. lower) triangular matrix.
- *
- * Example: \include MatrixBase_marked.cpp
- * Output: \verbinclude MatrixBase_marked.out
- *
- * This function returns an expression of the inverse-multiply and can works in-place if it is assigned
- * to the same matrix or vector \a other.
- *
- * For users coming from BLAS, this function (and more specifically solveInPlace()) offer
- * all the operations supported by the \c *TRSV and \c *TRSM BLAS routines.
- *
- * \sa TriangularView::solveInPlace()
- */
-template<typename Derived, unsigned int Mode>
-template<int Side, typename Other>
-const internal::triangular_solve_retval<Side,TriangularView<Derived,Mode>,Other>
-TriangularView<Derived,Mode>::solve(const MatrixBase<Other>& other) const
-{
- return internal::triangular_solve_retval<Side,TriangularView,Other>(*this, other.derived());
-}
-
-namespace internal {
-
-
-template<int Side, typename TriangularType, typename Rhs>
-struct traits<triangular_solve_retval<Side, TriangularType, Rhs> >
-{
- typedef typename internal::plain_matrix_type_column_major<Rhs>::type ReturnType;
-};
-
-template<int Side, typename TriangularType, typename Rhs> struct triangular_solve_retval
- : public ReturnByValue<triangular_solve_retval<Side, TriangularType, Rhs> >
-{
- typedef typename remove_all<typename Rhs::Nested>::type RhsNestedCleaned;
- typedef ReturnByValue<triangular_solve_retval> Base;
- typedef typename Base::Index Index;
-
- triangular_solve_retval(const TriangularType& tri, const Rhs& rhs)
- : m_triangularMatrix(tri), m_rhs(rhs)
- {}
-
- inline Index rows() const { return m_rhs.rows(); }
- inline Index cols() const { return m_rhs.cols(); }
-
- template<typename Dest> inline void evalTo(Dest& dst) const
- {
- if(!(is_same<RhsNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_rhs)))
- dst = m_rhs;
- m_triangularMatrix.template solveInPlace<Side>(dst);
- }
-
- protected:
- const TriangularType& m_triangularMatrix;
- const typename Rhs::Nested m_rhs;
-};
-
-} // namespace internal
-
-#endif // EIGEN_SOLVETRIANGULAR_H
diff --git a/extern/Eigen3/Eigen/src/Core/StableNorm.h b/extern/Eigen3/Eigen/src/Core/StableNorm.h
deleted file mode 100644
index f667272e4a4..00000000000
--- a/extern/Eigen3/Eigen/src/Core/StableNorm.h
+++ /dev/null
@@ -1,190 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_STABLENORM_H
-#define EIGEN_STABLENORM_H
-
-namespace internal {
-template<typename ExpressionType, typename Scalar>
-inline void stable_norm_kernel(const ExpressionType& bl, Scalar& ssq, Scalar& scale, Scalar& invScale)
-{
- Scalar max = bl.cwiseAbs().maxCoeff();
- if (max>scale)
- {
- ssq = ssq * abs2(scale/max);
- scale = max;
- invScale = Scalar(1)/scale;
- }
- // TODO if the max is much much smaller than the current scale,
- // then we can neglect this sub vector
- ssq += (bl*invScale).squaredNorm();
-}
-}
-
-/** \returns the \em l2 norm of \c *this avoiding underflow and overflow.
- * This version use a blockwise two passes algorithm:
- * 1 - find the absolute largest coefficient \c s
- * 2 - compute \f$ s \Vert \frac{*this}{s} \Vert \f$ in a standard way
- *
- * For architecture/scalar types supporting vectorization, this version
- * is faster than blueNorm(). Otherwise the blueNorm() is much faster.
- *
- * \sa norm(), blueNorm(), hypotNorm()
- */
-template<typename Derived>
-inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
-MatrixBase<Derived>::stableNorm() const
-{
- using std::min;
- const Index blockSize = 4096;
- RealScalar scale = 0;
- RealScalar invScale = 1;
- RealScalar ssq = 0; // sum of square
- enum {
- Alignment = (int(Flags)&DirectAccessBit) || (int(Flags)&AlignedBit) ? 1 : 0
- };
- Index n = size();
- Index bi = internal::first_aligned(derived());
- if (bi>0)
- internal::stable_norm_kernel(this->head(bi), ssq, scale, invScale);
- for (; bi<n; bi+=blockSize)
- internal::stable_norm_kernel(this->segment(bi,(min)(blockSize, n - bi)).template forceAlignedAccessIf<Alignment>(), ssq, scale, invScale);
- return scale * internal::sqrt(ssq);
-}
-
-/** \returns the \em l2 norm of \c *this using the Blue's algorithm.
- * A Portable Fortran Program to Find the Euclidean Norm of a Vector,
- * ACM TOMS, Vol 4, Issue 1, 1978.
- *
- * For architecture/scalar types without vectorization, this version
- * is much faster than stableNorm(). Otherwise the stableNorm() is faster.
- *
- * \sa norm(), stableNorm(), hypotNorm()
- */
-template<typename Derived>
-inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
-MatrixBase<Derived>::blueNorm() const
-{
- using std::pow;
- using std::min;
- using std::max;
- static Index nmax = -1;
- static RealScalar b1, b2, s1m, s2m, overfl, rbig, relerr;
- if(nmax <= 0)
- {
- int nbig, ibeta, it, iemin, iemax, iexp;
- RealScalar abig, eps;
- // This program calculates the machine-dependent constants
- // bl, b2, slm, s2m, relerr overfl, nmax
- // from the "basic" machine-dependent numbers
- // nbig, ibeta, it, iemin, iemax, rbig.
- // The following define the basic machine-dependent constants.
- // For portability, the PORT subprograms "ilmaeh" and "rlmach"
- // are used. For any specific computer, each of the assignment
- // statements can be replaced
- nbig = (std::numeric_limits<Index>::max)(); // largest integer
- ibeta = std::numeric_limits<RealScalar>::radix; // base for floating-point numbers
- it = std::numeric_limits<RealScalar>::digits; // number of base-beta digits in mantissa
- iemin = std::numeric_limits<RealScalar>::min_exponent; // minimum exponent
- iemax = std::numeric_limits<RealScalar>::max_exponent; // maximum exponent
- rbig = (std::numeric_limits<RealScalar>::max)(); // largest floating-point number
-
- iexp = -((1-iemin)/2);
- b1 = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // lower boundary of midrange
- iexp = (iemax + 1 - it)/2;
- b2 = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // upper boundary of midrange
-
- iexp = (2-iemin)/2;
- s1m = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for lower range
- iexp = - ((iemax+it)/2);
- s2m = RealScalar(pow(RealScalar(ibeta),RealScalar(iexp))); // scaling factor for upper range
-
- overfl = rbig*s2m; // overflow boundary for abig
- eps = RealScalar(pow(double(ibeta), 1-it));
- relerr = internal::sqrt(eps); // tolerance for neglecting asml
- abig = RealScalar(1.0/eps - 1.0);
- if (RealScalar(nbig)>abig) nmax = int(abig); // largest safe n
- else nmax = nbig;
- }
- Index n = size();
- RealScalar ab2 = b2 / RealScalar(n);
- RealScalar asml = RealScalar(0);
- RealScalar amed = RealScalar(0);
- RealScalar abig = RealScalar(0);
- for(Index j=0; j<n; ++j)
- {
- RealScalar ax = internal::abs(coeff(j));
- if(ax > ab2) abig += internal::abs2(ax*s2m);
- else if(ax < b1) asml += internal::abs2(ax*s1m);
- else amed += internal::abs2(ax);
- }
- if(abig > RealScalar(0))
- {
- abig = internal::sqrt(abig);
- if(abig > overfl)
- {
- eigen_assert(false && "overflow");
- return rbig;
- }
- if(amed > RealScalar(0))
- {
- abig = abig/s2m;
- amed = internal::sqrt(amed);
- }
- else
- return abig/s2m;
- }
- else if(asml > RealScalar(0))
- {
- if (amed > RealScalar(0))
- {
- abig = internal::sqrt(amed);
- amed = internal::sqrt(asml) / s1m;
- }
- else
- return internal::sqrt(asml)/s1m;
- }
- else
- return internal::sqrt(amed);
- asml = (min)(abig, amed);
- abig = (max)(abig, amed);
- if(asml <= abig*relerr)
- return abig;
- else
- return abig * internal::sqrt(RealScalar(1) + internal::abs2(asml/abig));
-}
-
-/** \returns the \em l2 norm of \c *this avoiding undeflow and overflow.
- * This version use a concatenation of hypot() calls, and it is very slow.
- *
- * \sa norm(), stableNorm()
- */
-template<typename Derived>
-inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
-MatrixBase<Derived>::hypotNorm() const
-{
- return this->cwiseAbs().redux(internal::scalar_hypot_op<RealScalar>());
-}
-
-#endif // EIGEN_STABLENORM_H
diff --git a/extern/Eigen3/Eigen/src/Core/Stride.h b/extern/Eigen3/Eigen/src/Core/Stride.h
deleted file mode 100644
index 0430f111627..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Stride.h
+++ /dev/null
@@ -1,119 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_STRIDE_H
-#define EIGEN_STRIDE_H
-
-/** \class Stride
- * \ingroup Core_Module
- *
- * \brief Holds strides information for Map
- *
- * This class holds the strides information for mapping arrays with strides with class Map.
- *
- * It holds two values: the inner stride and the outer stride.
- *
- * The inner stride is the pointer increment between two consecutive entries within a given row of a
- * row-major matrix or within a given column of a column-major matrix.
- *
- * The outer stride is the pointer increment between two consecutive rows of a row-major matrix or
- * between two consecutive columns of a column-major matrix.
- *
- * These two values can be passed either at compile-time as template parameters, or at runtime as
- * arguments to the constructor.
- *
- * Indeed, this class takes two template parameters:
- * \param _OuterStrideAtCompileTime the outer stride, or Dynamic if you want to specify it at runtime.
- * \param _InnerStrideAtCompileTime the inner stride, or Dynamic if you want to specify it at runtime.
- *
- * Here is an example:
- * \include Map_general_stride.cpp
- * Output: \verbinclude Map_general_stride.out
- *
- * \sa class InnerStride, class OuterStride, \ref TopicStorageOrders
- */
-template<int _OuterStrideAtCompileTime, int _InnerStrideAtCompileTime>
-class Stride
-{
- public:
- typedef DenseIndex Index;
- enum {
- InnerStrideAtCompileTime = _InnerStrideAtCompileTime,
- OuterStrideAtCompileTime = _OuterStrideAtCompileTime
- };
-
- /** Default constructor, for use when strides are fixed at compile time */
- Stride()
- : m_outer(OuterStrideAtCompileTime), m_inner(InnerStrideAtCompileTime)
- {
- eigen_assert(InnerStrideAtCompileTime != Dynamic && OuterStrideAtCompileTime != Dynamic);
- }
-
- /** Constructor allowing to pass the strides at runtime */
- Stride(Index outerStride, Index innerStride)
- : m_outer(outerStride), m_inner(innerStride)
- {
- eigen_assert(innerStride>=0 && outerStride>=0);
- }
-
- /** Copy constructor */
- Stride(const Stride& other)
- : m_outer(other.outer()), m_inner(other.inner())
- {}
-
- /** \returns the outer stride */
- inline Index outer() const { return m_outer.value(); }
- /** \returns the inner stride */
- inline Index inner() const { return m_inner.value(); }
-
- protected:
- internal::variable_if_dynamic<Index, OuterStrideAtCompileTime> m_outer;
- internal::variable_if_dynamic<Index, InnerStrideAtCompileTime> m_inner;
-};
-
-/** \brief Convenience specialization of Stride to specify only an inner stride
- * See class Map for some examples */
-template<int Value = Dynamic>
-class InnerStride : public Stride<0, Value>
-{
- typedef Stride<0, Value> Base;
- public:
- typedef DenseIndex Index;
- InnerStride() : Base() {}
- InnerStride(Index v) : Base(0, v) {}
-};
-
-/** \brief Convenience specialization of Stride to specify only an outer stride
- * See class Map for some examples */
-template<int Value = Dynamic>
-class OuterStride : public Stride<Value, 0>
-{
- typedef Stride<Value, 0> Base;
- public:
- typedef DenseIndex Index;
- OuterStride() : Base() {}
- OuterStride(Index v) : Base(v,0) {}
-};
-
-#endif // EIGEN_STRIDE_H
diff --git a/extern/Eigen3/Eigen/src/Core/Transpose.h b/extern/Eigen3/Eigen/src/Core/Transpose.h
deleted file mode 100644
index 3f7c7df6ee1..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Transpose.h
+++ /dev/null
@@ -1,425 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_TRANSPOSE_H
-#define EIGEN_TRANSPOSE_H
-
-/** \class Transpose
- * \ingroup Core_Module
- *
- * \brief Expression of the transpose of a matrix
- *
- * \param MatrixType the type of the object of which we are taking the transpose
- *
- * This class represents an expression of the transpose of a matrix.
- * It is the return type of MatrixBase::transpose() and MatrixBase::adjoint()
- * and most of the time this is the only way it is used.
- *
- * \sa MatrixBase::transpose(), MatrixBase::adjoint()
- */
-
-namespace internal {
-template<typename MatrixType>
-struct traits<Transpose<MatrixType> > : traits<MatrixType>
-{
- typedef typename MatrixType::Scalar Scalar;
- typedef typename nested<MatrixType>::type MatrixTypeNested;
- typedef typename remove_reference<MatrixTypeNested>::type MatrixTypeNestedPlain;
- typedef typename traits<MatrixType>::StorageKind StorageKind;
- typedef typename traits<MatrixType>::XprKind XprKind;
- enum {
- RowsAtCompileTime = MatrixType::ColsAtCompileTime,
- ColsAtCompileTime = MatrixType::RowsAtCompileTime,
- MaxRowsAtCompileTime = MatrixType::MaxColsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- FlagsLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
- Flags0 = MatrixTypeNestedPlain::Flags & ~(LvalueBit | NestByRefBit),
- Flags1 = Flags0 | FlagsLvalueBit,
- Flags = Flags1 ^ RowMajorBit,
- CoeffReadCost = MatrixTypeNestedPlain::CoeffReadCost,
- InnerStrideAtCompileTime = inner_stride_at_compile_time<MatrixType>::ret,
- OuterStrideAtCompileTime = outer_stride_at_compile_time<MatrixType>::ret
- };
-};
-}
-
-template<typename MatrixType, typename StorageKind> class TransposeImpl;
-
-template<typename MatrixType> class Transpose
- : public TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>
-{
- public:
-
- typedef typename TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base;
- EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose)
-
- inline Transpose(MatrixType& matrix) : m_matrix(matrix) {}
-
- EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Transpose)
-
- inline Index rows() const { return m_matrix.cols(); }
- inline Index cols() const { return m_matrix.rows(); }
-
- /** \returns the nested expression */
- const typename internal::remove_all<typename MatrixType::Nested>::type&
- nestedExpression() const { return m_matrix; }
-
- /** \returns the nested expression */
- typename internal::remove_all<typename MatrixType::Nested>::type&
- nestedExpression() { return m_matrix.const_cast_derived(); }
-
- protected:
- const typename MatrixType::Nested m_matrix;
-};
-
-namespace internal {
-
-template<typename MatrixType, bool HasDirectAccess = has_direct_access<MatrixType>::ret>
-struct TransposeImpl_base
-{
- typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
-};
-
-template<typename MatrixType>
-struct TransposeImpl_base<MatrixType, false>
-{
- typedef typename dense_xpr_base<Transpose<MatrixType> >::type type;
-};
-
-} // end namespace internal
-
-template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
- : public internal::TransposeImpl_base<MatrixType>::type
-{
- public:
-
- typedef typename internal::TransposeImpl_base<MatrixType>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>)
-
- inline Index innerStride() const { return derived().nestedExpression().innerStride(); }
- inline Index outerStride() const { return derived().nestedExpression().outerStride(); }
-
- typedef typename internal::conditional<
- internal::is_lvalue<MatrixType>::value,
- Scalar,
- const Scalar
- >::type ScalarWithConstIfNotLvalue;
-
- inline ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); }
- inline const Scalar* data() const { return derived().nestedExpression().data(); }
-
- inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col)
- {
- EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
- return derived().nestedExpression().const_cast_derived().coeffRef(col, row);
- }
-
- inline ScalarWithConstIfNotLvalue& coeffRef(Index index)
- {
- EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
- return derived().nestedExpression().const_cast_derived().coeffRef(index);
- }
-
- inline const Scalar& coeffRef(Index row, Index col) const
- {
- return derived().nestedExpression().coeffRef(col, row);
- }
-
- inline const Scalar& coeffRef(Index index) const
- {
- return derived().nestedExpression().coeffRef(index);
- }
-
- inline const CoeffReturnType coeff(Index row, Index col) const
- {
- return derived().nestedExpression().coeff(col, row);
- }
-
- inline const CoeffReturnType coeff(Index index) const
- {
- return derived().nestedExpression().coeff(index);
- }
-
- template<int LoadMode>
- inline const PacketScalar packet(Index row, Index col) const
- {
- return derived().nestedExpression().template packet<LoadMode>(col, row);
- }
-
- template<int LoadMode>
- inline void writePacket(Index row, Index col, const PacketScalar& x)
- {
- derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(col, row, x);
- }
-
- template<int LoadMode>
- inline const PacketScalar packet(Index index) const
- {
- return derived().nestedExpression().template packet<LoadMode>(index);
- }
-
- template<int LoadMode>
- inline void writePacket(Index index, const PacketScalar& x)
- {
- derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(index, x);
- }
-};
-
-/** \returns an expression of the transpose of *this.
- *
- * Example: \include MatrixBase_transpose.cpp
- * Output: \verbinclude MatrixBase_transpose.out
- *
- * \warning If you want to replace a matrix by its own transpose, do \b NOT do this:
- * \code
- * m = m.transpose(); // bug!!! caused by aliasing effect
- * \endcode
- * Instead, use the transposeInPlace() method:
- * \code
- * m.transposeInPlace();
- * \endcode
- * which gives Eigen good opportunities for optimization, or alternatively you can also do:
- * \code
- * m = m.transpose().eval();
- * \endcode
- *
- * \sa transposeInPlace(), adjoint() */
-template<typename Derived>
-inline Transpose<Derived>
-DenseBase<Derived>::transpose()
-{
- return derived();
-}
-
-/** This is the const version of transpose().
- *
- * Make sure you read the warning for transpose() !
- *
- * \sa transposeInPlace(), adjoint() */
-template<typename Derived>
-inline const typename DenseBase<Derived>::ConstTransposeReturnType
-DenseBase<Derived>::transpose() const
-{
- return ConstTransposeReturnType(derived());
-}
-
-/** \returns an expression of the adjoint (i.e. conjugate transpose) of *this.
- *
- * Example: \include MatrixBase_adjoint.cpp
- * Output: \verbinclude MatrixBase_adjoint.out
- *
- * \warning If you want to replace a matrix by its own adjoint, do \b NOT do this:
- * \code
- * m = m.adjoint(); // bug!!! caused by aliasing effect
- * \endcode
- * Instead, use the adjointInPlace() method:
- * \code
- * m.adjointInPlace();
- * \endcode
- * which gives Eigen good opportunities for optimization, or alternatively you can also do:
- * \code
- * m = m.adjoint().eval();
- * \endcode
- *
- * \sa adjointInPlace(), transpose(), conjugate(), class Transpose, class internal::scalar_conjugate_op */
-template<typename Derived>
-inline const typename MatrixBase<Derived>::AdjointReturnType
-MatrixBase<Derived>::adjoint() const
-{
- return this->transpose(); // in the complex case, the .conjugate() is be implicit here
- // due to implicit conversion to return type
-}
-
-/***************************************************************************
-* "in place" transpose implementation
-***************************************************************************/
-
-namespace internal {
-
-template<typename MatrixType,
- bool IsSquare = (MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime) && MatrixType::RowsAtCompileTime!=Dynamic>
-struct inplace_transpose_selector;
-
-template<typename MatrixType>
-struct inplace_transpose_selector<MatrixType,true> { // square matrix
- static void run(MatrixType& m) {
- m.template triangularView<StrictlyUpper>().swap(m.transpose());
- }
-};
-
-template<typename MatrixType>
-struct inplace_transpose_selector<MatrixType,false> { // non square matrix
- static void run(MatrixType& m) {
- if (m.rows()==m.cols())
- m.template triangularView<StrictlyUpper>().swap(m.transpose());
- else
- m = m.transpose().eval();
- }
-};
-
-} // end namespace internal
-
-/** This is the "in place" version of transpose(): it replaces \c *this by its own transpose.
- * Thus, doing
- * \code
- * m.transposeInPlace();
- * \endcode
- * has the same effect on m as doing
- * \code
- * m = m.transpose().eval();
- * \endcode
- * and is faster and also safer because in the latter line of code, forgetting the eval() results
- * in a bug caused by aliasing.
- *
- * Notice however that this method is only useful if you want to replace a matrix by its own transpose.
- * If you just need the transpose of a matrix, use transpose().
- *
- * \note if the matrix is not square, then \c *this must be a resizable matrix.
- *
- * \sa transpose(), adjoint(), adjointInPlace() */
-template<typename Derived>
-inline void DenseBase<Derived>::transposeInPlace()
-{
- internal::inplace_transpose_selector<Derived>::run(derived());
-}
-
-/***************************************************************************
-* "in place" adjoint implementation
-***************************************************************************/
-
-/** This is the "in place" version of adjoint(): it replaces \c *this by its own transpose.
- * Thus, doing
- * \code
- * m.adjointInPlace();
- * \endcode
- * has the same effect on m as doing
- * \code
- * m = m.adjoint().eval();
- * \endcode
- * and is faster and also safer because in the latter line of code, forgetting the eval() results
- * in a bug caused by aliasing.
- *
- * Notice however that this method is only useful if you want to replace a matrix by its own adjoint.
- * If you just need the adjoint of a matrix, use adjoint().
- *
- * \note if the matrix is not square, then \c *this must be a resizable matrix.
- *
- * \sa transpose(), adjoint(), transposeInPlace() */
-template<typename Derived>
-inline void MatrixBase<Derived>::adjointInPlace()
-{
- derived() = adjoint().eval();
-}
-
-#ifndef EIGEN_NO_DEBUG
-
-// The following is to detect aliasing problems in most common cases.
-
-namespace internal {
-
-template<typename BinOp,typename NestedXpr,typename Rhs>
-struct blas_traits<SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> >
- : blas_traits<NestedXpr>
-{
- typedef SelfCwiseBinaryOp<BinOp,NestedXpr,Rhs> XprType;
- static inline const XprType extract(const XprType& x) { return x; }
-};
-
-template<bool DestIsTransposed, typename OtherDerived>
-struct check_transpose_aliasing_compile_time_selector
-{
- enum { ret = bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed };
-};
-
-template<bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
-struct check_transpose_aliasing_compile_time_selector<DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
-{
- enum { ret = bool(blas_traits<DerivedA>::IsTransposed) != DestIsTransposed
- || bool(blas_traits<DerivedB>::IsTransposed) != DestIsTransposed
- };
-};
-
-template<typename Scalar, bool DestIsTransposed, typename OtherDerived>
-struct check_transpose_aliasing_run_time_selector
-{
- static bool run(const Scalar* dest, const OtherDerived& src)
- {
- return (bool(blas_traits<OtherDerived>::IsTransposed) != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src));
- }
-};
-
-template<typename Scalar, bool DestIsTransposed, typename BinOp, typename DerivedA, typename DerivedB>
-struct check_transpose_aliasing_run_time_selector<Scalar,DestIsTransposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
-{
- static bool run(const Scalar* dest, const CwiseBinaryOp<BinOp,DerivedA,DerivedB>& src)
- {
- return ((blas_traits<DerivedA>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src.lhs())))
- || ((blas_traits<DerivedB>::IsTransposed != DestIsTransposed) && (dest!=0 && dest==(Scalar*)extract_data(src.rhs())));
- }
-};
-
-// the following selector, checkTransposeAliasing_impl, based on MightHaveTransposeAliasing,
-// is because when the condition controlling the assert is known at compile time, ICC emits a warning.
-// This is actually a good warning: in expressions that don't have any transposing, the condition is
-// known at compile time to be false, and using that, we can avoid generating the code of the assert again
-// and again for all these expressions that don't need it.
-
-template<typename Derived, typename OtherDerived,
- bool MightHaveTransposeAliasing
- = check_transpose_aliasing_compile_time_selector
- <blas_traits<Derived>::IsTransposed,OtherDerived>::ret
- >
-struct checkTransposeAliasing_impl
-{
- static void run(const Derived& dst, const OtherDerived& other)
- {
- eigen_assert((!check_transpose_aliasing_run_time_selector
- <typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived>
- ::run(extract_data(dst), other))
- && "aliasing detected during tranposition, use transposeInPlace() "
- "or evaluate the rhs into a temporary using .eval()");
-
- }
-};
-
-template<typename Derived, typename OtherDerived>
-struct checkTransposeAliasing_impl<Derived, OtherDerived, false>
-{
- static void run(const Derived&, const OtherDerived&)
- {
- }
-};
-
-} // end namespace internal
-
-template<typename Derived>
-template<typename OtherDerived>
-void DenseBase<Derived>::checkTransposeAliasing(const OtherDerived& other) const
-{
- internal::checkTransposeAliasing_impl<Derived, OtherDerived>::run(derived(), other);
-}
-#endif
-
-#endif // EIGEN_TRANSPOSE_H
diff --git a/extern/Eigen3/Eigen/src/Core/Transpositions.h b/extern/Eigen3/Eigen/src/Core/Transpositions.h
deleted file mode 100644
index 88fdfb2226f..00000000000
--- a/extern/Eigen3/Eigen/src/Core/Transpositions.h
+++ /dev/null
@@ -1,447 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_TRANSPOSITIONS_H
-#define EIGEN_TRANSPOSITIONS_H
-
-/** \class Transpositions
- * \ingroup Core_Module
- *
- * \brief Represents a sequence of transpositions (row/column interchange)
- *
- * \param SizeAtCompileTime the number of transpositions, or Dynamic
- * \param MaxSizeAtCompileTime the maximum number of transpositions, or Dynamic. This optional parameter defaults to SizeAtCompileTime. Most of the time, you should not have to specify it.
- *
- * This class represents a permutation transformation as a sequence of \em n transpositions
- * \f$[T_{n-1} \ldots T_{i} \ldots T_{0}]\f$. It is internally stored as a vector of integers \c indices.
- * Each transposition \f$ T_{i} \f$ applied on the left of a matrix (\f$ T_{i} M\f$) interchanges
- * the rows \c i and \c indices[i] of the matrix \c M.
- * A transposition applied on the right (e.g., \f$ M T_{i}\f$) yields a column interchange.
- *
- * Compared to the class PermutationMatrix, such a sequence of transpositions is what is
- * computed during a decomposition with pivoting, and it is faster when applying the permutation in-place.
- *
- * To apply a sequence of transpositions to a matrix, simply use the operator * as in the following example:
- * \code
- * Transpositions tr;
- * MatrixXf mat;
- * mat = tr * mat;
- * \endcode
- * In this example, we detect that the matrix appears on both side, and so the transpositions
- * are applied in-place without any temporary or extra copy.
- *
- * \sa class PermutationMatrix
- */
-
-namespace internal {
-template<typename TranspositionType, typename MatrixType, int Side, bool Transposed=false> struct transposition_matrix_product_retval;
-}
-
-template<typename Derived>
-class TranspositionsBase
-{
- typedef internal::traits<Derived> Traits;
-
- public:
-
- typedef typename Traits::IndicesType IndicesType;
- typedef typename IndicesType::Scalar Index;
-
- Derived& derived() { return *static_cast<Derived*>(this); }
- const Derived& derived() const { return *static_cast<const Derived*>(this); }
-
- /** Copies the \a other transpositions into \c *this */
- template<typename OtherDerived>
- Derived& operator=(const TranspositionsBase<OtherDerived>& other)
- {
- indices() = other.indices();
- return derived();
- }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- /** This is a special case of the templated operator=. Its purpose is to
- * prevent a default operator= from hiding the templated operator=.
- */
- Derived& operator=(const TranspositionsBase& other)
- {
- indices() = other.indices();
- return derived();
- }
- #endif
-
- /** \returns the number of transpositions */
- inline Index size() const { return indices().size(); }
-
- /** Direct access to the underlying index vector */
- inline const Index& coeff(Index i) const { return indices().coeff(i); }
- /** Direct access to the underlying index vector */
- inline Index& coeffRef(Index i) { return indices().coeffRef(i); }
- /** Direct access to the underlying index vector */
- inline const Index& operator()(Index i) const { return indices()(i); }
- /** Direct access to the underlying index vector */
- inline Index& operator()(Index i) { return indices()(i); }
- /** Direct access to the underlying index vector */
- inline const Index& operator[](Index i) const { return indices()(i); }
- /** Direct access to the underlying index vector */
- inline Index& operator[](Index i) { return indices()(i); }
-
- /** const version of indices(). */
- const IndicesType& indices() const { return derived().indices(); }
- /** \returns a reference to the stored array representing the transpositions. */
- IndicesType& indices() { return derived().indices(); }
-
- /** Resizes to given size. */
- inline void resize(int size)
- {
- indices().resize(size);
- }
-
- /** Sets \c *this to represents an identity transformation */
- void setIdentity()
- {
- for(int i = 0; i < indices().size(); ++i)
- coeffRef(i) = i;
- }
-
- // FIXME: do we want such methods ?
- // might be usefull when the target matrix expression is complex, e.g.:
- // object.matrix().block(..,..,..,..) = trans * object.matrix().block(..,..,..,..);
- /*
- template<typename MatrixType>
- void applyForwardToRows(MatrixType& mat) const
- {
- for(Index k=0 ; k<size() ; ++k)
- if(m_indices(k)!=k)
- mat.row(k).swap(mat.row(m_indices(k)));
- }
-
- template<typename MatrixType>
- void applyBackwardToRows(MatrixType& mat) const
- {
- for(Index k=size()-1 ; k>=0 ; --k)
- if(m_indices(k)!=k)
- mat.row(k).swap(mat.row(m_indices(k)));
- }
- */
-
- /** \returns the inverse transformation */
- inline Transpose<TranspositionsBase> inverse() const
- { return Transpose<TranspositionsBase>(derived()); }
-
- /** \returns the tranpose transformation */
- inline Transpose<TranspositionsBase> transpose() const
- { return Transpose<TranspositionsBase>(derived()); }
-
- protected:
-};
-
-namespace internal {
-template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType>
-struct traits<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType> >
-{
- typedef IndexType Index;
- typedef Matrix<Index, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1> IndicesType;
-};
-}
-
-template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType>
-class Transpositions : public TranspositionsBase<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType> >
-{
- typedef internal::traits<Transpositions> Traits;
- public:
-
- typedef TranspositionsBase<Transpositions> Base;
- typedef typename Traits::IndicesType IndicesType;
- typedef typename IndicesType::Scalar Index;
-
- inline Transpositions() {}
-
- /** Copy constructor. */
- template<typename OtherDerived>
- inline Transpositions(const TranspositionsBase<OtherDerived>& other)
- : m_indices(other.indices()) {}
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- /** Standard copy constructor. Defined only to prevent a default copy constructor
- * from hiding the other templated constructor */
- inline Transpositions(const Transpositions& other) : m_indices(other.indices()) {}
- #endif
-
- /** Generic constructor from expression of the transposition indices. */
- template<typename Other>
- explicit inline Transpositions(const MatrixBase<Other>& indices) : m_indices(indices)
- {}
-
- /** Copies the \a other transpositions into \c *this */
- template<typename OtherDerived>
- Transpositions& operator=(const TranspositionsBase<OtherDerived>& other)
- {
- return Base::operator=(other);
- }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- /** This is a special case of the templated operator=. Its purpose is to
- * prevent a default operator= from hiding the templated operator=.
- */
- Transpositions& operator=(const Transpositions& other)
- {
- m_indices = other.m_indices;
- return *this;
- }
- #endif
-
- /** Constructs an uninitialized permutation matrix of given size.
- */
- inline Transpositions(Index size) : m_indices(size)
- {}
-
- /** const version of indices(). */
- const IndicesType& indices() const { return m_indices; }
- /** \returns a reference to the stored array representing the transpositions. */
- IndicesType& indices() { return m_indices; }
-
- protected:
-
- IndicesType m_indices;
-};
-
-
-namespace internal {
-template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int _PacketAccess>
-struct traits<Map<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType>,_PacketAccess> >
-{
- typedef IndexType Index;
- typedef Map<const Matrix<Index,SizeAtCompileTime,1,0,MaxSizeAtCompileTime,1>, _PacketAccess> IndicesType;
-};
-}
-
-template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int PacketAccess>
-class Map<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType>,PacketAccess>
- : public TranspositionsBase<Map<Transpositions<SizeAtCompileTime,MaxSizeAtCompileTime,IndexType>,PacketAccess> >
-{
- typedef internal::traits<Map> Traits;
- public:
-
- typedef TranspositionsBase<Map> Base;
- typedef typename Traits::IndicesType IndicesType;
- typedef typename IndicesType::Scalar Index;
-
- inline Map(const Index* indices)
- : m_indices(indices)
- {}
-
- inline Map(const Index* indices, Index size)
- : m_indices(indices,size)
- {}
-
- /** Copies the \a other transpositions into \c *this */
- template<typename OtherDerived>
- Map& operator=(const TranspositionsBase<OtherDerived>& other)
- {
- return Base::operator=(other);
- }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- /** This is a special case of the templated operator=. Its purpose is to
- * prevent a default operator= from hiding the templated operator=.
- */
- Map& operator=(const Map& other)
- {
- m_indices = other.m_indices;
- return *this;
- }
- #endif
-
- /** const version of indices(). */
- const IndicesType& indices() const { return m_indices; }
-
- /** \returns a reference to the stored array representing the transpositions. */
- IndicesType& indices() { return m_indices; }
-
- protected:
-
- IndicesType m_indices;
-};
-
-namespace internal {
-template<typename _IndicesType>
-struct traits<TranspositionsWrapper<_IndicesType> >
-{
- typedef typename _IndicesType::Scalar Index;
- typedef _IndicesType IndicesType;
-};
-}
-
-template<typename _IndicesType>
-class TranspositionsWrapper
- : public TranspositionsBase<TranspositionsWrapper<_IndicesType> >
-{
- typedef internal::traits<TranspositionsWrapper> Traits;
- public:
-
- typedef TranspositionsBase<TranspositionsWrapper> Base;
- typedef typename Traits::IndicesType IndicesType;
- typedef typename IndicesType::Scalar Index;
-
- inline TranspositionsWrapper(IndicesType& indices)
- : m_indices(indices)
- {}
-
- /** Copies the \a other transpositions into \c *this */
- template<typename OtherDerived>
- TranspositionsWrapper& operator=(const TranspositionsBase<OtherDerived>& other)
- {
- return Base::operator=(other);
- }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- /** This is a special case of the templated operator=. Its purpose is to
- * prevent a default operator= from hiding the templated operator=.
- */
- TranspositionsWrapper& operator=(const TranspositionsWrapper& other)
- {
- m_indices = other.m_indices;
- return *this;
- }
- #endif
-
- /** const version of indices(). */
- const IndicesType& indices() const { return m_indices; }
-
- /** \returns a reference to the stored array representing the transpositions. */
- IndicesType& indices() { return m_indices; }
-
- protected:
-
- const typename IndicesType::Nested m_indices;
-};
-
-/** \returns the \a matrix with the \a transpositions applied to the columns.
- */
-template<typename Derived, typename TranspositionsDerived>
-inline const internal::transposition_matrix_product_retval<TranspositionsDerived, Derived, OnTheRight>
-operator*(const MatrixBase<Derived>& matrix,
- const TranspositionsBase<TranspositionsDerived> &transpositions)
-{
- return internal::transposition_matrix_product_retval
- <TranspositionsDerived, Derived, OnTheRight>
- (transpositions.derived(), matrix.derived());
-}
-
-/** \returns the \a matrix with the \a transpositions applied to the rows.
- */
-template<typename Derived, typename TranspositionDerived>
-inline const internal::transposition_matrix_product_retval
- <TranspositionDerived, Derived, OnTheLeft>
-operator*(const TranspositionsBase<TranspositionDerived> &transpositions,
- const MatrixBase<Derived>& matrix)
-{
- return internal::transposition_matrix_product_retval
- <TranspositionDerived, Derived, OnTheLeft>
- (transpositions.derived(), matrix.derived());
-}
-
-namespace internal {
-
-template<typename TranspositionType, typename MatrixType, int Side, bool Transposed>
-struct traits<transposition_matrix_product_retval<TranspositionType, MatrixType, Side, Transposed> >
-{
- typedef typename MatrixType::PlainObject ReturnType;
-};
-
-template<typename TranspositionType, typename MatrixType, int Side, bool Transposed>
-struct transposition_matrix_product_retval
- : public ReturnByValue<transposition_matrix_product_retval<TranspositionType, MatrixType, Side, Transposed> >
-{
- typedef typename remove_all<typename MatrixType::Nested>::type MatrixTypeNestedCleaned;
- typedef typename TranspositionType::Index Index;
-
- transposition_matrix_product_retval(const TranspositionType& tr, const MatrixType& matrix)
- : m_transpositions(tr), m_matrix(matrix)
- {}
-
- inline int rows() const { return m_matrix.rows(); }
- inline int cols() const { return m_matrix.cols(); }
-
- template<typename Dest> inline void evalTo(Dest& dst) const
- {
- const int size = m_transpositions.size();
- Index j = 0;
-
- if(!(is_same<MatrixTypeNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_matrix)))
- dst = m_matrix;
-
- for(int k=(Transposed?size-1:0) ; Transposed?k>=0:k<size ; Transposed?--k:++k)
- if((j=m_transpositions.coeff(k))!=k)
- {
- if(Side==OnTheLeft)
- dst.row(k).swap(dst.row(j));
- else if(Side==OnTheRight)
- dst.col(k).swap(dst.col(j));
- }
- }
-
- protected:
- const TranspositionType& m_transpositions;
- const typename MatrixType::Nested m_matrix;
-};
-
-} // end namespace internal
-
-/* Template partial specialization for transposed/inverse transpositions */
-
-template<typename TranspositionsDerived>
-class Transpose<TranspositionsBase<TranspositionsDerived> >
-{
- typedef TranspositionsDerived TranspositionType;
- typedef typename TranspositionType::IndicesType IndicesType;
- public:
-
- Transpose(const TranspositionType& t) : m_transpositions(t) {}
-
- inline int size() const { return m_transpositions.size(); }
-
- /** \returns the \a matrix with the inverse transpositions applied to the columns.
- */
- template<typename Derived> friend
- inline const internal::transposition_matrix_product_retval<TranspositionType, Derived, OnTheRight, true>
- operator*(const MatrixBase<Derived>& matrix, const Transpose& trt)
- {
- return internal::transposition_matrix_product_retval<TranspositionType, Derived, OnTheRight, true>(trt.m_transpositions, matrix.derived());
- }
-
- /** \returns the \a matrix with the inverse transpositions applied to the rows.
- */
- template<typename Derived>
- inline const internal::transposition_matrix_product_retval<TranspositionType, Derived, OnTheLeft, true>
- operator*(const MatrixBase<Derived>& matrix) const
- {
- return internal::transposition_matrix_product_retval<TranspositionType, Derived, OnTheLeft, true>(m_transpositions, matrix.derived());
- }
-
- protected:
- const TranspositionType& m_transpositions;
-};
-
-#endif // EIGEN_TRANSPOSITIONS_H
diff --git a/extern/Eigen3/Eigen/src/Core/TriangularMatrix.h b/extern/Eigen3/Eigen/src/Core/TriangularMatrix.h
deleted file mode 100644
index 033e81036f3..00000000000
--- a/extern/Eigen3/Eigen/src/Core/TriangularMatrix.h
+++ /dev/null
@@ -1,838 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_TRIANGULARMATRIX_H
-#define EIGEN_TRIANGULARMATRIX_H
-
-namespace internal {
-
-template<int Side, typename TriangularType, typename Rhs> struct triangular_solve_retval;
-
-}
-
-/** \internal
- *
- * \class TriangularBase
- * \ingroup Core_Module
- *
- * \brief Base class for triangular part in a matrix
- */
-template<typename Derived> class TriangularBase : public EigenBase<Derived>
-{
- public:
-
- enum {
- Mode = internal::traits<Derived>::Mode,
- CoeffReadCost = internal::traits<Derived>::CoeffReadCost,
- RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
- ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
- MaxRowsAtCompileTime = internal::traits<Derived>::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = internal::traits<Derived>::MaxColsAtCompileTime
- };
- typedef typename internal::traits<Derived>::Scalar Scalar;
- typedef typename internal::traits<Derived>::StorageKind StorageKind;
- typedef typename internal::traits<Derived>::Index Index;
- typedef typename internal::traits<Derived>::DenseMatrixType DenseMatrixType;
- typedef DenseMatrixType DenseType;
-
- inline TriangularBase() { eigen_assert(!((Mode&UnitDiag) && (Mode&ZeroDiag))); }
-
- inline Index rows() const { return derived().rows(); }
- inline Index cols() const { return derived().cols(); }
- inline Index outerStride() const { return derived().outerStride(); }
- inline Index innerStride() const { return derived().innerStride(); }
-
- inline Scalar coeff(Index row, Index col) const { return derived().coeff(row,col); }
- inline Scalar& coeffRef(Index row, Index col) { return derived().coeffRef(row,col); }
-
- /** \see MatrixBase::copyCoeff(row,col)
- */
- template<typename Other>
- EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, Other& other)
- {
- derived().coeffRef(row, col) = other.coeff(row, col);
- }
-
- inline Scalar operator()(Index row, Index col) const
- {
- check_coordinates(row, col);
- return coeff(row,col);
- }
- inline Scalar& operator()(Index row, Index col)
- {
- check_coordinates(row, col);
- return coeffRef(row,col);
- }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
- inline Derived& derived() { return *static_cast<Derived*>(this); }
- #endif // not EIGEN_PARSED_BY_DOXYGEN
-
- template<typename DenseDerived>
- void evalTo(MatrixBase<DenseDerived> &other) const;
- template<typename DenseDerived>
- void evalToLazy(MatrixBase<DenseDerived> &other) const;
-
- DenseMatrixType toDenseMatrix() const
- {
- DenseMatrixType res(rows(), cols());
- evalToLazy(res);
- return res;
- }
-
- protected:
-
- void check_coordinates(Index row, Index col) const
- {
- EIGEN_ONLY_USED_FOR_DEBUG(row);
- EIGEN_ONLY_USED_FOR_DEBUG(col);
- eigen_assert(col>=0 && col<cols() && row>=0 && row<rows());
- const int mode = int(Mode) & ~SelfAdjoint;
- EIGEN_ONLY_USED_FOR_DEBUG(mode);
- eigen_assert((mode==Upper && col>=row)
- || (mode==Lower && col<=row)
- || ((mode==StrictlyUpper || mode==UnitUpper) && col>row)
- || ((mode==StrictlyLower || mode==UnitLower) && col<row));
- }
-
- #ifdef EIGEN_INTERNAL_DEBUGGING
- void check_coordinates_internal(Index row, Index col) const
- {
- check_coordinates(row, col);
- }
- #else
- void check_coordinates_internal(Index , Index ) const {}
- #endif
-
-};
-
-/** \class TriangularView
- * \ingroup Core_Module
- *
- * \brief Base class for triangular part in a matrix
- *
- * \param MatrixType the type of the object in which we are taking the triangular part
- * \param Mode the kind of triangular matrix expression to construct. Can be #Upper,
- * #Lower, #UnitUpper, #UnitLower, #StrictlyUpper, or #StrictlyLower.
- * This is in fact a bit field; it must have either #Upper or #Lower,
- * and additionnaly it may have #UnitDiag or #ZeroDiag or neither.
- *
- * This class represents a triangular part of a matrix, not necessarily square. Strictly speaking, for rectangular
- * matrices one should speak of "trapezoid" parts. This class is the return type
- * of MatrixBase::triangularView() and most of the time this is the only way it is used.
- *
- * \sa MatrixBase::triangularView()
- */
-namespace internal {
-template<typename MatrixType, unsigned int _Mode>
-struct traits<TriangularView<MatrixType, _Mode> > : traits<MatrixType>
-{
- typedef typename nested<MatrixType>::type MatrixTypeNested;
- typedef typename remove_reference<MatrixTypeNested>::type MatrixTypeNestedNonRef;
- typedef typename remove_all<MatrixTypeNested>::type MatrixTypeNestedCleaned;
- typedef MatrixType ExpressionType;
- typedef typename MatrixType::PlainObject DenseMatrixType;
- enum {
- Mode = _Mode,
- Flags = (MatrixTypeNestedCleaned::Flags & (HereditaryBits) & (~(PacketAccessBit | DirectAccessBit | LinearAccessBit))) | Mode,
- CoeffReadCost = MatrixTypeNestedCleaned::CoeffReadCost
- };
-};
-}
-
-template<int Mode, bool LhsIsTriangular,
- typename Lhs, bool LhsIsVector,
- typename Rhs, bool RhsIsVector>
-struct TriangularProduct;
-
-template<typename _MatrixType, unsigned int _Mode> class TriangularView
- : public TriangularBase<TriangularView<_MatrixType, _Mode> >
-{
- public:
-
- typedef TriangularBase<TriangularView> Base;
- typedef typename internal::traits<TriangularView>::Scalar Scalar;
-
- typedef _MatrixType MatrixType;
- typedef typename internal::traits<TriangularView>::DenseMatrixType DenseMatrixType;
- typedef DenseMatrixType PlainObject;
-
- protected:
- typedef typename internal::traits<TriangularView>::MatrixTypeNested MatrixTypeNested;
- typedef typename internal::traits<TriangularView>::MatrixTypeNestedNonRef MatrixTypeNestedNonRef;
- typedef typename internal::traits<TriangularView>::MatrixTypeNestedCleaned MatrixTypeNestedCleaned;
-
- typedef typename internal::remove_all<typename MatrixType::ConjugateReturnType>::type MatrixConjugateReturnType;
-
- public:
- using Base::evalToLazy;
-
-
- typedef typename internal::traits<TriangularView>::StorageKind StorageKind;
- typedef typename internal::traits<TriangularView>::Index Index;
-
- enum {
- Mode = _Mode,
- TransposeMode = (Mode & Upper ? Lower : 0)
- | (Mode & Lower ? Upper : 0)
- | (Mode & (UnitDiag))
- | (Mode & (ZeroDiag))
- };
-
- inline TriangularView(const MatrixType& matrix) : m_matrix(matrix)
- {}
-
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
- inline Index outerStride() const { return m_matrix.outerStride(); }
- inline Index innerStride() const { return m_matrix.innerStride(); }
-
- /** \sa MatrixBase::operator+=() */
- template<typename Other> TriangularView& operator+=(const DenseBase<Other>& other) { return *this = m_matrix + other.derived(); }
- /** \sa MatrixBase::operator-=() */
- template<typename Other> TriangularView& operator-=(const DenseBase<Other>& other) { return *this = m_matrix - other.derived(); }
- /** \sa MatrixBase::operator*=() */
- TriangularView& operator*=(const typename internal::traits<MatrixType>::Scalar& other) { return *this = m_matrix * other; }
- /** \sa MatrixBase::operator/=() */
- TriangularView& operator/=(const typename internal::traits<MatrixType>::Scalar& other) { return *this = m_matrix / other; }
-
- /** \sa MatrixBase::fill() */
- void fill(const Scalar& value) { setConstant(value); }
- /** \sa MatrixBase::setConstant() */
- TriangularView& setConstant(const Scalar& value)
- { return *this = MatrixType::Constant(rows(), cols(), value); }
- /** \sa MatrixBase::setZero() */
- TriangularView& setZero() { return setConstant(Scalar(0)); }
- /** \sa MatrixBase::setOnes() */
- TriangularView& setOnes() { return setConstant(Scalar(1)); }
-
- /** \sa MatrixBase::coeff()
- * \warning the coordinates must fit into the referenced triangular part
- */
- inline Scalar coeff(Index row, Index col) const
- {
- Base::check_coordinates_internal(row, col);
- return m_matrix.coeff(row, col);
- }
-
- /** \sa MatrixBase::coeffRef()
- * \warning the coordinates must fit into the referenced triangular part
- */
- inline Scalar& coeffRef(Index row, Index col)
- {
- Base::check_coordinates_internal(row, col);
- return m_matrix.const_cast_derived().coeffRef(row, col);
- }
-
- const MatrixTypeNestedCleaned& nestedExpression() const { return m_matrix; }
- MatrixTypeNestedCleaned& nestedExpression() { return *const_cast<MatrixTypeNestedCleaned*>(&m_matrix); }
-
- /** Assigns a triangular matrix to a triangular part of a dense matrix */
- template<typename OtherDerived>
- TriangularView& operator=(const TriangularBase<OtherDerived>& other);
-
- template<typename OtherDerived>
- TriangularView& operator=(const MatrixBase<OtherDerived>& other);
-
- TriangularView& operator=(const TriangularView& other)
- { return *this = other.nestedExpression(); }
-
- template<typename OtherDerived>
- void lazyAssign(const TriangularBase<OtherDerived>& other);
-
- template<typename OtherDerived>
- void lazyAssign(const MatrixBase<OtherDerived>& other);
-
- /** \sa MatrixBase::conjugate() */
- inline TriangularView<MatrixConjugateReturnType,Mode> conjugate()
- { return m_matrix.conjugate(); }
- /** \sa MatrixBase::conjugate() const */
- inline const TriangularView<MatrixConjugateReturnType,Mode> conjugate() const
- { return m_matrix.conjugate(); }
-
- /** \sa MatrixBase::adjoint() */
- inline TriangularView<typename MatrixType::AdjointReturnType,TransposeMode> adjoint()
- { return m_matrix.adjoint(); }
- /** \sa MatrixBase::adjoint() const */
- inline const TriangularView<typename MatrixType::AdjointReturnType,TransposeMode> adjoint() const
- { return m_matrix.adjoint(); }
-
- /** \sa MatrixBase::transpose() */
- inline TriangularView<Transpose<MatrixType>,TransposeMode> transpose()
- {
- EIGEN_STATIC_ASSERT_LVALUE(MatrixType)
- return m_matrix.const_cast_derived().transpose();
- }
- /** \sa MatrixBase::transpose() const */
- inline const TriangularView<Transpose<MatrixType>,TransposeMode> transpose() const
- { return m_matrix.transpose(); }
-
- /** Efficient triangular matrix times vector/matrix product */
- template<typename OtherDerived>
- TriangularProduct<Mode,true,MatrixType,false,OtherDerived,OtherDerived::IsVectorAtCompileTime>
- operator*(const MatrixBase<OtherDerived>& rhs) const
- {
- return TriangularProduct
- <Mode,true,MatrixType,false,OtherDerived,OtherDerived::IsVectorAtCompileTime>
- (m_matrix, rhs.derived());
- }
-
- /** Efficient vector/matrix times triangular matrix product */
- template<typename OtherDerived> friend
- TriangularProduct<Mode,false,OtherDerived,OtherDerived::IsVectorAtCompileTime,MatrixType,false>
- operator*(const MatrixBase<OtherDerived>& lhs, const TriangularView& rhs)
- {
- return TriangularProduct
- <Mode,false,OtherDerived,OtherDerived::IsVectorAtCompileTime,MatrixType,false>
- (lhs.derived(),rhs.m_matrix);
- }
-
- #ifdef EIGEN2_SUPPORT
- template<typename OtherDerived>
- struct eigen2_product_return_type
- {
- typedef typename TriangularView<MatrixType,Mode>::DenseMatrixType DenseMatrixType;
- typedef typename OtherDerived::PlainObject::DenseType OtherPlainObject;
- typedef typename ProductReturnType<DenseMatrixType, OtherPlainObject>::Type ProdRetType;
- typedef typename ProdRetType::PlainObject type;
- };
- template<typename OtherDerived>
- const typename eigen2_product_return_type<OtherDerived>::type
- operator*(const EigenBase<OtherDerived>& rhs) const
- {
- typename OtherDerived::PlainObject::DenseType rhsPlainObject;
- rhs.evalTo(rhsPlainObject);
- return this->toDenseMatrix() * rhsPlainObject;
- }
- template<typename OtherMatrixType>
- bool isApprox(const TriangularView<OtherMatrixType, Mode>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
- {
- return this->toDenseMatrix().isApprox(other.toDenseMatrix(), precision);
- }
- template<typename OtherDerived>
- bool isApprox(const MatrixBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const
- {
- return this->toDenseMatrix().isApprox(other, precision);
- }
- #endif // EIGEN2_SUPPORT
-
- template<int Side, typename Other>
- inline const internal::triangular_solve_retval<Side,TriangularView, Other>
- solve(const MatrixBase<Other>& other) const;
-
- template<int Side, typename OtherDerived>
- void solveInPlace(const MatrixBase<OtherDerived>& other) const;
-
- template<typename Other>
- inline const internal::triangular_solve_retval<OnTheLeft,TriangularView, Other>
- solve(const MatrixBase<Other>& other) const
- { return solve<OnTheLeft>(other); }
-
- template<typename OtherDerived>
- void solveInPlace(const MatrixBase<OtherDerived>& other) const
- { return solveInPlace<OnTheLeft>(other); }
-
- const SelfAdjointView<MatrixTypeNestedNonRef,Mode> selfadjointView() const
- {
- EIGEN_STATIC_ASSERT((Mode&UnitDiag)==0,PROGRAMMING_ERROR);
- return SelfAdjointView<MatrixTypeNestedNonRef,Mode>(m_matrix);
- }
- SelfAdjointView<MatrixTypeNestedNonRef,Mode> selfadjointView()
- {
- EIGEN_STATIC_ASSERT((Mode&UnitDiag)==0,PROGRAMMING_ERROR);
- return SelfAdjointView<MatrixTypeNestedNonRef,Mode>(m_matrix);
- }
-
- template<typename OtherDerived>
- void swap(TriangularBase<OtherDerived> const & other)
- {
- TriangularView<SwapWrapper<MatrixType>,Mode>(const_cast<MatrixType&>(m_matrix)).lazyAssign(other.derived());
- }
-
- template<typename OtherDerived>
- void swap(MatrixBase<OtherDerived> const & other)
- {
- TriangularView<SwapWrapper<MatrixType>,Mode>(const_cast<MatrixType&>(m_matrix)).lazyAssign(other.derived());
- }
-
- Scalar determinant() const
- {
- if (Mode & UnitDiag)
- return 1;
- else if (Mode & ZeroDiag)
- return 0;
- else
- return m_matrix.diagonal().prod();
- }
-
- // TODO simplify the following:
- template<typename ProductDerived, typename Lhs, typename Rhs>
- EIGEN_STRONG_INLINE TriangularView& operator=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
- {
- setZero();
- return assignProduct(other,1);
- }
-
- template<typename ProductDerived, typename Lhs, typename Rhs>
- EIGEN_STRONG_INLINE TriangularView& operator+=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
- {
- return assignProduct(other,1);
- }
-
- template<typename ProductDerived, typename Lhs, typename Rhs>
- EIGEN_STRONG_INLINE TriangularView& operator-=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
- {
- return assignProduct(other,-1);
- }
-
-
- template<typename ProductDerived>
- EIGEN_STRONG_INLINE TriangularView& operator=(const ScaledProduct<ProductDerived>& other)
- {
- setZero();
- return assignProduct(other,other.alpha());
- }
-
- template<typename ProductDerived>
- EIGEN_STRONG_INLINE TriangularView& operator+=(const ScaledProduct<ProductDerived>& other)
- {
- return assignProduct(other,other.alpha());
- }
-
- template<typename ProductDerived>
- EIGEN_STRONG_INLINE TriangularView& operator-=(const ScaledProduct<ProductDerived>& other)
- {
- return assignProduct(other,-other.alpha());
- }
-
- protected:
-
- template<typename ProductDerived, typename Lhs, typename Rhs>
- EIGEN_STRONG_INLINE TriangularView& assignProduct(const ProductBase<ProductDerived, Lhs,Rhs>& prod, const Scalar& alpha);
-
- const MatrixTypeNested m_matrix;
-};
-
-/***************************************************************************
-* Implementation of triangular evaluation/assignment
-***************************************************************************/
-
-namespace internal {
-
-template<typename Derived1, typename Derived2, unsigned int Mode, int UnrollCount, bool ClearOpposite>
-struct triangular_assignment_selector
-{
- enum {
- col = (UnrollCount-1) / Derived1::RowsAtCompileTime,
- row = (UnrollCount-1) % Derived1::RowsAtCompileTime
- };
-
- typedef typename Derived1::Scalar Scalar;
-
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- triangular_assignment_selector<Derived1, Derived2, Mode, UnrollCount-1, ClearOpposite>::run(dst, src);
-
- eigen_assert( Mode == Upper || Mode == Lower
- || Mode == StrictlyUpper || Mode == StrictlyLower
- || Mode == UnitUpper || Mode == UnitLower);
- if((Mode == Upper && row <= col)
- || (Mode == Lower && row >= col)
- || (Mode == StrictlyUpper && row < col)
- || (Mode == StrictlyLower && row > col)
- || (Mode == UnitUpper && row < col)
- || (Mode == UnitLower && row > col))
- dst.copyCoeff(row, col, src);
- else if(ClearOpposite)
- {
- if (Mode&UnitDiag && row==col)
- dst.coeffRef(row, col) = Scalar(1);
- else
- dst.coeffRef(row, col) = Scalar(0);
- }
- }
-};
-
-// prevent buggy user code from causing an infinite recursion
-template<typename Derived1, typename Derived2, unsigned int Mode, bool ClearOpposite>
-struct triangular_assignment_selector<Derived1, Derived2, Mode, 0, ClearOpposite>
-{
- inline static void run(Derived1 &, const Derived2 &) {}
-};
-
-template<typename Derived1, typename Derived2, bool ClearOpposite>
-struct triangular_assignment_selector<Derived1, Derived2, Upper, Dynamic, ClearOpposite>
-{
- typedef typename Derived1::Index Index;
- typedef typename Derived1::Scalar Scalar;
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- for(Index j = 0; j < dst.cols(); ++j)
- {
- Index maxi = (std::min)(j, dst.rows()-1);
- for(Index i = 0; i <= maxi; ++i)
- dst.copyCoeff(i, j, src);
- if (ClearOpposite)
- for(Index i = maxi+1; i < dst.rows(); ++i)
- dst.coeffRef(i, j) = Scalar(0);
- }
- }
-};
-
-template<typename Derived1, typename Derived2, bool ClearOpposite>
-struct triangular_assignment_selector<Derived1, Derived2, Lower, Dynamic, ClearOpposite>
-{
- typedef typename Derived1::Index Index;
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- for(Index j = 0; j < dst.cols(); ++j)
- {
- for(Index i = j; i < dst.rows(); ++i)
- dst.copyCoeff(i, j, src);
- Index maxi = (std::min)(j, dst.rows());
- if (ClearOpposite)
- for(Index i = 0; i < maxi; ++i)
- dst.coeffRef(i, j) = static_cast<typename Derived1::Scalar>(0);
- }
- }
-};
-
-template<typename Derived1, typename Derived2, bool ClearOpposite>
-struct triangular_assignment_selector<Derived1, Derived2, StrictlyUpper, Dynamic, ClearOpposite>
-{
- typedef typename Derived1::Index Index;
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- for(Index j = 0; j < dst.cols(); ++j)
- {
- Index maxi = (std::min)(j, dst.rows());
- for(Index i = 0; i < maxi; ++i)
- dst.copyCoeff(i, j, src);
- if (ClearOpposite)
- for(Index i = maxi; i < dst.rows(); ++i)
- dst.coeffRef(i, j) = 0;
- }
- }
-};
-
-template<typename Derived1, typename Derived2, bool ClearOpposite>
-struct triangular_assignment_selector<Derived1, Derived2, StrictlyLower, Dynamic, ClearOpposite>
-{
- typedef typename Derived1::Index Index;
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- for(Index j = 0; j < dst.cols(); ++j)
- {
- for(Index i = j+1; i < dst.rows(); ++i)
- dst.copyCoeff(i, j, src);
- Index maxi = (std::min)(j, dst.rows()-1);
- if (ClearOpposite)
- for(Index i = 0; i <= maxi; ++i)
- dst.coeffRef(i, j) = static_cast<typename Derived1::Scalar>(0);
- }
- }
-};
-
-template<typename Derived1, typename Derived2, bool ClearOpposite>
-struct triangular_assignment_selector<Derived1, Derived2, UnitUpper, Dynamic, ClearOpposite>
-{
- typedef typename Derived1::Index Index;
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- for(Index j = 0; j < dst.cols(); ++j)
- {
- Index maxi = (std::min)(j, dst.rows());
- for(Index i = 0; i < maxi; ++i)
- dst.copyCoeff(i, j, src);
- if (ClearOpposite)
- {
- for(Index i = maxi+1; i < dst.rows(); ++i)
- dst.coeffRef(i, j) = 0;
- }
- }
- dst.diagonal().setOnes();
- }
-};
-template<typename Derived1, typename Derived2, bool ClearOpposite>
-struct triangular_assignment_selector<Derived1, Derived2, UnitLower, Dynamic, ClearOpposite>
-{
- typedef typename Derived1::Index Index;
- inline static void run(Derived1 &dst, const Derived2 &src)
- {
- for(Index j = 0; j < dst.cols(); ++j)
- {
- Index maxi = (std::min)(j, dst.rows());
- for(Index i = maxi+1; i < dst.rows(); ++i)
- dst.copyCoeff(i, j, src);
- if (ClearOpposite)
- {
- for(Index i = 0; i < maxi; ++i)
- dst.coeffRef(i, j) = 0;
- }
- }
- dst.diagonal().setOnes();
- }
-};
-
-} // end namespace internal
-
-// FIXME should we keep that possibility
-template<typename MatrixType, unsigned int Mode>
-template<typename OtherDerived>
-inline TriangularView<MatrixType, Mode>&
-TriangularView<MatrixType, Mode>::operator=(const MatrixBase<OtherDerived>& other)
-{
- if(OtherDerived::Flags & EvalBeforeAssigningBit)
- {
- typename internal::plain_matrix_type<OtherDerived>::type other_evaluated(other.rows(), other.cols());
- other_evaluated.template triangularView<Mode>().lazyAssign(other.derived());
- lazyAssign(other_evaluated);
- }
- else
- lazyAssign(other.derived());
- return *this;
-}
-
-// FIXME should we keep that possibility
-template<typename MatrixType, unsigned int Mode>
-template<typename OtherDerived>
-void TriangularView<MatrixType, Mode>::lazyAssign(const MatrixBase<OtherDerived>& other)
-{
- enum {
- unroll = MatrixType::SizeAtCompileTime != Dynamic
- && internal::traits<OtherDerived>::CoeffReadCost != Dynamic
- && MatrixType::SizeAtCompileTime*internal::traits<OtherDerived>::CoeffReadCost/2 <= EIGEN_UNROLLING_LIMIT
- };
- eigen_assert(m_matrix.rows() == other.rows() && m_matrix.cols() == other.cols());
-
- internal::triangular_assignment_selector
- <MatrixType, OtherDerived, int(Mode),
- unroll ? int(MatrixType::SizeAtCompileTime) : Dynamic,
- false // do not change the opposite triangular part
- >::run(m_matrix.const_cast_derived(), other.derived());
-}
-
-
-
-template<typename MatrixType, unsigned int Mode>
-template<typename OtherDerived>
-inline TriangularView<MatrixType, Mode>&
-TriangularView<MatrixType, Mode>::operator=(const TriangularBase<OtherDerived>& other)
-{
- eigen_assert(Mode == int(OtherDerived::Mode));
- if(internal::traits<OtherDerived>::Flags & EvalBeforeAssigningBit)
- {
- typename OtherDerived::DenseMatrixType other_evaluated(other.rows(), other.cols());
- other_evaluated.template triangularView<Mode>().lazyAssign(other.derived().nestedExpression());
- lazyAssign(other_evaluated);
- }
- else
- lazyAssign(other.derived().nestedExpression());
- return *this;
-}
-
-template<typename MatrixType, unsigned int Mode>
-template<typename OtherDerived>
-void TriangularView<MatrixType, Mode>::lazyAssign(const TriangularBase<OtherDerived>& other)
-{
- enum {
- unroll = MatrixType::SizeAtCompileTime != Dynamic
- && internal::traits<OtherDerived>::CoeffReadCost != Dynamic
- && MatrixType::SizeAtCompileTime * internal::traits<OtherDerived>::CoeffReadCost / 2
- <= EIGEN_UNROLLING_LIMIT
- };
- eigen_assert(m_matrix.rows() == other.rows() && m_matrix.cols() == other.cols());
-
- internal::triangular_assignment_selector
- <MatrixType, OtherDerived, int(Mode),
- unroll ? int(MatrixType::SizeAtCompileTime) : Dynamic,
- false // preserve the opposite triangular part
- >::run(m_matrix.const_cast_derived(), other.derived().nestedExpression());
-}
-
-/***************************************************************************
-* Implementation of TriangularBase methods
-***************************************************************************/
-
-/** Assigns a triangular or selfadjoint matrix to a dense matrix.
- * If the matrix is triangular, the opposite part is set to zero. */
-template<typename Derived>
-template<typename DenseDerived>
-void TriangularBase<Derived>::evalTo(MatrixBase<DenseDerived> &other) const
-{
- if(internal::traits<Derived>::Flags & EvalBeforeAssigningBit)
- {
- typename internal::plain_matrix_type<Derived>::type other_evaluated(rows(), cols());
- evalToLazy(other_evaluated);
- other.derived().swap(other_evaluated);
- }
- else
- evalToLazy(other.derived());
-}
-
-/** Assigns a triangular or selfadjoint matrix to a dense matrix.
- * If the matrix is triangular, the opposite part is set to zero. */
-template<typename Derived>
-template<typename DenseDerived>
-void TriangularBase<Derived>::evalToLazy(MatrixBase<DenseDerived> &other) const
-{
- enum {
- unroll = DenseDerived::SizeAtCompileTime != Dynamic
- && internal::traits<Derived>::CoeffReadCost != Dynamic
- && DenseDerived::SizeAtCompileTime * internal::traits<Derived>::CoeffReadCost / 2
- <= EIGEN_UNROLLING_LIMIT
- };
- other.derived().resize(this->rows(), this->cols());
-
- internal::triangular_assignment_selector
- <DenseDerived, typename internal::traits<Derived>::MatrixTypeNestedCleaned, Derived::Mode,
- unroll ? int(DenseDerived::SizeAtCompileTime) : Dynamic,
- true // clear the opposite triangular part
- >::run(other.derived(), derived().nestedExpression());
-}
-
-/***************************************************************************
-* Implementation of TriangularView methods
-***************************************************************************/
-
-/***************************************************************************
-* Implementation of MatrixBase methods
-***************************************************************************/
-
-#ifdef EIGEN2_SUPPORT
-
-// implementation of part<>(), including the SelfAdjoint case.
-
-namespace internal {
-template<typename MatrixType, unsigned int Mode>
-struct eigen2_part_return_type
-{
- typedef TriangularView<MatrixType, Mode> type;
-};
-
-template<typename MatrixType>
-struct eigen2_part_return_type<MatrixType, SelfAdjoint>
-{
- typedef SelfAdjointView<MatrixType, Upper> type;
-};
-}
-
-/** \deprecated use MatrixBase::triangularView() */
-template<typename Derived>
-template<unsigned int Mode>
-const typename internal::eigen2_part_return_type<Derived, Mode>::type MatrixBase<Derived>::part() const
-{
- return derived();
-}
-
-/** \deprecated use MatrixBase::triangularView() */
-template<typename Derived>
-template<unsigned int Mode>
-typename internal::eigen2_part_return_type<Derived, Mode>::type MatrixBase<Derived>::part()
-{
- return derived();
-}
-#endif
-
-/**
- * \returns an expression of a triangular view extracted from the current matrix
- *
- * The parameter \a Mode can have the following values: \c #Upper, \c #StrictlyUpper, \c #UnitUpper,
- * \c #Lower, \c #StrictlyLower, \c #UnitLower.
- *
- * Example: \include MatrixBase_extract.cpp
- * Output: \verbinclude MatrixBase_extract.out
- *
- * \sa class TriangularView
- */
-template<typename Derived>
-template<unsigned int Mode>
-typename MatrixBase<Derived>::template TriangularViewReturnType<Mode>::Type
-MatrixBase<Derived>::triangularView()
-{
- return derived();
-}
-
-/** This is the const version of MatrixBase::triangularView() */
-template<typename Derived>
-template<unsigned int Mode>
-typename MatrixBase<Derived>::template ConstTriangularViewReturnType<Mode>::Type
-MatrixBase<Derived>::triangularView() const
-{
- return derived();
-}
-
-/** \returns true if *this is approximately equal to an upper triangular matrix,
- * within the precision given by \a prec.
- *
- * \sa isLowerTriangular()
- */
-template<typename Derived>
-bool MatrixBase<Derived>::isUpperTriangular(RealScalar prec) const
-{
- RealScalar maxAbsOnUpperPart = static_cast<RealScalar>(-1);
- for(Index j = 0; j < cols(); ++j)
- {
- Index maxi = (std::min)(j, rows()-1);
- for(Index i = 0; i <= maxi; ++i)
- {
- RealScalar absValue = internal::abs(coeff(i,j));
- if(absValue > maxAbsOnUpperPart) maxAbsOnUpperPart = absValue;
- }
- }
- RealScalar threshold = maxAbsOnUpperPart * prec;
- for(Index j = 0; j < cols(); ++j)
- for(Index i = j+1; i < rows(); ++i)
- if(internal::abs(coeff(i, j)) > threshold) return false;
- return true;
-}
-
-/** \returns true if *this is approximately equal to a lower triangular matrix,
- * within the precision given by \a prec.
- *
- * \sa isUpperTriangular()
- */
-template<typename Derived>
-bool MatrixBase<Derived>::isLowerTriangular(RealScalar prec) const
-{
- RealScalar maxAbsOnLowerPart = static_cast<RealScalar>(-1);
- for(Index j = 0; j < cols(); ++j)
- for(Index i = j; i < rows(); ++i)
- {
- RealScalar absValue = internal::abs(coeff(i,j));
- if(absValue > maxAbsOnLowerPart) maxAbsOnLowerPart = absValue;
- }
- RealScalar threshold = maxAbsOnLowerPart * prec;
- for(Index j = 1; j < cols(); ++j)
- {
- Index maxi = (std::min)(j, rows()-1);
- for(Index i = 0; i < maxi; ++i)
- if(internal::abs(coeff(i, j)) > threshold) return false;
- }
- return true;
-}
-
-#endif // EIGEN_TRIANGULARMATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Core/VectorBlock.h b/extern/Eigen3/Eigen/src/Core/VectorBlock.h
deleted file mode 100644
index 858e4c7865a..00000000000
--- a/extern/Eigen3/Eigen/src/Core/VectorBlock.h
+++ /dev/null
@@ -1,296 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_VECTORBLOCK_H
-#define EIGEN_VECTORBLOCK_H
-
-/** \class VectorBlock
- * \ingroup Core_Module
- *
- * \brief Expression of a fixed-size or dynamic-size sub-vector
- *
- * \param VectorType the type of the object in which we are taking a sub-vector
- * \param Size size of the sub-vector we are taking at compile time (optional)
- *
- * This class represents an expression of either a fixed-size or dynamic-size sub-vector.
- * It is the return type of DenseBase::segment(Index,Index) and DenseBase::segment<int>(Index) and
- * most of the time this is the only way it is used.
- *
- * However, if you want to directly maniputate sub-vector expressions,
- * for instance if you want to write a function returning such an expression, you
- * will need to use this class.
- *
- * Here is an example illustrating the dynamic case:
- * \include class_VectorBlock.cpp
- * Output: \verbinclude class_VectorBlock.out
- *
- * \note Even though this expression has dynamic size, in the case where \a VectorType
- * has fixed size, this expression inherits a fixed maximal size which means that evaluating
- * it does not cause a dynamic memory allocation.
- *
- * Here is an example illustrating the fixed-size case:
- * \include class_FixedVectorBlock.cpp
- * Output: \verbinclude class_FixedVectorBlock.out
- *
- * \sa class Block, DenseBase::segment(Index,Index,Index,Index), DenseBase::segment(Index,Index)
- */
-
-namespace internal {
-template<typename VectorType, int Size>
-struct traits<VectorBlock<VectorType, Size> >
- : public traits<Block<VectorType,
- traits<VectorType>::Flags & RowMajorBit ? 1 : Size,
- traits<VectorType>::Flags & RowMajorBit ? Size : 1> >
-{
-};
-}
-
-template<typename VectorType, int Size> class VectorBlock
- : public Block<VectorType,
- internal::traits<VectorType>::Flags & RowMajorBit ? 1 : Size,
- internal::traits<VectorType>::Flags & RowMajorBit ? Size : 1>
-{
- typedef Block<VectorType,
- internal::traits<VectorType>::Flags & RowMajorBit ? 1 : Size,
- internal::traits<VectorType>::Flags & RowMajorBit ? Size : 1> Base;
- enum {
- IsColVector = !(internal::traits<VectorType>::Flags & RowMajorBit)
- };
- public:
- EIGEN_DENSE_PUBLIC_INTERFACE(VectorBlock)
-
- using Base::operator=;
-
- /** Dynamic-size constructor
- */
- inline VectorBlock(VectorType& vector, Index start, Index size)
- : Base(vector,
- IsColVector ? start : 0, IsColVector ? 0 : start,
- IsColVector ? size : 1, IsColVector ? 1 : size)
- {
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorBlock);
- }
-
- /** Fixed-size constructor
- */
- inline VectorBlock(VectorType& vector, Index start)
- : Base(vector, IsColVector ? start : 0, IsColVector ? 0 : start)
- {
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorBlock);
- }
-};
-
-
-/** \returns a dynamic-size expression of a segment (i.e. a vector block) in *this.
- *
- * \only_for_vectors
- *
- * \param start the first coefficient in the segment
- * \param size the number of coefficients in the segment
- *
- * Example: \include MatrixBase_segment_int_int.cpp
- * Output: \verbinclude MatrixBase_segment_int_int.out
- *
- * \note Even though the returned expression has dynamic size, in the case
- * when it is applied to a fixed-size vector, it inherits a fixed maximal size,
- * which means that evaluating it does not cause a dynamic memory allocation.
- *
- * \sa class Block, segment(Index)
- */
-template<typename Derived>
-inline typename DenseBase<Derived>::SegmentReturnType
-DenseBase<Derived>::segment(Index start, Index size)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return SegmentReturnType(derived(), start, size);
-}
-
-/** This is the const version of segment(Index,Index).*/
-template<typename Derived>
-inline typename DenseBase<Derived>::ConstSegmentReturnType
-DenseBase<Derived>::segment(Index start, Index size) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return ConstSegmentReturnType(derived(), start, size);
-}
-
-/** \returns a dynamic-size expression of the first coefficients of *this.
- *
- * \only_for_vectors
- *
- * \param size the number of coefficients in the block
- *
- * Example: \include MatrixBase_start_int.cpp
- * Output: \verbinclude MatrixBase_start_int.out
- *
- * \note Even though the returned expression has dynamic size, in the case
- * when it is applied to a fixed-size vector, it inherits a fixed maximal size,
- * which means that evaluating it does not cause a dynamic memory allocation.
- *
- * \sa class Block, block(Index,Index)
- */
-template<typename Derived>
-inline typename DenseBase<Derived>::SegmentReturnType
-DenseBase<Derived>::head(Index size)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return SegmentReturnType(derived(), 0, size);
-}
-
-/** This is the const version of head(Index).*/
-template<typename Derived>
-inline typename DenseBase<Derived>::ConstSegmentReturnType
-DenseBase<Derived>::head(Index size) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return ConstSegmentReturnType(derived(), 0, size);
-}
-
-/** \returns a dynamic-size expression of the last coefficients of *this.
- *
- * \only_for_vectors
- *
- * \param size the number of coefficients in the block
- *
- * Example: \include MatrixBase_end_int.cpp
- * Output: \verbinclude MatrixBase_end_int.out
- *
- * \note Even though the returned expression has dynamic size, in the case
- * when it is applied to a fixed-size vector, it inherits a fixed maximal size,
- * which means that evaluating it does not cause a dynamic memory allocation.
- *
- * \sa class Block, block(Index,Index)
- */
-template<typename Derived>
-inline typename DenseBase<Derived>::SegmentReturnType
-DenseBase<Derived>::tail(Index size)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return SegmentReturnType(derived(), this->size() - size, size);
-}
-
-/** This is the const version of tail(Index).*/
-template<typename Derived>
-inline typename DenseBase<Derived>::ConstSegmentReturnType
-DenseBase<Derived>::tail(Index size) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return ConstSegmentReturnType(derived(), this->size() - size, size);
-}
-
-/** \returns a fixed-size expression of a segment (i.e. a vector block) in \c *this
- *
- * \only_for_vectors
- *
- * The template parameter \a Size is the number of coefficients in the block
- *
- * \param start the index of the first element of the sub-vector
- *
- * Example: \include MatrixBase_template_int_segment.cpp
- * Output: \verbinclude MatrixBase_template_int_segment.out
- *
- * \sa class Block
- */
-template<typename Derived>
-template<int Size>
-inline typename DenseBase<Derived>::template FixedSegmentReturnType<Size>::Type
-DenseBase<Derived>::segment(Index start)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return typename FixedSegmentReturnType<Size>::Type(derived(), start);
-}
-
-/** This is the const version of segment<int>(Index).*/
-template<typename Derived>
-template<int Size>
-inline typename DenseBase<Derived>::template ConstFixedSegmentReturnType<Size>::Type
-DenseBase<Derived>::segment(Index start) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return typename ConstFixedSegmentReturnType<Size>::Type(derived(), start);
-}
-
-/** \returns a fixed-size expression of the first coefficients of *this.
- *
- * \only_for_vectors
- *
- * The template parameter \a Size is the number of coefficients in the block
- *
- * Example: \include MatrixBase_template_int_start.cpp
- * Output: \verbinclude MatrixBase_template_int_start.out
- *
- * \sa class Block
- */
-template<typename Derived>
-template<int Size>
-inline typename DenseBase<Derived>::template FixedSegmentReturnType<Size>::Type
-DenseBase<Derived>::head()
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return typename FixedSegmentReturnType<Size>::Type(derived(), 0);
-}
-
-/** This is the const version of head<int>().*/
-template<typename Derived>
-template<int Size>
-inline typename DenseBase<Derived>::template ConstFixedSegmentReturnType<Size>::Type
-DenseBase<Derived>::head() const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return typename ConstFixedSegmentReturnType<Size>::Type(derived(), 0);
-}
-
-/** \returns a fixed-size expression of the last coefficients of *this.
- *
- * \only_for_vectors
- *
- * The template parameter \a Size is the number of coefficients in the block
- *
- * Example: \include MatrixBase_template_int_end.cpp
- * Output: \verbinclude MatrixBase_template_int_end.out
- *
- * \sa class Block
- */
-template<typename Derived>
-template<int Size>
-inline typename DenseBase<Derived>::template FixedSegmentReturnType<Size>::Type
-DenseBase<Derived>::tail()
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return typename FixedSegmentReturnType<Size>::Type(derived(), size() - Size);
-}
-
-/** This is the const version of tail<int>.*/
-template<typename Derived>
-template<int Size>
-inline typename DenseBase<Derived>::template ConstFixedSegmentReturnType<Size>::Type
-DenseBase<Derived>::tail() const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return typename ConstFixedSegmentReturnType<Size>::Type(derived(), size() - Size);
-}
-
-
-#endif // EIGEN_VECTORBLOCK_H
diff --git a/extern/Eigen3/Eigen/src/Core/VectorwiseOp.h b/extern/Eigen3/Eigen/src/Core/VectorwiseOp.h
deleted file mode 100644
index 20f6881575b..00000000000
--- a/extern/Eigen3/Eigen/src/Core/VectorwiseOp.h
+++ /dev/null
@@ -1,557 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_PARTIAL_REDUX_H
-#define EIGEN_PARTIAL_REDUX_H
-
-/** \class PartialReduxExpr
- * \ingroup Core_Module
- *
- * \brief Generic expression of a partially reduxed matrix
- *
- * \tparam MatrixType the type of the matrix we are applying the redux operation
- * \tparam MemberOp type of the member functor
- * \tparam Direction indicates the direction of the redux (#Vertical or #Horizontal)
- *
- * This class represents an expression of a partial redux operator of a matrix.
- * It is the return type of some VectorwiseOp functions,
- * and most of the time this is the only way it is used.
- *
- * \sa class VectorwiseOp
- */
-
-template< typename MatrixType, typename MemberOp, int Direction>
-class PartialReduxExpr;
-
-namespace internal {
-template<typename MatrixType, typename MemberOp, int Direction>
-struct traits<PartialReduxExpr<MatrixType, MemberOp, Direction> >
- : traits<MatrixType>
-{
- typedef typename MemberOp::result_type Scalar;
- typedef typename traits<MatrixType>::StorageKind StorageKind;
- typedef typename traits<MatrixType>::XprKind XprKind;
- typedef typename MatrixType::Scalar InputScalar;
- typedef typename nested<MatrixType>::type MatrixTypeNested;
- typedef typename remove_all<MatrixTypeNested>::type _MatrixTypeNested;
- enum {
- RowsAtCompileTime = Direction==Vertical ? 1 : MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::ColsAtCompileTime,
- MaxRowsAtCompileTime = Direction==Vertical ? 1 : MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::MaxColsAtCompileTime,
- Flags0 = (unsigned int)_MatrixTypeNested::Flags & HereditaryBits,
- Flags = (Flags0 & ~RowMajorBit) | (RowsAtCompileTime == 1 ? RowMajorBit : 0),
- TraversalSize = Direction==Vertical ? RowsAtCompileTime : ColsAtCompileTime
- };
- #if EIGEN_GNUC_AT_LEAST(3,4)
- typedef typename MemberOp::template Cost<InputScalar,int(TraversalSize)> CostOpType;
- #else
- typedef typename MemberOp::template Cost<InputScalar,TraversalSize> CostOpType;
- #endif
- enum {
- CoeffReadCost = TraversalSize * traits<_MatrixTypeNested>::CoeffReadCost + int(CostOpType::value)
- };
-};
-}
-
-template< typename MatrixType, typename MemberOp, int Direction>
-class PartialReduxExpr : internal::no_assignment_operator,
- public internal::dense_xpr_base< PartialReduxExpr<MatrixType, MemberOp, Direction> >::type
-{
- public:
-
- typedef typename internal::dense_xpr_base<PartialReduxExpr>::type Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(PartialReduxExpr)
- typedef typename internal::traits<PartialReduxExpr>::MatrixTypeNested MatrixTypeNested;
- typedef typename internal::traits<PartialReduxExpr>::_MatrixTypeNested _MatrixTypeNested;
-
- PartialReduxExpr(const MatrixType& mat, const MemberOp& func = MemberOp())
- : m_matrix(mat), m_functor(func) {}
-
- Index rows() const { return (Direction==Vertical ? 1 : m_matrix.rows()); }
- Index cols() const { return (Direction==Horizontal ? 1 : m_matrix.cols()); }
-
- EIGEN_STRONG_INLINE const Scalar coeff(Index i, Index j) const
- {
- if (Direction==Vertical)
- return m_functor(m_matrix.col(j));
- else
- return m_functor(m_matrix.row(i));
- }
-
- const Scalar coeff(Index index) const
- {
- if (Direction==Vertical)
- return m_functor(m_matrix.col(index));
- else
- return m_functor(m_matrix.row(index));
- }
-
- protected:
- const MatrixTypeNested m_matrix;
- const MemberOp m_functor;
-};
-
-#define EIGEN_MEMBER_FUNCTOR(MEMBER,COST) \
- template <typename ResultType> \
- struct member_##MEMBER { \
- EIGEN_EMPTY_STRUCT_CTOR(member_##MEMBER) \
- typedef ResultType result_type; \
- template<typename Scalar, int Size> struct Cost \
- { enum { value = COST }; }; \
- template<typename XprType> \
- EIGEN_STRONG_INLINE ResultType operator()(const XprType& mat) const \
- { return mat.MEMBER(); } \
- }
-
-namespace internal {
-
-EIGEN_MEMBER_FUNCTOR(squaredNorm, Size * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
-EIGEN_MEMBER_FUNCTOR(norm, (Size+5) * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
-EIGEN_MEMBER_FUNCTOR(stableNorm, (Size+5) * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
-EIGEN_MEMBER_FUNCTOR(blueNorm, (Size+5) * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
-EIGEN_MEMBER_FUNCTOR(hypotNorm, (Size-1) * functor_traits<scalar_hypot_op<Scalar> >::Cost );
-EIGEN_MEMBER_FUNCTOR(sum, (Size-1)*NumTraits<Scalar>::AddCost);
-EIGEN_MEMBER_FUNCTOR(mean, (Size-1)*NumTraits<Scalar>::AddCost + NumTraits<Scalar>::MulCost);
-EIGEN_MEMBER_FUNCTOR(minCoeff, (Size-1)*NumTraits<Scalar>::AddCost);
-EIGEN_MEMBER_FUNCTOR(maxCoeff, (Size-1)*NumTraits<Scalar>::AddCost);
-EIGEN_MEMBER_FUNCTOR(all, (Size-1)*NumTraits<Scalar>::AddCost);
-EIGEN_MEMBER_FUNCTOR(any, (Size-1)*NumTraits<Scalar>::AddCost);
-EIGEN_MEMBER_FUNCTOR(count, (Size-1)*NumTraits<Scalar>::AddCost);
-EIGEN_MEMBER_FUNCTOR(prod, (Size-1)*NumTraits<Scalar>::MulCost);
-
-
-template <typename BinaryOp, typename Scalar>
-struct member_redux {
- typedef typename result_of<
- BinaryOp(Scalar)
- >::type result_type;
- template<typename _Scalar, int Size> struct Cost
- { enum { value = (Size-1) * functor_traits<BinaryOp>::Cost }; };
- member_redux(const BinaryOp func) : m_functor(func) {}
- template<typename Derived>
- inline result_type operator()(const DenseBase<Derived>& mat) const
- { return mat.redux(m_functor); }
- const BinaryOp m_functor;
-};
-}
-
-/** \class VectorwiseOp
- * \ingroup Core_Module
- *
- * \brief Pseudo expression providing partial reduction operations
- *
- * \param ExpressionType the type of the object on which to do partial reductions
- * \param Direction indicates the direction of the redux (#Vertical or #Horizontal)
- *
- * This class represents a pseudo expression with partial reduction features.
- * It is the return type of DenseBase::colwise() and DenseBase::rowwise()
- * and most of the time this is the only way it is used.
- *
- * Example: \include MatrixBase_colwise.cpp
- * Output: \verbinclude MatrixBase_colwise.out
- *
- * \sa DenseBase::colwise(), DenseBase::rowwise(), class PartialReduxExpr
- */
-template<typename ExpressionType, int Direction> class VectorwiseOp
-{
- public:
-
- typedef typename ExpressionType::Scalar Scalar;
- typedef typename ExpressionType::RealScalar RealScalar;
- typedef typename ExpressionType::Index Index;
- typedef typename internal::conditional<internal::must_nest_by_value<ExpressionType>::ret,
- ExpressionType, ExpressionType&>::type ExpressionTypeNested;
- typedef typename internal::remove_all<ExpressionTypeNested>::type ExpressionTypeNestedCleaned;
-
- template<template<typename _Scalar> class Functor,
- typename Scalar=typename internal::traits<ExpressionType>::Scalar> struct ReturnType
- {
- typedef PartialReduxExpr<ExpressionType,
- Functor<Scalar>,
- Direction
- > Type;
- };
-
- template<typename BinaryOp> struct ReduxReturnType
- {
- typedef PartialReduxExpr<ExpressionType,
- internal::member_redux<BinaryOp,typename internal::traits<ExpressionType>::Scalar>,
- Direction
- > Type;
- };
-
- enum {
- IsVertical = (Direction==Vertical) ? 1 : 0,
- IsHorizontal = (Direction==Horizontal) ? 1 : 0
- };
-
- protected:
-
- /** \internal
- * \returns the i-th subvector according to the \c Direction */
- typedef typename internal::conditional<Direction==Vertical,
- typename ExpressionType::ColXpr,
- typename ExpressionType::RowXpr>::type SubVector;
- SubVector subVector(Index i)
- {
- return SubVector(m_matrix.derived(),i);
- }
-
- /** \internal
- * \returns the number of subvectors in the direction \c Direction */
- Index subVectors() const
- { return Direction==Vertical?m_matrix.cols():m_matrix.rows(); }
-
- template<typename OtherDerived> struct ExtendedType {
- typedef Replicate<OtherDerived,
- Direction==Vertical ? 1 : ExpressionType::RowsAtCompileTime,
- Direction==Horizontal ? 1 : ExpressionType::ColsAtCompileTime> Type;
- };
-
- /** \internal
- * Replicates a vector to match the size of \c *this */
- template<typename OtherDerived>
- typename ExtendedType<OtherDerived>::Type
- extendedTo(const DenseBase<OtherDerived>& other) const
- {
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived);
- return typename ExtendedType<OtherDerived>::Type
- (other.derived(),
- Direction==Vertical ? 1 : m_matrix.rows(),
- Direction==Horizontal ? 1 : m_matrix.cols());
- }
-
- public:
-
- inline VectorwiseOp(ExpressionType& matrix) : m_matrix(matrix) {}
-
- /** \internal */
- inline const ExpressionType& _expression() const { return m_matrix; }
-
- /** \returns a row or column vector expression of \c *this reduxed by \a func
- *
- * The template parameter \a BinaryOp is the type of the functor
- * of the custom redux operator. Note that func must be an associative operator.
- *
- * \sa class VectorwiseOp, DenseBase::colwise(), DenseBase::rowwise()
- */
- template<typename BinaryOp>
- const typename ReduxReturnType<BinaryOp>::Type
- redux(const BinaryOp& func = BinaryOp()) const
- { return typename ReduxReturnType<BinaryOp>::Type(_expression(), func); }
-
- /** \returns a row (or column) vector expression of the smallest coefficient
- * of each column (or row) of the referenced expression.
- *
- * Example: \include PartialRedux_minCoeff.cpp
- * Output: \verbinclude PartialRedux_minCoeff.out
- *
- * \sa DenseBase::minCoeff() */
- const typename ReturnType<internal::member_minCoeff>::Type minCoeff() const
- { return _expression(); }
-
- /** \returns a row (or column) vector expression of the largest coefficient
- * of each column (or row) of the referenced expression.
- *
- * Example: \include PartialRedux_maxCoeff.cpp
- * Output: \verbinclude PartialRedux_maxCoeff.out
- *
- * \sa DenseBase::maxCoeff() */
- const typename ReturnType<internal::member_maxCoeff>::Type maxCoeff() const
- { return _expression(); }
-
- /** \returns a row (or column) vector expression of the squared norm
- * of each column (or row) of the referenced expression.
- *
- * Example: \include PartialRedux_squaredNorm.cpp
- * Output: \verbinclude PartialRedux_squaredNorm.out
- *
- * \sa DenseBase::squaredNorm() */
- const typename ReturnType<internal::member_squaredNorm,RealScalar>::Type squaredNorm() const
- { return _expression(); }
-
- /** \returns a row (or column) vector expression of the norm
- * of each column (or row) of the referenced expression.
- *
- * Example: \include PartialRedux_norm.cpp
- * Output: \verbinclude PartialRedux_norm.out
- *
- * \sa DenseBase::norm() */
- const typename ReturnType<internal::member_norm,RealScalar>::Type norm() const
- { return _expression(); }
-
-
- /** \returns a row (or column) vector expression of the norm
- * of each column (or row) of the referenced expression, using
- * blue's algorithm.
- *
- * \sa DenseBase::blueNorm() */
- const typename ReturnType<internal::member_blueNorm,RealScalar>::Type blueNorm() const
- { return _expression(); }
-
-
- /** \returns a row (or column) vector expression of the norm
- * of each column (or row) of the referenced expression, avoiding
- * underflow and overflow.
- *
- * \sa DenseBase::stableNorm() */
- const typename ReturnType<internal::member_stableNorm,RealScalar>::Type stableNorm() const
- { return _expression(); }
-
-
- /** \returns a row (or column) vector expression of the norm
- * of each column (or row) of the referenced expression, avoiding
- * underflow and overflow using a concatenation of hypot() calls.
- *
- * \sa DenseBase::hypotNorm() */
- const typename ReturnType<internal::member_hypotNorm,RealScalar>::Type hypotNorm() const
- { return _expression(); }
-
- /** \returns a row (or column) vector expression of the sum
- * of each column (or row) of the referenced expression.
- *
- * Example: \include PartialRedux_sum.cpp
- * Output: \verbinclude PartialRedux_sum.out
- *
- * \sa DenseBase::sum() */
- const typename ReturnType<internal::member_sum>::Type sum() const
- { return _expression(); }
-
- /** \returns a row (or column) vector expression of the mean
- * of each column (or row) of the referenced expression.
- *
- * \sa DenseBase::mean() */
- const typename ReturnType<internal::member_mean>::Type mean() const
- { return _expression(); }
-
- /** \returns a row (or column) vector expression representing
- * whether \b all coefficients of each respective column (or row) are \c true.
- *
- * \sa DenseBase::all() */
- const typename ReturnType<internal::member_all>::Type all() const
- { return _expression(); }
-
- /** \returns a row (or column) vector expression representing
- * whether \b at \b least one coefficient of each respective column (or row) is \c true.
- *
- * \sa DenseBase::any() */
- const typename ReturnType<internal::member_any>::Type any() const
- { return _expression(); }
-
- /** \returns a row (or column) vector expression representing
- * the number of \c true coefficients of each respective column (or row).
- *
- * Example: \include PartialRedux_count.cpp
- * Output: \verbinclude PartialRedux_count.out
- *
- * \sa DenseBase::count() */
- const PartialReduxExpr<ExpressionType, internal::member_count<Index>, Direction> count() const
- { return _expression(); }
-
- /** \returns a row (or column) vector expression of the product
- * of each column (or row) of the referenced expression.
- *
- * Example: \include PartialRedux_prod.cpp
- * Output: \verbinclude PartialRedux_prod.out
- *
- * \sa DenseBase::prod() */
- const typename ReturnType<internal::member_prod>::Type prod() const
- { return _expression(); }
-
-
- /** \returns a matrix expression
- * where each column (or row) are reversed.
- *
- * Example: \include Vectorwise_reverse.cpp
- * Output: \verbinclude Vectorwise_reverse.out
- *
- * \sa DenseBase::reverse() */
- const Reverse<ExpressionType, Direction> reverse() const
- { return Reverse<ExpressionType, Direction>( _expression() ); }
-
- typedef Replicate<ExpressionType,Direction==Vertical?Dynamic:1,Direction==Horizontal?Dynamic:1> ReplicateReturnType;
- const ReplicateReturnType replicate(Index factor) const;
-
- /**
- * \return an expression of the replication of each column (or row) of \c *this
- *
- * Example: \include DirectionWise_replicate.cpp
- * Output: \verbinclude DirectionWise_replicate.out
- *
- * \sa VectorwiseOp::replicate(Index), DenseBase::replicate(), class Replicate
- */
- // NOTE implemented here because of sunstudio's compilation errors
- template<int Factor> const Replicate<ExpressionType,(IsVertical?Factor:1),(IsHorizontal?Factor:1)>
- replicate(Index factor = Factor) const
- {
- return Replicate<ExpressionType,Direction==Vertical?Factor:1,Direction==Horizontal?Factor:1>
- (_expression(),Direction==Vertical?factor:1,Direction==Horizontal?factor:1);
- }
-
-/////////// Artithmetic operators ///////////
-
- /** Copies the vector \a other to each subvector of \c *this */
- template<typename OtherDerived>
- ExpressionType& operator=(const DenseBase<OtherDerived>& other)
- {
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
- //eigen_assert((m_matrix.isNull()) == (other.isNull())); FIXME
- for(Index j=0; j<subVectors(); ++j)
- subVector(j) = other;
- return const_cast<ExpressionType&>(m_matrix);
- }
-
- /** Adds the vector \a other to each subvector of \c *this */
- template<typename OtherDerived>
- ExpressionType& operator+=(const DenseBase<OtherDerived>& other)
- {
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
- for(Index j=0; j<subVectors(); ++j)
- subVector(j) += other.derived();
- return const_cast<ExpressionType&>(m_matrix);
- }
-
- /** Substracts the vector \a other to each subvector of \c *this */
- template<typename OtherDerived>
- ExpressionType& operator-=(const DenseBase<OtherDerived>& other)
- {
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
- for(Index j=0; j<subVectors(); ++j)
- subVector(j) -= other.derived();
- return const_cast<ExpressionType&>(m_matrix);
- }
-
- /** Returns the expression of the sum of the vector \a other to each subvector of \c *this */
- template<typename OtherDerived> EIGEN_STRONG_INLINE
- CwiseBinaryOp<internal::scalar_sum_op<Scalar>,
- const ExpressionTypeNestedCleaned,
- const typename ExtendedType<OtherDerived>::Type>
- operator+(const DenseBase<OtherDerived>& other) const
- {
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived);
- return m_matrix + extendedTo(other.derived());
- }
-
- /** Returns the expression of the difference between each subvector of \c *this and the vector \a other */
- template<typename OtherDerived>
- CwiseBinaryOp<internal::scalar_difference_op<Scalar>,
- const ExpressionTypeNestedCleaned,
- const typename ExtendedType<OtherDerived>::Type>
- operator-(const DenseBase<OtherDerived>& other) const
- {
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived);
- return m_matrix - extendedTo(other.derived());
- }
-
-/////////// Geometry module ///////////
-
- #if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
- Homogeneous<ExpressionType,Direction> homogeneous() const;
- #endif
-
- typedef typename ExpressionType::PlainObject CrossReturnType;
- template<typename OtherDerived>
- const CrossReturnType cross(const MatrixBase<OtherDerived>& other) const;
-
- enum {
- HNormalized_Size = Direction==Vertical ? internal::traits<ExpressionType>::RowsAtCompileTime
- : internal::traits<ExpressionType>::ColsAtCompileTime,
- HNormalized_SizeMinusOne = HNormalized_Size==Dynamic ? Dynamic : HNormalized_Size-1
- };
- typedef Block<const ExpressionType,
- Direction==Vertical ? int(HNormalized_SizeMinusOne)
- : int(internal::traits<ExpressionType>::RowsAtCompileTime),
- Direction==Horizontal ? int(HNormalized_SizeMinusOne)
- : int(internal::traits<ExpressionType>::ColsAtCompileTime)>
- HNormalized_Block;
- typedef Block<const ExpressionType,
- Direction==Vertical ? 1 : int(internal::traits<ExpressionType>::RowsAtCompileTime),
- Direction==Horizontal ? 1 : int(internal::traits<ExpressionType>::ColsAtCompileTime)>
- HNormalized_Factors;
- typedef CwiseBinaryOp<internal::scalar_quotient_op<typename internal::traits<ExpressionType>::Scalar>,
- const HNormalized_Block,
- const Replicate<HNormalized_Factors,
- Direction==Vertical ? HNormalized_SizeMinusOne : 1,
- Direction==Horizontal ? HNormalized_SizeMinusOne : 1> >
- HNormalizedReturnType;
-
- const HNormalizedReturnType hnormalized() const;
-
- protected:
- ExpressionTypeNested m_matrix;
-};
-
-/** \returns a VectorwiseOp wrapper of *this providing additional partial reduction operations
- *
- * Example: \include MatrixBase_colwise.cpp
- * Output: \verbinclude MatrixBase_colwise.out
- *
- * \sa rowwise(), class VectorwiseOp
- */
-template<typename Derived>
-inline const typename DenseBase<Derived>::ConstColwiseReturnType
-DenseBase<Derived>::colwise() const
-{
- return derived();
-}
-
-/** \returns a writable VectorwiseOp wrapper of *this providing additional partial reduction operations
- *
- * \sa rowwise(), class VectorwiseOp
- */
-template<typename Derived>
-inline typename DenseBase<Derived>::ColwiseReturnType
-DenseBase<Derived>::colwise()
-{
- return derived();
-}
-
-/** \returns a VectorwiseOp wrapper of *this providing additional partial reduction operations
- *
- * Example: \include MatrixBase_rowwise.cpp
- * Output: \verbinclude MatrixBase_rowwise.out
- *
- * \sa colwise(), class VectorwiseOp
- */
-template<typename Derived>
-inline const typename DenseBase<Derived>::ConstRowwiseReturnType
-DenseBase<Derived>::rowwise() const
-{
- return derived();
-}
-
-/** \returns a writable VectorwiseOp wrapper of *this providing additional partial reduction operations
- *
- * \sa colwise(), class VectorwiseOp
- */
-template<typename Derived>
-inline typename DenseBase<Derived>::RowwiseReturnType
-DenseBase<Derived>::rowwise()
-{
- return derived();
-}
-
-#endif // EIGEN_PARTIAL_REDUX_H
diff --git a/extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h b/extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h
deleted file mode 100644
index f8adf1b6385..00000000000
--- a/extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h
+++ /dev/null
@@ -1,228 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_COMPLEX_ALTIVEC_H
-#define EIGEN_COMPLEX_ALTIVEC_H
-
-namespace internal {
-
-static Packet4ui p4ui_CONJ_XOR = vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_ZERO_);//{ 0x00000000, 0x80000000, 0x00000000, 0x80000000 };
-static Packet16uc p16uc_COMPLEX_RE = vec_sld((Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 0), (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 2), 8);//{ 0,1,2,3, 0,1,2,3, 8,9,10,11, 8,9,10,11 };
-static Packet16uc p16uc_COMPLEX_IM = vec_sld((Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 1), (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 3), 8);//{ 4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15 };
-static Packet16uc p16uc_COMPLEX_REV = vec_sld(p16uc_REVERSE, p16uc_REVERSE, 8);//{ 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11 };
-static Packet16uc p16uc_COMPLEX_REV2 = vec_sld(p16uc_FORWARD, p16uc_FORWARD, 8);//{ 8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7 };
-static Packet16uc p16uc_PSET_HI = (Packet16uc) vec_mergeh((Packet4ui) vec_splat((Packet4ui)p16uc_FORWARD, 0), (Packet4ui) vec_splat((Packet4ui)p16uc_FORWARD, 1));//{ 0,1,2,3, 4,5,6,7, 0,1,2,3, 4,5,6,7 };
-static Packet16uc p16uc_PSET_LO = (Packet16uc) vec_mergeh((Packet4ui) vec_splat((Packet4ui)p16uc_FORWARD, 2), (Packet4ui) vec_splat((Packet4ui)p16uc_FORWARD, 3));//{ 8,9,10,11, 12,13,14,15, 8,9,10,11, 12,13,14,15 };
-
-//---------- float ----------
-struct Packet2cf
-{
- EIGEN_STRONG_INLINE Packet2cf() {}
- EIGEN_STRONG_INLINE explicit Packet2cf(const Packet4f& a) : v(a) {}
- Packet4f v;
-};
-
-template<> struct packet_traits<std::complex<float> > : default_packet_traits
-{
- typedef Packet2cf type;
- enum {
- Vectorizable = 1,
- AlignedOnScalar = 1,
- size = 2,
-
- HasAdd = 1,
- HasSub = 1,
- HasMul = 1,
- HasDiv = 1,
- HasNegate = 1,
- HasAbs = 0,
- HasAbs2 = 0,
- HasMin = 0,
- HasMax = 0,
- HasSetLinear = 0
- };
-};
-
-template<> struct unpacket_traits<Packet2cf> { typedef std::complex<float> type; enum {size=2}; };
-
-template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from)
-{
- Packet2cf res;
- /* On AltiVec we cannot load 64-bit registers, so wa have to take care of alignment */
- if((ptrdiff_t(&from) % 16) == 0)
- res.v = pload<Packet4f>((const float *)&from);
- else
- res.v = ploadu<Packet4f>((const float *)&from);
- res.v = vec_perm(res.v, res.v, p16uc_PSET_HI);
- return res;
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(vec_add(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(vec_sub(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a) { return Packet2cf(pnegate(a.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a) { return Packet2cf((Packet4f)vec_xor((Packet4ui)a.v, p4ui_CONJ_XOR)); }
-
-template<> EIGEN_STRONG_INLINE Packet2cf pmul<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
-{
- Packet4f v1, v2;
-
- // Permute and multiply the real parts of a and b
- v1 = vec_perm(a.v, a.v, p16uc_COMPLEX_RE);
- // Get the imaginary parts of a
- v2 = vec_perm(a.v, a.v, p16uc_COMPLEX_IM);
- // multiply a_re * b
- v1 = vec_madd(v1, b.v, p4f_ZERO);
- // multiply a_im * b and get the conjugate result
- v2 = vec_madd(v2, b.v, p4f_ZERO);
- v2 = (Packet4f) vec_xor((Packet4ui)v2, p4ui_CONJ_XOR);
- // permute back to a proper order
- v2 = vec_perm(v2, v2, p16uc_COMPLEX_REV);
-
- return Packet2cf(vec_add(v1, v2));
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf pand <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(vec_and(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf por <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(vec_or(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf pxor <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(vec_xor(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf pandnot<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(vec_and(a.v, vec_nor(b.v,b.v))); }
-
-template<> EIGEN_STRONG_INLINE Packet2cf pload <Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_ALIGNED_LOAD return Packet2cf(pload<Packet4f>((const float*)from)); }
-template<> EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_UNALIGNED_LOAD return Packet2cf(ploadu<Packet4f>((const float*)from)); }
-
-template<> EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>* from)
-{
- return pset1<Packet2cf>(*from);
-}
-
-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) { vec_dstt((float *)addr, DST_CTRL(2,2,32), DST_CHAN); }
-
-template<> EIGEN_STRONG_INLINE std::complex<float> pfirst<Packet2cf>(const Packet2cf& a)
-{
- std::complex<float> EIGEN_ALIGN16 res[2];
- pstore((float *)&res, a.v);
-
- return res[0];
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf preverse(const Packet2cf& a)
-{
- Packet4f rev_a;
- rev_a = vec_perm(a.v, a.v, p16uc_COMPLEX_REV2);
- return Packet2cf(rev_a);
-}
-
-template<> EIGEN_STRONG_INLINE std::complex<float> predux<Packet2cf>(const Packet2cf& a)
-{
- Packet4f b;
- b = (Packet4f) vec_sld(a.v, a.v, 8);
- b = padd(a.v, b);
- return pfirst(Packet2cf(b));
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf preduxp<Packet2cf>(const Packet2cf* vecs)
-{
- Packet4f b1, b2;
-
- b1 = (Packet4f) vec_sld(vecs[0].v, vecs[1].v, 8);
- b2 = (Packet4f) vec_sld(vecs[1].v, vecs[0].v, 8);
- b2 = (Packet4f) vec_sld(b2, b2, 8);
- b2 = padd(b1, b2);
-
- return Packet2cf(b2);
-}
-
-template<> EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const Packet2cf& a)
-{
- Packet4f b;
- Packet2cf prod;
- b = (Packet4f) vec_sld(a.v, a.v, 8);
- prod = pmul(a, Packet2cf(b));
-
- return pfirst(prod);
-}
-
-template<int Offset>
-struct palign_impl<Offset,Packet2cf>
-{
- EIGEN_STRONG_INLINE static void run(Packet2cf& first, const Packet2cf& second)
- {
- if (Offset==1)
- {
- first.v = vec_sld(first.v, second.v, 8);
- }
- }
-};
-
-template<> struct conj_helper<Packet2cf, Packet2cf, false,true>
-{
- EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
- { return padd(pmul(x,y),c); }
-
- EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
- {
- return internal::pmul(a, pconj(b));
- }
-};
-
-template<> struct conj_helper<Packet2cf, Packet2cf, true,false>
-{
- EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
- { return padd(pmul(x,y),c); }
-
- EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
- {
- return internal::pmul(pconj(a), b);
- }
-};
-
-template<> struct conj_helper<Packet2cf, Packet2cf, true,true>
-{
- EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
- { return padd(pmul(x,y),c); }
-
- EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
- {
- return pconj(internal::pmul(a, b));
- }
-};
-
-template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
-{
- // TODO optimize it for AltiVec
- Packet2cf res = conj_helper<Packet2cf,Packet2cf,false,true>().pmul(a,b);
- Packet4f s = vec_madd(b.v, b.v, p4f_ZERO);
- return Packet2cf(pdiv(res.v, vec_add(s,vec_perm(s, s, p16uc_COMPLEX_REV))));
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf pcplxflip<Packet2cf>(const Packet2cf& x)
-{
- return Packet2cf(vec_perm(x.v, x.v, p16uc_COMPLEX_REV));
-}
-
-} // end namespace internal
-
-#endif // EIGEN_COMPLEX_ALTIVEC_H
diff --git a/extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h b/extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h
deleted file mode 100644
index dc34ebbd660..00000000000
--- a/extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h
+++ /dev/null
@@ -1,509 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Konstantinos Margaritis <markos@codex.gr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_PACKET_MATH_ALTIVEC_H
-#define EIGEN_PACKET_MATH_ALTIVEC_H
-
-namespace internal {
-
-#ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
-#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 4
-#endif
-
-#ifndef EIGEN_HAS_FUSE_CJMADD
-#define EIGEN_HAS_FUSE_CJMADD 1
-#endif
-
-// NOTE Altivec has 32 registers, but Eigen only accepts a value of 8 or 16
-#ifndef EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS
-#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS 16
-#endif
-
-typedef __vector float Packet4f;
-typedef __vector int Packet4i;
-typedef __vector unsigned int Packet4ui;
-typedef __vector __bool int Packet4bi;
-typedef __vector short int Packet8i;
-typedef __vector unsigned char Packet16uc;
-
-// We don't want to write the same code all the time, but we need to reuse the constants
-// and it doesn't really work to declare them global, so we define macros instead
-
-#define _EIGEN_DECLARE_CONST_FAST_Packet4f(NAME,X) \
- Packet4f p4f_##NAME = (Packet4f) vec_splat_s32(X)
-
-#define _EIGEN_DECLARE_CONST_FAST_Packet4i(NAME,X) \
- Packet4i p4i_##NAME = vec_splat_s32(X)
-
-#define _EIGEN_DECLARE_CONST_Packet4f(NAME,X) \
- Packet4f p4f_##NAME = pset1<Packet4f>(X)
-
-#define _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(NAME,X) \
- Packet4f p4f_##NAME = vreinterpretq_f32_u32(pset1<int>(X))
-
-#define _EIGEN_DECLARE_CONST_Packet4i(NAME,X) \
- Packet4i p4i_##NAME = pset1<Packet4i>(X)
-
-#define DST_CHAN 1
-#define DST_CTRL(size, count, stride) (((size) << 24) | ((count) << 16) | (stride))
-
-// Define global static constants:
-static Packet4f p4f_COUNTDOWN = { 3.0, 2.0, 1.0, 0.0 };
-static Packet4i p4i_COUNTDOWN = { 3, 2, 1, 0 };
-static Packet16uc p16uc_REVERSE = {12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3};
-static Packet16uc p16uc_FORWARD = vec_lvsl(0, (float*)0);
-static Packet16uc p16uc_DUPLICATE = {0,1,2,3, 0,1,2,3, 4,5,6,7, 4,5,6,7};
-
-static _EIGEN_DECLARE_CONST_FAST_Packet4f(ZERO, 0);
-static _EIGEN_DECLARE_CONST_FAST_Packet4i(ZERO, 0);
-static _EIGEN_DECLARE_CONST_FAST_Packet4i(ONE,1);
-static _EIGEN_DECLARE_CONST_FAST_Packet4i(MINUS16,-16);
-static _EIGEN_DECLARE_CONST_FAST_Packet4i(MINUS1,-1);
-static Packet4f p4f_ONE = vec_ctf(p4i_ONE, 0);
-static Packet4f p4f_ZERO_ = (Packet4f) vec_sl((Packet4ui)p4i_MINUS1, (Packet4ui)p4i_MINUS1);
-
-template<> struct packet_traits<float> : default_packet_traits
-{
- typedef Packet4f type;
- enum {
- Vectorizable = 1,
- AlignedOnScalar = 1,
- size=4,
-
- // FIXME check the Has*
- HasSin = 0,
- HasCos = 0,
- HasLog = 0,
- HasExp = 0,
- HasSqrt = 0
- };
-};
-template<> struct packet_traits<int> : default_packet_traits
-{
- typedef Packet4i type;
- enum {
- // FIXME check the Has*
- Vectorizable = 1,
- AlignedOnScalar = 1,
- size=4
- };
-};
-
-template<> struct unpacket_traits<Packet4f> { typedef float type; enum {size=4}; };
-template<> struct unpacket_traits<Packet4i> { typedef int type; enum {size=4}; };
-/*
-inline std::ostream & operator <<(std::ostream & s, const Packet4f & v)
-{
- union {
- Packet4f v;
- float n[4];
- } vt;
- vt.v = v;
- s << vt.n[0] << ", " << vt.n[1] << ", " << vt.n[2] << ", " << vt.n[3];
- return s;
-}
-
-inline std::ostream & operator <<(std::ostream & s, const Packet4i & v)
-{
- union {
- Packet4i v;
- int n[4];
- } vt;
- vt.v = v;
- s << vt.n[0] << ", " << vt.n[1] << ", " << vt.n[2] << ", " << vt.n[3];
- return s;
-}
-
-inline std::ostream & operator <<(std::ostream & s, const Packet4ui & v)
-{
- union {
- Packet4ui v;
- unsigned int n[4];
- } vt;
- vt.v = v;
- s << vt.n[0] << ", " << vt.n[1] << ", " << vt.n[2] << ", " << vt.n[3];
- return s;
-}
-
-inline std::ostream & operator <<(std::ostream & s, const Packetbi & v)
-{
- union {
- Packet4bi v;
- unsigned int n[4];
- } vt;
- vt.v = v;
- s << vt.n[0] << ", " << vt.n[1] << ", " << vt.n[2] << ", " << vt.n[3];
- return s;
-}
-*/
-template<> EIGEN_STRONG_INLINE Packet4f pset1<Packet4f>(const float& from) {
- // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html
- float EIGEN_ALIGN16 af[4];
- af[0] = from;
- Packet4f vc = vec_ld(0, af);
- vc = vec_splat(vc, 0);
- return vc;
-}
-
-template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int& from) {
- int EIGEN_ALIGN16 ai[4];
- ai[0] = from;
- Packet4i vc = vec_ld(0, ai);
- vc = vec_splat(vc, 0);
- return vc;
-}
-
-template<> EIGEN_STRONG_INLINE Packet4f plset<float>(const float& a) { return vec_add(pset1<Packet4f>(a), p4f_COUNTDOWN); }
-template<> EIGEN_STRONG_INLINE Packet4i plset<int>(const int& a) { return vec_add(pset1<Packet4i>(a), p4i_COUNTDOWN); }
-
-template<> EIGEN_STRONG_INLINE Packet4f padd<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_add(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i padd<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_add(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f psub<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_sub(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i psub<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_sub(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pnegate(const Packet4f& a) { return psub<Packet4f>(p4f_ZERO, a); }
-template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a) { return psub<Packet4i>(p4i_ZERO, a); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pmul<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_madd(a,b,p4f_ZERO); }
-/* Commented out: it's actually slower than processing it scalar
- *
-template<> EIGEN_STRONG_INLINE Packet4i pmul<Packet4i>(const Packet4i& a, const Packet4i& b)
-{
- // Detailed in: http://freevec.org/content/32bit_signed_integer_multiplication_altivec
- //Set up constants, variables
- Packet4i a1, b1, bswap, low_prod, high_prod, prod, prod_, v1sel;
-
- // Get the absolute values
- a1 = vec_abs(a);
- b1 = vec_abs(b);
-
- // Get the signs using xor
- Packet4bi sgn = (Packet4bi) vec_cmplt(vec_xor(a, b), p4i_ZERO);
-
- // Do the multiplication for the asbolute values.
- bswap = (Packet4i) vec_rl((Packet4ui) b1, (Packet4ui) p4i_MINUS16 );
- low_prod = vec_mulo((Packet8i) a1, (Packet8i)b1);
- high_prod = vec_msum((Packet8i) a1, (Packet8i) bswap, p4i_ZERO);
- high_prod = (Packet4i) vec_sl((Packet4ui) high_prod, (Packet4ui) p4i_MINUS16);
- prod = vec_add( low_prod, high_prod );
-
- // NOR the product and select only the negative elements according to the sign mask
- prod_ = vec_nor(prod, prod);
- prod_ = vec_sel(p4i_ZERO, prod_, sgn);
-
- // Add 1 to the result to get the negative numbers
- v1sel = vec_sel(p4i_ZERO, p4i_ONE, sgn);
- prod_ = vec_add(prod_, v1sel);
-
- // Merge the results back to the final vector.
- prod = vec_sel(prod, prod_, sgn);
-
- return prod;
-}
-*/
-template<> EIGEN_STRONG_INLINE Packet4f pdiv<Packet4f>(const Packet4f& a, const Packet4f& b)
-{
- Packet4f t, y_0, y_1, res;
-
- // Altivec does not offer a divide instruction, we have to do a reciprocal approximation
- y_0 = vec_re(b);
-
- // Do one Newton-Raphson iteration to get the needed accuracy
- t = vec_nmsub(y_0, b, p4f_ONE);
- y_1 = vec_madd(y_0, t, y_0);
-
- res = vec_madd(a, y_1, p4f_ZERO);
- return res;
-}
-
-template<> EIGEN_STRONG_INLINE Packet4i pdiv<Packet4i>(const Packet4i& /*a*/, const Packet4i& /*b*/)
-{ eigen_assert(false && "packet integer division are not supported by AltiVec");
- return pset1<Packet4i>(0);
-}
-
-// for some weird raisons, it has to be overloaded for packet of integers
-template<> EIGEN_STRONG_INLINE Packet4f pmadd(const Packet4f& a, const Packet4f& b, const Packet4f& c) { return vec_madd(a, b, c); }
-template<> EIGEN_STRONG_INLINE Packet4i pmadd(const Packet4i& a, const Packet4i& b, const Packet4i& c) { return padd(pmul(a,b), c); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pmin<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_min(a, b); }
-template<> EIGEN_STRONG_INLINE Packet4i pmin<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_min(a, b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pmax<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_max(a, b); }
-template<> EIGEN_STRONG_INLINE Packet4i pmax<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_max(a, b); }
-
-// Logical Operations are not supported for float, so we have to reinterpret casts using NEON intrinsics
-template<> EIGEN_STRONG_INLINE Packet4f pand<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_and(a, b); }
-template<> EIGEN_STRONG_INLINE Packet4i pand<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_and(a, b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f por<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_or(a, b); }
-template<> EIGEN_STRONG_INLINE Packet4i por<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_or(a, b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pxor<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_xor(a, b); }
-template<> EIGEN_STRONG_INLINE Packet4i pxor<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_xor(a, b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pandnot<Packet4f>(const Packet4f& a, const Packet4f& b) { return vec_and(a, vec_nor(b, b)); }
-template<> EIGEN_STRONG_INLINE Packet4i pandnot<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_and(a, vec_nor(b, b)); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pload<Packet4f>(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return vec_ld(0, from); }
-template<> EIGEN_STRONG_INLINE Packet4i pload<Packet4i>(const int* from) { EIGEN_DEBUG_ALIGNED_LOAD return vec_ld(0, from); }
-
-template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from)
-{
- EIGEN_DEBUG_ALIGNED_LOAD
- // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html
- Packet16uc MSQ, LSQ;
- Packet16uc mask;
- MSQ = vec_ld(0, (unsigned char *)from); // most significant quadword
- LSQ = vec_ld(15, (unsigned char *)from); // least significant quadword
- mask = vec_lvsl(0, from); // create the permute mask
- return (Packet4f) vec_perm(MSQ, LSQ, mask); // align the data
-
-}
-template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from)
-{
- EIGEN_DEBUG_ALIGNED_LOAD
- // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html
- Packet16uc MSQ, LSQ;
- Packet16uc mask;
- MSQ = vec_ld(0, (unsigned char *)from); // most significant quadword
- LSQ = vec_ld(15, (unsigned char *)from); // least significant quadword
- mask = vec_lvsl(0, from); // create the permute mask
- return (Packet4i) vec_perm(MSQ, LSQ, mask); // align the data
-}
-
-template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
-{
- Packet4f p;
- if((ptrdiff_t(&from) % 16) == 0) p = pload<Packet4f>(from);
- else p = ploadu<Packet4f>(from);
- return vec_perm(p, p, p16uc_DUPLICATE);
-}
-template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from)
-{
- Packet4i p;
- if((ptrdiff_t(&from) % 16) == 0) p = pload<Packet4i>(from);
- else p = ploadu<Packet4i>(from);
- return vec_perm(p, p, p16uc_DUPLICATE);
-}
-
-template<> EIGEN_STRONG_INLINE void pstore<float>(float* to, const Packet4f& from) { EIGEN_DEBUG_ALIGNED_STORE vec_st(from, 0, to); }
-template<> EIGEN_STRONG_INLINE void pstore<int>(int* to, const Packet4i& from) { EIGEN_DEBUG_ALIGNED_STORE vec_st(from, 0, to); }
-
-template<> EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const Packet4f& from)
-{
- EIGEN_DEBUG_UNALIGNED_STORE
- // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html
- // Warning: not thread safe!
- Packet16uc MSQ, LSQ, edges;
- Packet16uc edgeAlign, align;
-
- MSQ = vec_ld(0, (unsigned char *)to); // most significant quadword
- LSQ = vec_ld(15, (unsigned char *)to); // least significant quadword
- edgeAlign = vec_lvsl(0, to); // permute map to extract edges
- edges=vec_perm(LSQ,MSQ,edgeAlign); // extract the edges
- align = vec_lvsr( 0, to ); // permute map to misalign data
- MSQ = vec_perm(edges,(Packet16uc)from,align); // misalign the data (MSQ)
- LSQ = vec_perm((Packet16uc)from,edges,align); // misalign the data (LSQ)
- vec_st( LSQ, 15, (unsigned char *)to ); // Store the LSQ part first
- vec_st( MSQ, 0, (unsigned char *)to ); // Store the MSQ part
-}
-template<> EIGEN_STRONG_INLINE void pstoreu<int>(int* to, const Packet4i& from)
-{
- EIGEN_DEBUG_UNALIGNED_STORE
- // Taken from http://developer.apple.com/hardwaredrivers/ve/alignment.html
- // Warning: not thread safe!
- Packet16uc MSQ, LSQ, edges;
- Packet16uc edgeAlign, align;
-
- MSQ = vec_ld(0, (unsigned char *)to); // most significant quadword
- LSQ = vec_ld(15, (unsigned char *)to); // least significant quadword
- edgeAlign = vec_lvsl(0, to); // permute map to extract edges
- edges=vec_perm(LSQ, MSQ, edgeAlign); // extract the edges
- align = vec_lvsr( 0, to ); // permute map to misalign data
- MSQ = vec_perm(edges, (Packet16uc) from, align); // misalign the data (MSQ)
- LSQ = vec_perm((Packet16uc) from, edges, align); // misalign the data (LSQ)
- vec_st( LSQ, 15, (unsigned char *)to ); // Store the LSQ part first
- vec_st( MSQ, 0, (unsigned char *)to ); // Store the MSQ part
-}
-
-template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { vec_dstt(addr, DST_CTRL(2,2,32), DST_CHAN); }
-template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { vec_dstt(addr, DST_CTRL(2,2,32), DST_CHAN); }
-
-template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { float EIGEN_ALIGN16 x[4]; vec_st(a, 0, x); return x[0]; }
-template<> EIGEN_STRONG_INLINE int pfirst<Packet4i>(const Packet4i& a) { int EIGEN_ALIGN16 x[4]; vec_st(a, 0, x); return x[0]; }
-
-template<> EIGEN_STRONG_INLINE Packet4f preverse(const Packet4f& a) { return (Packet4f)vec_perm((Packet16uc)a,(Packet16uc)a, p16uc_REVERSE); }
-template<> EIGEN_STRONG_INLINE Packet4i preverse(const Packet4i& a) { return (Packet4i)vec_perm((Packet16uc)a,(Packet16uc)a, p16uc_REVERSE); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pabs(const Packet4f& a) { return vec_abs(a); }
-template<> EIGEN_STRONG_INLINE Packet4i pabs(const Packet4i& a) { return vec_abs(a); }
-
-template<> EIGEN_STRONG_INLINE float predux<Packet4f>(const Packet4f& a)
-{
- Packet4f b, sum;
- b = (Packet4f) vec_sld(a, a, 8);
- sum = vec_add(a, b);
- b = (Packet4f) vec_sld(sum, sum, 4);
- sum = vec_add(sum, b);
- return pfirst(sum);
-}
-
-template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs)
-{
- Packet4f v[4], sum[4];
-
- // It's easier and faster to transpose then add as columns
- // Check: http://www.freevec.org/function/matrix_4x4_transpose_floats for explanation
- // Do the transpose, first set of moves
- v[0] = vec_mergeh(vecs[0], vecs[2]);
- v[1] = vec_mergel(vecs[0], vecs[2]);
- v[2] = vec_mergeh(vecs[1], vecs[3]);
- v[3] = vec_mergel(vecs[1], vecs[3]);
- // Get the resulting vectors
- sum[0] = vec_mergeh(v[0], v[2]);
- sum[1] = vec_mergel(v[0], v[2]);
- sum[2] = vec_mergeh(v[1], v[3]);
- sum[3] = vec_mergel(v[1], v[3]);
-
- // Now do the summation:
- // Lines 0+1
- sum[0] = vec_add(sum[0], sum[1]);
- // Lines 2+3
- sum[1] = vec_add(sum[2], sum[3]);
- // Add the results
- sum[0] = vec_add(sum[0], sum[1]);
-
- return sum[0];
-}
-
-template<> EIGEN_STRONG_INLINE int predux<Packet4i>(const Packet4i& a)
-{
- Packet4i sum;
- sum = vec_sums(a, p4i_ZERO);
- sum = vec_sld(sum, p4i_ZERO, 12);
- return pfirst(sum);
-}
-
-template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs)
-{
- Packet4i v[4], sum[4];
-
- // It's easier and faster to transpose then add as columns
- // Check: http://www.freevec.org/function/matrix_4x4_transpose_floats for explanation
- // Do the transpose, first set of moves
- v[0] = vec_mergeh(vecs[0], vecs[2]);
- v[1] = vec_mergel(vecs[0], vecs[2]);
- v[2] = vec_mergeh(vecs[1], vecs[3]);
- v[3] = vec_mergel(vecs[1], vecs[3]);
- // Get the resulting vectors
- sum[0] = vec_mergeh(v[0], v[2]);
- sum[1] = vec_mergel(v[0], v[2]);
- sum[2] = vec_mergeh(v[1], v[3]);
- sum[3] = vec_mergel(v[1], v[3]);
-
- // Now do the summation:
- // Lines 0+1
- sum[0] = vec_add(sum[0], sum[1]);
- // Lines 2+3
- sum[1] = vec_add(sum[2], sum[3]);
- // Add the results
- sum[0] = vec_add(sum[0], sum[1]);
-
- return sum[0];
-}
-
-// Other reduction functions:
-// mul
-template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a)
-{
- Packet4f prod;
- prod = pmul(a, (Packet4f)vec_sld(a, a, 8));
- return pfirst(pmul(prod, (Packet4f)vec_sld(prod, prod, 4)));
-}
-
-template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
-{
- EIGEN_ALIGN16 int aux[4];
- pstore(aux, a);
- return aux[0] * aux[1] * aux[2] * aux[3];
-}
-
-// min
-template<> EIGEN_STRONG_INLINE float predux_min<Packet4f>(const Packet4f& a)
-{
- Packet4f b, res;
- b = vec_min(a, vec_sld(a, a, 8));
- res = vec_min(b, vec_sld(b, b, 4));
- return pfirst(res);
-}
-
-template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a)
-{
- Packet4i b, res;
- b = vec_min(a, vec_sld(a, a, 8));
- res = vec_min(b, vec_sld(b, b, 4));
- return pfirst(res);
-}
-
-// max
-template<> EIGEN_STRONG_INLINE float predux_max<Packet4f>(const Packet4f& a)
-{
- Packet4f b, res;
- b = vec_max(a, vec_sld(a, a, 8));
- res = vec_max(b, vec_sld(b, b, 4));
- return pfirst(res);
-}
-
-template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
-{
- Packet4i b, res;
- b = vec_max(a, vec_sld(a, a, 8));
- res = vec_max(b, vec_sld(b, b, 4));
- return pfirst(res);
-}
-
-template<int Offset>
-struct palign_impl<Offset,Packet4f>
-{
- EIGEN_STRONG_INLINE static void run(Packet4f& first, const Packet4f& second)
- {
- if (Offset!=0)
- first = vec_sld(first, second, Offset*4);
- }
-};
-
-template<int Offset>
-struct palign_impl<Offset,Packet4i>
-{
- EIGEN_STRONG_INLINE static void run(Packet4i& first, const Packet4i& second)
- {
- if (Offset!=0)
- first = vec_sld(first, second, Offset*4);
- }
-};
-
-} // end namespace internal
-
-#endif // EIGEN_PACKET_MATH_ALTIVEC_H
diff --git a/extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h b/extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h
deleted file mode 100644
index 957adc8fe42..00000000000
--- a/extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-
-/* All the parameters defined in this file can be specialized in the
- * architecture specific files, and/or by the user.
- * More to come... */
-
-#ifndef EIGEN_DEFAULT_SETTINGS_H
-#define EIGEN_DEFAULT_SETTINGS_H
-
-/** Defines the maximal loop size to enable meta unrolling of loops.
- * Note that the value here is expressed in Eigen's own notion of "number of FLOPS",
- * it does not correspond to the number of iterations or the number of instructions
- */
-#ifndef EIGEN_UNROLLING_LIMIT
-#define EIGEN_UNROLLING_LIMIT 100
-#endif
-
-/** Defines the threshold between a "small" and a "large" matrix.
- * This threshold is mainly used to select the proper product implementation.
- */
-#ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
-#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 8
-#endif
-
-/** Defines the maximal width of the blocks used in the triangular product and solver
- * for vectors (level 2 blas xTRMV and xTRSV). The default is 8.
- */
-#ifndef EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH
-#define EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH 8
-#endif
-
-
-/** Defines the default number of registers available for that architecture.
- * Currently it must be 8 or 16. Other values will fail.
- */
-#ifndef EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS
-#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS 8
-#endif
-
-#endif // EIGEN_DEFAULT_SETTINGS_H
diff --git a/extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h b/extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h
deleted file mode 100644
index 8e55548c946..00000000000
--- a/extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h
+++ /dev/null
@@ -1,270 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_COMPLEX_NEON_H
-#define EIGEN_COMPLEX_NEON_H
-
-namespace internal {
-
-static uint32x4_t p4ui_CONJ_XOR = { 0x00000000, 0x80000000, 0x00000000, 0x80000000 };
-static uint32x2_t p2ui_CONJ_XOR = { 0x00000000, 0x80000000 };
-
-//---------- float ----------
-struct Packet2cf
-{
- EIGEN_STRONG_INLINE Packet2cf() {}
- EIGEN_STRONG_INLINE explicit Packet2cf(const Packet4f& a) : v(a) {}
- Packet4f v;
-};
-
-template<> struct packet_traits<std::complex<float> > : default_packet_traits
-{
- typedef Packet2cf type;
- enum {
- Vectorizable = 1,
- AlignedOnScalar = 1,
- size = 2,
-
- HasAdd = 1,
- HasSub = 1,
- HasMul = 1,
- HasDiv = 1,
- HasNegate = 1,
- HasAbs = 0,
- HasAbs2 = 0,
- HasMin = 0,
- HasMax = 0,
- HasSetLinear = 0
- };
-};
-
-template<> struct unpacket_traits<Packet2cf> { typedef std::complex<float> type; enum {size=2}; };
-
-template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from)
-{
- float32x2_t r64;
- r64 = vld1_f32((float *)&from);
-
- return Packet2cf(vcombine_f32(r64, r64));
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(padd<Packet4f>(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(psub<Packet4f>(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a) { return Packet2cf(pnegate<Packet4f>(a.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a)
-{
- Packet4ui b = vreinterpretq_u32_f32(a.v);
- return Packet2cf(vreinterpretq_f32_u32(veorq_u32(b, p4ui_CONJ_XOR)));
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf pmul<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
-{
- Packet4f v1, v2;
- float32x2_t a_lo, a_hi;
-
- // Get the real values of a | a1_re | a1_re | a2_re | a2_re |
- v1 = vcombine_f32(vdup_lane_f32(vget_low_f32(a.v), 0), vdup_lane_f32(vget_high_f32(a.v), 0));
- // Get the real values of a | a1_im | a1_im | a2_im | a2_im |
- v2 = vcombine_f32(vdup_lane_f32(vget_low_f32(a.v), 1), vdup_lane_f32(vget_high_f32(a.v), 1));
- // Multiply the real a with b
- v1 = vmulq_f32(v1, b.v);
- // Multiply the imag a with b
- v2 = vmulq_f32(v2, b.v);
- // Conjugate v2
- v2 = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(v2), p4ui_CONJ_XOR));
- // Swap real/imag elements in v2.
- a_lo = vrev64_f32(vget_low_f32(v2));
- a_hi = vrev64_f32(vget_high_f32(v2));
- v2 = vcombine_f32(a_lo, a_hi);
- // Add and return the result
- return Packet2cf(vaddq_f32(v1, v2));
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf pand <Packet2cf>(const Packet2cf& a, const Packet2cf& b)
-{
- return Packet2cf(vreinterpretq_f32_u32(vorrq_u32(vreinterpretq_u32_f32(a.v),vreinterpretq_u32_f32(b.v))));
-}
-template<> EIGEN_STRONG_INLINE Packet2cf por <Packet2cf>(const Packet2cf& a, const Packet2cf& b)
-{
- return Packet2cf(vreinterpretq_f32_u32(vorrq_u32(vreinterpretq_u32_f32(a.v),vreinterpretq_u32_f32(b.v))));
-}
-template<> EIGEN_STRONG_INLINE Packet2cf pxor <Packet2cf>(const Packet2cf& a, const Packet2cf& b)
-{
- return Packet2cf(vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(a.v),vreinterpretq_u32_f32(b.v))));
-}
-template<> EIGEN_STRONG_INLINE Packet2cf pandnot<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
-{
- return Packet2cf(vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(a.v),vreinterpretq_u32_f32(b.v))));
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf pload<Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_ALIGNED_LOAD return Packet2cf(pload<Packet4f>((const float*)from)); }
-template<> EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_UNALIGNED_LOAD return Packet2cf(ploadu<Packet4f>((const float*)from)); }
-
-template<> EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>* from) { return pset1<Packet2cf>(*from); }
-
-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 std::complex<float> pfirst<Packet2cf>(const Packet2cf& a)
-{
- std::complex<float> EIGEN_ALIGN16 x[2];
- vst1q_f32((float *)x, a.v);
- return x[0];
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf preverse(const Packet2cf& a)
-{
- float32x2_t a_lo, a_hi;
- Packet4f a_r128;
-
- a_lo = vget_low_f32(a.v);
- a_hi = vget_high_f32(a.v);
- a_r128 = vcombine_f32(a_hi, a_lo);
-
- return Packet2cf(a_r128);
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf pcplxflip<Packet2cf>(const Packet2cf& a)
-{
- return Packet2cf(vrev64q_f32(a.v));
-}
-
-template<> EIGEN_STRONG_INLINE std::complex<float> predux<Packet2cf>(const Packet2cf& a)
-{
- float32x2_t a1, a2;
- std::complex<float> s;
-
- a1 = vget_low_f32(a.v);
- a2 = vget_high_f32(a.v);
- a2 = vadd_f32(a1, a2);
- vst1_f32((float *)&s, a2);
-
- return s;
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf preduxp<Packet2cf>(const Packet2cf* vecs)
-{
- Packet4f sum1, sum2, sum;
-
- // Add the first two 64-bit float32x2_t of vecs[0]
- sum1 = vcombine_f32(vget_low_f32(vecs[0].v), vget_low_f32(vecs[1].v));
- sum2 = vcombine_f32(vget_high_f32(vecs[0].v), vget_high_f32(vecs[1].v));
- sum = vaddq_f32(sum1, sum2);
-
- return Packet2cf(sum);
-}
-
-template<> EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const Packet2cf& a)
-{
- float32x2_t a1, a2, v1, v2, prod;
- std::complex<float> s;
-
- a1 = vget_low_f32(a.v);
- a2 = vget_high_f32(a.v);
- // Get the real values of a | a1_re | a1_re | a2_re | a2_re |
- v1 = vdup_lane_f32(a1, 0);
- // Get the real values of a | a1_im | a1_im | a2_im | a2_im |
- v2 = vdup_lane_f32(a1, 1);
- // Multiply the real a with b
- v1 = vmul_f32(v1, a2);
- // Multiply the imag a with b
- v2 = vmul_f32(v2, a2);
- // Conjugate v2
- v2 = vreinterpret_f32_u32(veor_u32(vreinterpret_u32_f32(v2), p2ui_CONJ_XOR));
- // Swap real/imag elements in v2.
- v2 = vrev64_f32(v2);
- // Add v1, v2
- prod = vadd_f32(v1, v2);
-
- vst1_f32((float *)&s, prod);
-
- return s;
-}
-
-template<int Offset>
-struct palign_impl<Offset,Packet2cf>
-{
- EIGEN_STRONG_INLINE static void run(Packet2cf& first, const Packet2cf& second)
- {
- if (Offset==1)
- {
- first.v = vextq_f32(first.v, second.v, 2);
- }
- }
-};
-
-template<> struct conj_helper<Packet2cf, Packet2cf, false,true>
-{
- EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
- { return padd(pmul(x,y),c); }
-
- EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
- {
- return internal::pmul(a, pconj(b));
- }
-};
-
-template<> struct conj_helper<Packet2cf, Packet2cf, true,false>
-{
- EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
- { return padd(pmul(x,y),c); }
-
- EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
- {
- return internal::pmul(pconj(a), b);
- }
-};
-
-template<> struct conj_helper<Packet2cf, Packet2cf, true,true>
-{
- EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
- { return padd(pmul(x,y),c); }
-
- EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
- {
- return pconj(internal::pmul(a, b));
- }
-};
-
-template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
-{
- // TODO optimize it for AltiVec
- Packet2cf res = conj_helper<Packet2cf,Packet2cf,false,true>().pmul(a,b);
- Packet4f s, rev_s;
- float32x2_t a_lo, a_hi;
-
- // this computes the norm
- s = vmulq_f32(b.v, b.v);
- a_lo = vrev64_f32(vget_low_f32(s));
- a_hi = vrev64_f32(vget_high_f32(s));
- rev_s = vcombine_f32(a_lo, a_hi);
-
- return Packet2cf(pdiv(res.v, vaddq_f32(s,rev_s)));
-}
-
-} // end namespace internal
-
-#endif // EIGEN_COMPLEX_NEON_H
diff --git a/extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h b/extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h
deleted file mode 100644
index 478ef8038c0..00000000000
--- a/extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h
+++ /dev/null
@@ -1,420 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Konstantinos Margaritis <markos@codex.gr>
-// Heavily based on Gael's SSE version.
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_PACKET_MATH_NEON_H
-#define EIGEN_PACKET_MATH_NEON_H
-
-namespace internal {
-
-#ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
-#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 8
-#endif
-
-// FIXME NEON has 16 quad registers, but since the current register allocator
-// is so bad, it is much better to reduce it to 8
-#ifndef EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS
-#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS 8
-#endif
-
-typedef float32x4_t Packet4f;
-typedef int32x4_t Packet4i;
-typedef uint32x4_t Packet4ui;
-
-#define _EIGEN_DECLARE_CONST_Packet4f(NAME,X) \
- const Packet4f p4f_##NAME = pset1<Packet4f>(X)
-
-#define _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(NAME,X) \
- const Packet4f p4f_##NAME = vreinterpretq_f32_u32(pset1<int>(X))
-
-#define _EIGEN_DECLARE_CONST_Packet4i(NAME,X) \
- const Packet4i p4i_##NAME = pset1<Packet4i>(X)
-
-#ifndef __pld
-#define __pld(x) asm volatile ( " pld [%[addr]]\n" :: [addr] "r" (x) : "cc" );
-#endif
-
-template<> struct packet_traits<float> : default_packet_traits
-{
- typedef Packet4f type;
- enum {
- Vectorizable = 1,
- AlignedOnScalar = 1,
- size = 4,
-
- HasDiv = 1,
- // FIXME check the Has*
- HasSin = 0,
- HasCos = 0,
- HasLog = 0,
- HasExp = 0,
- HasSqrt = 0
- };
-};
-template<> struct packet_traits<int> : default_packet_traits
-{
- typedef Packet4i type;
- enum {
- Vectorizable = 1,
- AlignedOnScalar = 1,
- size=4
- // FIXME check the Has*
- };
-};
-
-#if EIGEN_GNUC_AT_MOST(4,4)
-// workaround gcc 4.2, 4.3 and 4.4 compilatin issue
-EIGEN_STRONG_INLINE float32x4_t vld1q_f32(const float* x) { return ::vld1q_f32((const float32_t*)x); }
-EIGEN_STRONG_INLINE float32x2_t vld1_f32 (const float* x) { return ::vld1_f32 ((const float32_t*)x); }
-EIGEN_STRONG_INLINE void vst1q_f32(float* to, float32x4_t from) { ::vst1q_f32((float32_t*)to,from); }
-EIGEN_STRONG_INLINE void vst1_f32 (float* to, float32x2_t from) { ::vst1_f32 ((float32_t*)to,from); }
-#endif
-
-template<> struct unpacket_traits<Packet4f> { typedef float type; enum {size=4}; };
-template<> struct unpacket_traits<Packet4i> { typedef int type; enum {size=4}; };
-
-template<> EIGEN_STRONG_INLINE Packet4f pset1<Packet4f>(const float& from) { return vdupq_n_f32(from); }
-template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int& from) { return vdupq_n_s32(from); }
-
-template<> EIGEN_STRONG_INLINE Packet4f plset<float>(const float& a)
-{
- Packet4f countdown = { 0, 1, 2, 3 };
- return vaddq_f32(pset1<Packet4f>(a), countdown);
-}
-template<> EIGEN_STRONG_INLINE Packet4i plset<int>(const int& a)
-{
- Packet4i countdown = { 0, 1, 2, 3 };
- return vaddq_s32(pset1<Packet4i>(a), countdown);
-}
-
-template<> EIGEN_STRONG_INLINE Packet4f padd<Packet4f>(const Packet4f& a, const Packet4f& b) { return vaddq_f32(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i padd<Packet4i>(const Packet4i& a, const Packet4i& b) { return vaddq_s32(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f psub<Packet4f>(const Packet4f& a, const Packet4f& b) { return vsubq_f32(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i psub<Packet4i>(const Packet4i& a, const Packet4i& b) { return vsubq_s32(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pnegate(const Packet4f& a) { return vnegq_f32(a); }
-template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a) { return vnegq_s32(a); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pmul<Packet4f>(const Packet4f& a, const Packet4f& b) { return vmulq_f32(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i pmul<Packet4i>(const Packet4i& a, const Packet4i& b) { return vmulq_s32(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pdiv<Packet4f>(const Packet4f& a, const Packet4f& b)
-{
- Packet4f inv, restep, div;
-
- // NEON does not offer a divide instruction, we have to do a reciprocal approximation
- // However NEON in contrast to other SIMD engines (AltiVec/SSE), offers
- // a reciprocal estimate AND a reciprocal step -which saves a few instructions
- // vrecpeq_f32() returns an estimate to 1/b, which we will finetune with
- // Newton-Raphson and vrecpsq_f32()
- inv = vrecpeq_f32(b);
-
- // This returns a differential, by which we will have to multiply inv to get a better
- // approximation of 1/b.
- restep = vrecpsq_f32(b, inv);
- inv = vmulq_f32(restep, inv);
-
- // Finally, multiply a by 1/b and get the wanted result of the division.
- div = vmulq_f32(a, inv);
-
- return div;
-}
-template<> EIGEN_STRONG_INLINE Packet4i pdiv<Packet4i>(const Packet4i& /*a*/, const Packet4i& /*b*/)
-{ eigen_assert(false && "packet integer division are not supported by NEON");
- return pset1<Packet4i>(0);
-}
-
-// for some weird raisons, it has to be overloaded for packet of integers
-template<> EIGEN_STRONG_INLINE Packet4i pmadd(const Packet4i& a, const Packet4i& b, const Packet4i& c) { return padd(pmul(a,b), c); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pmin<Packet4f>(const Packet4f& a, const Packet4f& b) { return vminq_f32(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i pmin<Packet4i>(const Packet4i& a, const Packet4i& b) { return vminq_s32(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pmax<Packet4f>(const Packet4f& a, const Packet4f& b) { return vmaxq_f32(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i pmax<Packet4i>(const Packet4i& a, const Packet4i& b) { return vmaxq_s32(a,b); }
-
-// Logical Operations are not supported for float, so we have to reinterpret casts using NEON intrinsics
-template<> EIGEN_STRONG_INLINE Packet4f pand<Packet4f>(const Packet4f& a, const Packet4f& b)
-{
- return vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(a),vreinterpretq_u32_f32(b)));
-}
-template<> EIGEN_STRONG_INLINE Packet4i pand<Packet4i>(const Packet4i& a, const Packet4i& b) { return vandq_s32(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f por<Packet4f>(const Packet4f& a, const Packet4f& b)
-{
- return vreinterpretq_f32_u32(vorrq_u32(vreinterpretq_u32_f32(a),vreinterpretq_u32_f32(b)));
-}
-template<> EIGEN_STRONG_INLINE Packet4i por<Packet4i>(const Packet4i& a, const Packet4i& b) { return vorrq_s32(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pxor<Packet4f>(const Packet4f& a, const Packet4f& b)
-{
- return vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(a),vreinterpretq_u32_f32(b)));
-}
-template<> EIGEN_STRONG_INLINE Packet4i pxor<Packet4i>(const Packet4i& a, const Packet4i& b) { return veorq_s32(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pandnot<Packet4f>(const Packet4f& a, const Packet4f& b)
-{
- return vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(a),vreinterpretq_u32_f32(b)));
-}
-template<> EIGEN_STRONG_INLINE Packet4i pandnot<Packet4i>(const Packet4i& a, const Packet4i& b) { return vbicq_s32(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pload<Packet4f>(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_f32(from); }
-template<> EIGEN_STRONG_INLINE Packet4i pload<Packet4i>(const int* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_s32(from); }
-
-template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_f32(from); }
-template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_s32(from); }
-
-template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
-{
- float32x2_t lo, hi;
- lo = vdup_n_f32(*from);
- hi = vdup_n_f32(*(from+1));
- return vcombine_f32(lo, hi);
-}
-template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from)
-{
- int32x2_t lo, hi;
- lo = vdup_n_s32(*from);
- hi = vdup_n_s32(*(from+1));
- return vcombine_s32(lo, hi);
-}
-
-template<> EIGEN_STRONG_INLINE void pstore<float>(float* to, const Packet4f& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_f32(to, from); }
-template<> EIGEN_STRONG_INLINE void pstore<int>(int* to, const Packet4i& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_s32(to, from); }
-
-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); }
-
-// 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]; }
-template<> EIGEN_STRONG_INLINE int pfirst<Packet4i>(const Packet4i& a) { int EIGEN_ALIGN16 x[4]; vst1q_s32(x, a); return x[0]; }
-
-template<> EIGEN_STRONG_INLINE Packet4f preverse(const Packet4f& a) {
- float32x2_t a_lo, a_hi;
- Packet4f a_r64;
-
- a_r64 = vrev64q_f32(a);
- a_lo = vget_low_f32(a_r64);
- a_hi = vget_high_f32(a_r64);
- return vcombine_f32(a_hi, a_lo);
-}
-template<> EIGEN_STRONG_INLINE Packet4i preverse(const Packet4i& a) {
- int32x2_t a_lo, a_hi;
- Packet4i a_r64;
-
- a_r64 = vrev64q_s32(a);
- a_lo = vget_low_s32(a_r64);
- a_hi = vget_high_s32(a_r64);
- return vcombine_s32(a_hi, a_lo);
-}
-template<> EIGEN_STRONG_INLINE Packet4f pabs(const Packet4f& a) { return vabsq_f32(a); }
-template<> EIGEN_STRONG_INLINE Packet4i pabs(const Packet4i& a) { return vabsq_s32(a); }
-
-template<> EIGEN_STRONG_INLINE float predux<Packet4f>(const Packet4f& a)
-{
- float32x2_t a_lo, a_hi, sum;
- float s[2];
-
- a_lo = vget_low_f32(a);
- a_hi = vget_high_f32(a);
- sum = vpadd_f32(a_lo, a_hi);
- sum = vpadd_f32(sum, sum);
- vst1_f32(s, sum);
-
- return s[0];
-}
-
-template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs)
-{
- float32x4x2_t vtrn1, vtrn2, res1, res2;
- Packet4f sum1, sum2, sum;
-
- // NEON zip performs interleaving of the supplied vectors.
- // We perform two interleaves in a row to acquire the transposed vector
- vtrn1 = vzipq_f32(vecs[0], vecs[2]);
- vtrn2 = vzipq_f32(vecs[1], vecs[3]);
- res1 = vzipq_f32(vtrn1.val[0], vtrn2.val[0]);
- res2 = vzipq_f32(vtrn1.val[1], vtrn2.val[1]);
-
- // Do the addition of the resulting vectors
- sum1 = vaddq_f32(res1.val[0], res1.val[1]);
- sum2 = vaddq_f32(res2.val[0], res2.val[1]);
- sum = vaddq_f32(sum1, sum2);
-
- return sum;
-}
-
-template<> EIGEN_STRONG_INLINE int predux<Packet4i>(const Packet4i& a)
-{
- int32x2_t a_lo, a_hi, sum;
- int32_t s[2];
-
- a_lo = vget_low_s32(a);
- a_hi = vget_high_s32(a);
- sum = vpadd_s32(a_lo, a_hi);
- sum = vpadd_s32(sum, sum);
- vst1_s32(s, sum);
-
- return s[0];
-}
-
-template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs)
-{
- int32x4x2_t vtrn1, vtrn2, res1, res2;
- Packet4i sum1, sum2, sum;
-
- // NEON zip performs interleaving of the supplied vectors.
- // We perform two interleaves in a row to acquire the transposed vector
- vtrn1 = vzipq_s32(vecs[0], vecs[2]);
- vtrn2 = vzipq_s32(vecs[1], vecs[3]);
- res1 = vzipq_s32(vtrn1.val[0], vtrn2.val[0]);
- res2 = vzipq_s32(vtrn1.val[1], vtrn2.val[1]);
-
- // Do the addition of the resulting vectors
- sum1 = vaddq_s32(res1.val[0], res1.val[1]);
- sum2 = vaddq_s32(res2.val[0], res2.val[1]);
- sum = vaddq_s32(sum1, sum2);
-
- return sum;
-}
-
-// Other reduction functions:
-// mul
-template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a)
-{
- float32x2_t a_lo, a_hi, prod;
- float s[2];
-
- // Get a_lo = |a1|a2| and a_hi = |a3|a4|
- a_lo = vget_low_f32(a);
- a_hi = vget_high_f32(a);
- // Get the product of a_lo * a_hi -> |a1*a3|a2*a4|
- prod = vmul_f32(a_lo, a_hi);
- // Multiply prod with its swapped value |a2*a4|a1*a3|
- prod = vmul_f32(prod, vrev64_f32(prod));
- vst1_f32(s, prod);
-
- return s[0];
-}
-template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
-{
- int32x2_t a_lo, a_hi, prod;
- int32_t s[2];
-
- // Get a_lo = |a1|a2| and a_hi = |a3|a4|
- a_lo = vget_low_s32(a);
- a_hi = vget_high_s32(a);
- // Get the product of a_lo * a_hi -> |a1*a3|a2*a4|
- prod = vmul_s32(a_lo, a_hi);
- // Multiply prod with its swapped value |a2*a4|a1*a3|
- prod = vmul_s32(prod, vrev64_s32(prod));
- vst1_s32(s, prod);
-
- return s[0];
-}
-
-// min
-template<> EIGEN_STRONG_INLINE float predux_min<Packet4f>(const Packet4f& a)
-{
- float32x2_t a_lo, a_hi, min;
- float s[2];
-
- a_lo = vget_low_f32(a);
- a_hi = vget_high_f32(a);
- min = vpmin_f32(a_lo, a_hi);
- min = vpmin_f32(min, min);
- vst1_f32(s, min);
-
- return s[0];
-}
-template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a)
-{
- int32x2_t a_lo, a_hi, min;
- int32_t s[2];
-
- a_lo = vget_low_s32(a);
- a_hi = vget_high_s32(a);
- min = vpmin_s32(a_lo, a_hi);
- min = vpmin_s32(min, min);
- vst1_s32(s, min);
-
- return s[0];
-}
-
-// max
-template<> EIGEN_STRONG_INLINE float predux_max<Packet4f>(const Packet4f& a)
-{
- float32x2_t a_lo, a_hi, max;
- float s[2];
-
- a_lo = vget_low_f32(a);
- a_hi = vget_high_f32(a);
- max = vpmax_f32(a_lo, a_hi);
- max = vpmax_f32(max, max);
- vst1_f32(s, max);
-
- return s[0];
-}
-template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
-{
- int32x2_t a_lo, a_hi, max;
- int32_t s[2];
-
- a_lo = vget_low_s32(a);
- a_hi = vget_high_s32(a);
- max = vpmax_s32(a_lo, a_hi);
- max = vpmax_s32(max, max);
- vst1_s32(s, max);
-
- return s[0];
-}
-
-template<int Offset>
-struct palign_impl<Offset,Packet4f>
-{
- EIGEN_STRONG_INLINE static void run(Packet4f& first, const Packet4f& second)
- {
- if (Offset!=0)
- first = vextq_f32(first, second, Offset);
- }
-};
-
-template<int Offset>
-struct palign_impl<Offset,Packet4i>
-{
- EIGEN_STRONG_INLINE static void run(Packet4i& first, const Packet4i& second)
- {
- if (Offset!=0)
- first = vextq_s32(first, second, Offset);
- }
-};
-
-} // end namespace internal
-
-#endif // EIGEN_PACKET_MATH_NEON_H
diff --git a/extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h b/extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h
deleted file mode 100644
index c352bb3e6cf..00000000000
--- a/extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h
+++ /dev/null
@@ -1,447 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_COMPLEX_SSE_H
-#define EIGEN_COMPLEX_SSE_H
-
-namespace internal {
-
-//---------- float ----------
-struct Packet2cf
-{
- EIGEN_STRONG_INLINE Packet2cf() {}
- EIGEN_STRONG_INLINE explicit Packet2cf(const __m128& a) : v(a) {}
- __m128 v;
-};
-
-template<> struct packet_traits<std::complex<float> > : default_packet_traits
-{
- typedef Packet2cf type;
- enum {
- Vectorizable = 1,
- AlignedOnScalar = 1,
- size = 2,
-
- HasAdd = 1,
- HasSub = 1,
- HasMul = 1,
- HasDiv = 1,
- HasNegate = 1,
- HasAbs = 0,
- HasAbs2 = 0,
- HasMin = 0,
- HasMax = 0,
- HasSetLinear = 0
- };
-};
-
-template<> struct unpacket_traits<Packet2cf> { typedef std::complex<float> type; enum {size=2}; };
-
-template<> EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_add_ps(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_sub_ps(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a)
-{
- const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x80000000,0x80000000,0x80000000,0x80000000));
- return Packet2cf(_mm_xor_ps(a.v,mask));
-}
-template<> EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a)
-{
- const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x00000000,0x80000000,0x00000000,0x80000000));
- return Packet2cf(_mm_xor_ps(a.v,mask));
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf pmul<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
-{
- // TODO optimize it for SSE3 and 4
- #ifdef EIGEN_VECTORIZE_SSE3
- return Packet2cf(_mm_addsub_ps(_mm_mul_ps(_mm_moveldup_ps(a.v), b.v),
- _mm_mul_ps(_mm_movehdup_ps(a.v),
- vec4f_swizzle1(b.v, 1, 0, 3, 2))));
-// return Packet2cf(_mm_addsub_ps(_mm_mul_ps(vec4f_swizzle1(a.v, 0, 0, 2, 2), b.v),
-// _mm_mul_ps(vec4f_swizzle1(a.v, 1, 1, 3, 3),
-// vec4f_swizzle1(b.v, 1, 0, 3, 2))));
- #else
- const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x80000000,0x00000000,0x80000000,0x00000000));
- return Packet2cf(_mm_add_ps(_mm_mul_ps(vec4f_swizzle1(a.v, 0, 0, 2, 2), b.v),
- _mm_xor_ps(_mm_mul_ps(vec4f_swizzle1(a.v, 1, 1, 3, 3),
- vec4f_swizzle1(b.v, 1, 0, 3, 2)), mask)));
- #endif
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf pand <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_and_ps(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf por <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_or_ps(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf pxor <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_xor_ps(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet2cf pandnot<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(_mm_andnot_ps(a.v,b.v)); }
-
-template<> EIGEN_STRONG_INLINE Packet2cf pload <Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_ALIGNED_LOAD return Packet2cf(pload<Packet4f>(&real_ref(*from))); }
-template<> EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<float>* from) { EIGEN_DEBUG_UNALIGNED_LOAD return Packet2cf(ploadu<Packet4f>(&real_ref(*from))); }
-
-template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from)
-{
- Packet2cf res;
- #if EIGEN_GNUC_AT_MOST(4,2)
- // workaround annoying "may be used uninitialized in this function" warning with gcc 4.2
- res.v = _mm_loadl_pi(_mm_set1_ps(0.0f), (const __m64*)&from);
- #else
- res.v = _mm_loadl_pi(res.v, (const __m64*)&from);
- #endif
- return Packet2cf(_mm_movelh_ps(res.v,res.v));
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>* from) { return pset1<Packet2cf>(*from); }
-
-template<> EIGEN_STRONG_INLINE void pstore <std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_ALIGNED_STORE pstore(&real_ref(*to), from.v); }
-template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float> * to, const Packet2cf& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(&real_ref(*to), from.v); }
-
-template<> EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float> * addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
-
-template<> EIGEN_STRONG_INLINE std::complex<float> pfirst<Packet2cf>(const Packet2cf& a)
-{
- #if EIGEN_GNUC_AT_MOST(4,3)
- // Workaround gcc 4.2 ICE - this is not performance wise ideal, but who cares...
- // This workaround also fix invalid code generation with gcc 4.3
- EIGEN_ALIGN16 std::complex<float> res[2];
- _mm_store_ps((float*)res, a.v);
- return res[0];
- #else
- std::complex<float> res;
- _mm_storel_pi((__m64*)&res, a.v);
- return res;
- #endif
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf preverse(const Packet2cf& a) { return Packet2cf(_mm_castpd_ps(preverse(_mm_castps_pd(a.v)))); }
-
-template<> EIGEN_STRONG_INLINE std::complex<float> predux<Packet2cf>(const Packet2cf& a)
-{
- return pfirst(Packet2cf(_mm_add_ps(a.v, _mm_movehl_ps(a.v,a.v))));
-}
-
-template<> EIGEN_STRONG_INLINE Packet2cf preduxp<Packet2cf>(const Packet2cf* vecs)
-{
- return Packet2cf(_mm_add_ps(_mm_movelh_ps(vecs[0].v,vecs[1].v), _mm_movehl_ps(vecs[1].v,vecs[0].v)));
-}
-
-template<> EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const Packet2cf& a)
-{
- return pfirst(pmul(a, Packet2cf(_mm_movehl_ps(a.v,a.v))));
-}
-
-template<int Offset>
-struct palign_impl<Offset,Packet2cf>
-{
- EIGEN_STRONG_INLINE static void run(Packet2cf& first, const Packet2cf& second)
- {
- if (Offset==1)
- {
- first.v = _mm_movehl_ps(first.v, first.v);
- first.v = _mm_movelh_ps(first.v, second.v);
- }
- }
-};
-
-template<> struct conj_helper<Packet2cf, Packet2cf, false,true>
-{
- EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
- { return padd(pmul(x,y),c); }
-
- EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
- {
- #ifdef EIGEN_VECTORIZE_SSE3
- return internal::pmul(a, pconj(b));
- #else
- const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x00000000,0x80000000,0x00000000,0x80000000));
- return Packet2cf(_mm_add_ps(_mm_xor_ps(_mm_mul_ps(vec4f_swizzle1(a.v, 0, 0, 2, 2), b.v), mask),
- _mm_mul_ps(vec4f_swizzle1(a.v, 1, 1, 3, 3),
- vec4f_swizzle1(b.v, 1, 0, 3, 2))));
- #endif
- }
-};
-
-template<> struct conj_helper<Packet2cf, Packet2cf, true,false>
-{
- EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
- { return padd(pmul(x,y),c); }
-
- EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
- {
- #ifdef EIGEN_VECTORIZE_SSE3
- return internal::pmul(pconj(a), b);
- #else
- const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x00000000,0x80000000,0x00000000,0x80000000));
- return Packet2cf(_mm_add_ps(_mm_mul_ps(vec4f_swizzle1(a.v, 0, 0, 2, 2), b.v),
- _mm_xor_ps(_mm_mul_ps(vec4f_swizzle1(a.v, 1, 1, 3, 3),
- vec4f_swizzle1(b.v, 1, 0, 3, 2)), mask)));
- #endif
- }
-};
-
-template<> struct conj_helper<Packet2cf, Packet2cf, true,true>
-{
- EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
- { return padd(pmul(x,y),c); }
-
- EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
- {
- #ifdef EIGEN_VECTORIZE_SSE3
- return pconj(internal::pmul(a, b));
- #else
- const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x00000000,0x80000000,0x00000000,0x80000000));
- return Packet2cf(_mm_sub_ps(_mm_xor_ps(_mm_mul_ps(vec4f_swizzle1(a.v, 0, 0, 2, 2), b.v), mask),
- _mm_mul_ps(vec4f_swizzle1(a.v, 1, 1, 3, 3),
- vec4f_swizzle1(b.v, 1, 0, 3, 2))));
- #endif
- }
-};
-
-template<> struct conj_helper<Packet4f, Packet2cf, false,false>
-{
- EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet4f& x, const Packet2cf& y, const Packet2cf& c) const
- { return padd(c, pmul(x,y)); }
-
- EIGEN_STRONG_INLINE Packet2cf pmul(const Packet4f& x, const Packet2cf& y) const
- { return Packet2cf(Eigen::internal::pmul(x, y.v)); }
-};
-
-template<> struct conj_helper<Packet2cf, Packet4f, false,false>
-{
- EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet4f& y, const Packet2cf& c) const
- { return padd(c, pmul(x,y)); }
-
- EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& x, const Packet4f& y) const
- { return Packet2cf(Eigen::internal::pmul(x.v, y)); }
-};
-
-template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
-{
- // TODO optimize it for SSE3 and 4
- Packet2cf res = conj_helper<Packet2cf,Packet2cf,false,true>().pmul(a,b);
- __m128 s = _mm_mul_ps(b.v,b.v);
- return Packet2cf(_mm_div_ps(res.v,_mm_add_ps(s,_mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(s), 0xb1)))));
-}
-
-EIGEN_STRONG_INLINE Packet2cf pcplxflip/*<Packet2cf>*/(const Packet2cf& x)
-{
- return Packet2cf(vec4f_swizzle1(x.v, 1, 0, 3, 2));
-}
-
-
-//---------- double ----------
-struct Packet1cd
-{
- EIGEN_STRONG_INLINE Packet1cd() {}
- EIGEN_STRONG_INLINE explicit Packet1cd(const __m128d& a) : v(a) {}
- __m128d v;
-};
-
-template<> struct packet_traits<std::complex<double> > : default_packet_traits
-{
- typedef Packet1cd type;
- enum {
- Vectorizable = 1,
- AlignedOnScalar = 0,
- size = 1,
-
- HasAdd = 1,
- HasSub = 1,
- HasMul = 1,
- HasDiv = 1,
- HasNegate = 1,
- HasAbs = 0,
- HasAbs2 = 0,
- HasMin = 0,
- HasMax = 0,
- HasSetLinear = 0
- };
-};
-
-template<> struct unpacket_traits<Packet1cd> { typedef std::complex<double> type; enum {size=1}; };
-
-template<> EIGEN_STRONG_INLINE Packet1cd padd<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(_mm_add_pd(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet1cd psub<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(_mm_sub_pd(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a) { return Packet1cd(pnegate(a.v)); }
-template<> EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a)
-{
- const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0));
- return Packet1cd(_mm_xor_pd(a.v,mask));
-}
-
-template<> EIGEN_STRONG_INLINE Packet1cd pmul<Packet1cd>(const Packet1cd& a, const Packet1cd& b)
-{
- // TODO optimize it for SSE3 and 4
- #ifdef EIGEN_VECTORIZE_SSE3
- return Packet1cd(_mm_addsub_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 0, 0), b.v),
- _mm_mul_pd(vec2d_swizzle1(a.v, 1, 1),
- vec2d_swizzle1(b.v, 1, 0))));
- #else
- const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x0,0x0,0x80000000,0x0));
- return Packet1cd(_mm_add_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 0, 0), b.v),
- _mm_xor_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 1, 1),
- vec2d_swizzle1(b.v, 1, 0)), mask)));
- #endif
-}
-
-template<> EIGEN_STRONG_INLINE Packet1cd pand <Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(_mm_and_pd(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet1cd por <Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(_mm_or_pd(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet1cd pxor <Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(_mm_xor_pd(a.v,b.v)); }
-template<> EIGEN_STRONG_INLINE Packet1cd pandnot<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(_mm_andnot_pd(a.v,b.v)); }
-
-// FIXME force unaligned load, this is a temporary fix
-template<> EIGEN_STRONG_INLINE Packet1cd pload <Packet1cd>(const std::complex<double>* from)
-{ EIGEN_DEBUG_ALIGNED_LOAD return Packet1cd(pload<Packet2d>((const double*)from)); }
-template<> EIGEN_STRONG_INLINE Packet1cd ploadu<Packet1cd>(const std::complex<double>* from)
-{ EIGEN_DEBUG_UNALIGNED_LOAD return Packet1cd(ploadu<Packet2d>((const double*)from)); }
-template<> EIGEN_STRONG_INLINE Packet1cd pset1<Packet1cd>(const std::complex<double>& from)
-{ /* here we really have to use unaligned loads :( */ return ploadu<Packet1cd>(&from); }
-
-template<> EIGEN_STRONG_INLINE Packet1cd ploaddup<Packet1cd>(const std::complex<double>* from) { return pset1<Packet1cd>(*from); }
-
-// FIXME force unaligned store, this is a temporary fix
-template<> EIGEN_STRONG_INLINE void pstore <std::complex<double> >(std::complex<double> * to, const Packet1cd& from) { EIGEN_DEBUG_ALIGNED_STORE pstore((double*)to, from.v); }
-template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<double> >(std::complex<double> * to, const Packet1cd& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, from.v); }
-
-template<> EIGEN_STRONG_INLINE void prefetch<std::complex<double> >(const std::complex<double> * addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
-
-template<> EIGEN_STRONG_INLINE std::complex<double> pfirst<Packet1cd>(const Packet1cd& a)
-{
- EIGEN_ALIGN16 double res[2];
- _mm_store_pd(res, a.v);
- return std::complex<double>(res[0],res[1]);
-}
-
-template<> EIGEN_STRONG_INLINE Packet1cd preverse(const Packet1cd& a) { return a; }
-
-template<> EIGEN_STRONG_INLINE std::complex<double> predux<Packet1cd>(const Packet1cd& a)
-{
- return pfirst(a);
-}
-
-template<> EIGEN_STRONG_INLINE Packet1cd preduxp<Packet1cd>(const Packet1cd* vecs)
-{
- return vecs[0];
-}
-
-template<> EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet1cd>(const Packet1cd& a)
-{
- return pfirst(a);
-}
-
-template<int Offset>
-struct palign_impl<Offset,Packet1cd>
-{
- EIGEN_STRONG_INLINE static void run(Packet1cd& /*first*/, const Packet1cd& /*second*/)
- {
- // FIXME is it sure we never have to align a Packet1cd?
- // Even though a std::complex<double> has 16 bytes, it is not necessarily aligned on a 16 bytes boundary...
- }
-};
-
-template<> struct conj_helper<Packet1cd, Packet1cd, false,true>
-{
- EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
- { return padd(pmul(x,y),c); }
-
- EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
- {
- #ifdef EIGEN_VECTORIZE_SSE3
- return internal::pmul(a, pconj(b));
- #else
- const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0));
- return Packet1cd(_mm_add_pd(_mm_xor_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 0, 0), b.v), mask),
- _mm_mul_pd(vec2d_swizzle1(a.v, 1, 1),
- vec2d_swizzle1(b.v, 1, 0))));
- #endif
- }
-};
-
-template<> struct conj_helper<Packet1cd, Packet1cd, true,false>
-{
- EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
- { return padd(pmul(x,y),c); }
-
- EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
- {
- #ifdef EIGEN_VECTORIZE_SSE3
- return internal::pmul(pconj(a), b);
- #else
- const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0));
- return Packet1cd(_mm_add_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 0, 0), b.v),
- _mm_xor_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 1, 1),
- vec2d_swizzle1(b.v, 1, 0)), mask)));
- #endif
- }
-};
-
-template<> struct conj_helper<Packet1cd, Packet1cd, true,true>
-{
- EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
- { return padd(pmul(x,y),c); }
-
- EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
- {
- #ifdef EIGEN_VECTORIZE_SSE3
- return pconj(internal::pmul(a, b));
- #else
- const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0));
- return Packet1cd(_mm_sub_pd(_mm_xor_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 0, 0), b.v), mask),
- _mm_mul_pd(vec2d_swizzle1(a.v, 1, 1),
- vec2d_swizzle1(b.v, 1, 0))));
- #endif
- }
-};
-
-template<> struct conj_helper<Packet2d, Packet1cd, false,false>
-{
- EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet2d& x, const Packet1cd& y, const Packet1cd& c) const
- { return padd(c, pmul(x,y)); }
-
- EIGEN_STRONG_INLINE Packet1cd pmul(const Packet2d& x, const Packet1cd& y) const
- { return Packet1cd(Eigen::internal::pmul(x, y.v)); }
-};
-
-template<> struct conj_helper<Packet1cd, Packet2d, false,false>
-{
- EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet2d& y, const Packet1cd& c) const
- { return padd(c, pmul(x,y)); }
-
- EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& x, const Packet2d& y) const
- { return Packet1cd(Eigen::internal::pmul(x.v, y)); }
-};
-
-template<> EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b)
-{
- // TODO optimize it for SSE3 and 4
- Packet1cd res = conj_helper<Packet1cd,Packet1cd,false,true>().pmul(a,b);
- __m128d s = _mm_mul_pd(b.v,b.v);
- return Packet1cd(_mm_div_pd(res.v, _mm_add_pd(s,_mm_shuffle_pd(s, s, 0x1))));
-}
-
-EIGEN_STRONG_INLINE Packet1cd pcplxflip/*<Packet1cd>*/(const Packet1cd& x)
-{
- return Packet1cd(preverse(x.v));
-}
-
-} // end namespace internal
-
-#endif // EIGEN_COMPLEX_SSE_H
diff --git a/extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h b/extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h
deleted file mode 100644
index 9d56d82180b..00000000000
--- a/extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h
+++ /dev/null
@@ -1,395 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2007 Julien Pommier
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-/* The sin, cos, exp, and log functions of this file come from
- * Julien Pommier's sse math library: http://gruntthepeon.free.fr/ssemath/
- */
-
-#ifndef EIGEN_MATH_FUNCTIONS_SSE_H
-#define EIGEN_MATH_FUNCTIONS_SSE_H
-
-namespace internal {
-
-template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
-Packet4f plog<Packet4f>(const Packet4f& _x)
-{
- Packet4f x = _x;
- _EIGEN_DECLARE_CONST_Packet4f(1 , 1.0f);
- _EIGEN_DECLARE_CONST_Packet4f(half, 0.5f);
- _EIGEN_DECLARE_CONST_Packet4i(0x7f, 0x7f);
-
- _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(inv_mant_mask, ~0x7f800000);
-
- /* the smallest non denormalized float number */
- _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(min_norm_pos, 0x00800000);
-
- /* natural logarithm computed for 4 simultaneous float
- return NaN for x <= 0
- */
- _EIGEN_DECLARE_CONST_Packet4f(cephes_SQRTHF, 0.707106781186547524f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_log_p0, 7.0376836292E-2f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_log_p1, - 1.1514610310E-1f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_log_p2, 1.1676998740E-1f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_log_p3, - 1.2420140846E-1f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_log_p4, + 1.4249322787E-1f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_log_p5, - 1.6668057665E-1f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_log_p6, + 2.0000714765E-1f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_log_p7, - 2.4999993993E-1f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_log_p8, + 3.3333331174E-1f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_log_q1, -2.12194440e-4f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_log_q2, 0.693359375f);
-
-
- Packet4i emm0;
-
- Packet4f invalid_mask = _mm_cmple_ps(x, _mm_setzero_ps());
-
- x = pmax(x, p4f_min_norm_pos); /* cut off denormalized stuff */
- emm0 = _mm_srli_epi32(_mm_castps_si128(x), 23);
-
- /* keep only the fractional part */
- x = _mm_and_ps(x, p4f_inv_mant_mask);
- x = _mm_or_ps(x, p4f_half);
-
- emm0 = _mm_sub_epi32(emm0, p4i_0x7f);
- Packet4f e = padd(_mm_cvtepi32_ps(emm0), p4f_1);
-
- /* part2:
- if( x < SQRTHF ) {
- e -= 1;
- x = x + x - 1.0;
- } else { x = x - 1.0; }
- */
- Packet4f mask = _mm_cmplt_ps(x, p4f_cephes_SQRTHF);
- Packet4f tmp = _mm_and_ps(x, mask);
- x = psub(x, p4f_1);
- e = psub(e, _mm_and_ps(p4f_1, mask));
- x = padd(x, tmp);
-
- Packet4f x2 = pmul(x,x);
- Packet4f x3 = pmul(x2,x);
-
- Packet4f y, y1, y2;
- y = pmadd(p4f_cephes_log_p0, x, p4f_cephes_log_p1);
- y1 = pmadd(p4f_cephes_log_p3, x, p4f_cephes_log_p4);
- y2 = pmadd(p4f_cephes_log_p6, x, p4f_cephes_log_p7);
- y = pmadd(y , x, p4f_cephes_log_p2);
- y1 = pmadd(y1, x, p4f_cephes_log_p5);
- y2 = pmadd(y2, x, p4f_cephes_log_p8);
- y = pmadd(y, x3, y1);
- y = pmadd(y, x3, y2);
- y = pmul(y, x3);
-
- y1 = pmul(e, p4f_cephes_log_q1);
- tmp = pmul(x2, p4f_half);
- y = padd(y, y1);
- x = psub(x, tmp);
- y2 = pmul(e, p4f_cephes_log_q2);
- x = padd(x, y);
- x = padd(x, y2);
- return _mm_or_ps(x, invalid_mask); // negative arg will be NAN
-}
-
-template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
-Packet4f pexp<Packet4f>(const Packet4f& _x)
-{
- Packet4f x = _x;
- _EIGEN_DECLARE_CONST_Packet4f(1 , 1.0f);
- _EIGEN_DECLARE_CONST_Packet4f(half, 0.5f);
- _EIGEN_DECLARE_CONST_Packet4i(0x7f, 0x7f);
-
-
- _EIGEN_DECLARE_CONST_Packet4f(exp_hi, 88.3762626647949f);
- _EIGEN_DECLARE_CONST_Packet4f(exp_lo, -88.3762626647949f);
-
- _EIGEN_DECLARE_CONST_Packet4f(cephes_LOG2EF, 1.44269504088896341f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_C1, 0.693359375f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_C2, -2.12194440e-4f);
-
- _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p0, 1.9875691500E-4f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p1, 1.3981999507E-3f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p2, 8.3334519073E-3f);
- _EIGEN_DECLARE_CONST_Packet4f(cephes_exp_p3, 4.1665795894E-2f);
- _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;
- Packet4i emm0;
-
- // clamp x
- x = pmax(pmin(x, p4f_exp_hi), p4f_exp_lo);
-
- /* express exp(x) as exp(g + n*log(2)) */
- fx = pmadd(x, p4f_cephes_LOG2EF, p4f_half);
-
- /* how to perform a floorf with SSE: just below */
- emm0 = _mm_cvttps_epi32(fx);
- tmp = _mm_cvtepi32_ps(emm0);
- /* if greater, substract 1 */
- Packet4f mask = _mm_cmpgt_ps(tmp, fx);
- mask = _mm_and_ps(mask, p4f_1);
- fx = psub(tmp, mask);
-
- tmp = pmul(fx, p4f_cephes_exp_C1);
- Packet4f z = pmul(fx, p4f_cephes_exp_C2);
- x = psub(x, tmp);
- x = psub(x, z);
-
- z = pmul(x,x);
-
- Packet4f y = p4f_cephes_exp_p0;
- y = pmadd(y, x, p4f_cephes_exp_p1);
- y = pmadd(y, x, p4f_cephes_exp_p2);
- y = pmadd(y, x, p4f_cephes_exp_p3);
- y = pmadd(y, x, p4f_cephes_exp_p4);
- y = pmadd(y, x, p4f_cephes_exp_p5);
- y = pmadd(y, z, x);
- y = padd(y, p4f_1);
-
- /* build 2^n */
- 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));
-}
-
-/* evaluation of 4 sines at onces, using SSE2 intrinsics.
-
- The code is the exact rewriting of the cephes sinf function.
- Precision is excellent as long as x < 8192 (I did not bother to
- take into account the special handling they have for greater values
- -- it does not return garbage for arguments over 8192, though, but
- the extra precision is missing).
-
- Note that it is such that sinf((float)M_PI) = 8.74e-8, which is the
- surprising but correct result.
-*/
-
-template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
-Packet4f psin<Packet4f>(const Packet4f& _x)
-{
- Packet4f x = _x;
- _EIGEN_DECLARE_CONST_Packet4f(1 , 1.0f);
- _EIGEN_DECLARE_CONST_Packet4f(half, 0.5f);
-
- _EIGEN_DECLARE_CONST_Packet4i(1, 1);
- _EIGEN_DECLARE_CONST_Packet4i(not1, ~1);
- _EIGEN_DECLARE_CONST_Packet4i(2, 2);
- _EIGEN_DECLARE_CONST_Packet4i(4, 4);
-
- _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(sign_mask, 0x80000000);
-
- _EIGEN_DECLARE_CONST_Packet4f(minus_cephes_DP1,-0.78515625f);
- _EIGEN_DECLARE_CONST_Packet4f(minus_cephes_DP2, -2.4187564849853515625e-4f);
- _EIGEN_DECLARE_CONST_Packet4f(minus_cephes_DP3, -3.77489497744594108e-8f);
- _EIGEN_DECLARE_CONST_Packet4f(sincof_p0, -1.9515295891E-4f);
- _EIGEN_DECLARE_CONST_Packet4f(sincof_p1, 8.3321608736E-3f);
- _EIGEN_DECLARE_CONST_Packet4f(sincof_p2, -1.6666654611E-1f);
- _EIGEN_DECLARE_CONST_Packet4f(coscof_p0, 2.443315711809948E-005f);
- _EIGEN_DECLARE_CONST_Packet4f(coscof_p1, -1.388731625493765E-003f);
- _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;
-
- Packet4i emm0, emm2;
- sign_bit = x;
- /* take the absolute value */
- x = pabs(x);
-
- /* take the modulo */
-
- /* extract the sign bit (upper one) */
- sign_bit = _mm_and_ps(sign_bit, p4f_sign_mask);
-
- /* scale by 4/Pi */
- y = pmul(x, p4f_cephes_FOPI);
-
- /* store the integer part of y in mm0 */
- emm2 = _mm_cvttps_epi32(y);
- /* j=(j+1) & (~1) (see the cephes sources) */
- emm2 = _mm_add_epi32(emm2, p4i_1);
- emm2 = _mm_and_si128(emm2, p4i_not1);
- y = _mm_cvtepi32_ps(emm2);
- /* get the swap sign flag */
- emm0 = _mm_and_si128(emm2, p4i_4);
- emm0 = _mm_slli_epi32(emm0, 29);
- /* get the polynom selection mask
- there is one polynom for 0 <= x <= Pi/4
- and another one for Pi/4<x<=Pi/2
-
- Both branches will be computed.
- */
- emm2 = _mm_and_si128(emm2, p4i_2);
- emm2 = _mm_cmpeq_epi32(emm2, _mm_setzero_si128());
-
- Packet4f swap_sign_bit = _mm_castsi128_ps(emm0);
- Packet4f poly_mask = _mm_castsi128_ps(emm2);
- sign_bit = _mm_xor_ps(sign_bit, swap_sign_bit);
-
- /* The magic pass: "Extended precision modular arithmetic"
- x = ((x - y * DP1) - y * DP2) - y * DP3; */
- xmm1 = pmul(y, p4f_minus_cephes_DP1);
- xmm2 = pmul(y, p4f_minus_cephes_DP2);
- xmm3 = pmul(y, p4f_minus_cephes_DP3);
- x = padd(x, xmm1);
- x = padd(x, xmm2);
- x = padd(x, xmm3);
-
- /* Evaluate the first polynom (0 <= x <= Pi/4) */
- y = p4f_coscof_p0;
- Packet4f z = _mm_mul_ps(x,x);
-
- y = pmadd(y, z, p4f_coscof_p1);
- y = pmadd(y, z, p4f_coscof_p2);
- y = pmul(y, z);
- y = pmul(y, z);
- Packet4f tmp = pmul(z, p4f_half);
- y = psub(y, tmp);
- y = padd(y, p4f_1);
-
- /* Evaluate the second polynom (Pi/4 <= x <= 0) */
-
- Packet4f y2 = p4f_sincof_p0;
- y2 = pmadd(y2, z, p4f_sincof_p1);
- y2 = pmadd(y2, z, p4f_sincof_p2);
- y2 = pmul(y2, z);
- y2 = pmul(y2, x);
- y2 = padd(y2, x);
-
- /* select the correct result from the two polynoms */
- y2 = _mm_and_ps(poly_mask, y2);
- y = _mm_andnot_ps(poly_mask, y);
- y = _mm_or_ps(y,y2);
- /* update the sign */
- return _mm_xor_ps(y, sign_bit);
-}
-
-/* almost the same as psin */
-template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
-Packet4f pcos<Packet4f>(const Packet4f& _x)
-{
- Packet4f x = _x;
- _EIGEN_DECLARE_CONST_Packet4f(1 , 1.0f);
- _EIGEN_DECLARE_CONST_Packet4f(half, 0.5f);
-
- _EIGEN_DECLARE_CONST_Packet4i(1, 1);
- _EIGEN_DECLARE_CONST_Packet4i(not1, ~1);
- _EIGEN_DECLARE_CONST_Packet4i(2, 2);
- _EIGEN_DECLARE_CONST_Packet4i(4, 4);
-
- _EIGEN_DECLARE_CONST_Packet4f(minus_cephes_DP1,-0.78515625f);
- _EIGEN_DECLARE_CONST_Packet4f(minus_cephes_DP2, -2.4187564849853515625e-4f);
- _EIGEN_DECLARE_CONST_Packet4f(minus_cephes_DP3, -3.77489497744594108e-8f);
- _EIGEN_DECLARE_CONST_Packet4f(sincof_p0, -1.9515295891E-4f);
- _EIGEN_DECLARE_CONST_Packet4f(sincof_p1, 8.3321608736E-3f);
- _EIGEN_DECLARE_CONST_Packet4f(sincof_p2, -1.6666654611E-1f);
- _EIGEN_DECLARE_CONST_Packet4f(coscof_p0, 2.443315711809948E-005f);
- _EIGEN_DECLARE_CONST_Packet4f(coscof_p1, -1.388731625493765E-003f);
- _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;
- Packet4i emm0, emm2;
-
- x = pabs(x);
-
- /* scale by 4/Pi */
- y = pmul(x, p4f_cephes_FOPI);
-
- /* get the integer part of y */
- emm2 = _mm_cvttps_epi32(y);
- /* j=(j+1) & (~1) (see the cephes sources) */
- emm2 = _mm_add_epi32(emm2, p4i_1);
- emm2 = _mm_and_si128(emm2, p4i_not1);
- y = _mm_cvtepi32_ps(emm2);
-
- emm2 = _mm_sub_epi32(emm2, p4i_2);
-
- /* get the swap sign flag */
- emm0 = _mm_andnot_si128(emm2, p4i_4);
- emm0 = _mm_slli_epi32(emm0, 29);
- /* get the polynom selection mask */
- emm2 = _mm_and_si128(emm2, p4i_2);
- emm2 = _mm_cmpeq_epi32(emm2, _mm_setzero_si128());
-
- Packet4f sign_bit = _mm_castsi128_ps(emm0);
- Packet4f poly_mask = _mm_castsi128_ps(emm2);
-
- /* The magic pass: "Extended precision modular arithmetic"
- x = ((x - y * DP1) - y * DP2) - y * DP3; */
- xmm1 = pmul(y, p4f_minus_cephes_DP1);
- xmm2 = pmul(y, p4f_minus_cephes_DP2);
- xmm3 = pmul(y, p4f_minus_cephes_DP3);
- x = padd(x, xmm1);
- x = padd(x, xmm2);
- x = padd(x, xmm3);
-
- /* Evaluate the first polynom (0 <= x <= Pi/4) */
- y = p4f_coscof_p0;
- Packet4f z = pmul(x,x);
-
- y = pmadd(y,z,p4f_coscof_p1);
- y = pmadd(y,z,p4f_coscof_p2);
- y = pmul(y, z);
- y = pmul(y, z);
- Packet4f tmp = _mm_mul_ps(z, p4f_half);
- y = psub(y, tmp);
- y = padd(y, p4f_1);
-
- /* Evaluate the second polynom (Pi/4 <= x <= 0) */
- Packet4f y2 = p4f_sincof_p0;
- y2 = pmadd(y2, z, p4f_sincof_p1);
- y2 = pmadd(y2, z, p4f_sincof_p2);
- y2 = pmul(y2, z);
- y2 = pmadd(y2, x, x);
-
- /* select the correct result from the two polynoms */
- y2 = _mm_and_ps(poly_mask, y2);
- y = _mm_andnot_ps(poly_mask, y);
- y = _mm_or_ps(y,y2);
-
- /* update the sign */
- return _mm_xor_ps(y, sign_bit);
-}
-
-// This is based on Quake3's fast inverse square root.
-// For detail see here: http://www.beyond3d.com/content/articles/8/
-template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED
-Packet4f psqrt<Packet4f>(const Packet4f& _x)
-{
- Packet4f half = pmul(_x, pset1<Packet4f>(.5f));
-
- /* select only the inverse sqrt of non-zero inputs */
- Packet4f non_zero_mask = _mm_cmpgt_ps(_x, pset1<Packet4f>(std::numeric_limits<float>::epsilon()));
- Packet4f x = _mm_and_ps(non_zero_mask, _mm_rsqrt_ps(_x));
-
- x = pmul(x, psub(pset1<Packet4f>(1.5f), pmul(half, pmul(x,x))));
- return pmul(_x,x);
-}
-
-} // end namespace internal
-
-#endif // EIGEN_MATH_FUNCTIONS_SSE_H
diff --git a/extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h b/extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h
deleted file mode 100644
index 908e27368e8..00000000000
--- a/extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h
+++ /dev/null
@@ -1,634 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_PACKET_MATH_SSE_H
-#define EIGEN_PACKET_MATH_SSE_H
-
-namespace internal {
-
-#ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
-#define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 8
-#endif
-
-#ifndef EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS
-#define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS (2*sizeof(void*))
-#endif
-
-typedef __m128 Packet4f;
-typedef __m128i Packet4i;
-typedef __m128d Packet2d;
-
-template<> struct is_arithmetic<__m128> { enum { value = true }; };
-template<> struct is_arithmetic<__m128i> { enum { value = true }; };
-template<> struct is_arithmetic<__m128d> { enum { value = true }; };
-
-#define vec4f_swizzle1(v,p,q,r,s) \
- (_mm_castsi128_ps(_mm_shuffle_epi32( _mm_castps_si128(v), ((s)<<6|(r)<<4|(q)<<2|(p)))))
-
-#define vec4i_swizzle1(v,p,q,r,s) \
- (_mm_shuffle_epi32( v, ((s)<<6|(r)<<4|(q)<<2|(p))))
-
-#define vec2d_swizzle1(v,p,q) \
- (_mm_castsi128_pd(_mm_shuffle_epi32( _mm_castpd_si128(v), ((q*2+1)<<6|(q*2)<<4|(p*2+1)<<2|(p*2)))))
-
-#define vec4f_swizzle2(a,b,p,q,r,s) \
- (_mm_shuffle_ps( (a), (b), ((s)<<6|(r)<<4|(q)<<2|(p))))
-
-#define vec4i_swizzle2(a,b,p,q,r,s) \
- (_mm_castps_si128( (_mm_shuffle_ps( _mm_castsi128_ps(a), _mm_castsi128_ps(b), ((s)<<6|(r)<<4|(q)<<2|(p))))))
-
-#define _EIGEN_DECLARE_CONST_Packet4f(NAME,X) \
- const Packet4f p4f_##NAME = pset1<Packet4f>(X)
-
-#define _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(NAME,X) \
- const Packet4f p4f_##NAME = _mm_castsi128_ps(pset1<Packet4i>(X))
-
-#define _EIGEN_DECLARE_CONST_Packet4i(NAME,X) \
- const Packet4i p4i_##NAME = pset1<Packet4i>(X)
-
-
-template<> struct packet_traits<float> : default_packet_traits
-{
- typedef Packet4f type;
- enum {
- Vectorizable = 1,
- AlignedOnScalar = 1,
- size=4,
-
- HasDiv = 1,
- HasSin = EIGEN_FAST_MATH,
- HasCos = EIGEN_FAST_MATH,
- HasLog = 1,
- HasExp = 1,
- HasSqrt = 1
- };
-};
-template<> struct packet_traits<double> : default_packet_traits
-{
- typedef Packet2d type;
- enum {
- Vectorizable = 1,
- AlignedOnScalar = 1,
- size=2,
-
- HasDiv = 1
- };
-};
-template<> struct packet_traits<int> : default_packet_traits
-{
- typedef Packet4i type;
- enum {
- // FIXME check the Has*
- Vectorizable = 1,
- AlignedOnScalar = 1,
- size=4
- };
-};
-
-template<> struct unpacket_traits<Packet4f> { typedef float type; enum {size=4}; };
-template<> struct unpacket_traits<Packet2d> { typedef double type; enum {size=2}; };
-template<> struct unpacket_traits<Packet4i> { typedef int type; enum {size=4}; };
-
-template<> EIGEN_STRONG_INLINE Packet4f pset1<Packet4f>(const float& from) { return _mm_set1_ps(from); }
-template<> EIGEN_STRONG_INLINE Packet2d pset1<Packet2d>(const double& from) { return _mm_set1_pd(from); }
-template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int& from) { return _mm_set1_epi32(from); }
-
-template<> EIGEN_STRONG_INLINE Packet4f plset<float>(const float& a) { return _mm_add_ps(pset1<Packet4f>(a), _mm_set_ps(3,2,1,0)); }
-template<> EIGEN_STRONG_INLINE Packet2d plset<double>(const double& a) { return _mm_add_pd(pset1<Packet2d>(a),_mm_set_pd(1,0)); }
-template<> EIGEN_STRONG_INLINE Packet4i plset<int>(const int& a) { return _mm_add_epi32(pset1<Packet4i>(a),_mm_set_epi32(3,2,1,0)); }
-
-template<> EIGEN_STRONG_INLINE Packet4f padd<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_add_ps(a,b); }
-template<> EIGEN_STRONG_INLINE Packet2d padd<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_add_pd(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i padd<Packet4i>(const Packet4i& a, const Packet4i& b) { return _mm_add_epi32(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f psub<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_sub_ps(a,b); }
-template<> EIGEN_STRONG_INLINE Packet2d psub<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_sub_pd(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i psub<Packet4i>(const Packet4i& a, const Packet4i& b) { return _mm_sub_epi32(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pnegate(const Packet4f& a)
-{
- const Packet4f mask = _mm_castsi128_ps(_mm_setr_epi32(0x80000000,0x80000000,0x80000000,0x80000000));
- return _mm_xor_ps(a,mask);
-}
-template<> EIGEN_STRONG_INLINE Packet2d pnegate(const Packet2d& a)
-{
- const Packet2d mask = _mm_castsi128_pd(_mm_setr_epi32(0x0,0x80000000,0x0,0x80000000));
- return _mm_xor_pd(a,mask);
-}
-template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a)
-{
- return psub(_mm_setr_epi32(0,0,0,0), a);
-}
-
-template<> EIGEN_STRONG_INLINE Packet4f pmul<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_mul_ps(a,b); }
-template<> EIGEN_STRONG_INLINE Packet2d pmul<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_mul_pd(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i pmul<Packet4i>(const Packet4i& a, const Packet4i& b)
-{
-#ifdef EIGEN_VECTORIZE_SSE4_1
- return _mm_mullo_epi32(a,b);
-#else
- // this version is slightly faster than 4 scalar products
- return vec4i_swizzle1(
- vec4i_swizzle2(
- _mm_mul_epu32(a,b),
- _mm_mul_epu32(vec4i_swizzle1(a,1,0,3,2),
- vec4i_swizzle1(b,1,0,3,2)),
- 0,2,0,2),
- 0,2,1,3);
-#endif
-}
-
-template<> EIGEN_STRONG_INLINE Packet4f pdiv<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_div_ps(a,b); }
-template<> EIGEN_STRONG_INLINE Packet2d pdiv<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_div_pd(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i pdiv<Packet4i>(const Packet4i& /*a*/, const Packet4i& /*b*/)
-{ eigen_assert(false && "packet integer division are not supported by SSE");
- return pset1<Packet4i>(0);
-}
-
-// for some weird raisons, it has to be overloaded for packet of integers
-template<> EIGEN_STRONG_INLINE Packet4i pmadd(const Packet4i& a, const Packet4i& b, const Packet4i& c) { return padd(pmul(a,b), c); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pmin<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_min_ps(a,b); }
-template<> EIGEN_STRONG_INLINE Packet2d pmin<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_min_pd(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i pmin<Packet4i>(const Packet4i& a, const Packet4i& b)
-{
- // after some bench, this version *is* faster than a scalar implementation
- Packet4i mask = _mm_cmplt_epi32(a,b);
- return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b));
-}
-
-template<> EIGEN_STRONG_INLINE Packet4f pmax<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_max_ps(a,b); }
-template<> EIGEN_STRONG_INLINE Packet2d pmax<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_max_pd(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i pmax<Packet4i>(const Packet4i& a, const Packet4i& b)
-{
- // after some bench, this version *is* faster than a scalar implementation
- Packet4i mask = _mm_cmpgt_epi32(a,b);
- return _mm_or_si128(_mm_and_si128(mask,a),_mm_andnot_si128(mask,b));
-}
-
-template<> EIGEN_STRONG_INLINE Packet4f pand<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_and_ps(a,b); }
-template<> EIGEN_STRONG_INLINE Packet2d pand<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_and_pd(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i pand<Packet4i>(const Packet4i& a, const Packet4i& b) { return _mm_and_si128(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f por<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_or_ps(a,b); }
-template<> EIGEN_STRONG_INLINE Packet2d por<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_or_pd(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i por<Packet4i>(const Packet4i& a, const Packet4i& b) { return _mm_or_si128(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pxor<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_xor_ps(a,b); }
-template<> EIGEN_STRONG_INLINE Packet2d pxor<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_xor_pd(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i pxor<Packet4i>(const Packet4i& a, const Packet4i& b) { return _mm_xor_si128(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pandnot<Packet4f>(const Packet4f& a, const Packet4f& b) { return _mm_andnot_ps(a,b); }
-template<> EIGEN_STRONG_INLINE Packet2d pandnot<Packet2d>(const Packet2d& a, const Packet2d& b) { return _mm_andnot_pd(a,b); }
-template<> EIGEN_STRONG_INLINE Packet4i pandnot<Packet4i>(const Packet4i& a, const Packet4i& b) { return _mm_andnot_si128(a,b); }
-
-template<> EIGEN_STRONG_INLINE Packet4f pload<Packet4f>(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm_load_ps(from); }
-template<> EIGEN_STRONG_INLINE Packet2d pload<Packet2d>(const double* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm_load_pd(from); }
-template<> EIGEN_STRONG_INLINE Packet4i pload<Packet4i>(const int* from) { EIGEN_DEBUG_ALIGNED_LOAD return _mm_load_si128(reinterpret_cast<const Packet4i*>(from)); }
-
-#if defined(_MSC_VER)
- template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from) {
- EIGEN_DEBUG_UNALIGNED_LOAD
- #if (_MSC_VER==1600)
- // NOTE Some version of MSVC10 generates bad code when using _mm_loadu_ps
- // (i.e., it does not generate an unaligned load!!
- // TODO On most architectures this version should also be faster than a single _mm_loadu_ps
- // so we could also enable it for MSVC08 but first we have to make this later does not generate crap when doing so...
- __m128 res = _mm_loadl_pi(_mm_set1_ps(0.0f), (const __m64*)(from));
- res = _mm_loadh_pi(res, (const __m64*)(from+2));
- return res;
- #else
- return _mm_loadu_ps(from);
- #endif
- }
- template<> EIGEN_STRONG_INLINE Packet2d ploadu<Packet2d>(const double* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_pd(from); }
- template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm_loadu_si128(reinterpret_cast<const Packet4i*>(from)); }
-#else
-// Fast unaligned loads. Note that here we cannot directly use intrinsics: this would
-// require pointer casting to incompatible pointer types and leads to invalid code
-// because of the strict aliasing rule. The "dummy" stuff are required to enforce
-// a correct instruction dependency.
-// TODO: do the same for MSVC (ICC is compatible)
-// NOTE: with the code below, MSVC's compiler crashes!
-
-#if defined(__GNUC__) && defined(__i386__)
- // bug 195: gcc/i386 emits weird x87 fldl/fstpl instructions for _mm_load_sd
- #define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1
-#elif defined(__clang__)
- // bug 201: Segfaults in __mm_loadh_pd with clang 2.8
- #define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 1
-#else
- #define EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS 0
-#endif
-
-template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from)
-{
- EIGEN_DEBUG_UNALIGNED_LOAD
-#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS
- return _mm_loadu_ps(from);
-#else
- __m128d res;
- res = _mm_load_sd((const double*)(from)) ;
- res = _mm_loadh_pd(res, (const double*)(from+2)) ;
- return _mm_castpd_ps(res);
-#endif
-}
-template<> EIGEN_STRONG_INLINE Packet2d ploadu<Packet2d>(const double* from)
-{
- EIGEN_DEBUG_UNALIGNED_LOAD
-#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS
- return _mm_loadu_pd(from);
-#else
- __m128d res;
- res = _mm_load_sd(from) ;
- res = _mm_loadh_pd(res,from+1);
- return res;
-#endif
-}
-template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from)
-{
- EIGEN_DEBUG_UNALIGNED_LOAD
-#if EIGEN_AVOID_CUSTOM_UNALIGNED_LOADS
- return _mm_loadu_si128(reinterpret_cast<const Packet4i*>(from));
-#else
- __m128d res;
- res = _mm_load_sd((const double*)(from)) ;
- res = _mm_loadh_pd(res, (const double*)(from+2)) ;
- return _mm_castpd_si128(res);
-#endif
-}
-#endif
-
-template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
-{
- return vec4f_swizzle1(_mm_castpd_ps(_mm_load_sd((const double*)from)), 0, 0, 1, 1);
-}
-template<> EIGEN_STRONG_INLINE Packet2d ploaddup<Packet2d>(const double* from)
-{ return pset1<Packet2d>(from[0]); }
-template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from)
-{
- Packet4i tmp;
- tmp = _mm_loadl_epi64(reinterpret_cast<const Packet4i*>(from));
- return vec4i_swizzle1(tmp, 0, 0, 1, 1);
-}
-
-template<> EIGEN_STRONG_INLINE void pstore<float>(float* to, const Packet4f& from) { EIGEN_DEBUG_ALIGNED_STORE _mm_store_ps(to, from); }
-template<> EIGEN_STRONG_INLINE void pstore<double>(double* to, const Packet2d& from) { EIGEN_DEBUG_ALIGNED_STORE _mm_store_pd(to, from); }
-template<> EIGEN_STRONG_INLINE void pstore<int>(int* to, const Packet4i& from) { EIGEN_DEBUG_ALIGNED_STORE _mm_store_si128(reinterpret_cast<Packet4i*>(to), from); }
-
-template<> EIGEN_STRONG_INLINE void pstoreu<double>(double* to, const Packet2d& from) {
- EIGEN_DEBUG_UNALIGNED_STORE
- _mm_storel_pd((to), from);
- _mm_storeh_pd((to+1), from);
-}
-template<> EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, _mm_castps_pd(from)); }
-template<> EIGEN_STRONG_INLINE void pstoreu<int>(int* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, _mm_castsi128_pd(from)); }
-
-// some compilers might be tempted to perform multiple moves instead of using a vector path.
-template<> EIGEN_STRONG_INLINE void pstore1<Packet4f>(float* to, const float& a)
-{
- Packet4f pa = _mm_set_ss(a);
- pstore(to, vec4f_swizzle1(pa,0,0,0,0));
-}
-// some compilers might be tempted to perform multiple moves instead of using a vector path.
-template<> EIGEN_STRONG_INLINE void pstore1<Packet2d>(double* to, const double& a)
-{
- Packet2d pa = _mm_set_sd(a);
- pstore(to, vec2d_swizzle1(pa,0,0));
-}
-
-template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
-template<> EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
-template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { _mm_prefetch((const char*)(addr), _MM_HINT_T0); }
-
-#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER)
-// The temporary variable fixes an internal compilation error in vs <= 2008 and a wrong-result bug in vs 2010
-// Direct of the struct members fixed bug #62.
-template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { return a.m128_f32[0]; }
-template<> EIGEN_STRONG_INLINE double pfirst<Packet2d>(const Packet2d& a) { return a.m128d_f64[0]; }
-template<> EIGEN_STRONG_INLINE int pfirst<Packet4i>(const Packet4i& a) { int x = _mm_cvtsi128_si32(a); return x; }
-#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER)
-// The temporary variable fixes an internal compilation error in vs <= 2008 and a wrong-result bug in vs 2010
-template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { float x = _mm_cvtss_f32(a); return x; }
-template<> EIGEN_STRONG_INLINE double pfirst<Packet2d>(const Packet2d& a) { double x = _mm_cvtsd_f64(a); return x; }
-template<> EIGEN_STRONG_INLINE int pfirst<Packet4i>(const Packet4i& a) { int x = _mm_cvtsi128_si32(a); return x; }
-#else
-template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { return _mm_cvtss_f32(a); }
-template<> EIGEN_STRONG_INLINE double pfirst<Packet2d>(const Packet2d& a) { return _mm_cvtsd_f64(a); }
-template<> EIGEN_STRONG_INLINE int pfirst<Packet4i>(const Packet4i& a) { return _mm_cvtsi128_si32(a); }
-#endif
-
-template<> EIGEN_STRONG_INLINE Packet4f preverse(const Packet4f& a)
-{ return _mm_shuffle_ps(a,a,0x1B); }
-template<> EIGEN_STRONG_INLINE Packet2d preverse(const Packet2d& a)
-{ return _mm_shuffle_pd(a,a,0x1); }
-template<> EIGEN_STRONG_INLINE Packet4i preverse(const Packet4i& a)
-{ return _mm_shuffle_epi32(a,0x1B); }
-
-
-template<> EIGEN_STRONG_INLINE Packet4f pabs(const Packet4f& a)
-{
- const Packet4f mask = _mm_castsi128_ps(_mm_setr_epi32(0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF));
- return _mm_and_ps(a,mask);
-}
-template<> EIGEN_STRONG_INLINE Packet2d pabs(const Packet2d& a)
-{
- const Packet2d mask = _mm_castsi128_pd(_mm_setr_epi32(0xFFFFFFFF,0x7FFFFFFF,0xFFFFFFFF,0x7FFFFFFF));
- return _mm_and_pd(a,mask);
-}
-template<> EIGEN_STRONG_INLINE Packet4i pabs(const Packet4i& a)
-{
- #ifdef EIGEN_VECTORIZE_SSSE3
- return _mm_abs_epi32(a);
- #else
- Packet4i aux = _mm_srai_epi32(a,31);
- return _mm_sub_epi32(_mm_xor_si128(a,aux),aux);
- #endif
-}
-
-EIGEN_STRONG_INLINE void punpackp(Packet4f* vecs)
-{
- vecs[1] = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(vecs[0]), 0x55));
- vecs[2] = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(vecs[0]), 0xAA));
- vecs[3] = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(vecs[0]), 0xFF));
- vecs[0] = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(vecs[0]), 0x00));
-}
-
-#ifdef EIGEN_VECTORIZE_SSE3
-// TODO implement SSE2 versions as well as integer versions
-template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs)
-{
- return _mm_hadd_ps(_mm_hadd_ps(vecs[0], vecs[1]),_mm_hadd_ps(vecs[2], vecs[3]));
-}
-template<> EIGEN_STRONG_INLINE Packet2d preduxp<Packet2d>(const Packet2d* vecs)
-{
- return _mm_hadd_pd(vecs[0], vecs[1]);
-}
-// SSSE3 version:
-// EIGEN_STRONG_INLINE Packet4i preduxp(const Packet4i* vecs)
-// {
-// return _mm_hadd_epi32(_mm_hadd_epi32(vecs[0], vecs[1]),_mm_hadd_epi32(vecs[2], vecs[3]));
-// }
-
-template<> EIGEN_STRONG_INLINE float predux<Packet4f>(const Packet4f& a)
-{
- Packet4f tmp0 = _mm_hadd_ps(a,a);
- return pfirst(_mm_hadd_ps(tmp0, tmp0));
-}
-
-template<> EIGEN_STRONG_INLINE double predux<Packet2d>(const Packet2d& a) { return pfirst(_mm_hadd_pd(a, a)); }
-
-// SSSE3 version:
-// EIGEN_STRONG_INLINE float predux(const Packet4i& a)
-// {
-// Packet4i tmp0 = _mm_hadd_epi32(a,a);
-// return pfirst(_mm_hadd_epi32(tmp0, tmp0));
-// }
-#else
-// SSE2 versions
-template<> EIGEN_STRONG_INLINE float predux<Packet4f>(const Packet4f& a)
-{
- Packet4f tmp = _mm_add_ps(a, _mm_movehl_ps(a,a));
- return pfirst(_mm_add_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1)));
-}
-template<> EIGEN_STRONG_INLINE double predux<Packet2d>(const Packet2d& a)
-{
- return pfirst(_mm_add_sd(a, _mm_unpackhi_pd(a,a)));
-}
-
-template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs)
-{
- Packet4f tmp0, tmp1, tmp2;
- tmp0 = _mm_unpacklo_ps(vecs[0], vecs[1]);
- tmp1 = _mm_unpackhi_ps(vecs[0], vecs[1]);
- tmp2 = _mm_unpackhi_ps(vecs[2], vecs[3]);
- tmp0 = _mm_add_ps(tmp0, tmp1);
- tmp1 = _mm_unpacklo_ps(vecs[2], vecs[3]);
- tmp1 = _mm_add_ps(tmp1, tmp2);
- tmp2 = _mm_movehl_ps(tmp1, tmp0);
- tmp0 = _mm_movelh_ps(tmp0, tmp1);
- return _mm_add_ps(tmp0, tmp2);
-}
-
-template<> EIGEN_STRONG_INLINE Packet2d preduxp<Packet2d>(const Packet2d* vecs)
-{
- return _mm_add_pd(_mm_unpacklo_pd(vecs[0], vecs[1]), _mm_unpackhi_pd(vecs[0], vecs[1]));
-}
-#endif // SSE3
-
-template<> EIGEN_STRONG_INLINE int predux<Packet4i>(const Packet4i& a)
-{
- Packet4i tmp = _mm_add_epi32(a, _mm_unpackhi_epi64(a,a));
- return pfirst(tmp) + pfirst(_mm_shuffle_epi32(tmp, 1));
-}
-
-template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs)
-{
- Packet4i tmp0, tmp1, tmp2;
- tmp0 = _mm_unpacklo_epi32(vecs[0], vecs[1]);
- tmp1 = _mm_unpackhi_epi32(vecs[0], vecs[1]);
- tmp2 = _mm_unpackhi_epi32(vecs[2], vecs[3]);
- tmp0 = _mm_add_epi32(tmp0, tmp1);
- tmp1 = _mm_unpacklo_epi32(vecs[2], vecs[3]);
- tmp1 = _mm_add_epi32(tmp1, tmp2);
- tmp2 = _mm_unpacklo_epi64(tmp0, tmp1);
- tmp0 = _mm_unpackhi_epi64(tmp0, tmp1);
- return _mm_add_epi32(tmp0, tmp2);
-}
-
-// Other reduction functions:
-
-// mul
-template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a)
-{
- Packet4f tmp = _mm_mul_ps(a, _mm_movehl_ps(a,a));
- return pfirst(_mm_mul_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1)));
-}
-template<> EIGEN_STRONG_INLINE double predux_mul<Packet2d>(const Packet2d& a)
-{
- return pfirst(_mm_mul_sd(a, _mm_unpackhi_pd(a,a)));
-}
-template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
-{
- // after some experiments, it is seems this is the fastest way to implement it
- // for GCC (eg., reusing pmul is very slow !)
- // TODO try to call _mm_mul_epu32 directly
- EIGEN_ALIGN16 int aux[4];
- pstore(aux, a);
- return (aux[0] * aux[1]) * (aux[2] * aux[3]);;
-}
-
-// min
-template<> EIGEN_STRONG_INLINE float predux_min<Packet4f>(const Packet4f& a)
-{
- Packet4f tmp = _mm_min_ps(a, _mm_movehl_ps(a,a));
- return pfirst(_mm_min_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1)));
-}
-template<> EIGEN_STRONG_INLINE double predux_min<Packet2d>(const Packet2d& a)
-{
- return pfirst(_mm_min_sd(a, _mm_unpackhi_pd(a,a)));
-}
-template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a)
-{
- // after some experiments, it is seems this is the fastest way to implement it
- // for GCC (eg., it does not like using std::min after the pstore !!)
- EIGEN_ALIGN16 int aux[4];
- pstore(aux, a);
- register int aux0 = aux[0]<aux[1] ? aux[0] : aux[1];
- register int aux2 = aux[2]<aux[3] ? aux[2] : aux[3];
- return aux0<aux2 ? aux0 : aux2;
-}
-
-// max
-template<> EIGEN_STRONG_INLINE float predux_max<Packet4f>(const Packet4f& a)
-{
- Packet4f tmp = _mm_max_ps(a, _mm_movehl_ps(a,a));
- return pfirst(_mm_max_ss(tmp, _mm_shuffle_ps(tmp,tmp, 1)));
-}
-template<> EIGEN_STRONG_INLINE double predux_max<Packet2d>(const Packet2d& a)
-{
- return pfirst(_mm_max_sd(a, _mm_unpackhi_pd(a,a)));
-}
-template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
-{
- // after some experiments, it is seems this is the fastest way to implement it
- // for GCC (eg., it does not like using std::min after the pstore !!)
- EIGEN_ALIGN16 int aux[4];
- pstore(aux, a);
- register int aux0 = aux[0]>aux[1] ? aux[0] : aux[1];
- register int aux2 = aux[2]>aux[3] ? aux[2] : aux[3];
- return aux0>aux2 ? aux0 : aux2;
-}
-
-#if (defined __GNUC__)
-// template <> EIGEN_STRONG_INLINE Packet4f pmadd(const Packet4f& a, const Packet4f& b, const Packet4f& c)
-// {
-// Packet4f res = b;
-// asm("mulps %[a], %[b] \n\taddps %[c], %[b]" : [b] "+x" (res) : [a] "x" (a), [c] "x" (c));
-// return res;
-// }
-// EIGEN_STRONG_INLINE Packet4i _mm_alignr_epi8(const Packet4i& a, const Packet4i& b, const int i)
-// {
-// Packet4i res = a;
-// asm("palignr %[i], %[a], %[b] " : [b] "+x" (res) : [a] "x" (a), [i] "i" (i));
-// return res;
-// }
-#endif
-
-#ifdef EIGEN_VECTORIZE_SSSE3
-// SSSE3 versions
-template<int Offset>
-struct palign_impl<Offset,Packet4f>
-{
- EIGEN_STRONG_INLINE static void run(Packet4f& first, const Packet4f& second)
- {
- if (Offset!=0)
- first = _mm_castsi128_ps(_mm_alignr_epi8(_mm_castps_si128(second), _mm_castps_si128(first), Offset*4));
- }
-};
-
-template<int Offset>
-struct palign_impl<Offset,Packet4i>
-{
- EIGEN_STRONG_INLINE static void run(Packet4i& first, const Packet4i& second)
- {
- if (Offset!=0)
- first = _mm_alignr_epi8(second,first, Offset*4);
- }
-};
-
-template<int Offset>
-struct palign_impl<Offset,Packet2d>
-{
- EIGEN_STRONG_INLINE static void run(Packet2d& first, const Packet2d& second)
- {
- if (Offset==1)
- first = _mm_castsi128_pd(_mm_alignr_epi8(_mm_castpd_si128(second), _mm_castpd_si128(first), 8));
- }
-};
-#else
-// SSE2 versions
-template<int Offset>
-struct palign_impl<Offset,Packet4f>
-{
- EIGEN_STRONG_INLINE static void run(Packet4f& first, const Packet4f& second)
- {
- if (Offset==1)
- {
- first = _mm_move_ss(first,second);
- first = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(first),0x39));
- }
- else if (Offset==2)
- {
- first = _mm_movehl_ps(first,first);
- first = _mm_movelh_ps(first,second);
- }
- else if (Offset==3)
- {
- first = _mm_move_ss(first,second);
- first = _mm_shuffle_ps(first,second,0x93);
- }
- }
-};
-
-template<int Offset>
-struct palign_impl<Offset,Packet4i>
-{
- EIGEN_STRONG_INLINE static void run(Packet4i& first, const Packet4i& second)
- {
- if (Offset==1)
- {
- first = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(first),_mm_castsi128_ps(second)));
- first = _mm_shuffle_epi32(first,0x39);
- }
- else if (Offset==2)
- {
- first = _mm_castps_si128(_mm_movehl_ps(_mm_castsi128_ps(first),_mm_castsi128_ps(first)));
- first = _mm_castps_si128(_mm_movelh_ps(_mm_castsi128_ps(first),_mm_castsi128_ps(second)));
- }
- else if (Offset==3)
- {
- first = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(first),_mm_castsi128_ps(second)));
- first = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(first),_mm_castsi128_ps(second),0x93));
- }
- }
-};
-
-template<int Offset>
-struct palign_impl<Offset,Packet2d>
-{
- EIGEN_STRONG_INLINE static void run(Packet2d& first, const Packet2d& second)
- {
- if (Offset==1)
- {
- first = _mm_castps_pd(_mm_movehl_ps(_mm_castpd_ps(first),_mm_castpd_ps(first)));
- first = _mm_castps_pd(_mm_movelh_ps(_mm_castpd_ps(first),_mm_castpd_ps(second)));
- }
- }
-};
-#endif
-
-} // end namespace internal
-
-#endif // EIGEN_PACKET_MATH_SSE_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h b/extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h
deleted file mode 100644
index dc20f7e1e29..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h
+++ /dev/null
@@ -1,452 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_COEFFBASED_PRODUCT_H
-#define EIGEN_COEFFBASED_PRODUCT_H
-
-namespace internal {
-
-/*********************************************************************************
-* Coefficient based product implementation.
-* It is designed for the following use cases:
-* - small fixed sizes
-* - lazy products
-*********************************************************************************/
-
-/* Since the all the dimensions of the product are small, here we can rely
- * on the generic Assign mechanism to evaluate the product per coeff (or packet).
- *
- * Note that here the inner-loops should always be unrolled.
- */
-
-template<int Traversal, int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar>
-struct product_coeff_impl;
-
-template<int StorageOrder, int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode>
-struct product_packet_impl;
-
-template<typename LhsNested, typename RhsNested, int NestingFlags>
-struct traits<CoeffBasedProduct<LhsNested,RhsNested,NestingFlags> >
-{
- typedef MatrixXpr XprKind;
- typedef typename remove_all<LhsNested>::type _LhsNested;
- typedef typename remove_all<RhsNested>::type _RhsNested;
- typedef typename scalar_product_traits<typename _LhsNested::Scalar, typename _RhsNested::Scalar>::ReturnType Scalar;
- typedef typename promote_storage_type<typename traits<_LhsNested>::StorageKind,
- typename traits<_RhsNested>::StorageKind>::ret StorageKind;
- typedef typename promote_index_type<typename traits<_LhsNested>::Index,
- typename traits<_RhsNested>::Index>::type Index;
-
- enum {
- LhsCoeffReadCost = _LhsNested::CoeffReadCost,
- RhsCoeffReadCost = _RhsNested::CoeffReadCost,
- LhsFlags = _LhsNested::Flags,
- RhsFlags = _RhsNested::Flags,
-
- RowsAtCompileTime = _LhsNested::RowsAtCompileTime,
- ColsAtCompileTime = _RhsNested::ColsAtCompileTime,
- InnerSize = EIGEN_SIZE_MIN_PREFER_FIXED(_LhsNested::ColsAtCompileTime, _RhsNested::RowsAtCompileTime),
-
- MaxRowsAtCompileTime = _LhsNested::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = _RhsNested::MaxColsAtCompileTime,
-
- LhsRowMajor = LhsFlags & RowMajorBit,
- RhsRowMajor = RhsFlags & RowMajorBit,
-
- SameType = is_same<typename _LhsNested::Scalar,typename _RhsNested::Scalar>::value,
-
- CanVectorizeRhs = RhsRowMajor && (RhsFlags & PacketAccessBit)
- && (ColsAtCompileTime == Dynamic
- || ( (ColsAtCompileTime % packet_traits<Scalar>::size) == 0
- && (RhsFlags&AlignedBit)
- )
- ),
-
- CanVectorizeLhs = (!LhsRowMajor) && (LhsFlags & PacketAccessBit)
- && (RowsAtCompileTime == Dynamic
- || ( (RowsAtCompileTime % packet_traits<Scalar>::size) == 0
- && (LhsFlags&AlignedBit)
- )
- ),
-
- EvalToRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
- : (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
- : (RhsRowMajor && !CanVectorizeLhs),
-
- Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & ~RowMajorBit)
- | (EvalToRowMajor ? RowMajorBit : 0)
- | NestingFlags
- | (LhsFlags & RhsFlags & AlignedBit)
- // TODO enable vectorization for mixed types
- | (SameType && (CanVectorizeLhs || CanVectorizeRhs) ? PacketAccessBit : 0),
-
- CoeffReadCost = InnerSize == Dynamic ? Dynamic
- : InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost)
- + (InnerSize - 1) * NumTraits<Scalar>::AddCost,
-
- /* CanVectorizeInner deserves special explanation. It does not affect the product flags. It is not used outside
- * of Product. If the Product itself is not a packet-access expression, there is still a chance that the inner
- * loop of the product might be vectorized. This is the meaning of CanVectorizeInner. Since it doesn't affect
- * the Flags, it is safe to make this value depend on ActualPacketAccessBit, that doesn't affect the ABI.
- */
- CanVectorizeInner = SameType
- && LhsRowMajor
- && (!RhsRowMajor)
- && (LhsFlags & RhsFlags & ActualPacketAccessBit)
- && (LhsFlags & RhsFlags & AlignedBit)
- && (InnerSize % packet_traits<Scalar>::size == 0)
- };
-};
-
-} // end namespace internal
-
-template<typename LhsNested, typename RhsNested, int NestingFlags>
-class CoeffBasedProduct
- : internal::no_assignment_operator,
- public MatrixBase<CoeffBasedProduct<LhsNested, RhsNested, NestingFlags> >
-{
- public:
-
- typedef MatrixBase<CoeffBasedProduct> Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(CoeffBasedProduct)
- typedef typename Base::PlainObject PlainObject;
-
- private:
-
- typedef typename internal::traits<CoeffBasedProduct>::_LhsNested _LhsNested;
- typedef typename internal::traits<CoeffBasedProduct>::_RhsNested _RhsNested;
-
- enum {
- PacketSize = internal::packet_traits<Scalar>::size,
- InnerSize = internal::traits<CoeffBasedProduct>::InnerSize,
- Unroll = CoeffReadCost != Dynamic && CoeffReadCost <= EIGEN_UNROLLING_LIMIT,
- CanVectorizeInner = internal::traits<CoeffBasedProduct>::CanVectorizeInner
- };
-
- typedef internal::product_coeff_impl<CanVectorizeInner ? InnerVectorizedTraversal : DefaultTraversal,
- Unroll ? InnerSize-1 : Dynamic,
- _LhsNested, _RhsNested, Scalar> ScalarCoeffImpl;
-
- typedef CoeffBasedProduct<LhsNested,RhsNested,NestByRefBit> LazyCoeffBasedProductType;
-
- public:
-
- inline CoeffBasedProduct(const CoeffBasedProduct& other)
- : Base(), m_lhs(other.m_lhs), m_rhs(other.m_rhs)
- {}
-
- template<typename Lhs, typename Rhs>
- inline CoeffBasedProduct(const Lhs& lhs, const Rhs& rhs)
- : m_lhs(lhs), m_rhs(rhs)
- {
- // we don't allow taking products of matrices of different real types, as that wouldn't be vectorizable.
- // We still allow to mix T and complex<T>.
- EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value),
- YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
- eigen_assert(lhs.cols() == rhs.rows()
- && "invalid matrix product"
- && "if you wanted a coeff-wise or a dot product use the respective explicit functions");
- }
-
- EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); }
- EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); }
-
- EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
- {
- Scalar res;
- ScalarCoeffImpl::run(row, col, m_lhs, m_rhs, res);
- return res;
- }
-
- /* Allow index-based non-packet access. It is impossible though to allow index-based packed access,
- * which is why we don't set the LinearAccessBit.
- */
- EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
- {
- Scalar res;
- const Index row = RowsAtCompileTime == 1 ? 0 : index;
- const Index col = RowsAtCompileTime == 1 ? index : 0;
- ScalarCoeffImpl::run(row, col, m_lhs, m_rhs, res);
- return res;
- }
-
- template<int LoadMode>
- EIGEN_STRONG_INLINE const PacketScalar packet(Index row, Index col) const
- {
- PacketScalar res;
- internal::product_packet_impl<Flags&RowMajorBit ? RowMajor : ColMajor,
- Unroll ? InnerSize-1 : Dynamic,
- _LhsNested, _RhsNested, PacketScalar, LoadMode>
- ::run(row, col, m_lhs, m_rhs, res);
- return res;
- }
-
- // Implicit conversion to the nested type (trigger the evaluation of the product)
- EIGEN_STRONG_INLINE operator const PlainObject& () const
- {
- m_result.lazyAssign(*this);
- return m_result;
- }
-
- const _LhsNested& lhs() const { return m_lhs; }
- const _RhsNested& rhs() const { return m_rhs; }
-
- const Diagonal<const LazyCoeffBasedProductType,0> diagonal() const
- { return reinterpret_cast<const LazyCoeffBasedProductType&>(*this); }
-
- template<int DiagonalIndex>
- const Diagonal<const LazyCoeffBasedProductType,DiagonalIndex> diagonal() const
- { return reinterpret_cast<const LazyCoeffBasedProductType&>(*this); }
-
- const Diagonal<const LazyCoeffBasedProductType,Dynamic> diagonal(Index index) const
- { return reinterpret_cast<const LazyCoeffBasedProductType&>(*this).diagonal(index); }
-
- protected:
- const LhsNested m_lhs;
- const RhsNested m_rhs;
-
- mutable PlainObject m_result;
-};
-
-namespace internal {
-
-// here we need to overload the nested rule for products
-// such that the nested type is a const reference to a plain matrix
-template<typename Lhs, typename Rhs, int N, typename PlainObject>
-struct nested<CoeffBasedProduct<Lhs,Rhs,EvalBeforeNestingBit|EvalBeforeAssigningBit>, N, PlainObject>
-{
- typedef PlainObject const& type;
-};
-
-/***************************************************************************
-* Normal product .coeff() implementation (with meta-unrolling)
-***************************************************************************/
-
-/**************************************
-*** Scalar path - no vectorization ***
-**************************************/
-
-template<int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar>
-struct product_coeff_impl<DefaultTraversal, UnrollingIndex, Lhs, Rhs, RetScalar>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static 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);
- }
-};
-
-template<typename Lhs, typename Rhs, typename RetScalar>
-struct product_coeff_impl<DefaultTraversal, 0, Lhs, Rhs, RetScalar>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
- {
- res = lhs.coeff(row, 0) * rhs.coeff(0, col);
- }
-};
-
-template<typename Lhs, typename Rhs, typename RetScalar>
-struct product_coeff_impl<DefaultTraversal, Dynamic, Lhs, Rhs, RetScalar>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static 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);
- }
-};
-
-/*******************************************
-*** Scalar path with inner vectorization ***
-*******************************************/
-
-template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet>
-struct product_coeff_vectorized_unroller
-{
- typedef typename Lhs::Index Index;
- enum { PacketSize = packet_traits<typename Lhs::Scalar>::size };
- EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres)
- {
- product_coeff_vectorized_unroller<UnrollingIndex-PacketSize, Lhs, Rhs, Packet>::run(row, col, lhs, rhs, pres);
- pres = padd(pres, pmul( lhs.template packet<Aligned>(row, UnrollingIndex) , rhs.template packet<Aligned>(UnrollingIndex, col) ));
- }
-};
-
-template<typename Lhs, typename Rhs, typename Packet>
-struct product_coeff_vectorized_unroller<0, Lhs, Rhs, Packet>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres)
- {
- pres = pmul(lhs.template packet<Aligned>(row, 0) , rhs.template packet<Aligned>(0, col));
- }
-};
-
-template<int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar>
-struct product_coeff_impl<InnerVectorizedTraversal, UnrollingIndex, Lhs, Rhs, RetScalar>
-{
- typedef typename Lhs::PacketScalar Packet;
- typedef typename Lhs::Index Index;
- enum { PacketSize = packet_traits<typename Lhs::Scalar>::size };
- EIGEN_STRONG_INLINE static 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);
- res = predux(pres);
- }
-};
-
-template<typename Lhs, typename Rhs, int LhsRows = Lhs::RowsAtCompileTime, int RhsCols = Rhs::ColsAtCompileTime>
-struct product_coeff_vectorized_dyn_selector
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
- {
- res = lhs.row(row).transpose().cwiseProduct(rhs.col(col)).sum();
- }
-};
-
-// NOTE the 3 following specializations are because taking .col(0) on a vector is a bit slower
-// NOTE maybe they are now useless since we have a specialization for Block<Matrix>
-template<typename Lhs, typename Rhs, int RhsCols>
-struct product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,RhsCols>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static void run(Index /*row*/, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
- {
- res = lhs.transpose().cwiseProduct(rhs.col(col)).sum();
- }
-};
-
-template<typename Lhs, typename Rhs, int LhsRows>
-struct product_coeff_vectorized_dyn_selector<Lhs,Rhs,LhsRows,1>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static void run(Index row, Index /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
- {
- res = lhs.row(row).transpose().cwiseProduct(rhs).sum();
- }
-};
-
-template<typename Lhs, typename Rhs>
-struct product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,1>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static void run(Index /*row*/, Index /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
- {
- res = lhs.transpose().cwiseProduct(rhs).sum();
- }
-};
-
-template<typename Lhs, typename Rhs, typename RetScalar>
-struct product_coeff_impl<InnerVectorizedTraversal, Dynamic, Lhs, Rhs, RetScalar>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
- {
- product_coeff_vectorized_dyn_selector<Lhs,Rhs>::run(row, col, lhs, rhs, res);
- }
-};
-
-/*******************
-*** Packet path ***
-*******************/
-
-template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode>
-struct product_packet_impl<RowMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static 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);
- }
-};
-
-template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode>
-struct product_packet_impl<ColMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static 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);
- }
-};
-
-template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
-struct product_packet_impl<RowMajor, 0, Lhs, Rhs, Packet, LoadMode>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
- {
- res = pmul(pset1<Packet>(lhs.coeff(row, 0)),rhs.template packet<LoadMode>(0, col));
- }
-};
-
-template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
-struct product_packet_impl<ColMajor, 0, Lhs, Rhs, Packet, LoadMode>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
- {
- res = pmul(lhs.template packet<LoadMode>(row, 0), pset1<Packet>(rhs.coeff(0, col)));
- }
-};
-
-template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
-struct product_packet_impl<RowMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static 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);
- }
-};
-
-template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
-struct product_packet_impl<ColMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
-{
- typedef typename Lhs::Index Index;
- EIGEN_STRONG_INLINE static 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);
- }
-};
-
-} // end namespace internal
-
-#endif // EIGEN_COEFFBASED_PRODUCT_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h b/extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h
deleted file mode 100644
index 6f3f2717007..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h
+++ /dev/null
@@ -1,1285 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_GENERAL_BLOCK_PANEL_H
-#define EIGEN_GENERAL_BLOCK_PANEL_H
-
-namespace internal {
-
-template<typename _LhsScalar, typename _RhsScalar, bool _ConjLhs=false, bool _ConjRhs=false>
-class gebp_traits;
-
-/** \internal */
-inline void manage_caching_sizes(Action action, std::ptrdiff_t* l1=0, std::ptrdiff_t* l2=0)
-{
- static std::ptrdiff_t m_l1CacheSize = 0;
- static std::ptrdiff_t m_l2CacheSize = 0;
- if(m_l1CacheSize==0)
- {
- m_l1CacheSize = queryL1CacheSize();
- m_l2CacheSize = queryTopLevelCacheSize();
-
- if(m_l1CacheSize<=0) m_l1CacheSize = 8 * 1024;
- if(m_l2CacheSize<=0) m_l2CacheSize = 1 * 1024 * 1024;
- }
-
- if(action==SetAction)
- {
- // set the cpu cache size and cache all block sizes from a global cache size in byte
- eigen_internal_assert(l1!=0 && l2!=0);
- m_l1CacheSize = *l1;
- m_l2CacheSize = *l2;
- }
- else if(action==GetAction)
- {
- eigen_internal_assert(l1!=0 && l2!=0);
- *l1 = m_l1CacheSize;
- *l2 = m_l2CacheSize;
- }
- else
- {
- eigen_internal_assert(false);
- }
-}
-
-/** \brief Computes the blocking parameters for a m x k times k x n matrix product
- *
- * \param[in,out] k Input: the third dimension of the product. Output: the blocking size along the same dimension.
- * \param[in,out] m Input: the number of rows of the left hand side. Output: the blocking size along the same dimension.
- * \param[in,out] n Input: the number of columns of the right hand side. Output: the blocking size along the same dimension.
- *
- * Given a m x k times k x n matrix product of scalar types \c LhsScalar and \c RhsScalar,
- * this function computes the blocking size parameters along the respective dimensions
- * for matrix products and related algorithms. The blocking sizes depends on various
- * parameters:
- * - the L1 and L2 cache sizes,
- * - the register level blocking sizes defined by gebp_traits,
- * - the number of scalars that fit into a packet (when vectorization is enabled).
- *
- * \sa setCpuCacheSizes */
-template<typename LhsScalar, typename RhsScalar, int KcFactor>
-void computeProductBlockingSizes(std::ptrdiff_t& k, std::ptrdiff_t& m, std::ptrdiff_t& n)
-{
- EIGEN_UNUSED_VARIABLE(n);
- // Explanations:
- // Let's recall the product algorithms form kc x nc horizontal panels B' on the rhs and
- // mc x kc blocks A' on the lhs. A' has to fit into L2 cache. Moreover, B' is processed
- // per kc x nr vertical small panels where nr is the blocking size along the n dimension
- // at the register level. For vectorization purpose, these small vertical panels are unpacked,
- // e.g., each coefficient is replicated to fit a packet. This small vertical panel has to
- // stay in L1 cache.
- std::ptrdiff_t l1, l2;
-
- typedef gebp_traits<LhsScalar,RhsScalar> Traits;
- enum {
- kdiv = KcFactor * 2 * Traits::nr
- * Traits::RhsProgress * sizeof(RhsScalar),
- mr = gebp_traits<LhsScalar,RhsScalar>::mr,
- mr_mask = (0xffffffff/mr)*mr
- };
-
- manage_caching_sizes(GetAction, &l1, &l2);
- k = std::min<std::ptrdiff_t>(k, l1/kdiv);
- std::ptrdiff_t _m = k>0 ? l2/(4 * sizeof(LhsScalar) * k) : 0;
- if(_m<m) m = _m & mr_mask;
-}
-
-template<typename LhsScalar, typename RhsScalar>
-inline void computeProductBlockingSizes(std::ptrdiff_t& k, std::ptrdiff_t& m, std::ptrdiff_t& n)
-{
- computeProductBlockingSizes<LhsScalar,RhsScalar,1>(k, m, n);
-}
-
-#ifdef EIGEN_HAS_FUSE_CJMADD
- #define MADD(CJ,A,B,C,T) C = CJ.pmadd(A,B,C);
-#else
-
- // FIXME (a bit overkill maybe ?)
-
- template<typename CJ, typename A, typename B, typename C, typename T> struct gebp_madd_selector {
- EIGEN_STRONG_INLINE EIGEN_ALWAYS_INLINE_ATTRIB static void run(const CJ& cj, A& a, B& b, C& c, T& /*t*/)
- {
- c = cj.pmadd(a,b,c);
- }
- };
-
- template<typename CJ, typename T> struct gebp_madd_selector<CJ,T,T,T,T> {
- EIGEN_STRONG_INLINE EIGEN_ALWAYS_INLINE_ATTRIB static void run(const CJ& cj, T& a, T& b, T& c, T& t)
- {
- t = b; t = cj.pmul(a,t); c = padd(c,t);
- }
- };
-
- template<typename CJ, typename A, typename B, typename C, typename T>
- EIGEN_STRONG_INLINE void gebp_madd(const CJ& cj, A& a, B& b, C& c, T& t)
- {
- gebp_madd_selector<CJ,A,B,C,T>::run(cj,a,b,c,t);
- }
-
- #define MADD(CJ,A,B,C,T) gebp_madd(CJ,A,B,C,T);
-// #define MADD(CJ,A,B,C,T) T = B; T = CJ.pmul(A,T); C = padd(C,T);
-#endif
-
-/* Vectorization logic
- * real*real: unpack rhs to constant packets, ...
- *
- * cd*cd : unpack rhs to (b_r,b_r), (b_i,b_i), mul to get (a_r b_r,a_i b_r) (a_r b_i,a_i b_i),
- * storing each res packet into two packets (2x2),
- * at the end combine them: swap the second and addsub them
- * cf*cf : same but with 2x4 blocks
- * cplx*real : unpack rhs to constant packets, ...
- * real*cplx : load lhs as (a0,a0,a1,a1), and mul as usual
- */
-template<typename _LhsScalar, typename _RhsScalar, bool _ConjLhs, bool _ConjRhs>
-class gebp_traits
-{
-public:
- typedef _LhsScalar LhsScalar;
- typedef _RhsScalar RhsScalar;
- typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
-
- enum {
- ConjLhs = _ConjLhs,
- ConjRhs = _ConjRhs,
- Vectorizable = packet_traits<LhsScalar>::Vectorizable && packet_traits<RhsScalar>::Vectorizable,
- LhsPacketSize = Vectorizable ? packet_traits<LhsScalar>::size : 1,
- RhsPacketSize = Vectorizable ? packet_traits<RhsScalar>::size : 1,
- ResPacketSize = Vectorizable ? packet_traits<ResScalar>::size : 1,
-
- NumberOfRegisters = EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS,
-
- // register block size along the N direction (must be either 2 or 4)
- nr = NumberOfRegisters/4,
-
- // register block size along the M direction (currently, this one cannot be modified)
- mr = 2 * LhsPacketSize,
-
- WorkSpaceFactor = nr * RhsPacketSize,
-
- LhsProgress = LhsPacketSize,
- RhsProgress = RhsPacketSize
- };
-
- typedef typename packet_traits<LhsScalar>::type _LhsPacket;
- typedef typename packet_traits<RhsScalar>::type _RhsPacket;
- typedef typename packet_traits<ResScalar>::type _ResPacket;
-
- typedef typename conditional<Vectorizable,_LhsPacket,LhsScalar>::type LhsPacket;
- typedef typename conditional<Vectorizable,_RhsPacket,RhsScalar>::type RhsPacket;
- typedef typename conditional<Vectorizable,_ResPacket,ResScalar>::type ResPacket;
-
- typedef ResPacket AccPacket;
-
- EIGEN_STRONG_INLINE void initAcc(AccPacket& p)
- {
- p = pset1<ResPacket>(ResScalar(0));
- }
-
- EIGEN_STRONG_INLINE void unpackRhs(DenseIndex n, const RhsScalar* rhs, RhsScalar* b)
- {
- for(DenseIndex k=0; k<n; k++)
- pstore1<RhsPacket>(&b[k*RhsPacketSize], rhs[k]);
- }
-
- EIGEN_STRONG_INLINE void loadRhs(const RhsScalar* b, RhsPacket& dest) const
- {
- dest = pload<RhsPacket>(b);
- }
-
- EIGEN_STRONG_INLINE void loadLhs(const LhsScalar* a, LhsPacket& dest) const
- {
- dest = pload<LhsPacket>(a);
- }
-
- EIGEN_STRONG_INLINE void madd(const LhsPacket& a, const RhsPacket& b, AccPacket& c, AccPacket& tmp) const
- {
- tmp = b; tmp = pmul(a,tmp); c = padd(c,tmp);
- }
-
- EIGEN_STRONG_INLINE void acc(const AccPacket& c, const ResPacket& alpha, ResPacket& r) const
- {
- r = pmadd(c,alpha,r);
- }
-
-protected:
-// conj_helper<LhsScalar,RhsScalar,ConjLhs,ConjRhs> cj;
-// conj_helper<LhsPacket,RhsPacket,ConjLhs,ConjRhs> pcj;
-};
-
-template<typename RealScalar, bool _ConjLhs>
-class gebp_traits<std::complex<RealScalar>, RealScalar, _ConjLhs, false>
-{
-public:
- typedef std::complex<RealScalar> LhsScalar;
- typedef RealScalar RhsScalar;
- typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
-
- enum {
- ConjLhs = _ConjLhs,
- ConjRhs = false,
- Vectorizable = packet_traits<LhsScalar>::Vectorizable && packet_traits<RhsScalar>::Vectorizable,
- LhsPacketSize = Vectorizable ? packet_traits<LhsScalar>::size : 1,
- RhsPacketSize = Vectorizable ? packet_traits<RhsScalar>::size : 1,
- ResPacketSize = Vectorizable ? packet_traits<ResScalar>::size : 1,
-
- NumberOfRegisters = EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS,
- nr = NumberOfRegisters/4,
- mr = 2 * LhsPacketSize,
- WorkSpaceFactor = nr*RhsPacketSize,
-
- LhsProgress = LhsPacketSize,
- RhsProgress = RhsPacketSize
- };
-
- typedef typename packet_traits<LhsScalar>::type _LhsPacket;
- typedef typename packet_traits<RhsScalar>::type _RhsPacket;
- typedef typename packet_traits<ResScalar>::type _ResPacket;
-
- typedef typename conditional<Vectorizable,_LhsPacket,LhsScalar>::type LhsPacket;
- typedef typename conditional<Vectorizable,_RhsPacket,RhsScalar>::type RhsPacket;
- typedef typename conditional<Vectorizable,_ResPacket,ResScalar>::type ResPacket;
-
- typedef ResPacket AccPacket;
-
- EIGEN_STRONG_INLINE void initAcc(AccPacket& p)
- {
- p = pset1<ResPacket>(ResScalar(0));
- }
-
- EIGEN_STRONG_INLINE void unpackRhs(DenseIndex n, const RhsScalar* rhs, RhsScalar* b)
- {
- for(DenseIndex k=0; k<n; k++)
- pstore1<RhsPacket>(&b[k*RhsPacketSize], rhs[k]);
- }
-
- EIGEN_STRONG_INLINE void loadRhs(const RhsScalar* b, RhsPacket& dest) const
- {
- dest = pload<RhsPacket>(b);
- }
-
- EIGEN_STRONG_INLINE void loadLhs(const LhsScalar* a, LhsPacket& dest) const
- {
- dest = pload<LhsPacket>(a);
- }
-
- EIGEN_STRONG_INLINE void madd(const LhsPacket& a, const RhsPacket& b, AccPacket& c, RhsPacket& tmp) const
- {
- madd_impl(a, b, c, tmp, typename conditional<Vectorizable,true_type,false_type>::type());
- }
-
- EIGEN_STRONG_INLINE void madd_impl(const LhsPacket& a, const RhsPacket& b, AccPacket& c, RhsPacket& tmp, const true_type&) const
- {
- tmp = b; tmp = pmul(a.v,tmp); c.v = padd(c.v,tmp);
- }
-
- EIGEN_STRONG_INLINE void madd_impl(const LhsScalar& a, const RhsScalar& b, ResScalar& c, RhsScalar& /*tmp*/, const false_type&) const
- {
- c += a * b;
- }
-
- EIGEN_STRONG_INLINE void acc(const AccPacket& c, const ResPacket& alpha, ResPacket& r) const
- {
- r = cj.pmadd(c,alpha,r);
- }
-
-protected:
- conj_helper<ResPacket,ResPacket,ConjLhs,false> cj;
-};
-
-template<typename RealScalar, bool _ConjLhs, bool _ConjRhs>
-class gebp_traits<std::complex<RealScalar>, std::complex<RealScalar>, _ConjLhs, _ConjRhs >
-{
-public:
- typedef std::complex<RealScalar> Scalar;
- typedef std::complex<RealScalar> LhsScalar;
- typedef std::complex<RealScalar> RhsScalar;
- typedef std::complex<RealScalar> ResScalar;
-
- enum {
- ConjLhs = _ConjLhs,
- ConjRhs = _ConjRhs,
- Vectorizable = packet_traits<RealScalar>::Vectorizable
- && packet_traits<Scalar>::Vectorizable,
- RealPacketSize = Vectorizable ? packet_traits<RealScalar>::size : 1,
- ResPacketSize = Vectorizable ? packet_traits<ResScalar>::size : 1,
-
- nr = 2,
- mr = 2 * ResPacketSize,
- WorkSpaceFactor = Vectorizable ? 2*nr*RealPacketSize : nr,
-
- LhsProgress = ResPacketSize,
- RhsProgress = Vectorizable ? 2*ResPacketSize : 1
- };
-
- typedef typename packet_traits<RealScalar>::type RealPacket;
- typedef typename packet_traits<Scalar>::type ScalarPacket;
- struct DoublePacket
- {
- RealPacket first;
- RealPacket second;
- };
-
- typedef typename conditional<Vectorizable,RealPacket, Scalar>::type LhsPacket;
- typedef typename conditional<Vectorizable,DoublePacket,Scalar>::type RhsPacket;
- typedef typename conditional<Vectorizable,ScalarPacket,Scalar>::type ResPacket;
- typedef typename conditional<Vectorizable,DoublePacket,Scalar>::type AccPacket;
-
- EIGEN_STRONG_INLINE void initAcc(Scalar& p) { p = Scalar(0); }
-
- EIGEN_STRONG_INLINE void initAcc(DoublePacket& p)
- {
- p.first = pset1<RealPacket>(RealScalar(0));
- p.second = pset1<RealPacket>(RealScalar(0));
- }
-
- /* Unpack the rhs coeff such that each complex coefficient is spread into
- * two packects containing respectively the real and imaginary coefficient
- * duplicated as many time as needed: (x+iy) => [x, ..., x] [y, ..., y]
- */
- EIGEN_STRONG_INLINE void unpackRhs(DenseIndex n, const Scalar* rhs, Scalar* b)
- {
- for(DenseIndex k=0; k<n; k++)
- {
- if(Vectorizable)
- {
- pstore1<RealPacket>((RealScalar*)&b[k*ResPacketSize*2+0], real(rhs[k]));
- pstore1<RealPacket>((RealScalar*)&b[k*ResPacketSize*2+ResPacketSize], imag(rhs[k]));
- }
- else
- b[k] = rhs[k];
- }
- }
-
- EIGEN_STRONG_INLINE void loadRhs(const RhsScalar* b, ResPacket& dest) const { dest = *b; }
-
- EIGEN_STRONG_INLINE void loadRhs(const RhsScalar* b, DoublePacket& dest) const
- {
- dest.first = pload<RealPacket>((const RealScalar*)b);
- dest.second = pload<RealPacket>((const RealScalar*)(b+ResPacketSize));
- }
-
- // nothing special here
- EIGEN_STRONG_INLINE void loadLhs(const LhsScalar* a, LhsPacket& dest) const
- {
- dest = pload<LhsPacket>((const typename unpacket_traits<LhsPacket>::type*)(a));
- }
-
- EIGEN_STRONG_INLINE void madd(const LhsPacket& a, const RhsPacket& b, DoublePacket& c, RhsPacket& /*tmp*/) const
- {
- c.first = padd(pmul(a,b.first), c.first);
- c.second = padd(pmul(a,b.second),c.second);
- }
-
- EIGEN_STRONG_INLINE void madd(const LhsPacket& a, const RhsPacket& b, ResPacket& c, RhsPacket& /*tmp*/) const
- {
- c = cj.pmadd(a,b,c);
- }
-
- EIGEN_STRONG_INLINE void acc(const Scalar& c, const Scalar& alpha, Scalar& r) const { r += alpha * c; }
-
- EIGEN_STRONG_INLINE void acc(const DoublePacket& c, const ResPacket& alpha, ResPacket& r) const
- {
- // assemble c
- ResPacket tmp;
- if((!ConjLhs)&&(!ConjRhs))
- {
- tmp = pcplxflip(pconj(ResPacket(c.second)));
- tmp = padd(ResPacket(c.first),tmp);
- }
- else if((!ConjLhs)&&(ConjRhs))
- {
- tmp = pconj(pcplxflip(ResPacket(c.second)));
- tmp = padd(ResPacket(c.first),tmp);
- }
- else if((ConjLhs)&&(!ConjRhs))
- {
- tmp = pcplxflip(ResPacket(c.second));
- tmp = padd(pconj(ResPacket(c.first)),tmp);
- }
- else if((ConjLhs)&&(ConjRhs))
- {
- tmp = pcplxflip(ResPacket(c.second));
- tmp = psub(pconj(ResPacket(c.first)),tmp);
- }
-
- r = pmadd(tmp,alpha,r);
- }
-
-protected:
- conj_helper<LhsScalar,RhsScalar,ConjLhs,ConjRhs> cj;
-};
-
-template<typename RealScalar, bool _ConjRhs>
-class gebp_traits<RealScalar, std::complex<RealScalar>, false, _ConjRhs >
-{
-public:
- typedef std::complex<RealScalar> Scalar;
- typedef RealScalar LhsScalar;
- typedef Scalar RhsScalar;
- typedef Scalar ResScalar;
-
- enum {
- ConjLhs = false,
- ConjRhs = _ConjRhs,
- Vectorizable = packet_traits<RealScalar>::Vectorizable
- && packet_traits<Scalar>::Vectorizable,
- LhsPacketSize = Vectorizable ? packet_traits<LhsScalar>::size : 1,
- RhsPacketSize = Vectorizable ? packet_traits<RhsScalar>::size : 1,
- ResPacketSize = Vectorizable ? packet_traits<ResScalar>::size : 1,
-
- NumberOfRegisters = EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS,
- nr = 4,
- mr = 2*ResPacketSize,
- WorkSpaceFactor = nr*RhsPacketSize,
-
- LhsProgress = ResPacketSize,
- RhsProgress = ResPacketSize
- };
-
- typedef typename packet_traits<LhsScalar>::type _LhsPacket;
- typedef typename packet_traits<RhsScalar>::type _RhsPacket;
- typedef typename packet_traits<ResScalar>::type _ResPacket;
-
- typedef typename conditional<Vectorizable,_LhsPacket,LhsScalar>::type LhsPacket;
- typedef typename conditional<Vectorizable,_RhsPacket,RhsScalar>::type RhsPacket;
- typedef typename conditional<Vectorizable,_ResPacket,ResScalar>::type ResPacket;
-
- typedef ResPacket AccPacket;
-
- EIGEN_STRONG_INLINE void initAcc(AccPacket& p)
- {
- p = pset1<ResPacket>(ResScalar(0));
- }
-
- EIGEN_STRONG_INLINE void unpackRhs(DenseIndex n, const RhsScalar* rhs, RhsScalar* b)
- {
- for(DenseIndex k=0; k<n; k++)
- pstore1<RhsPacket>(&b[k*RhsPacketSize], rhs[k]);
- }
-
- EIGEN_STRONG_INLINE void loadRhs(const RhsScalar* b, RhsPacket& dest) const
- {
- dest = pload<RhsPacket>(b);
- }
-
- EIGEN_STRONG_INLINE void loadLhs(const LhsScalar* a, LhsPacket& dest) const
- {
- dest = ploaddup<LhsPacket>(a);
- }
-
- EIGEN_STRONG_INLINE void madd(const LhsPacket& a, const RhsPacket& b, AccPacket& c, RhsPacket& tmp) const
- {
- madd_impl(a, b, c, tmp, typename conditional<Vectorizable,true_type,false_type>::type());
- }
-
- EIGEN_STRONG_INLINE void madd_impl(const LhsPacket& a, const RhsPacket& b, AccPacket& c, RhsPacket& tmp, const true_type&) const
- {
- tmp = b; tmp.v = pmul(a,tmp.v); c = padd(c,tmp);
- }
-
- EIGEN_STRONG_INLINE void madd_impl(const LhsScalar& a, const RhsScalar& b, ResScalar& c, RhsScalar& /*tmp*/, const false_type&) const
- {
- c += a * b;
- }
-
- EIGEN_STRONG_INLINE void acc(const AccPacket& c, const ResPacket& alpha, ResPacket& r) const
- {
- r = cj.pmadd(alpha,c,r);
- }
-
-protected:
- conj_helper<ResPacket,ResPacket,false,ConjRhs> cj;
-};
-
-/* optimized GEneral packed Block * packed Panel product kernel
- *
- * Mixing type logic: C += A * B
- * | A | B | comments
- * |real |cplx | no vectorization yet, would require to pack A with duplication
- * |cplx |real | easy vectorization
- */
-template<typename LhsScalar, typename RhsScalar, typename Index, int mr, int nr, bool ConjugateLhs, bool ConjugateRhs>
-struct gebp_kernel
-{
- typedef gebp_traits<LhsScalar,RhsScalar,ConjugateLhs,ConjugateRhs> Traits;
- typedef typename Traits::ResScalar ResScalar;
- typedef typename Traits::LhsPacket LhsPacket;
- typedef typename Traits::RhsPacket RhsPacket;
- typedef typename Traits::ResPacket ResPacket;
- typedef typename Traits::AccPacket AccPacket;
-
- enum {
- Vectorizable = Traits::Vectorizable,
- LhsProgress = Traits::LhsProgress,
- RhsProgress = Traits::RhsProgress,
- ResPacketSize = Traits::ResPacketSize
- };
-
- EIGEN_FLATTEN_ATTRIB
- void operator()(ResScalar* res, Index resStride, const LhsScalar* blockA, const RhsScalar* blockB, Index rows, Index depth, Index cols, ResScalar alpha,
- Index strideA=-1, Index strideB=-1, Index offsetA=0, Index offsetB=0, RhsScalar* unpackedB = 0)
- {
- Traits traits;
-
- if(strideA==-1) strideA = depth;
- if(strideB==-1) strideB = depth;
- conj_helper<LhsScalar,RhsScalar,ConjugateLhs,ConjugateRhs> cj;
-// conj_helper<LhsPacket,RhsPacket,ConjugateLhs,ConjugateRhs> pcj;
- Index packet_cols = (cols/nr) * nr;
- const Index peeled_mc = (rows/mr)*mr;
- // FIXME:
- const Index peeled_mc2 = peeled_mc + (rows-peeled_mc >= LhsProgress ? LhsProgress : 0);
- const Index peeled_kc = (depth/4)*4;
-
- if(unpackedB==0)
- unpackedB = const_cast<RhsScalar*>(blockB - strideB * nr * RhsProgress);
-
- // loops on each micro vertical panel of rhs (depth x nr)
- for(Index j2=0; j2<packet_cols; j2+=nr)
- {
- traits.unpackRhs(depth*nr,&blockB[j2*strideB+offsetB*nr],unpackedB);
-
- // loops on each largest micro horizontal panel of lhs (mr x depth)
- // => we select a mr x nr micro block of res which is entirely
- // stored into mr/packet_size x nr registers.
- for(Index i=0; i<peeled_mc; i+=mr)
- {
- const LhsScalar* blA = &blockA[i*strideA+offsetA*mr];
- prefetch(&blA[0]);
-
- // gets res block as register
- AccPacket C0, C1, C2, C3, C4, C5, C6, C7;
- traits.initAcc(C0);
- traits.initAcc(C1);
- if(nr==4) traits.initAcc(C2);
- if(nr==4) traits.initAcc(C3);
- traits.initAcc(C4);
- traits.initAcc(C5);
- if(nr==4) traits.initAcc(C6);
- if(nr==4) traits.initAcc(C7);
-
- ResScalar* r0 = &res[(j2+0)*resStride + i];
- ResScalar* r1 = r0 + resStride;
- ResScalar* r2 = r1 + resStride;
- ResScalar* r3 = r2 + resStride;
-
- prefetch(r0+16);
- prefetch(r1+16);
- prefetch(r2+16);
- prefetch(r3+16);
-
- // performs "inner" product
- // TODO let's check wether the folowing peeled loop could not be
- // optimized via optimal prefetching from one loop to the other
- const RhsScalar* blB = unpackedB;
- for(Index k=0; k<peeled_kc; k+=4)
- {
- if(nr==2)
- {
- LhsPacket A0, A1;
- RhsPacket B0;
- RhsPacket T0;
-
-EIGEN_ASM_COMMENT("mybegin2");
- traits.loadLhs(&blA[0*LhsProgress], A0);
- traits.loadLhs(&blA[1*LhsProgress], A1);
- traits.loadRhs(&blB[0*RhsProgress], B0);
- traits.madd(A0,B0,C0,T0);
- traits.madd(A1,B0,C4,B0);
- traits.loadRhs(&blB[1*RhsProgress], B0);
- traits.madd(A0,B0,C1,T0);
- traits.madd(A1,B0,C5,B0);
-
- traits.loadLhs(&blA[2*LhsProgress], A0);
- traits.loadLhs(&blA[3*LhsProgress], A1);
- traits.loadRhs(&blB[2*RhsProgress], B0);
- traits.madd(A0,B0,C0,T0);
- traits.madd(A1,B0,C4,B0);
- traits.loadRhs(&blB[3*RhsProgress], B0);
- traits.madd(A0,B0,C1,T0);
- traits.madd(A1,B0,C5,B0);
-
- traits.loadLhs(&blA[4*LhsProgress], A0);
- traits.loadLhs(&blA[5*LhsProgress], A1);
- traits.loadRhs(&blB[4*RhsProgress], B0);
- traits.madd(A0,B0,C0,T0);
- traits.madd(A1,B0,C4,B0);
- traits.loadRhs(&blB[5*RhsProgress], B0);
- traits.madd(A0,B0,C1,T0);
- traits.madd(A1,B0,C5,B0);
-
- traits.loadLhs(&blA[6*LhsProgress], A0);
- traits.loadLhs(&blA[7*LhsProgress], A1);
- traits.loadRhs(&blB[6*RhsProgress], B0);
- traits.madd(A0,B0,C0,T0);
- traits.madd(A1,B0,C4,B0);
- traits.loadRhs(&blB[7*RhsProgress], B0);
- traits.madd(A0,B0,C1,T0);
- traits.madd(A1,B0,C5,B0);
-EIGEN_ASM_COMMENT("myend");
- }
- else
- {
-EIGEN_ASM_COMMENT("mybegin4");
- LhsPacket A0, A1;
- RhsPacket B0, B1, B2, B3;
- RhsPacket T0;
-
- traits.loadLhs(&blA[0*LhsProgress], A0);
- traits.loadLhs(&blA[1*LhsProgress], A1);
- traits.loadRhs(&blB[0*RhsProgress], B0);
- traits.loadRhs(&blB[1*RhsProgress], B1);
-
- traits.madd(A0,B0,C0,T0);
- traits.loadRhs(&blB[2*RhsProgress], B2);
- traits.madd(A1,B0,C4,B0);
- traits.loadRhs(&blB[3*RhsProgress], B3);
- traits.loadRhs(&blB[4*RhsProgress], B0);
- traits.madd(A0,B1,C1,T0);
- traits.madd(A1,B1,C5,B1);
- traits.loadRhs(&blB[5*RhsProgress], B1);
- traits.madd(A0,B2,C2,T0);
- traits.madd(A1,B2,C6,B2);
- traits.loadRhs(&blB[6*RhsProgress], B2);
- traits.madd(A0,B3,C3,T0);
- traits.loadLhs(&blA[2*LhsProgress], A0);
- traits.madd(A1,B3,C7,B3);
- traits.loadLhs(&blA[3*LhsProgress], A1);
- traits.loadRhs(&blB[7*RhsProgress], B3);
- traits.madd(A0,B0,C0,T0);
- traits.madd(A1,B0,C4,B0);
- traits.loadRhs(&blB[8*RhsProgress], B0);
- traits.madd(A0,B1,C1,T0);
- traits.madd(A1,B1,C5,B1);
- traits.loadRhs(&blB[9*RhsProgress], B1);
- traits.madd(A0,B2,C2,T0);
- traits.madd(A1,B2,C6,B2);
- traits.loadRhs(&blB[10*RhsProgress], B2);
- traits.madd(A0,B3,C3,T0);
- traits.loadLhs(&blA[4*LhsProgress], A0);
- traits.madd(A1,B3,C7,B3);
- traits.loadLhs(&blA[5*LhsProgress], A1);
- traits.loadRhs(&blB[11*RhsProgress], B3);
-
- traits.madd(A0,B0,C0,T0);
- traits.madd(A1,B0,C4,B0);
- traits.loadRhs(&blB[12*RhsProgress], B0);
- traits.madd(A0,B1,C1,T0);
- traits.madd(A1,B1,C5,B1);
- traits.loadRhs(&blB[13*RhsProgress], B1);
- traits.madd(A0,B2,C2,T0);
- traits.madd(A1,B2,C6,B2);
- traits.loadRhs(&blB[14*RhsProgress], B2);
- traits.madd(A0,B3,C3,T0);
- traits.loadLhs(&blA[6*LhsProgress], A0);
- traits.madd(A1,B3,C7,B3);
- traits.loadLhs(&blA[7*LhsProgress], A1);
- traits.loadRhs(&blB[15*RhsProgress], B3);
- traits.madd(A0,B0,C0,T0);
- traits.madd(A1,B0,C4,B0);
- traits.madd(A0,B1,C1,T0);
- traits.madd(A1,B1,C5,B1);
- traits.madd(A0,B2,C2,T0);
- traits.madd(A1,B2,C6,B2);
- traits.madd(A0,B3,C3,T0);
- traits.madd(A1,B3,C7,B3);
- }
-
- blB += 4*nr*RhsProgress;
- blA += 4*mr;
- }
- // process remaining peeled loop
- for(Index k=peeled_kc; k<depth; k++)
- {
- if(nr==2)
- {
- LhsPacket A0, A1;
- RhsPacket B0;
- RhsPacket T0;
-
- traits.loadLhs(&blA[0*LhsProgress], A0);
- traits.loadLhs(&blA[1*LhsProgress], A1);
- traits.loadRhs(&blB[0*RhsProgress], B0);
- traits.madd(A0,B0,C0,T0);
- traits.madd(A1,B0,C4,B0);
- traits.loadRhs(&blB[1*RhsProgress], B0);
- traits.madd(A0,B0,C1,T0);
- traits.madd(A1,B0,C5,B0);
- }
- else
- {
- LhsPacket A0, A1;
- RhsPacket B0, B1, B2, B3;
- RhsPacket T0;
-
- traits.loadLhs(&blA[0*LhsProgress], A0);
- traits.loadLhs(&blA[1*LhsProgress], A1);
- traits.loadRhs(&blB[0*RhsProgress], B0);
- traits.loadRhs(&blB[1*RhsProgress], B1);
-
- traits.madd(A0,B0,C0,T0);
- traits.loadRhs(&blB[2*RhsProgress], B2);
- traits.madd(A1,B0,C4,B0);
- traits.loadRhs(&blB[3*RhsProgress], B3);
- traits.madd(A0,B1,C1,T0);
- traits.madd(A1,B1,C5,B1);
- traits.madd(A0,B2,C2,T0);
- traits.madd(A1,B2,C6,B2);
- traits.madd(A0,B3,C3,T0);
- traits.madd(A1,B3,C7,B3);
- }
-
- blB += nr*RhsProgress;
- blA += mr;
- }
-
- if(nr==4)
- {
- ResPacket R0, R1, R2, R3, R4, R5, R6;
- ResPacket alphav = pset1<ResPacket>(alpha);
-
- R0 = ploadu<ResPacket>(r0);
- R1 = ploadu<ResPacket>(r1);
- R2 = ploadu<ResPacket>(r2);
- R3 = ploadu<ResPacket>(r3);
- R4 = ploadu<ResPacket>(r0 + ResPacketSize);
- R5 = ploadu<ResPacket>(r1 + ResPacketSize);
- R6 = ploadu<ResPacket>(r2 + ResPacketSize);
- traits.acc(C0, alphav, R0);
- pstoreu(r0, R0);
- R0 = ploadu<ResPacket>(r3 + ResPacketSize);
-
- traits.acc(C1, alphav, R1);
- traits.acc(C2, alphav, R2);
- traits.acc(C3, alphav, R3);
- traits.acc(C4, alphav, R4);
- traits.acc(C5, alphav, R5);
- traits.acc(C6, alphav, R6);
- traits.acc(C7, alphav, R0);
-
- pstoreu(r1, R1);
- pstoreu(r2, R2);
- pstoreu(r3, R3);
- pstoreu(r0 + ResPacketSize, R4);
- pstoreu(r1 + ResPacketSize, R5);
- pstoreu(r2 + ResPacketSize, R6);
- pstoreu(r3 + ResPacketSize, R0);
- }
- else
- {
- ResPacket R0, R1, R4;
- ResPacket alphav = pset1<ResPacket>(alpha);
-
- R0 = ploadu<ResPacket>(r0);
- R1 = ploadu<ResPacket>(r1);
- R4 = ploadu<ResPacket>(r0 + ResPacketSize);
- traits.acc(C0, alphav, R0);
- pstoreu(r0, R0);
- R0 = ploadu<ResPacket>(r1 + ResPacketSize);
- traits.acc(C1, alphav, R1);
- traits.acc(C4, alphav, R4);
- traits.acc(C5, alphav, R0);
- pstoreu(r1, R1);
- pstoreu(r0 + ResPacketSize, R4);
- pstoreu(r1 + ResPacketSize, R0);
- }
-
- }
-
- if(rows-peeled_mc>=LhsProgress)
- {
- Index i = peeled_mc;
- const LhsScalar* blA = &blockA[i*strideA+offsetA*LhsProgress];
- prefetch(&blA[0]);
-
- // gets res block as register
- AccPacket C0, C1, C2, C3;
- traits.initAcc(C0);
- traits.initAcc(C1);
- if(nr==4) traits.initAcc(C2);
- if(nr==4) traits.initAcc(C3);
-
- // performs "inner" product
- const RhsScalar* blB = unpackedB;
- for(Index k=0; k<peeled_kc; k+=4)
- {
- if(nr==2)
- {
- LhsPacket A0;
- RhsPacket B0, B1;
-
- traits.loadLhs(&blA[0*LhsProgress], A0);
- traits.loadRhs(&blB[0*RhsProgress], B0);
- traits.loadRhs(&blB[1*RhsProgress], B1);
- traits.madd(A0,B0,C0,B0);
- traits.loadRhs(&blB[2*RhsProgress], B0);
- traits.madd(A0,B1,C1,B1);
- traits.loadLhs(&blA[1*LhsProgress], A0);
- traits.loadRhs(&blB[3*RhsProgress], B1);
- traits.madd(A0,B0,C0,B0);
- traits.loadRhs(&blB[4*RhsProgress], B0);
- traits.madd(A0,B1,C1,B1);
- traits.loadLhs(&blA[2*LhsProgress], A0);
- traits.loadRhs(&blB[5*RhsProgress], B1);
- traits.madd(A0,B0,C0,B0);
- traits.loadRhs(&blB[6*RhsProgress], B0);
- traits.madd(A0,B1,C1,B1);
- traits.loadLhs(&blA[3*LhsProgress], A0);
- traits.loadRhs(&blB[7*RhsProgress], B1);
- traits.madd(A0,B0,C0,B0);
- traits.madd(A0,B1,C1,B1);
- }
- else
- {
- LhsPacket A0;
- RhsPacket B0, B1, B2, B3;
-
- traits.loadLhs(&blA[0*LhsProgress], A0);
- traits.loadRhs(&blB[0*RhsProgress], B0);
- traits.loadRhs(&blB[1*RhsProgress], B1);
-
- traits.madd(A0,B0,C0,B0);
- traits.loadRhs(&blB[2*RhsProgress], B2);
- traits.loadRhs(&blB[3*RhsProgress], B3);
- traits.loadRhs(&blB[4*RhsProgress], B0);
- traits.madd(A0,B1,C1,B1);
- traits.loadRhs(&blB[5*RhsProgress], B1);
- traits.madd(A0,B2,C2,B2);
- traits.loadRhs(&blB[6*RhsProgress], B2);
- traits.madd(A0,B3,C3,B3);
- traits.loadLhs(&blA[1*LhsProgress], A0);
- traits.loadRhs(&blB[7*RhsProgress], B3);
- traits.madd(A0,B0,C0,B0);
- traits.loadRhs(&blB[8*RhsProgress], B0);
- traits.madd(A0,B1,C1,B1);
- traits.loadRhs(&blB[9*RhsProgress], B1);
- traits.madd(A0,B2,C2,B2);
- traits.loadRhs(&blB[10*RhsProgress], B2);
- traits.madd(A0,B3,C3,B3);
- traits.loadLhs(&blA[2*LhsProgress], A0);
- traits.loadRhs(&blB[11*RhsProgress], B3);
-
- traits.madd(A0,B0,C0,B0);
- traits.loadRhs(&blB[12*RhsProgress], B0);
- traits.madd(A0,B1,C1,B1);
- traits.loadRhs(&blB[13*RhsProgress], B1);
- traits.madd(A0,B2,C2,B2);
- traits.loadRhs(&blB[14*RhsProgress], B2);
- traits.madd(A0,B3,C3,B3);
-
- traits.loadLhs(&blA[3*LhsProgress], A0);
- traits.loadRhs(&blB[15*RhsProgress], B3);
- traits.madd(A0,B0,C0,B0);
- traits.madd(A0,B1,C1,B1);
- traits.madd(A0,B2,C2,B2);
- traits.madd(A0,B3,C3,B3);
- }
-
- blB += nr*4*RhsProgress;
- blA += 4*LhsProgress;
- }
- // process remaining peeled loop
- for(Index k=peeled_kc; k<depth; k++)
- {
- if(nr==2)
- {
- LhsPacket A0;
- RhsPacket B0, B1;
-
- traits.loadLhs(&blA[0*LhsProgress], A0);
- traits.loadRhs(&blB[0*RhsProgress], B0);
- traits.loadRhs(&blB[1*RhsProgress], B1);
- traits.madd(A0,B0,C0,B0);
- traits.madd(A0,B1,C1,B1);
- }
- else
- {
- LhsPacket A0;
- RhsPacket B0, B1, B2, B3;
-
- traits.loadLhs(&blA[0*LhsProgress], A0);
- traits.loadRhs(&blB[0*RhsProgress], B0);
- traits.loadRhs(&blB[1*RhsProgress], B1);
- traits.loadRhs(&blB[2*RhsProgress], B2);
- traits.loadRhs(&blB[3*RhsProgress], B3);
-
- traits.madd(A0,B0,C0,B0);
- traits.madd(A0,B1,C1,B1);
- traits.madd(A0,B2,C2,B2);
- traits.madd(A0,B3,C3,B3);
- }
-
- blB += nr*RhsProgress;
- blA += LhsProgress;
- }
-
- ResPacket R0, R1, R2, R3;
- ResPacket alphav = pset1<ResPacket>(alpha);
-
- ResScalar* r0 = &res[(j2+0)*resStride + i];
- ResScalar* r1 = r0 + resStride;
- ResScalar* r2 = r1 + resStride;
- ResScalar* r3 = r2 + resStride;
-
- R0 = ploadu<ResPacket>(r0);
- R1 = ploadu<ResPacket>(r1);
- if(nr==4) R2 = ploadu<ResPacket>(r2);
- if(nr==4) R3 = ploadu<ResPacket>(r3);
-
- traits.acc(C0, alphav, R0);
- traits.acc(C1, alphav, R1);
- if(nr==4) traits.acc(C2, alphav, R2);
- if(nr==4) traits.acc(C3, alphav, R3);
-
- pstoreu(r0, R0);
- pstoreu(r1, R1);
- if(nr==4) pstoreu(r2, R2);
- if(nr==4) pstoreu(r3, R3);
- }
- for(Index i=peeled_mc2; i<rows; i++)
- {
- const LhsScalar* blA = &blockA[i*strideA+offsetA];
- prefetch(&blA[0]);
-
- // gets a 1 x nr res block as registers
- ResScalar C0(0), C1(0), C2(0), C3(0);
- // TODO directly use blockB ???
- const RhsScalar* blB = &blockB[j2*strideB+offsetB*nr];
- for(Index k=0; k<depth; k++)
- {
- if(nr==2)
- {
- LhsScalar A0;
- RhsScalar B0, B1;
-
- A0 = blA[k];
- B0 = blB[0];
- B1 = blB[1];
- MADD(cj,A0,B0,C0,B0);
- MADD(cj,A0,B1,C1,B1);
- }
- else
- {
- LhsScalar A0;
- RhsScalar B0, B1, B2, B3;
-
- A0 = blA[k];
- B0 = blB[0];
- B1 = blB[1];
- B2 = blB[2];
- B3 = blB[3];
-
- MADD(cj,A0,B0,C0,B0);
- MADD(cj,A0,B1,C1,B1);
- MADD(cj,A0,B2,C2,B2);
- MADD(cj,A0,B3,C3,B3);
- }
-
- blB += nr;
- }
- res[(j2+0)*resStride + i] += alpha*C0;
- res[(j2+1)*resStride + i] += alpha*C1;
- if(nr==4) res[(j2+2)*resStride + i] += alpha*C2;
- if(nr==4) res[(j2+3)*resStride + i] += alpha*C3;
- }
- }
- // process remaining rhs/res columns one at a time
- // => do the same but with nr==1
- for(Index j2=packet_cols; j2<cols; j2++)
- {
- // unpack B
- traits.unpackRhs(depth, &blockB[j2*strideB+offsetB], unpackedB);
-
- for(Index i=0; i<peeled_mc; i+=mr)
- {
- const LhsScalar* blA = &blockA[i*strideA+offsetA*mr];
- prefetch(&blA[0]);
-
- // TODO move the res loads to the stores
-
- // get res block as registers
- AccPacket C0, C4;
- traits.initAcc(C0);
- traits.initAcc(C4);
-
- const RhsScalar* blB = unpackedB;
- for(Index k=0; k<depth; k++)
- {
- LhsPacket A0, A1;
- RhsPacket B0;
- RhsPacket T0;
-
- traits.loadLhs(&blA[0*LhsProgress], A0);
- traits.loadLhs(&blA[1*LhsProgress], A1);
- traits.loadRhs(&blB[0*RhsProgress], B0);
- traits.madd(A0,B0,C0,T0);
- traits.madd(A1,B0,C4,B0);
-
- blB += RhsProgress;
- blA += 2*LhsProgress;
- }
- ResPacket R0, R4;
- ResPacket alphav = pset1<ResPacket>(alpha);
-
- ResScalar* r0 = &res[(j2+0)*resStride + i];
-
- R0 = ploadu<ResPacket>(r0);
- R4 = ploadu<ResPacket>(r0+ResPacketSize);
-
- traits.acc(C0, alphav, R0);
- traits.acc(C4, alphav, R4);
-
- pstoreu(r0, R0);
- pstoreu(r0+ResPacketSize, R4);
- }
- if(rows-peeled_mc>=LhsProgress)
- {
- Index i = peeled_mc;
- const LhsScalar* blA = &blockA[i*strideA+offsetA*LhsProgress];
- prefetch(&blA[0]);
-
- AccPacket C0;
- traits.initAcc(C0);
-
- const RhsScalar* blB = unpackedB;
- for(Index k=0; k<depth; k++)
- {
- LhsPacket A0;
- RhsPacket B0;
- traits.loadLhs(blA, A0);
- traits.loadRhs(blB, B0);
- traits.madd(A0, B0, C0, B0);
- blB += RhsProgress;
- blA += LhsProgress;
- }
-
- ResPacket alphav = pset1<ResPacket>(alpha);
- ResPacket R0 = ploadu<ResPacket>(&res[(j2+0)*resStride + i]);
- traits.acc(C0, alphav, R0);
- pstoreu(&res[(j2+0)*resStride + i], R0);
- }
- for(Index i=peeled_mc2; i<rows; i++)
- {
- const LhsScalar* blA = &blockA[i*strideA+offsetA];
- prefetch(&blA[0]);
-
- // gets a 1 x 1 res block as registers
- ResScalar C0(0);
- // FIXME directly use blockB ??
- const RhsScalar* blB = &blockB[j2*strideB+offsetB];
- for(Index k=0; k<depth; k++)
- {
- LhsScalar A0 = blA[k];
- RhsScalar B0 = blB[k];
- MADD(cj, A0, B0, C0, B0);
- }
- res[(j2+0)*resStride + i] += alpha*C0;
- }
- }
- }
-};
-
-#undef CJMADD
-
-// pack a block of the lhs
-// The travesal is as follow (mr==4):
-// 0 4 8 12 ...
-// 1 5 9 13 ...
-// 2 6 10 14 ...
-// 3 7 11 15 ...
-//
-// 16 20 24 28 ...
-// 17 21 25 29 ...
-// 18 22 26 30 ...
-// 19 23 27 31 ...
-//
-// 32 33 34 35 ...
-// 36 36 38 39 ...
-template<typename Scalar, typename Index, int Pack1, int Pack2, int StorageOrder, bool Conjugate, bool PanelMode>
-struct gemm_pack_lhs
-{
- void operator()(Scalar* blockA, const Scalar* EIGEN_RESTRICT _lhs, Index lhsStride, Index depth, Index rows,
- Index stride=0, Index offset=0)
- {
-// enum { PacketSize = packet_traits<Scalar>::size };
- eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
- conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
- const_blas_data_mapper<Scalar, Index, StorageOrder> lhs(_lhs,lhsStride);
- Index count = 0;
- Index peeled_mc = (rows/Pack1)*Pack1;
- for(Index i=0; i<peeled_mc; i+=Pack1)
- {
- if(PanelMode) count += Pack1 * offset;
- for(Index k=0; k<depth; k++)
- for(Index w=0; w<Pack1; w++)
- blockA[count++] = cj(lhs(i+w, k));
- if(PanelMode) count += Pack1 * (stride-offset-depth);
- }
- if(rows-peeled_mc>=Pack2)
- {
- if(PanelMode) count += Pack2*offset;
- for(Index k=0; k<depth; k++)
- for(Index w=0; w<Pack2; w++)
- blockA[count++] = cj(lhs(peeled_mc+w, k));
- if(PanelMode) count += Pack2 * (stride-offset-depth);
- peeled_mc += Pack2;
- }
- for(Index i=peeled_mc; i<rows; i++)
- {
- if(PanelMode) count += offset;
- for(Index k=0; k<depth; k++)
- blockA[count++] = cj(lhs(i, k));
- if(PanelMode) count += (stride-offset-depth);
- }
- }
-};
-
-// copy a complete panel of the rhs
-// this version is optimized for column major matrices
-// The traversal order is as follow: (nr==4):
-// 0 1 2 3 12 13 14 15 24 27
-// 4 5 6 7 16 17 18 19 25 28
-// 8 9 10 11 20 21 22 23 26 29
-// . . . . . . . . . .
-template<typename Scalar, typename Index, int nr, bool Conjugate, bool PanelMode>
-struct gemm_pack_rhs<Scalar, Index, nr, ColMajor, Conjugate, PanelMode>
-{
- typedef typename packet_traits<Scalar>::type Packet;
- enum { PacketSize = packet_traits<Scalar>::size };
- void operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols,
- Index stride=0, Index offset=0)
- {
- eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
- conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
- Index packet_cols = (cols/nr) * nr;
- Index count = 0;
- for(Index j2=0; j2<packet_cols; j2+=nr)
- {
- // skip what we have before
- if(PanelMode) count += nr * offset;
- const Scalar* b0 = &rhs[(j2+0)*rhsStride];
- const Scalar* b1 = &rhs[(j2+1)*rhsStride];
- const Scalar* b2 = &rhs[(j2+2)*rhsStride];
- const Scalar* b3 = &rhs[(j2+3)*rhsStride];
- for(Index k=0; k<depth; k++)
- {
- blockB[count+0] = cj(b0[k]);
- blockB[count+1] = cj(b1[k]);
- if(nr==4) blockB[count+2] = cj(b2[k]);
- if(nr==4) blockB[count+3] = cj(b3[k]);
- count += nr;
- }
- // skip what we have after
- if(PanelMode) count += nr * (stride-offset-depth);
- }
-
- // copy the remaining columns one at a time (nr==1)
- for(Index j2=packet_cols; j2<cols; ++j2)
- {
- if(PanelMode) count += offset;
- const Scalar* b0 = &rhs[(j2+0)*rhsStride];
- for(Index k=0; k<depth; k++)
- {
- blockB[count] = cj(b0[k]);
- count += 1;
- }
- if(PanelMode) count += (stride-offset-depth);
- }
- }
-};
-
-// this version is optimized for row major matrices
-template<typename Scalar, typename Index, int nr, bool Conjugate, bool PanelMode>
-struct gemm_pack_rhs<Scalar, Index, nr, RowMajor, Conjugate, PanelMode>
-{
- enum { PacketSize = packet_traits<Scalar>::size };
- void operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols,
- Index stride=0, Index offset=0)
- {
- eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
- conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
- Index packet_cols = (cols/nr) * nr;
- Index count = 0;
- for(Index j2=0; j2<packet_cols; j2+=nr)
- {
- // skip what we have before
- if(PanelMode) count += nr * offset;
- for(Index k=0; k<depth; k++)
- {
- const Scalar* b0 = &rhs[k*rhsStride + j2];
- blockB[count+0] = cj(b0[0]);
- blockB[count+1] = cj(b0[1]);
- if(nr==4) blockB[count+2] = cj(b0[2]);
- if(nr==4) blockB[count+3] = cj(b0[3]);
- count += nr;
- }
- // skip what we have after
- if(PanelMode) count += nr * (stride-offset-depth);
- }
- // copy the remaining columns one at a time (nr==1)
- for(Index j2=packet_cols; j2<cols; ++j2)
- {
- if(PanelMode) count += offset;
- const Scalar* b0 = &rhs[j2];
- for(Index k=0; k<depth; k++)
- {
- blockB[count] = cj(b0[k*rhsStride]);
- count += 1;
- }
- if(PanelMode) count += stride-offset-depth;
- }
- }
-};
-
-} // end namespace internal
-
-/** \returns the currently set level 1 cpu cache size (in bytes) used to estimate the ideal blocking size parameters.
- * \sa setCpuCacheSize */
-inline std::ptrdiff_t l1CacheSize()
-{
- std::ptrdiff_t l1, l2;
- internal::manage_caching_sizes(GetAction, &l1, &l2);
- return l1;
-}
-
-/** \returns the currently set level 2 cpu cache size (in bytes) used to estimate the ideal blocking size parameters.
- * \sa setCpuCacheSize */
-inline std::ptrdiff_t l2CacheSize()
-{
- std::ptrdiff_t l1, l2;
- internal::manage_caching_sizes(GetAction, &l1, &l2);
- return l2;
-}
-
-/** Set the cpu L1 and L2 cache sizes (in bytes).
- * These values are use to adjust the size of the blocks
- * for the algorithms working per blocks.
- *
- * \sa computeProductBlockingSizes */
-inline void setCpuCacheSizes(std::ptrdiff_t l1, std::ptrdiff_t l2)
-{
- internal::manage_caching_sizes(SetAction, &l1, &l2);
-}
-
-#endif // EIGEN_GENERAL_BLOCK_PANEL_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h
deleted file mode 100644
index ae94a27953b..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h
+++ /dev/null
@@ -1,439 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_GENERAL_MATRIX_MATRIX_H
-#define EIGEN_GENERAL_MATRIX_MATRIX_H
-
-namespace internal {
-
-template<typename _LhsScalar, typename _RhsScalar> class level3_blocking;
-
-/* Specialization for a row-major destination matrix => simple transposition of the product */
-template<
- typename Index,
- typename LhsScalar, int LhsStorageOrder, bool ConjugateLhs,
- typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs>
-struct general_matrix_matrix_product<Index,LhsScalar,LhsStorageOrder,ConjugateLhs,RhsScalar,RhsStorageOrder,ConjugateRhs,RowMajor>
-{
- typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
- static EIGEN_STRONG_INLINE void run(
- Index rows, Index cols, Index depth,
- const LhsScalar* lhs, Index lhsStride,
- const RhsScalar* rhs, Index rhsStride,
- ResScalar* res, Index resStride,
- ResScalar alpha,
- level3_blocking<RhsScalar,LhsScalar>& blocking,
- GemmParallelInfo<Index>* info = 0)
- {
- // transpose the product such that the result is column major
- general_matrix_matrix_product<Index,
- RhsScalar, RhsStorageOrder==RowMajor ? ColMajor : RowMajor, ConjugateRhs,
- LhsScalar, LhsStorageOrder==RowMajor ? ColMajor : RowMajor, ConjugateLhs,
- ColMajor>
- ::run(cols,rows,depth,rhs,rhsStride,lhs,lhsStride,res,resStride,alpha,blocking,info);
- }
-};
-
-/* Specialization for a col-major destination matrix
- * => Blocking algorithm following Goto's paper */
-template<
- typename Index,
- typename LhsScalar, int LhsStorageOrder, bool ConjugateLhs,
- typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs>
-struct general_matrix_matrix_product<Index,LhsScalar,LhsStorageOrder,ConjugateLhs,RhsScalar,RhsStorageOrder,ConjugateRhs,ColMajor>
-{
-typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
-static void run(Index rows, Index cols, Index depth,
- const LhsScalar* _lhs, Index lhsStride,
- const RhsScalar* _rhs, Index rhsStride,
- ResScalar* res, Index resStride,
- ResScalar alpha,
- level3_blocking<LhsScalar,RhsScalar>& blocking,
- GemmParallelInfo<Index>* info = 0)
-{
- const_blas_data_mapper<LhsScalar, Index, LhsStorageOrder> lhs(_lhs,lhsStride);
- const_blas_data_mapper<RhsScalar, Index, RhsStorageOrder> rhs(_rhs,rhsStride);
-
- typedef gebp_traits<LhsScalar,RhsScalar> Traits;
-
- Index kc = blocking.kc(); // cache block size along the K direction
- Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction
- //Index nc = blocking.nc(); // cache block size along the N direction
-
- gemm_pack_lhs<LhsScalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder> pack_lhs;
- gemm_pack_rhs<RhsScalar, Index, Traits::nr, RhsStorageOrder> pack_rhs;
- gebp_kernel<LhsScalar, RhsScalar, Index, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp;
-
-#ifdef EIGEN_HAS_OPENMP
- if(info)
- {
- // this is the parallel version!
- Index tid = omp_get_thread_num();
- Index threads = omp_get_num_threads();
-
- std::size_t sizeA = kc*mc;
- std::size_t sizeW = kc*Traits::WorkSpaceFactor;
- ei_declare_aligned_stack_constructed_variable(LhsScalar, blockA, sizeA, 0);
- ei_declare_aligned_stack_constructed_variable(RhsScalar, w, sizeW, 0);
-
- RhsScalar* blockB = blocking.blockB();
- eigen_internal_assert(blockB!=0);
-
- // For each horizontal panel of the rhs, and corresponding vertical panel of the lhs...
- for(Index k=0; k<depth; k+=kc)
- {
- const Index actual_kc = (std::min)(k+kc,depth)-k; // => rows of B', and cols of the A'
-
- // In order to reduce the chance that a thread has to wait for the other,
- // let's start by packing A'.
- pack_lhs(blockA, &lhs(0,k), lhsStride, actual_kc, mc);
-
- // Pack B_k to B' in a parallel fashion:
- // each thread packs the sub block B_k,j to B'_j where j is the thread id.
-
- // However, before copying to B'_j, we have to make sure that no other thread is still using it,
- // i.e., we test that info[tid].users equals 0.
- // Then, we set info[tid].users to the number of threads to mark that all other threads are going to use it.
- while(info[tid].users!=0) {}
- info[tid].users += threads;
-
- pack_rhs(blockB+info[tid].rhs_start*actual_kc, &rhs(k,info[tid].rhs_start), rhsStride, actual_kc, info[tid].rhs_length);
-
- // Notify the other threads that the part B'_j is ready to go.
- info[tid].sync = k;
-
- // Computes C_i += A' * B' per B'_j
- for(Index shift=0; shift<threads; ++shift)
- {
- Index j = (tid+shift)%threads;
-
- // At this point we have to make sure that B'_j has been updated by the thread j,
- // we use testAndSetOrdered to mimic a volatile access.
- // However, no need to wait for the B' part which has been updated by the current thread!
- if(shift>0)
- while(info[j].sync!=k) {}
-
- gebp(res+info[j].rhs_start*resStride, resStride, blockA, blockB+info[j].rhs_start*actual_kc, mc, actual_kc, info[j].rhs_length, alpha, -1,-1,0,0, w);
- }
-
- // Then keep going as usual with the remaining A'
- for(Index i=mc; i<rows; i+=mc)
- {
- const Index actual_mc = (std::min)(i+mc,rows)-i;
-
- // pack A_i,k to A'
- pack_lhs(blockA, &lhs(i,k), lhsStride, actual_kc, actual_mc);
-
- // C_i += A' * B'
- gebp(res+i, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha, -1,-1,0,0, w);
- }
-
- // 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
- --(info[j].users);
- }
- }
- else
-#endif // EIGEN_HAS_OPENMP
- {
- EIGEN_UNUSED_VARIABLE(info);
-
- // this is the sequential version!
- std::size_t sizeA = kc*mc;
- std::size_t sizeB = kc*cols;
- std::size_t sizeW = kc*Traits::WorkSpaceFactor;
-
- ei_declare_aligned_stack_constructed_variable(LhsScalar, blockA, sizeA, blocking.blockA());
- ei_declare_aligned_stack_constructed_variable(RhsScalar, blockB, sizeB, blocking.blockB());
- ei_declare_aligned_stack_constructed_variable(RhsScalar, blockW, sizeW, blocking.blockW());
-
- // For each horizontal panel of the rhs, and corresponding panel of the lhs...
- // (==GEMM_VAR1)
- for(Index k2=0; k2<depth; k2+=kc)
- {
- const Index actual_kc = (std::min)(k2+kc,depth)-k2;
-
- // OK, here we have selected one horizontal panel of rhs and one vertical panel of lhs.
- // => Pack rhs's panel into a sequential chunk of memory (L2 caching)
- // Note that this panel will be read as many times as the number of blocks in the lhs's
- // vertical panel which is, in practice, a very low number.
- pack_rhs(blockB, &rhs(k2,0), rhsStride, actual_kc, cols);
-
-
- // For each mc x kc block of the lhs's vertical panel...
- // (==GEPP_VAR1)
- for(Index i2=0; i2<rows; i2+=mc)
- {
- const Index actual_mc = (std::min)(i2+mc,rows)-i2;
-
- // We pack the lhs's block into a sequential chunk of memory (L1 caching)
- // Note that this block will be read a very high number of times, which is equal to the number of
- // micro vertical panel of the large rhs's panel (e.g., cols/4 times).
- pack_lhs(blockA, &lhs(i2,k2), lhsStride, actual_kc, actual_mc);
-
- // Everything is packed, we can now call the block * panel kernel:
- gebp(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha, -1, -1, 0, 0, blockW);
-
- }
- }
- }
-}
-
-};
-
-/*********************************************************************************
-* Specialization of GeneralProduct<> for "large" GEMM, i.e.,
-* implementation of the high level wrapper to general_matrix_matrix_product
-**********************************************************************************/
-
-template<typename Lhs, typename Rhs>
-struct traits<GeneralProduct<Lhs,Rhs,GemmProduct> >
- : traits<ProductBase<GeneralProduct<Lhs,Rhs,GemmProduct>, Lhs, Rhs> >
-{};
-
-template<typename Scalar, typename Index, typename Gemm, typename Lhs, typename Rhs, typename Dest, typename BlockingType>
-struct gemm_functor
-{
- gemm_functor(const Lhs& lhs, const Rhs& rhs, Dest& dest, Scalar actualAlpha,
- BlockingType& blocking)
- : m_lhs(lhs), m_rhs(rhs), m_dest(dest), m_actualAlpha(actualAlpha), m_blocking(blocking)
- {}
-
- void initParallelSession() const
- {
- m_blocking.allocateB();
- }
-
- void operator() (Index row, Index rows, Index col=0, Index cols=-1, GemmParallelInfo<Index>* info=0) const
- {
- if(cols==-1)
- cols = m_rhs.cols();
-
- Gemm::run(rows, cols, m_lhs.cols(),
- /*(const Scalar*)*/&m_lhs.coeffRef(row,0), m_lhs.outerStride(),
- /*(const Scalar*)*/&m_rhs.coeffRef(0,col), m_rhs.outerStride(),
- (Scalar*)&(m_dest.coeffRef(row,col)), m_dest.outerStride(),
- m_actualAlpha, m_blocking, info);
- }
-
- protected:
- const Lhs& m_lhs;
- const Rhs& m_rhs;
- Dest& m_dest;
- Scalar m_actualAlpha;
- BlockingType& m_blocking;
-};
-
-template<int StorageOrder, typename LhsScalar, typename RhsScalar, int MaxRows, int MaxCols, int MaxDepth,
-bool FiniteAtCompileTime = MaxRows!=Dynamic && MaxCols!=Dynamic && MaxDepth != Dynamic> class gemm_blocking_space;
-
-template<typename _LhsScalar, typename _RhsScalar>
-class level3_blocking
-{
- typedef _LhsScalar LhsScalar;
- typedef _RhsScalar RhsScalar;
-
- protected:
- LhsScalar* m_blockA;
- RhsScalar* m_blockB;
- RhsScalar* m_blockW;
-
- DenseIndex m_mc;
- DenseIndex m_nc;
- DenseIndex m_kc;
-
- public:
-
- level3_blocking()
- : m_blockA(0), m_blockB(0), m_blockW(0), m_mc(0), m_nc(0), m_kc(0)
- {}
-
- inline DenseIndex mc() const { return m_mc; }
- inline DenseIndex nc() const { return m_nc; }
- inline DenseIndex kc() const { return m_kc; }
-
- inline LhsScalar* blockA() { return m_blockA; }
- inline RhsScalar* blockB() { return m_blockB; }
- inline RhsScalar* blockW() { return m_blockW; }
-};
-
-template<int StorageOrder, typename _LhsScalar, typename _RhsScalar, int MaxRows, int MaxCols, int MaxDepth>
-class gemm_blocking_space<StorageOrder,_LhsScalar,_RhsScalar,MaxRows, MaxCols, MaxDepth, true>
- : public level3_blocking<
- typename conditional<StorageOrder==RowMajor,_RhsScalar,_LhsScalar>::type,
- typename conditional<StorageOrder==RowMajor,_LhsScalar,_RhsScalar>::type>
-{
- enum {
- Transpose = StorageOrder==RowMajor,
- ActualRows = Transpose ? MaxCols : MaxRows,
- ActualCols = Transpose ? MaxRows : MaxCols
- };
- typedef typename conditional<Transpose,_RhsScalar,_LhsScalar>::type LhsScalar;
- typedef typename conditional<Transpose,_LhsScalar,_RhsScalar>::type RhsScalar;
- typedef gebp_traits<LhsScalar,RhsScalar> Traits;
- enum {
- SizeA = ActualRows * MaxDepth,
- SizeB = ActualCols * MaxDepth,
- SizeW = MaxDepth * Traits::WorkSpaceFactor
- };
-
- EIGEN_ALIGN16 LhsScalar m_staticA[SizeA];
- EIGEN_ALIGN16 RhsScalar m_staticB[SizeB];
- EIGEN_ALIGN16 RhsScalar m_staticW[SizeW];
-
- public:
-
- gemm_blocking_space(DenseIndex /*rows*/, DenseIndex /*cols*/, DenseIndex /*depth*/)
- {
- this->m_mc = ActualRows;
- this->m_nc = ActualCols;
- this->m_kc = MaxDepth;
- this->m_blockA = m_staticA;
- this->m_blockB = m_staticB;
- this->m_blockW = m_staticW;
- }
-
- inline void allocateA() {}
- inline void allocateB() {}
- inline void allocateW() {}
- inline void allocateAll() {}
-};
-
-template<int StorageOrder, typename _LhsScalar, typename _RhsScalar, int MaxRows, int MaxCols, int MaxDepth>
-class gemm_blocking_space<StorageOrder,_LhsScalar,_RhsScalar,MaxRows, MaxCols, MaxDepth, false>
- : public level3_blocking<
- typename conditional<StorageOrder==RowMajor,_RhsScalar,_LhsScalar>::type,
- typename conditional<StorageOrder==RowMajor,_LhsScalar,_RhsScalar>::type>
-{
- enum {
- Transpose = StorageOrder==RowMajor
- };
- typedef typename conditional<Transpose,_RhsScalar,_LhsScalar>::type LhsScalar;
- typedef typename conditional<Transpose,_LhsScalar,_RhsScalar>::type RhsScalar;
- typedef gebp_traits<LhsScalar,RhsScalar> Traits;
-
- DenseIndex m_sizeA;
- DenseIndex m_sizeB;
- DenseIndex m_sizeW;
-
- public:
-
- gemm_blocking_space(DenseIndex rows, DenseIndex cols, DenseIndex depth)
- {
- this->m_mc = Transpose ? cols : rows;
- this->m_nc = Transpose ? rows : cols;
- this->m_kc = depth;
-
- computeProductBlockingSizes<LhsScalar,RhsScalar>(this->m_kc, this->m_mc, this->m_nc);
- m_sizeA = this->m_mc * this->m_kc;
- m_sizeB = this->m_kc * this->m_nc;
- m_sizeW = this->m_kc*Traits::WorkSpaceFactor;
- }
-
- void allocateA()
- {
- if(this->m_blockA==0)
- this->m_blockA = aligned_new<LhsScalar>(m_sizeA);
- }
-
- void allocateB()
- {
- if(this->m_blockB==0)
- this->m_blockB = aligned_new<RhsScalar>(m_sizeB);
- }
-
- void allocateW()
- {
- if(this->m_blockW==0)
- this->m_blockW = aligned_new<RhsScalar>(m_sizeW);
- }
-
- void allocateAll()
- {
- allocateA();
- allocateB();
- allocateW();
- }
-
- ~gemm_blocking_space()
- {
- aligned_delete(this->m_blockA, m_sizeA);
- aligned_delete(this->m_blockB, m_sizeB);
- aligned_delete(this->m_blockW, m_sizeW);
- }
-};
-
-} // end namespace internal
-
-template<typename Lhs, typename Rhs>
-class GeneralProduct<Lhs, Rhs, GemmProduct>
- : public ProductBase<GeneralProduct<Lhs,Rhs,GemmProduct>, Lhs, Rhs>
-{
- enum {
- MaxDepthAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(Lhs::MaxColsAtCompileTime,Rhs::MaxRowsAtCompileTime)
- };
- public:
- EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct)
-
- typedef typename Lhs::Scalar LhsScalar;
- typedef typename Rhs::Scalar RhsScalar;
- typedef Scalar ResScalar;
-
- GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
- {
- typedef internal::scalar_product_op<LhsScalar,RhsScalar> BinOp;
- EIGEN_CHECK_BINARY_COMPATIBILIY(BinOp,LhsScalar,RhsScalar);
- }
-
- template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
- {
- eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
-
- const ActualLhsType lhs = LhsBlasTraits::extract(m_lhs);
- const ActualRhsType rhs = RhsBlasTraits::extract(m_rhs);
-
- Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(m_lhs)
- * RhsBlasTraits::extractScalarFactor(m_rhs);
-
- typedef internal::gemm_blocking_space<(Dest::Flags&RowMajorBit) ? RowMajor : ColMajor,LhsScalar,RhsScalar,
- Dest::MaxRowsAtCompileTime,Dest::MaxColsAtCompileTime,MaxDepthAtCompileTime> BlockingType;
-
- typedef internal::gemm_functor<
- Scalar, Index,
- internal::general_matrix_matrix_product<
- Index,
- LhsScalar, (_ActualLhsType::Flags&RowMajorBit) ? RowMajor : ColMajor, bool(LhsBlasTraits::NeedToConjugate),
- RhsScalar, (_ActualRhsType::Flags&RowMajorBit) ? RowMajor : ColMajor, bool(RhsBlasTraits::NeedToConjugate),
- (Dest::Flags&RowMajorBit) ? RowMajor : ColMajor>,
- _ActualLhsType, _ActualRhsType, Dest, BlockingType> GemmFunctor;
-
- BlockingType blocking(dst.rows(), dst.cols(), lhs.cols());
-
- internal::parallelize_gemm<(Dest::MaxRowsAtCompileTime>32 || Dest::MaxRowsAtCompileTime==Dynamic)>(GemmFunctor(lhs, rhs, dst, actualAlpha, blocking), this->rows(), this->cols(), Dest::Flags&RowMajorBit);
- }
-};
-
-#endif // EIGEN_GENERAL_MATRIX_MATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h
deleted file mode 100644
index 5043b64fe2e..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h
+++ /dev/null
@@ -1,225 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_H
-#define EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_H
-
-namespace internal {
-
-/**********************************************************************
-* This file implements a general A * B product while
-* evaluating only one triangular part of the product.
-* This is more general version of self adjoint product (C += A A^T)
-* as the level 3 SYRK Blas routine.
-**********************************************************************/
-
-// forward declarations (defined at the end of this file)
-template<typename LhsScalar, typename RhsScalar, typename Index, int mr, int nr, bool ConjLhs, bool ConjRhs, int UpLo>
-struct tribb_kernel;
-
-/* Optimized matrix-matrix product evaluating only one triangular half */
-template <typename Index,
- typename LhsScalar, int LhsStorageOrder, bool ConjugateLhs,
- typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs,
- int ResStorageOrder, int UpLo>
-struct general_matrix_matrix_triangular_product;
-
-// as usual if the result is row major => we transpose the product
-template <typename Index, typename LhsScalar, int LhsStorageOrder, bool ConjugateLhs,
- typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs, int UpLo>
-struct general_matrix_matrix_triangular_product<Index,LhsScalar,LhsStorageOrder,ConjugateLhs,RhsScalar,RhsStorageOrder,ConjugateRhs,RowMajor,UpLo>
-{
- typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
- static EIGEN_STRONG_INLINE void run(Index size, Index depth,const LhsScalar* lhs, Index lhsStride,
- const RhsScalar* rhs, Index rhsStride, ResScalar* res, Index resStride, ResScalar alpha)
- {
- general_matrix_matrix_triangular_product<Index,
- RhsScalar, RhsStorageOrder==RowMajor ? ColMajor : RowMajor, ConjugateRhs,
- LhsScalar, LhsStorageOrder==RowMajor ? ColMajor : RowMajor, ConjugateLhs,
- ColMajor, UpLo==Lower?Upper:Lower>
- ::run(size,depth,rhs,rhsStride,lhs,lhsStride,res,resStride,alpha);
- }
-};
-
-template <typename Index, typename LhsScalar, int LhsStorageOrder, bool ConjugateLhs,
- typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs, int UpLo>
-struct general_matrix_matrix_triangular_product<Index,LhsScalar,LhsStorageOrder,ConjugateLhs,RhsScalar,RhsStorageOrder,ConjugateRhs,ColMajor,UpLo>
-{
- typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
- static EIGEN_STRONG_INLINE void run(Index size, Index depth,const LhsScalar* _lhs, Index lhsStride,
- const RhsScalar* _rhs, Index rhsStride, ResScalar* res, Index resStride, ResScalar alpha)
- {
- const_blas_data_mapper<LhsScalar, Index, LhsStorageOrder> lhs(_lhs,lhsStride);
- const_blas_data_mapper<RhsScalar, Index, RhsStorageOrder> rhs(_rhs,rhsStride);
-
- typedef gebp_traits<LhsScalar,RhsScalar> Traits;
-
- Index kc = depth; // cache block size along the K direction
- Index mc = size; // cache block size along the M direction
- Index nc = size; // cache block size along the N direction
- computeProductBlockingSizes<LhsScalar,RhsScalar>(kc, mc, nc);
- // !!! mc must be a multiple of nr:
- if(mc > Traits::nr)
- mc = (mc/Traits::nr)*Traits::nr;
-
- std::size_t sizeW = kc*Traits::WorkSpaceFactor;
- std::size_t sizeB = sizeW + kc*size;
- ei_declare_aligned_stack_constructed_variable(LhsScalar, blockA, kc*mc, 0);
- ei_declare_aligned_stack_constructed_variable(RhsScalar, allocatedBlockB, sizeB, 0);
- RhsScalar* blockB = allocatedBlockB + sizeW;
-
- gemm_pack_lhs<LhsScalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder> pack_lhs;
- gemm_pack_rhs<RhsScalar, Index, Traits::nr, RhsStorageOrder> pack_rhs;
- gebp_kernel <LhsScalar, RhsScalar, Index, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp;
- tribb_kernel<LhsScalar, RhsScalar, Index, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs, UpLo> sybb;
-
- for(Index k2=0; k2<depth; k2+=kc)
- {
- const Index actual_kc = (std::min)(k2+kc,depth)-k2;
-
- // note that the actual rhs is the transpose/adjoint of mat
- pack_rhs(blockB, &rhs(k2,0), rhsStride, actual_kc, size);
-
- for(Index i2=0; i2<size; i2+=mc)
- {
- const Index actual_mc = (std::min)(i2+mc,size)-i2;
-
- pack_lhs(blockA, &lhs(i2, k2), lhsStride, actual_kc, actual_mc);
-
- // the selected actual_mc * size panel of res is split into three different part:
- // 1 - before the diagonal => processed with gebp or skipped
- // 2 - the actual_mc x actual_mc symmetric block => processed with a special kernel
- // 3 - after the diagonal => processed with gebp or skipped
- if (UpLo==Lower)
- gebp(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, (std::min)(size,i2), alpha,
- -1, -1, 0, 0, allocatedBlockB);
-
- sybb(res+resStride*i2 + i2, resStride, blockA, blockB + actual_kc*i2, actual_mc, actual_kc, alpha, allocatedBlockB);
-
- if (UpLo==Upper)
- {
- Index j2 = i2+actual_mc;
- gebp(res+resStride*j2+i2, resStride, blockA, blockB+actual_kc*j2, actual_mc, actual_kc, (std::max)(Index(0), size-j2), alpha,
- -1, -1, 0, 0, allocatedBlockB);
- }
- }
- }
- }
-};
-
-// Optimized packed Block * packed Block product kernel evaluating only one given triangular part
-// This kernel is built on top of the gebp kernel:
-// - the current destination block is processed per panel of actual_mc x BlockSize
-// where BlockSize is set to the minimal value allowing gebp to be as fast as possible
-// - then, as usual, each panel is split into three parts along the diagonal,
-// the sub blocks above and below the diagonal are processed as usual,
-// while the triangular block overlapping the diagonal is evaluated into a
-// small temporary buffer which is then accumulated into the result using a
-// triangular traversal.
-template<typename LhsScalar, typename RhsScalar, typename Index, int mr, int nr, bool ConjLhs, bool ConjRhs, int UpLo>
-struct tribb_kernel
-{
- typedef gebp_traits<LhsScalar,RhsScalar,ConjLhs,ConjRhs> Traits;
- typedef typename Traits::ResScalar ResScalar;
-
- enum {
- BlockSize = EIGEN_PLAIN_ENUM_MAX(mr,nr)
- };
- void operator()(ResScalar* res, Index resStride, const LhsScalar* blockA, const RhsScalar* blockB, Index size, Index depth, ResScalar alpha, RhsScalar* workspace)
- {
- gebp_kernel<LhsScalar, RhsScalar, Index, mr, nr, ConjLhs, ConjRhs> gebp_kernel;
- Matrix<ResScalar,BlockSize,BlockSize,ColMajor> buffer;
-
- // let's process the block per panel of actual_mc x BlockSize,
- // again, each is split into three parts, etc.
- for (Index j=0; j<size; j+=BlockSize)
- {
- Index actualBlockSize = std::min<Index>(BlockSize,size - j);
- const RhsScalar* actual_b = blockB+j*depth;
-
- if(UpLo==Upper)
- gebp_kernel(res+j*resStride, resStride, blockA, actual_b, j, depth, actualBlockSize, alpha,
- -1, -1, 0, 0, workspace);
-
- // selfadjoint micro block
- {
- Index i = j;
- buffer.setZero();
- // 1 - apply the kernel on the temporary buffer
- gebp_kernel(buffer.data(), BlockSize, blockA+depth*i, actual_b, actualBlockSize, depth, actualBlockSize, alpha,
- -1, -1, 0, 0, workspace);
- // 2 - triangular accumulation
- for(Index j1=0; j1<actualBlockSize; ++j1)
- {
- ResScalar* r = res + (j+j1)*resStride + i;
- for(Index i1=UpLo==Lower ? j1 : 0;
- UpLo==Lower ? i1<actualBlockSize : i1<=j1; ++i1)
- r[i1] += buffer(i1,j1);
- }
- }
-
- if(UpLo==Lower)
- {
- Index i = j+actualBlockSize;
- gebp_kernel(res+j*resStride+i, resStride, blockA+depth*i, actual_b, size-i, depth, actualBlockSize, alpha,
- -1, -1, 0, 0, workspace);
- }
- }
- }
-};
-
-} // end namespace internal
-
-// high level API
-
-template<typename MatrixType, unsigned int UpLo>
-template<typename ProductDerived, typename _Lhs, typename _Rhs>
-TriangularView<MatrixType,UpLo>& TriangularView<MatrixType,UpLo>::assignProduct(const ProductBase<ProductDerived, _Lhs,_Rhs>& prod, const Scalar& alpha)
-{
- typedef typename internal::remove_all<typename ProductDerived::LhsNested>::type Lhs;
- typedef internal::blas_traits<Lhs> LhsBlasTraits;
- typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhs;
- typedef typename internal::remove_all<ActualLhs>::type _ActualLhs;
- const ActualLhs actualLhs = LhsBlasTraits::extract(prod.lhs());
-
- typedef typename internal::remove_all<typename ProductDerived::RhsNested>::type Rhs;
- typedef internal::blas_traits<Rhs> RhsBlasTraits;
- typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhs;
- typedef typename internal::remove_all<ActualRhs>::type _ActualRhs;
- const ActualRhs actualRhs = RhsBlasTraits::extract(prod.rhs());
-
- typename ProductDerived::Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs().derived()) * RhsBlasTraits::extractScalarFactor(prod.rhs().derived());
-
- internal::general_matrix_matrix_triangular_product<Index,
- typename Lhs::Scalar, _ActualLhs::Flags&RowMajorBit ? RowMajor : ColMajor, LhsBlasTraits::NeedToConjugate,
- typename Rhs::Scalar, _ActualRhs::Flags&RowMajorBit ? RowMajor : ColMajor, RhsBlasTraits::NeedToConjugate,
- MatrixType::Flags&RowMajorBit ? RowMajor : ColMajor, UpLo>
- ::run(m_matrix.cols(), actualLhs.cols(),
- &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &actualRhs.coeffRef(0,0), actualRhs.outerStride(),
- const_cast<Scalar*>(m_matrix.data()), m_matrix.outerStride(), actualAlpha);
-
- return *this;
-}
-
-#endif // EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h
deleted file mode 100644
index e0e2cbf8f62..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h
+++ /dev/null
@@ -1,559 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_GENERAL_MATRIX_VECTOR_H
-#define EIGEN_GENERAL_MATRIX_VECTOR_H
-
-namespace internal {
-
-/* Optimized col-major matrix * vector product:
- * This algorithm processes 4 columns at onces that allows to both reduce
- * the number of load/stores of the result by a factor 4 and to reduce
- * the instruction dependency. Moreover, we know that all bands have the
- * same alignment pattern.
- *
- * Mixing type logic: C += alpha * A * B
- * | A | B |alpha| comments
- * |real |cplx |cplx | no vectorization
- * |real |cplx |real | alpha is converted to a cplx when calling the run function, no vectorization
- * |cplx |real |cplx | invalid, the caller has to do tmp: = A * B; C += alpha*tmp
- * |cplx |real |real | optimal case, vectorization possible via real-cplx mul
- */
-template<typename Index, typename LhsScalar, bool ConjugateLhs, typename RhsScalar, bool ConjugateRhs>
-struct general_matrix_vector_product<Index,LhsScalar,ColMajor,ConjugateLhs,RhsScalar,ConjugateRhs>
-{
-typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
-
-enum {
- Vectorizable = packet_traits<LhsScalar>::Vectorizable && packet_traits<RhsScalar>::Vectorizable
- && int(packet_traits<LhsScalar>::size)==int(packet_traits<RhsScalar>::size),
- LhsPacketSize = Vectorizable ? packet_traits<LhsScalar>::size : 1,
- RhsPacketSize = Vectorizable ? packet_traits<RhsScalar>::size : 1,
- ResPacketSize = Vectorizable ? packet_traits<ResScalar>::size : 1
-};
-
-typedef typename packet_traits<LhsScalar>::type _LhsPacket;
-typedef typename packet_traits<RhsScalar>::type _RhsPacket;
-typedef typename packet_traits<ResScalar>::type _ResPacket;
-
-typedef typename conditional<Vectorizable,_LhsPacket,LhsScalar>::type LhsPacket;
-typedef typename conditional<Vectorizable,_RhsPacket,RhsScalar>::type RhsPacket;
-typedef typename conditional<Vectorizable,_ResPacket,ResScalar>::type ResPacket;
-
-EIGEN_DONT_INLINE static void run(
- Index rows, Index cols,
- const LhsScalar* lhs, Index lhsStride,
- const RhsScalar* rhs, Index rhsIncr,
- ResScalar* res, Index
- #ifdef EIGEN_INTERNAL_DEBUGGING
- resIncr
- #endif
- , RhsScalar alpha)
-{
- eigen_internal_assert(resIncr==1);
- #ifdef _EIGEN_ACCUMULATE_PACKETS
- #error _EIGEN_ACCUMULATE_PACKETS has already been defined
- #endif
- #define _EIGEN_ACCUMULATE_PACKETS(A0,A13,A2) \
- pstore(&res[j], \
- padd(pload<ResPacket>(&res[j]), \
- padd( \
- padd(pcj.pmul(EIGEN_CAT(ploa , A0)<LhsPacket>(&lhs0[j]), ptmp0), \
- pcj.pmul(EIGEN_CAT(ploa , A13)<LhsPacket>(&lhs1[j]), ptmp1)), \
- padd(pcj.pmul(EIGEN_CAT(ploa , A2)<LhsPacket>(&lhs2[j]), ptmp2), \
- pcj.pmul(EIGEN_CAT(ploa , A13)<LhsPacket>(&lhs3[j]), ptmp3)) )))
-
- conj_helper<LhsScalar,RhsScalar,ConjugateLhs,ConjugateRhs> cj;
- conj_helper<LhsPacket,RhsPacket,ConjugateLhs,ConjugateRhs> pcj;
- if(ConjugateRhs)
- alpha = conj(alpha);
-
- enum { AllAligned = 0, EvenAligned, FirstAligned, NoneAligned };
- const Index columnsAtOnce = 4;
- const Index peels = 2;
- const Index LhsPacketAlignedMask = LhsPacketSize-1;
- const Index ResPacketAlignedMask = ResPacketSize-1;
- const Index PeelAlignedMask = ResPacketSize*peels-1;
- const Index size = rows;
-
- // How many coeffs of the result do we have to skip to be aligned.
- // Here we assume data are at least aligned on the base scalar type.
- Index alignedStart = first_aligned(res,size);
- Index alignedSize = ResPacketSize>1 ? alignedStart + ((size-alignedStart) & ~ResPacketAlignedMask) : 0;
- const Index peeledSize = peels>1 ? alignedStart + ((alignedSize-alignedStart) & ~PeelAlignedMask) : alignedStart;
-
- const Index alignmentStep = LhsPacketSize>1 ? (LhsPacketSize - lhsStride % LhsPacketSize) & LhsPacketAlignedMask : 0;
- Index alignmentPattern = alignmentStep==0 ? AllAligned
- : alignmentStep==(LhsPacketSize/2) ? EvenAligned
- : FirstAligned;
-
- // we cannot assume the first element is aligned because of sub-matrices
- const Index lhsAlignmentOffset = first_aligned(lhs,size);
-
- // find how many columns do we have to skip to be aligned with the result (if possible)
- Index skipColumns = 0;
- // if the data cannot be aligned (TODO add some compile time tests when possible, e.g. for floats)
- if( (size_t(lhs)%sizeof(LhsScalar)) || (size_t(res)%sizeof(ResScalar)) )
- {
- alignedSize = 0;
- alignedStart = 0;
- }
- else if (LhsPacketSize>1)
- {
- eigen_internal_assert(size_t(lhs+lhsAlignmentOffset)%sizeof(LhsPacket)==0 || size<LhsPacketSize);
-
- while (skipColumns<LhsPacketSize &&
- alignedStart != ((lhsAlignmentOffset + alignmentStep*skipColumns)%LhsPacketSize))
- ++skipColumns;
- if (skipColumns==LhsPacketSize)
- {
- // nothing can be aligned, no need to skip any column
- alignmentPattern = NoneAligned;
- skipColumns = 0;
- }
- else
- {
- skipColumns = (std::min)(skipColumns,cols);
- // note that the skiped columns are processed later.
- }
-
- eigen_internal_assert( (alignmentPattern==NoneAligned)
- || (skipColumns + columnsAtOnce >= cols)
- || LhsPacketSize > size
- || (size_t(lhs+alignedStart+lhsStride*skipColumns)%sizeof(LhsPacket))==0);
- }
- else if(Vectorizable)
- {
- alignedStart = 0;
- alignedSize = size;
- alignmentPattern = AllAligned;
- }
-
- Index offset1 = (FirstAligned && alignmentStep==1?3:1);
- Index offset3 = (FirstAligned && alignmentStep==1?1:3);
-
- Index columnBound = ((cols-skipColumns)/columnsAtOnce)*columnsAtOnce + skipColumns;
- for (Index i=skipColumns; i<columnBound; i+=columnsAtOnce)
- {
- RhsPacket ptmp0 = pset1<RhsPacket>(alpha*rhs[i*rhsIncr]),
- ptmp1 = pset1<RhsPacket>(alpha*rhs[(i+offset1)*rhsIncr]),
- ptmp2 = pset1<RhsPacket>(alpha*rhs[(i+2)*rhsIncr]),
- ptmp3 = pset1<RhsPacket>(alpha*rhs[(i+offset3)*rhsIncr]);
-
- // this helps a lot generating better binary code
- const LhsScalar *lhs0 = lhs + i*lhsStride, *lhs1 = lhs + (i+offset1)*lhsStride,
- *lhs2 = lhs + (i+2)*lhsStride, *lhs3 = lhs + (i+offset3)*lhsStride;
-
- if (Vectorizable)
- {
- /* explicit vectorization */
- // process initial unaligned coeffs
- for (Index j=0; j<alignedStart; ++j)
- {
- res[j] = cj.pmadd(lhs0[j], pfirst(ptmp0), res[j]);
- res[j] = cj.pmadd(lhs1[j], pfirst(ptmp1), res[j]);
- res[j] = cj.pmadd(lhs2[j], pfirst(ptmp2), res[j]);
- res[j] = cj.pmadd(lhs3[j], pfirst(ptmp3), res[j]);
- }
-
- if (alignedSize>alignedStart)
- {
- switch(alignmentPattern)
- {
- case AllAligned:
- for (Index j = alignedStart; j<alignedSize; j+=ResPacketSize)
- _EIGEN_ACCUMULATE_PACKETS(d,d,d);
- break;
- case EvenAligned:
- for (Index j = alignedStart; j<alignedSize; j+=ResPacketSize)
- _EIGEN_ACCUMULATE_PACKETS(d,du,d);
- break;
- case FirstAligned:
- if(peels>1)
- {
- LhsPacket A00, A01, A02, A03, A10, A11, A12, A13;
- ResPacket T0, T1;
-
- A01 = pload<LhsPacket>(&lhs1[alignedStart-1]);
- A02 = pload<LhsPacket>(&lhs2[alignedStart-2]);
- A03 = pload<LhsPacket>(&lhs3[alignedStart-3]);
-
- for (Index j = alignedStart; j<peeledSize; j+=peels*ResPacketSize)
- {
- A11 = pload<LhsPacket>(&lhs1[j-1+LhsPacketSize]); palign<1>(A01,A11);
- A12 = pload<LhsPacket>(&lhs2[j-2+LhsPacketSize]); palign<2>(A02,A12);
- A13 = pload<LhsPacket>(&lhs3[j-3+LhsPacketSize]); palign<3>(A03,A13);
-
- A00 = pload<LhsPacket>(&lhs0[j]);
- A10 = pload<LhsPacket>(&lhs0[j+LhsPacketSize]);
- T0 = pcj.pmadd(A00, ptmp0, pload<ResPacket>(&res[j]));
- T1 = pcj.pmadd(A10, ptmp0, pload<ResPacket>(&res[j+ResPacketSize]));
-
- T0 = pcj.pmadd(A01, ptmp1, T0);
- A01 = pload<LhsPacket>(&lhs1[j-1+2*LhsPacketSize]); palign<1>(A11,A01);
- T0 = pcj.pmadd(A02, ptmp2, T0);
- A02 = pload<LhsPacket>(&lhs2[j-2+2*LhsPacketSize]); palign<2>(A12,A02);
- T0 = pcj.pmadd(A03, ptmp3, T0);
- pstore(&res[j],T0);
- A03 = pload<LhsPacket>(&lhs3[j-3+2*LhsPacketSize]); palign<3>(A13,A03);
- T1 = pcj.pmadd(A11, ptmp1, T1);
- T1 = pcj.pmadd(A12, ptmp2, T1);
- T1 = pcj.pmadd(A13, ptmp3, T1);
- pstore(&res[j+ResPacketSize],T1);
- }
- }
- for (Index j = peeledSize; j<alignedSize; j+=ResPacketSize)
- _EIGEN_ACCUMULATE_PACKETS(d,du,du);
- break;
- default:
- for (Index j = alignedStart; j<alignedSize; j+=ResPacketSize)
- _EIGEN_ACCUMULATE_PACKETS(du,du,du);
- break;
- }
- }
- } // end explicit vectorization
-
- /* process remaining coeffs (or all if there is no explicit vectorization) */
- for (Index j=alignedSize; j<size; ++j)
- {
- res[j] = cj.pmadd(lhs0[j], pfirst(ptmp0), res[j]);
- res[j] = cj.pmadd(lhs1[j], pfirst(ptmp1), res[j]);
- res[j] = cj.pmadd(lhs2[j], pfirst(ptmp2), res[j]);
- res[j] = cj.pmadd(lhs3[j], pfirst(ptmp3), res[j]);
- }
- }
-
- // process remaining first and last columns (at most columnsAtOnce-1)
- Index end = cols;
- Index start = columnBound;
- do
- {
- for (Index k=start; k<end; ++k)
- {
- RhsPacket ptmp0 = pset1<RhsPacket>(alpha*rhs[k*rhsIncr]);
- const LhsScalar* lhs0 = lhs + k*lhsStride;
-
- if (Vectorizable)
- {
- /* explicit vectorization */
- // process first unaligned result's coeffs
- for (Index j=0; j<alignedStart; ++j)
- res[j] += cj.pmul(lhs0[j], pfirst(ptmp0));
- // process aligned result's coeffs
- if ((size_t(lhs0+alignedStart)%sizeof(LhsPacket))==0)
- for (Index i = alignedStart;i<alignedSize;i+=ResPacketSize)
- pstore(&res[i], pcj.pmadd(ploadu<LhsPacket>(&lhs0[i]), ptmp0, pload<ResPacket>(&res[i])));
- else
- for (Index i = alignedStart;i<alignedSize;i+=ResPacketSize)
- pstore(&res[i], pcj.pmadd(ploadu<LhsPacket>(&lhs0[i]), ptmp0, pload<ResPacket>(&res[i])));
- }
-
- // process remaining scalars (or all if no explicit vectorization)
- for (Index i=alignedSize; i<size; ++i)
- res[i] += cj.pmul(lhs0[i], pfirst(ptmp0));
- }
- if (skipColumns)
- {
- start = 0;
- end = skipColumns;
- skipColumns = 0;
- }
- else
- break;
- } while(Vectorizable);
- #undef _EIGEN_ACCUMULATE_PACKETS
-}
-};
-
-/* Optimized row-major matrix * vector product:
- * This algorithm processes 4 rows at onces that allows to both reduce
- * the number of load/stores of the result by a factor 4 and to reduce
- * the instruction dependency. Moreover, we know that all bands have the
- * same alignment pattern.
- *
- * Mixing type logic:
- * - alpha is always a complex (or converted to a complex)
- * - no vectorization
- */
-template<typename Index, typename LhsScalar, bool ConjugateLhs, typename RhsScalar, bool ConjugateRhs>
-struct general_matrix_vector_product<Index,LhsScalar,RowMajor,ConjugateLhs,RhsScalar,ConjugateRhs>
-{
-typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
-
-enum {
- Vectorizable = packet_traits<LhsScalar>::Vectorizable && packet_traits<RhsScalar>::Vectorizable
- && int(packet_traits<LhsScalar>::size)==int(packet_traits<RhsScalar>::size),
- LhsPacketSize = Vectorizable ? packet_traits<LhsScalar>::size : 1,
- RhsPacketSize = Vectorizable ? packet_traits<RhsScalar>::size : 1,
- ResPacketSize = Vectorizable ? packet_traits<ResScalar>::size : 1
-};
-
-typedef typename packet_traits<LhsScalar>::type _LhsPacket;
-typedef typename packet_traits<RhsScalar>::type _RhsPacket;
-typedef typename packet_traits<ResScalar>::type _ResPacket;
-
-typedef typename conditional<Vectorizable,_LhsPacket,LhsScalar>::type LhsPacket;
-typedef typename conditional<Vectorizable,_RhsPacket,RhsScalar>::type RhsPacket;
-typedef typename conditional<Vectorizable,_ResPacket,ResScalar>::type ResPacket;
-
-EIGEN_DONT_INLINE static void run(
- Index rows, Index cols,
- const LhsScalar* lhs, Index lhsStride,
- const RhsScalar* rhs, Index rhsIncr,
- ResScalar* res, Index resIncr,
- ResScalar alpha)
-{
- EIGEN_UNUSED_VARIABLE(rhsIncr);
- eigen_internal_assert(rhsIncr==1);
- #ifdef _EIGEN_ACCUMULATE_PACKETS
- #error _EIGEN_ACCUMULATE_PACKETS has already been defined
- #endif
-
- #define _EIGEN_ACCUMULATE_PACKETS(A0,A13,A2) {\
- RhsPacket b = pload<RhsPacket>(&rhs[j]); \
- ptmp0 = pcj.pmadd(EIGEN_CAT(ploa,A0) <LhsPacket>(&lhs0[j]), b, ptmp0); \
- ptmp1 = pcj.pmadd(EIGEN_CAT(ploa,A13)<LhsPacket>(&lhs1[j]), b, ptmp1); \
- ptmp2 = pcj.pmadd(EIGEN_CAT(ploa,A2) <LhsPacket>(&lhs2[j]), b, ptmp2); \
- ptmp3 = pcj.pmadd(EIGEN_CAT(ploa,A13)<LhsPacket>(&lhs3[j]), b, ptmp3); }
-
- conj_helper<LhsScalar,RhsScalar,ConjugateLhs,ConjugateRhs> cj;
- conj_helper<LhsPacket,RhsPacket,ConjugateLhs,ConjugateRhs> pcj;
-
- enum { AllAligned=0, EvenAligned=1, FirstAligned=2, NoneAligned=3 };
- const Index rowsAtOnce = 4;
- const Index peels = 2;
- const Index RhsPacketAlignedMask = RhsPacketSize-1;
- const Index LhsPacketAlignedMask = LhsPacketSize-1;
- const Index PeelAlignedMask = RhsPacketSize*peels-1;
- const Index depth = cols;
-
- // How many coeffs of the result do we have to skip to be aligned.
- // Here we assume data are at least aligned on the base scalar type
- // if that's not the case then vectorization is discarded, see below.
- Index alignedStart = first_aligned(rhs, depth);
- Index alignedSize = RhsPacketSize>1 ? alignedStart + ((depth-alignedStart) & ~RhsPacketAlignedMask) : 0;
- const Index peeledSize = peels>1 ? alignedStart + ((alignedSize-alignedStart) & ~PeelAlignedMask) : alignedStart;
-
- const Index alignmentStep = LhsPacketSize>1 ? (LhsPacketSize - lhsStride % LhsPacketSize) & LhsPacketAlignedMask : 0;
- Index alignmentPattern = alignmentStep==0 ? AllAligned
- : alignmentStep==(LhsPacketSize/2) ? EvenAligned
- : FirstAligned;
-
- // we cannot assume the first element is aligned because of sub-matrices
- const Index lhsAlignmentOffset = first_aligned(lhs,depth);
-
- // find how many rows do we have to skip to be aligned with rhs (if possible)
- Index skipRows = 0;
- // if the data cannot be aligned (TODO add some compile time tests when possible, e.g. for floats)
- if( (sizeof(LhsScalar)!=sizeof(RhsScalar)) || (size_t(lhs)%sizeof(LhsScalar)) || (size_t(rhs)%sizeof(RhsScalar)) )
- {
- alignedSize = 0;
- alignedStart = 0;
- }
- else if (LhsPacketSize>1)
- {
- eigen_internal_assert(size_t(lhs+lhsAlignmentOffset)%sizeof(LhsPacket)==0 || depth<LhsPacketSize);
-
- while (skipRows<LhsPacketSize &&
- alignedStart != ((lhsAlignmentOffset + alignmentStep*skipRows)%LhsPacketSize))
- ++skipRows;
- if (skipRows==LhsPacketSize)
- {
- // nothing can be aligned, no need to skip any column
- alignmentPattern = NoneAligned;
- skipRows = 0;
- }
- else
- {
- skipRows = (std::min)(skipRows,Index(rows));
- // note that the skiped columns are processed later.
- }
- eigen_internal_assert( alignmentPattern==NoneAligned
- || LhsPacketSize==1
- || (skipRows + rowsAtOnce >= rows)
- || LhsPacketSize > depth
- || (size_t(lhs+alignedStart+lhsStride*skipRows)%sizeof(LhsPacket))==0);
- }
- else if(Vectorizable)
- {
- alignedStart = 0;
- alignedSize = depth;
- alignmentPattern = AllAligned;
- }
-
- Index offset1 = (FirstAligned && alignmentStep==1?3:1);
- Index offset3 = (FirstAligned && alignmentStep==1?1:3);
-
- Index rowBound = ((rows-skipRows)/rowsAtOnce)*rowsAtOnce + skipRows;
- for (Index i=skipRows; i<rowBound; i+=rowsAtOnce)
- {
- EIGEN_ALIGN16 ResScalar tmp0 = ResScalar(0);
- ResScalar tmp1 = ResScalar(0), tmp2 = ResScalar(0), tmp3 = ResScalar(0);
-
- // this helps the compiler generating good binary code
- const LhsScalar *lhs0 = lhs + i*lhsStride, *lhs1 = lhs + (i+offset1)*lhsStride,
- *lhs2 = lhs + (i+2)*lhsStride, *lhs3 = lhs + (i+offset3)*lhsStride;
-
- if (Vectorizable)
- {
- /* explicit vectorization */
- ResPacket ptmp0 = pset1<ResPacket>(ResScalar(0)), ptmp1 = pset1<ResPacket>(ResScalar(0)),
- ptmp2 = pset1<ResPacket>(ResScalar(0)), ptmp3 = pset1<ResPacket>(ResScalar(0));
-
- // process initial unaligned coeffs
- // FIXME this loop get vectorized by the compiler !
- for (Index j=0; j<alignedStart; ++j)
- {
- RhsScalar b = rhs[j];
- tmp0 += cj.pmul(lhs0[j],b); tmp1 += cj.pmul(lhs1[j],b);
- tmp2 += cj.pmul(lhs2[j],b); tmp3 += cj.pmul(lhs3[j],b);
- }
-
- if (alignedSize>alignedStart)
- {
- switch(alignmentPattern)
- {
- case AllAligned:
- for (Index j = alignedStart; j<alignedSize; j+=RhsPacketSize)
- _EIGEN_ACCUMULATE_PACKETS(d,d,d);
- break;
- case EvenAligned:
- for (Index j = alignedStart; j<alignedSize; j+=RhsPacketSize)
- _EIGEN_ACCUMULATE_PACKETS(d,du,d);
- break;
- case FirstAligned:
- if (peels>1)
- {
- /* Here we proccess 4 rows with with two peeled iterations to hide
- * tghe overhead of unaligned loads. Moreover unaligned loads are handled
- * using special shift/move operations between the two aligned packets
- * overlaping the desired unaligned packet. This is *much* more efficient
- * than basic unaligned loads.
- */
- LhsPacket A01, A02, A03, A11, A12, A13;
- A01 = pload<LhsPacket>(&lhs1[alignedStart-1]);
- A02 = pload<LhsPacket>(&lhs2[alignedStart-2]);
- A03 = pload<LhsPacket>(&lhs3[alignedStart-3]);
-
- for (Index j = alignedStart; j<peeledSize; j+=peels*RhsPacketSize)
- {
- RhsPacket b = pload<RhsPacket>(&rhs[j]);
- A11 = pload<LhsPacket>(&lhs1[j-1+LhsPacketSize]); palign<1>(A01,A11);
- A12 = pload<LhsPacket>(&lhs2[j-2+LhsPacketSize]); palign<2>(A02,A12);
- A13 = pload<LhsPacket>(&lhs3[j-3+LhsPacketSize]); palign<3>(A03,A13);
-
- ptmp0 = pcj.pmadd(pload<LhsPacket>(&lhs0[j]), b, ptmp0);
- ptmp1 = pcj.pmadd(A01, b, ptmp1);
- A01 = pload<LhsPacket>(&lhs1[j-1+2*LhsPacketSize]); palign<1>(A11,A01);
- ptmp2 = pcj.pmadd(A02, b, ptmp2);
- A02 = pload<LhsPacket>(&lhs2[j-2+2*LhsPacketSize]); palign<2>(A12,A02);
- ptmp3 = pcj.pmadd(A03, b, ptmp3);
- A03 = pload<LhsPacket>(&lhs3[j-3+2*LhsPacketSize]); palign<3>(A13,A03);
-
- b = pload<RhsPacket>(&rhs[j+RhsPacketSize]);
- ptmp0 = pcj.pmadd(pload<LhsPacket>(&lhs0[j+LhsPacketSize]), b, ptmp0);
- ptmp1 = pcj.pmadd(A11, b, ptmp1);
- ptmp2 = pcj.pmadd(A12, b, ptmp2);
- ptmp3 = pcj.pmadd(A13, b, ptmp3);
- }
- }
- for (Index j = peeledSize; j<alignedSize; j+=RhsPacketSize)
- _EIGEN_ACCUMULATE_PACKETS(d,du,du);
- break;
- default:
- for (Index j = alignedStart; j<alignedSize; j+=RhsPacketSize)
- _EIGEN_ACCUMULATE_PACKETS(du,du,du);
- break;
- }
- tmp0 += predux(ptmp0);
- tmp1 += predux(ptmp1);
- tmp2 += predux(ptmp2);
- tmp3 += predux(ptmp3);
- }
- } // end explicit vectorization
-
- // process remaining coeffs (or all if no explicit vectorization)
- // FIXME this loop get vectorized by the compiler !
- for (Index j=alignedSize; j<depth; ++j)
- {
- RhsScalar b = rhs[j];
- tmp0 += cj.pmul(lhs0[j],b); tmp1 += cj.pmul(lhs1[j],b);
- tmp2 += cj.pmul(lhs2[j],b); tmp3 += cj.pmul(lhs3[j],b);
- }
- res[i*resIncr] += alpha*tmp0;
- res[(i+offset1)*resIncr] += alpha*tmp1;
- res[(i+2)*resIncr] += alpha*tmp2;
- res[(i+offset3)*resIncr] += alpha*tmp3;
- }
-
- // process remaining first and last rows (at most columnsAtOnce-1)
- Index end = rows;
- Index start = rowBound;
- do
- {
- for (Index i=start; i<end; ++i)
- {
- EIGEN_ALIGN16 ResScalar tmp0 = ResScalar(0);
- ResPacket ptmp0 = pset1<ResPacket>(tmp0);
- const LhsScalar* lhs0 = lhs + i*lhsStride;
- // process first unaligned result's coeffs
- // FIXME this loop get vectorized by the compiler !
- for (Index j=0; j<alignedStart; ++j)
- tmp0 += cj.pmul(lhs0[j], rhs[j]);
-
- if (alignedSize>alignedStart)
- {
- // process aligned rhs coeffs
- if ((size_t(lhs0+alignedStart)%sizeof(LhsPacket))==0)
- for (Index j = alignedStart;j<alignedSize;j+=RhsPacketSize)
- ptmp0 = pcj.pmadd(pload<LhsPacket>(&lhs0[j]), pload<RhsPacket>(&rhs[j]), ptmp0);
- else
- for (Index j = alignedStart;j<alignedSize;j+=RhsPacketSize)
- ptmp0 = pcj.pmadd(ploadu<LhsPacket>(&lhs0[j]), pload<RhsPacket>(&rhs[j]), ptmp0);
- tmp0 += predux(ptmp0);
- }
-
- // process remaining scalars
- // FIXME this loop get vectorized by the compiler !
- for (Index j=alignedSize; j<depth; ++j)
- tmp0 += cj.pmul(lhs0[j], rhs[j]);
- res[i*resIncr] += alpha*tmp0;
- }
- if (skipRows)
- {
- start = 0;
- end = skipRows;
- skipRows = 0;
- }
- else
- break;
- } while(Vectorizable);
-
- #undef _EIGEN_ACCUMULATE_PACKETS
-}
-};
-
-} // end namespace internal
-
-#endif // EIGEN_GENERAL_MATRIX_VECTOR_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/Parallelizer.h b/extern/Eigen3/Eigen/src/Core/products/Parallelizer.h
deleted file mode 100644
index ecdedc363ce..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/Parallelizer.h
+++ /dev/null
@@ -1,154 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_PARALLELIZER_H
-#define EIGEN_PARALLELIZER_H
-
-namespace internal {
-
-/** \internal */
-inline void manage_multi_threading(Action action, int* v)
-{
- static EIGEN_UNUSED int m_maxThreads = -1;
-
- if(action==SetAction)
- {
- eigen_internal_assert(v!=0);
- m_maxThreads = *v;
- }
- else if(action==GetAction)
- {
- eigen_internal_assert(v!=0);
- #ifdef EIGEN_HAS_OPENMP
- if(m_maxThreads>0)
- *v = m_maxThreads;
- else
- *v = omp_get_max_threads();
- #else
- *v = 1;
- #endif
- }
- else
- {
- eigen_internal_assert(false);
- }
-}
-
-/** \returns the max number of threads reserved for Eigen
- * \sa setNbThreads */
-inline int nbThreads()
-{
- int ret;
- manage_multi_threading(GetAction, &ret);
- return ret;
-}
-
-/** Sets the max number of threads reserved for Eigen
- * \sa nbThreads */
-inline void setNbThreads(int v)
-{
- manage_multi_threading(SetAction, &v);
-}
-
-template<typename Index> struct GemmParallelInfo
-{
- GemmParallelInfo() : sync(-1), users(0), rhs_start(0), rhs_length(0) {}
-
- int volatile sync;
- int volatile users;
-
- Index rhs_start;
- Index rhs_length;
-};
-
-template<bool Condition, typename Functor, typename Index>
-void parallelize_gemm(const Functor& func, Index rows, Index cols, bool transpose)
-{
-#ifndef EIGEN_HAS_OPENMP
- // FIXME the transpose variable is only needed to properly split
- // the matrix product when multithreading is enabled. This is a temporary
- // fix to support row-major destination matrices. This whole
- // parallelizer mechanism has to be redisigned anyway.
- EIGEN_UNUSED_VARIABLE(transpose);
- func(0,rows, 0,cols);
-#else
-
- // Dynamically check whether we should enable or disable OpenMP.
- // The conditions are:
- // - the max number of threads we can create is greater than 1
- // - we are not already in a parallel code
- // - the sizes are large enough
-
- // 1- are we already in a parallel session?
- // FIXME omp_get_num_threads()>1 only works for openmp, what if the user does not use openmp?
- if((!Condition) || (omp_get_num_threads()>1))
- return func(0,rows, 0,cols);
-
- Index size = transpose ? cols : rows;
-
- // 2- compute the maximal number of threads from the size of the product:
- // FIXME this has to be fine tuned
- Index max_threads = std::max<Index>(1,size / 32);
-
- // 3 - compute the number of threads we are going to use
- Index threads = std::min<Index>(nbThreads(), max_threads);
-
- if(threads==1)
- return func(0,rows, 0,cols);
-
- func.initParallelSession();
-
- 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)
- {
- Index r0 = i*blockRows;
- Index actualBlockRows = (i+1==threads) ? rows-r0 : blockRows;
-
- Index c0 = i*blockCols;
- Index actualBlockCols = (i+1==threads) ? cols-c0 : blockCols;
-
- info[i].rhs_start = c0;
- info[i].rhs_length = actualBlockCols;
-
- if(transpose)
- func(0, cols, r0, actualBlockRows, info);
- else
- func(r0, actualBlockRows, 0,cols, info);
- }
-
- delete[] info;
-#endif
-}
-
-} // end namespace internal
-
-#endif // EIGEN_PARALLELIZER_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h b/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h
deleted file mode 100644
index ccd757cfaf8..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h
+++ /dev/null
@@ -1,427 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SELFADJOINT_MATRIX_MATRIX_H
-#define EIGEN_SELFADJOINT_MATRIX_MATRIX_H
-
-namespace internal {
-
-// pack a selfadjoint block diagonal for use with the gebp_kernel
-template<typename Scalar, typename Index, int Pack1, int Pack2, int StorageOrder>
-struct symm_pack_lhs
-{
- template<int BlockRows> inline
- void pack(Scalar* blockA, const const_blas_data_mapper<Scalar,Index,StorageOrder>& lhs, Index cols, Index i, Index& count)
- {
- // normal copy
- for(Index k=0; k<i; k++)
- for(Index w=0; w<BlockRows; w++)
- blockA[count++] = lhs(i+w,k); // normal
- // symmetric copy
- Index h = 0;
- for(Index k=i; k<i+BlockRows; k++)
- {
- for(Index w=0; w<h; w++)
- blockA[count++] = conj(lhs(k, i+w)); // transposed
-
- blockA[count++] = real(lhs(k,k)); // real (diagonal)
-
- for(Index w=h+1; w<BlockRows; w++)
- blockA[count++] = lhs(i+w, k); // normal
- ++h;
- }
- // transposed copy
- for(Index k=i+BlockRows; k<cols; k++)
- for(Index w=0; w<BlockRows; w++)
- blockA[count++] = conj(lhs(k, i+w)); // transposed
- }
- void operator()(Scalar* blockA, const Scalar* _lhs, Index lhsStride, Index cols, Index rows)
- {
- const_blas_data_mapper<Scalar,Index,StorageOrder> lhs(_lhs,lhsStride);
- Index count = 0;
- Index peeled_mc = (rows/Pack1)*Pack1;
- for(Index i=0; i<peeled_mc; i+=Pack1)
- {
- pack<Pack1>(blockA, lhs, cols, i, count);
- }
-
- if(rows-peeled_mc>=Pack2)
- {
- pack<Pack2>(blockA, lhs, cols, peeled_mc, count);
- peeled_mc += Pack2;
- }
-
- // do the same with mr==1
- for(Index i=peeled_mc; i<rows; i++)
- {
- for(Index k=0; k<i; k++)
- blockA[count++] = lhs(i, k); // normal
-
- blockA[count++] = real(lhs(i, i)); // real (diagonal)
-
- for(Index k=i+1; k<cols; k++)
- blockA[count++] = conj(lhs(k, i)); // transposed
- }
- }
-};
-
-template<typename Scalar, typename Index, int nr, int StorageOrder>
-struct symm_pack_rhs
-{
- enum { PacketSize = packet_traits<Scalar>::size };
- void operator()(Scalar* blockB, const Scalar* _rhs, Index rhsStride, Index rows, Index cols, Index k2)
- {
- Index end_k = k2 + rows;
- Index count = 0;
- const_blas_data_mapper<Scalar,Index,StorageOrder> rhs(_rhs,rhsStride);
- Index packet_cols = (cols/nr)*nr;
-
- // first part: normal case
- for(Index j2=0; j2<k2; j2+=nr)
- {
- for(Index k=k2; k<end_k; k++)
- {
- blockB[count+0] = rhs(k,j2+0);
- blockB[count+1] = rhs(k,j2+1);
- if (nr==4)
- {
- blockB[count+2] = rhs(k,j2+2);
- blockB[count+3] = rhs(k,j2+3);
- }
- count += nr;
- }
- }
-
- // second part: diagonal block
- for(Index j2=k2; j2<(std::min)(k2+rows,packet_cols); j2+=nr)
- {
- // again we can split vertically in three different parts (transpose, symmetric, normal)
- // transpose
- for(Index k=k2; k<j2; k++)
- {
- blockB[count+0] = conj(rhs(j2+0,k));
- blockB[count+1] = conj(rhs(j2+1,k));
- if (nr==4)
- {
- blockB[count+2] = conj(rhs(j2+2,k));
- blockB[count+3] = conj(rhs(j2+3,k));
- }
- count += nr;
- }
- // symmetric
- Index h = 0;
- for(Index k=j2; k<j2+nr; k++)
- {
- // normal
- for (Index w=0 ; w<h; ++w)
- blockB[count+w] = rhs(k,j2+w);
-
- blockB[count+h] = real(rhs(k,k));
-
- // transpose
- for (Index w=h+1 ; w<nr; ++w)
- blockB[count+w] = conj(rhs(j2+w,k));
- count += nr;
- ++h;
- }
- // normal
- for(Index k=j2+nr; k<end_k; k++)
- {
- blockB[count+0] = rhs(k,j2+0);
- blockB[count+1] = rhs(k,j2+1);
- if (nr==4)
- {
- blockB[count+2] = rhs(k,j2+2);
- blockB[count+3] = rhs(k,j2+3);
- }
- count += nr;
- }
- }
-
- // third part: transposed
- for(Index j2=k2+rows; j2<packet_cols; j2+=nr)
- {
- for(Index k=k2; k<end_k; k++)
- {
- blockB[count+0] = conj(rhs(j2+0,k));
- blockB[count+1] = conj(rhs(j2+1,k));
- if (nr==4)
- {
- blockB[count+2] = conj(rhs(j2+2,k));
- blockB[count+3] = conj(rhs(j2+3,k));
- }
- count += nr;
- }
- }
-
- // copy the remaining columns one at a time (=> the same with nr==1)
- for(Index j2=packet_cols; j2<cols; ++j2)
- {
- // transpose
- Index half = (std::min)(end_k,j2);
- for(Index k=k2; k<half; k++)
- {
- blockB[count] = conj(rhs(j2,k));
- count += 1;
- }
-
- if(half==j2 && half<k2+rows)
- {
- blockB[count] = real(rhs(j2,j2));
- count += 1;
- }
- else
- half--;
-
- // normal
- for(Index k=half+1; k<k2+rows; k++)
- {
- blockB[count] = rhs(k,j2);
- count += 1;
- }
- }
- }
-};
-
-/* Optimized selfadjoint matrix * matrix (_SYMM) product built on top of
- * the general matrix matrix product.
- */
-template <typename Scalar, typename Index,
- int LhsStorageOrder, bool LhsSelfAdjoint, bool ConjugateLhs,
- int RhsStorageOrder, bool RhsSelfAdjoint, bool ConjugateRhs,
- int ResStorageOrder>
-struct product_selfadjoint_matrix;
-
-template <typename Scalar, typename Index,
- int LhsStorageOrder, bool LhsSelfAdjoint, bool ConjugateLhs,
- int RhsStorageOrder, bool RhsSelfAdjoint, bool ConjugateRhs>
-struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,LhsSelfAdjoint,ConjugateLhs, RhsStorageOrder,RhsSelfAdjoint,ConjugateRhs,RowMajor>
-{
-
- static EIGEN_STRONG_INLINE void run(
- Index rows, Index cols,
- const Scalar* lhs, Index lhsStride,
- const Scalar* rhs, Index rhsStride,
- Scalar* res, Index resStride,
- Scalar alpha)
- {
- product_selfadjoint_matrix<Scalar, Index,
- EIGEN_LOGICAL_XOR(RhsSelfAdjoint,RhsStorageOrder==RowMajor) ? ColMajor : RowMajor,
- RhsSelfAdjoint, NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(RhsSelfAdjoint,ConjugateRhs),
- EIGEN_LOGICAL_XOR(LhsSelfAdjoint,LhsStorageOrder==RowMajor) ? ColMajor : RowMajor,
- LhsSelfAdjoint, NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(LhsSelfAdjoint,ConjugateLhs),
- ColMajor>
- ::run(cols, rows, rhs, rhsStride, lhs, lhsStride, res, resStride, alpha);
- }
-};
-
-template <typename Scalar, typename Index,
- int LhsStorageOrder, bool ConjugateLhs,
- int RhsStorageOrder, bool ConjugateRhs>
-struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,true,ConjugateLhs, RhsStorageOrder,false,ConjugateRhs,ColMajor>
-{
-
- static EIGEN_DONT_INLINE void run(
- Index rows, Index cols,
- const Scalar* _lhs, Index lhsStride,
- const Scalar* _rhs, Index rhsStride,
- Scalar* res, Index resStride,
- Scalar alpha)
- {
- Index size = rows;
-
- const_blas_data_mapper<Scalar, Index, LhsStorageOrder> lhs(_lhs,lhsStride);
- const_blas_data_mapper<Scalar, Index, RhsStorageOrder> rhs(_rhs,rhsStride);
-
- typedef gebp_traits<Scalar,Scalar> Traits;
-
- Index kc = size; // cache block size along the K direction
- Index mc = rows; // cache block size along the M direction
- Index nc = cols; // cache block size along the N direction
- computeProductBlockingSizes<Scalar,Scalar>(kc, mc, nc);
- // kc must smaller than mc
- kc = (std::min)(kc,mc);
-
- std::size_t sizeW = kc*Traits::WorkSpaceFactor;
- std::size_t sizeB = sizeW + kc*cols;
- ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0);
- ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0);
- Scalar* blockB = allocatedBlockB + sizeW;
-
- gebp_kernel<Scalar, Scalar, Index, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp_kernel;
- symm_pack_lhs<Scalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder> pack_lhs;
- gemm_pack_rhs<Scalar, Index, Traits::nr,RhsStorageOrder> pack_rhs;
- gemm_pack_lhs<Scalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder==RowMajor?ColMajor:RowMajor, true> pack_lhs_transposed;
-
- for(Index k2=0; k2<size; k2+=kc)
- {
- const Index actual_kc = (std::min)(k2+kc,size)-k2;
-
- // we have selected one row panel of rhs and one column panel of lhs
- // pack rhs's panel into a sequential chunk of memory
- // and expand each coeff to a constant packet for further reuse
- pack_rhs(blockB, &rhs(k2,0), rhsStride, actual_kc, cols);
-
- // the select lhs's panel has to be split in three different parts:
- // 1 - the transposed panel above the diagonal block => transposed packed copy
- // 2 - the diagonal block => special packed copy
- // 3 - the panel below the diagonal block => generic packed copy
- for(Index i2=0; i2<k2; i2+=mc)
- {
- const Index actual_mc = (std::min)(i2+mc,k2)-i2;
- // transposed packed copy
- pack_lhs_transposed(blockA, &lhs(k2, i2), lhsStride, actual_kc, actual_mc);
-
- gebp_kernel(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha);
- }
- // the block diagonal
- {
- const Index actual_mc = (std::min)(k2+kc,size)-k2;
- // symmetric packed copy
- pack_lhs(blockA, &lhs(k2,k2), lhsStride, actual_kc, actual_mc);
-
- gebp_kernel(res+k2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha);
- }
-
- for(Index i2=k2+kc; i2<size; i2+=mc)
- {
- const Index actual_mc = (std::min)(i2+mc,size)-i2;
- gemm_pack_lhs<Scalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder,false>()
- (blockA, &lhs(i2, k2), lhsStride, actual_kc, actual_mc);
-
- gebp_kernel(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha);
- }
- }
- }
-};
-
-// matrix * selfadjoint product
-template <typename Scalar, typename Index,
- int LhsStorageOrder, bool ConjugateLhs,
- int RhsStorageOrder, bool ConjugateRhs>
-struct product_selfadjoint_matrix<Scalar,Index,LhsStorageOrder,false,ConjugateLhs, RhsStorageOrder,true,ConjugateRhs,ColMajor>
-{
-
- static EIGEN_DONT_INLINE void run(
- Index rows, Index cols,
- const Scalar* _lhs, Index lhsStride,
- const Scalar* _rhs, Index rhsStride,
- Scalar* res, Index resStride,
- Scalar alpha)
- {
- Index size = cols;
-
- const_blas_data_mapper<Scalar, Index, LhsStorageOrder> lhs(_lhs,lhsStride);
-
- typedef gebp_traits<Scalar,Scalar> Traits;
-
- Index kc = size; // cache block size along the K direction
- Index mc = rows; // cache block size along the M direction
- Index nc = cols; // cache block size along the N direction
- computeProductBlockingSizes<Scalar,Scalar>(kc, mc, nc);
- std::size_t sizeW = kc*Traits::WorkSpaceFactor;
- std::size_t sizeB = sizeW + kc*cols;
- ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0);
- ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0);
- Scalar* blockB = allocatedBlockB + sizeW;
-
- gebp_kernel<Scalar, Scalar, Index, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp_kernel;
- gemm_pack_lhs<Scalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder> pack_lhs;
- symm_pack_rhs<Scalar, Index, Traits::nr,RhsStorageOrder> pack_rhs;
-
- for(Index k2=0; k2<size; k2+=kc)
- {
- const Index actual_kc = (std::min)(k2+kc,size)-k2;
-
- pack_rhs(blockB, _rhs, rhsStride, actual_kc, cols, k2);
-
- // => GEPP
- for(Index i2=0; i2<rows; i2+=mc)
- {
- const Index actual_mc = (std::min)(i2+mc,rows)-i2;
- pack_lhs(blockA, &lhs(i2, k2), lhsStride, actual_kc, actual_mc);
-
- gebp_kernel(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha);
- }
- }
- }
-};
-
-} // end namespace internal
-
-/***************************************************************************
-* Wrapper to product_selfadjoint_matrix
-***************************************************************************/
-
-namespace internal {
-template<typename Lhs, int LhsMode, typename Rhs, int RhsMode>
-struct traits<SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,RhsMode,false> >
- : traits<ProductBase<SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,RhsMode,false>, Lhs, Rhs> >
-{};
-}
-
-template<typename Lhs, int LhsMode, typename Rhs, int RhsMode>
-struct SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,RhsMode,false>
- : public ProductBase<SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,RhsMode,false>, Lhs, Rhs >
-{
- EIGEN_PRODUCT_PUBLIC_INTERFACE(SelfadjointProductMatrix)
-
- SelfadjointProductMatrix(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {}
-
- enum {
- LhsIsUpper = (LhsMode&(Upper|Lower))==Upper,
- LhsIsSelfAdjoint = (LhsMode&SelfAdjoint)==SelfAdjoint,
- RhsIsUpper = (RhsMode&(Upper|Lower))==Upper,
- RhsIsSelfAdjoint = (RhsMode&SelfAdjoint)==SelfAdjoint
- };
-
- template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
- {
- eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
-
- const ActualLhsType lhs = LhsBlasTraits::extract(m_lhs);
- const ActualRhsType rhs = RhsBlasTraits::extract(m_rhs);
-
- Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(m_lhs)
- * RhsBlasTraits::extractScalarFactor(m_rhs);
-
- internal::product_selfadjoint_matrix<Scalar, Index,
- EIGEN_LOGICAL_XOR(LhsIsUpper,
- internal::traits<Lhs>::Flags &RowMajorBit) ? RowMajor : ColMajor, LhsIsSelfAdjoint,
- NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(LhsIsUpper,bool(LhsBlasTraits::NeedToConjugate)),
- EIGEN_LOGICAL_XOR(RhsIsUpper,
- internal::traits<Rhs>::Flags &RowMajorBit) ? RowMajor : ColMajor, RhsIsSelfAdjoint,
- NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(RhsIsUpper,bool(RhsBlasTraits::NeedToConjugate)),
- internal::traits<Dest>::Flags&RowMajorBit ? RowMajor : ColMajor>
- ::run(
- lhs.rows(), rhs.cols(), // sizes
- &lhs.coeffRef(0,0), lhs.outerStride(), // lhs info
- &rhs.coeffRef(0,0), rhs.outerStride(), // rhs info
- &dst.coeffRef(0,0), dst.outerStride(), // result info
- actualAlpha // alpha
- );
- }
-};
-
-#endif // EIGEN_SELFADJOINT_MATRIX_MATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h b/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h
deleted file mode 100644
index d6121fc07bd..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h
+++ /dev/null
@@ -1,278 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SELFADJOINT_MATRIX_VECTOR_H
-#define EIGEN_SELFADJOINT_MATRIX_VECTOR_H
-
-namespace internal {
-
-/* Optimized selfadjoint matrix * vector product:
- * This algorithm processes 2 columns at onces that allows to both reduce
- * the number of load/stores of the result by a factor 2 and to reduce
- * the instruction dependency.
- */
-template<typename Scalar, typename Index, int StorageOrder, int UpLo, bool ConjugateLhs, bool ConjugateRhs>
-static EIGEN_DONT_INLINE void product_selfadjoint_vector(
- Index size,
- const Scalar* lhs, Index lhsStride,
- const Scalar* _rhs, Index rhsIncr,
- Scalar* res,
- Scalar alpha)
-{
- typedef typename packet_traits<Scalar>::type Packet;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- const Index PacketSize = sizeof(Packet)/sizeof(Scalar);
-
- enum {
- IsRowMajor = StorageOrder==RowMajor ? 1 : 0,
- IsLower = UpLo == Lower ? 1 : 0,
- FirstTriangular = IsRowMajor == IsLower
- };
-
- conj_helper<Scalar,Scalar,NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, IsRowMajor), ConjugateRhs> cj0;
- conj_helper<Scalar,Scalar,NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, !IsRowMajor), ConjugateRhs> cj1;
- conj_helper<Scalar,Scalar,NumTraits<Scalar>::IsComplex, ConjugateRhs> cjd;
-
- conj_helper<Packet,Packet,NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, IsRowMajor), ConjugateRhs> pcj0;
- conj_helper<Packet,Packet,NumTraits<Scalar>::IsComplex && EIGEN_LOGICAL_XOR(ConjugateLhs, !IsRowMajor), ConjugateRhs> pcj1;
-
- Scalar cjAlpha = ConjugateRhs ? conj(alpha) : alpha;
-
- // FIXME this copy is now handled outside product_selfadjoint_vector, so it could probably be removed.
- // if the rhs is not sequentially stored in memory we copy it to a temporary buffer,
- // this is because we need to extract packets
- ei_declare_aligned_stack_constructed_variable(Scalar,rhs,size,rhsIncr==1 ? const_cast<Scalar*>(_rhs) : 0);
- if (rhsIncr!=1)
- {
- const Scalar* it = _rhs;
- for (Index i=0; i<size; ++i, it+=rhsIncr)
- rhs[i] = *it;
- }
-
- Index bound = (std::max)(Index(0),size-8) & 0xfffffffe;
- if (FirstTriangular)
- bound = size - bound;
-
- for (Index j=FirstTriangular ? bound : 0;
- j<(FirstTriangular ? size : bound);j+=2)
- {
- register const Scalar* EIGEN_RESTRICT A0 = lhs + j*lhsStride;
- register const Scalar* EIGEN_RESTRICT A1 = lhs + (j+1)*lhsStride;
-
- Scalar t0 = cjAlpha * rhs[j];
- Packet ptmp0 = pset1<Packet>(t0);
- Scalar t1 = cjAlpha * rhs[j+1];
- Packet ptmp1 = pset1<Packet>(t1);
-
- Scalar t2 = 0;
- Packet ptmp2 = pset1<Packet>(t2);
- Scalar t3 = 0;
- Packet ptmp3 = pset1<Packet>(t3);
-
- size_t starti = FirstTriangular ? 0 : j+2;
- size_t endi = FirstTriangular ? j : size;
- size_t alignedStart = (starti) + first_aligned(&res[starti], endi-starti);
- size_t alignedEnd = alignedStart + ((endi-alignedStart)/(PacketSize))*(PacketSize);
-
- // TODO make sure this product is a real * complex and that the rhs is properly conjugated if needed
- res[j] += cjd.pmul(internal::real(A0[j]), t0);
- res[j+1] += cjd.pmul(internal::real(A1[j+1]), t1);
- if(FirstTriangular)
- {
- res[j] += cj0.pmul(A1[j], t1);
- t3 += cj1.pmul(A1[j], rhs[j]);
- }
- else
- {
- res[j+1] += cj0.pmul(A0[j+1],t0);
- t2 += cj1.pmul(A0[j+1], rhs[j+1]);
- }
-
- for (size_t i=starti; i<alignedStart; ++i)
- {
- res[i] += t0 * A0[i] + t1 * A1[i];
- t2 += conj(A0[i]) * rhs[i];
- t3 += conj(A1[i]) * rhs[i];
- }
- // Yes this an optimization for gcc 4.3 and 4.4 (=> huge speed up)
- // gcc 4.2 does this optimization automatically.
- const Scalar* EIGEN_RESTRICT a0It = A0 + alignedStart;
- const Scalar* EIGEN_RESTRICT a1It = A1 + alignedStart;
- const Scalar* EIGEN_RESTRICT rhsIt = rhs + alignedStart;
- Scalar* EIGEN_RESTRICT resIt = res + alignedStart;
- for (size_t i=alignedStart; i<alignedEnd; i+=PacketSize)
- {
- Packet A0i = ploadu<Packet>(a0It); a0It += PacketSize;
- Packet A1i = ploadu<Packet>(a1It); a1It += PacketSize;
- Packet Bi = ploadu<Packet>(rhsIt); rhsIt += PacketSize; // FIXME should be aligned in most cases
- Packet Xi = pload <Packet>(resIt);
-
- Xi = pcj0.pmadd(A0i,ptmp0, pcj0.pmadd(A1i,ptmp1,Xi));
- ptmp2 = pcj1.pmadd(A0i, Bi, ptmp2);
- ptmp3 = pcj1.pmadd(A1i, Bi, ptmp3);
- pstore(resIt,Xi); resIt += PacketSize;
- }
- for (size_t i=alignedEnd; i<endi; i++)
- {
- res[i] += cj0.pmul(A0[i], t0) + cj0.pmul(A1[i],t1);
- t2 += cj1.pmul(A0[i], rhs[i]);
- t3 += cj1.pmul(A1[i], rhs[i]);
- }
-
- res[j] += alpha * (t2 + predux(ptmp2));
- res[j+1] += alpha * (t3 + predux(ptmp3));
- }
- for (Index j=FirstTriangular ? 0 : bound;j<(FirstTriangular ? bound : size);j++)
- {
- register const Scalar* EIGEN_RESTRICT A0 = lhs + j*lhsStride;
-
- Scalar t1 = cjAlpha * rhs[j];
- Scalar t2 = 0;
- // TODO make sure this product is a real * complex and that the rhs is properly conjugated if needed
- res[j] += cjd.pmul(internal::real(A0[j]), t1);
- for (Index i=FirstTriangular ? 0 : j+1; i<(FirstTriangular ? j : size); i++)
- {
- res[i] += cj0.pmul(A0[i], t1);
- t2 += cj1.pmul(A0[i], rhs[i]);
- }
- res[j] += alpha * t2;
- }
-}
-
-} // end namespace internal
-
-/***************************************************************************
-* Wrapper to product_selfadjoint_vector
-***************************************************************************/
-
-namespace internal {
-template<typename Lhs, int LhsMode, typename Rhs>
-struct traits<SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,0,true> >
- : traits<ProductBase<SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,0,true>, Lhs, Rhs> >
-{};
-}
-
-template<typename Lhs, int LhsMode, typename Rhs>
-struct SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,0,true>
- : public ProductBase<SelfadjointProductMatrix<Lhs,LhsMode,false,Rhs,0,true>, Lhs, Rhs >
-{
- EIGEN_PRODUCT_PUBLIC_INTERFACE(SelfadjointProductMatrix)
-
- enum {
- LhsUpLo = LhsMode&(Upper|Lower)
- };
-
- SelfadjointProductMatrix(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {}
-
- template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
- {
- typedef typename Dest::Scalar ResScalar;
- typedef typename Base::RhsScalar RhsScalar;
- typedef Map<Matrix<ResScalar,Dynamic,1>, Aligned> MappedDest;
-
- eigen_assert(dest.rows()==m_lhs.rows() && dest.cols()==m_rhs.cols());
-
- const ActualLhsType lhs = LhsBlasTraits::extract(m_lhs);
- const ActualRhsType rhs = RhsBlasTraits::extract(m_rhs);
-
- Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(m_lhs)
- * RhsBlasTraits::extractScalarFactor(m_rhs);
-
- enum {
- EvalToDest = (Dest::InnerStrideAtCompileTime==1),
- UseRhs = (_ActualRhsType::InnerStrideAtCompileTime==1)
- };
-
- internal::gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,!EvalToDest> static_dest;
- internal::gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!UseRhs> static_rhs;
-
- ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(),
- EvalToDest ? dest.data() : static_dest.data());
-
- ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,rhs.size(),
- UseRhs ? const_cast<RhsScalar*>(rhs.data()) : static_rhs.data());
-
- if(!EvalToDest)
- {
- #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- int size = dest.size();
- EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- #endif
- MappedDest(actualDestPtr, dest.size()) = dest;
- }
-
- if(!UseRhs)
- {
- #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- int size = rhs.size();
- EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- #endif
- Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, rhs.size()) = rhs;
- }
-
-
- internal::product_selfadjoint_vector<Scalar, Index, (internal::traits<_ActualLhsType>::Flags&RowMajorBit) ? RowMajor : ColMajor, int(LhsUpLo), bool(LhsBlasTraits::NeedToConjugate), bool(RhsBlasTraits::NeedToConjugate)>
- (
- lhs.rows(), // size
- &lhs.coeffRef(0,0), lhs.outerStride(), // lhs info
- actualRhsPtr, 1, // rhs info
- actualDestPtr, // result info
- actualAlpha // scale factor
- );
-
- if(!EvalToDest)
- dest = MappedDest(actualDestPtr, dest.size());
- }
-};
-
-namespace internal {
-template<typename Lhs, typename Rhs, int RhsMode>
-struct traits<SelfadjointProductMatrix<Lhs,0,true,Rhs,RhsMode,false> >
- : traits<ProductBase<SelfadjointProductMatrix<Lhs,0,true,Rhs,RhsMode,false>, Lhs, Rhs> >
-{};
-}
-
-template<typename Lhs, typename Rhs, int RhsMode>
-struct SelfadjointProductMatrix<Lhs,0,true,Rhs,RhsMode,false>
- : public ProductBase<SelfadjointProductMatrix<Lhs,0,true,Rhs,RhsMode,false>, Lhs, Rhs >
-{
- EIGEN_PRODUCT_PUBLIC_INTERFACE(SelfadjointProductMatrix)
-
- enum {
- RhsUpLo = RhsMode&(Upper|Lower)
- };
-
- SelfadjointProductMatrix(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {}
-
- template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
- {
- // let's simply transpose the product
- Transpose<Dest> destT(dest);
- SelfadjointProductMatrix<Transpose<const Rhs>, int(RhsUpLo)==Upper ? Lower : Upper, false,
- Transpose<const Lhs>, 0, true>(m_rhs.transpose(), m_lhs.transpose()).scaleAndAddTo(destT, alpha);
- }
-};
-
-
-#endif // EIGEN_SELFADJOINT_MATRIX_VECTOR_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h b/extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h
deleted file mode 100644
index 3a4523fa4a9..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SELFADJOINT_PRODUCT_H
-#define EIGEN_SELFADJOINT_PRODUCT_H
-
-/**********************************************************************
-* This file implements a self adjoint product: C += A A^T updating only
-* half of the selfadjoint matrix C.
-* It corresponds to the level 3 SYRK and level 2 SYR Blas routines.
-**********************************************************************/
-
-template<typename Scalar, typename Index, int StorageOrder, int UpLo, bool ConjLhs, bool ConjRhs>
-struct selfadjoint_rank1_update;
-
-template<typename Scalar, typename Index, int UpLo, bool ConjLhs, bool ConjRhs>
-struct selfadjoint_rank1_update<Scalar,Index,ColMajor,UpLo,ConjLhs,ConjRhs>
-{
- static void run(Index size, Scalar* mat, Index stride, const Scalar* vec, Scalar alpha)
- {
- internal::conj_if<ConjRhs> cj;
- typedef Map<const Matrix<Scalar,Dynamic,1> > OtherMap;
- typedef typename internal::conditional<ConjLhs,typename OtherMap::ConjugateReturnType,const OtherMap&>::type ConjRhsType;
- for (Index i=0; i<size; ++i)
- {
- Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i+(UpLo==Lower ? i : 0), (UpLo==Lower ? size-i : (i+1)))
- += (alpha * cj(vec[i])) * ConjRhsType(OtherMap(vec+(UpLo==Lower ? i : 0),UpLo==Lower ? size-i : (i+1)));
- }
- }
-};
-
-template<typename Scalar, typename Index, int UpLo, bool ConjLhs, bool ConjRhs>
-struct selfadjoint_rank1_update<Scalar,Index,RowMajor,UpLo,ConjLhs,ConjRhs>
-{
- static void run(Index size, Scalar* mat, Index stride, const Scalar* vec, Scalar alpha)
- {
- selfadjoint_rank1_update<Scalar,Index,ColMajor,UpLo==Lower?Upper:Lower,ConjRhs,ConjLhs>::run(size,mat,stride,vec,alpha);
- }
-};
-
-template<typename MatrixType, typename OtherType, int UpLo, bool OtherIsVector = OtherType::IsVectorAtCompileTime>
-struct selfadjoint_product_selector;
-
-template<typename MatrixType, typename OtherType, int UpLo>
-struct selfadjoint_product_selector<MatrixType,OtherType,UpLo,true>
-{
- static void run(MatrixType& mat, const OtherType& other, typename MatrixType::Scalar alpha)
- {
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::Index Index;
- typedef internal::blas_traits<OtherType> OtherBlasTraits;
- typedef typename OtherBlasTraits::DirectLinearAccessType ActualOtherType;
- typedef typename internal::remove_all<ActualOtherType>::type _ActualOtherType;
- const ActualOtherType actualOther = OtherBlasTraits::extract(other.derived());
-
- Scalar actualAlpha = alpha * OtherBlasTraits::extractScalarFactor(other.derived());
-
- enum {
- StorageOrder = (internal::traits<MatrixType>::Flags&RowMajorBit) ? RowMajor : ColMajor,
- UseOtherDirectly = _ActualOtherType::InnerStrideAtCompileTime==1
- };
- internal::gemv_static_vector_if<Scalar,OtherType::SizeAtCompileTime,OtherType::MaxSizeAtCompileTime,!UseOtherDirectly> static_other;
-
- ei_declare_aligned_stack_constructed_variable(Scalar, actualOtherPtr, other.size(),
- (UseOtherDirectly ? const_cast<Scalar*>(actualOther.data()) : static_other.data()));
-
- if(!UseOtherDirectly)
- Map<typename _ActualOtherType::PlainObject>(actualOtherPtr, actualOther.size()) = actualOther;
-
- selfadjoint_rank1_update<Scalar,Index,StorageOrder,UpLo,
- OtherBlasTraits::NeedToConjugate && NumTraits<Scalar>::IsComplex,
- (!OtherBlasTraits::NeedToConjugate) && NumTraits<Scalar>::IsComplex>
- ::run(other.size(), mat.data(), mat.outerStride(), actualOtherPtr, actualAlpha);
- }
-};
-
-template<typename MatrixType, typename OtherType, int UpLo>
-struct selfadjoint_product_selector<MatrixType,OtherType,UpLo,false>
-{
- static void run(MatrixType& mat, const OtherType& other, typename MatrixType::Scalar alpha)
- {
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::Index Index;
- typedef internal::blas_traits<OtherType> OtherBlasTraits;
- typedef typename OtherBlasTraits::DirectLinearAccessType ActualOtherType;
- typedef typename internal::remove_all<ActualOtherType>::type _ActualOtherType;
- const ActualOtherType actualOther = OtherBlasTraits::extract(other.derived());
-
- Scalar actualAlpha = alpha * OtherBlasTraits::extractScalarFactor(other.derived());
-
- enum { IsRowMajor = (internal::traits<MatrixType>::Flags&RowMajorBit) ? 1 : 0 };
-
- internal::general_matrix_matrix_triangular_product<Index,
- Scalar, _ActualOtherType::Flags&RowMajorBit ? RowMajor : ColMajor, OtherBlasTraits::NeedToConjugate && NumTraits<Scalar>::IsComplex,
- Scalar, _ActualOtherType::Flags&RowMajorBit ? ColMajor : RowMajor, (!OtherBlasTraits::NeedToConjugate) && NumTraits<Scalar>::IsComplex,
- MatrixType::Flags&RowMajorBit ? RowMajor : ColMajor, UpLo>
- ::run(mat.cols(), actualOther.cols(),
- &actualOther.coeffRef(0,0), actualOther.outerStride(), &actualOther.coeffRef(0,0), actualOther.outerStride(),
- mat.data(), mat.outerStride(), actualAlpha);
- }
-};
-
-// high level API
-
-template<typename MatrixType, unsigned int UpLo>
-template<typename DerivedU>
-SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
-::rankUpdate(const MatrixBase<DerivedU>& u, Scalar alpha)
-{
- selfadjoint_product_selector<MatrixType,DerivedU,UpLo>::run(_expression().const_cast_derived(), u.derived(), alpha);
-
- return *this;
-}
-
-#endif // EIGEN_SELFADJOINT_PRODUCT_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h b/extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h
deleted file mode 100644
index 9f8b8438a5d..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SELFADJOINTRANK2UPTADE_H
-#define EIGEN_SELFADJOINTRANK2UPTADE_H
-
-namespace internal {
-
-/* Optimized selfadjoint matrix += alpha * uv' + conj(alpha)*vu'
- * It corresponds to the Level2 syr2 BLAS routine
- */
-
-template<typename Scalar, typename Index, typename UType, typename VType, int UpLo>
-struct selfadjoint_rank2_update_selector;
-
-template<typename Scalar, typename Index, typename UType, typename VType>
-struct selfadjoint_rank2_update_selector<Scalar,Index,UType,VType,Lower>
-{
- static void run(Scalar* mat, Index stride, const UType& u, const VType& v, Scalar alpha)
- {
- const Index size = u.size();
- for (Index i=0; i<size; ++i)
- {
- Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i+i, size-i) +=
- (conj(alpha) * conj(u.coeff(i))) * v.tail(size-i)
- + (alpha * conj(v.coeff(i))) * u.tail(size-i);
- }
- }
-};
-
-template<typename Scalar, typename Index, typename UType, typename VType>
-struct selfadjoint_rank2_update_selector<Scalar,Index,UType,VType,Upper>
-{
- static void run(Scalar* mat, Index stride, const UType& u, const VType& v, Scalar alpha)
- {
- const Index size = u.size();
- for (Index i=0; i<size; ++i)
- Map<Matrix<Scalar,Dynamic,1> >(mat+stride*i, i+1) +=
- (conj(alpha) * conj(u.coeff(i))) * v.head(i+1)
- + (alpha * conj(v.coeff(i))) * u.head(i+1);
- }
-};
-
-template<bool Cond, typename T> struct conj_expr_if
- : conditional<!Cond, const T&,
- CwiseUnaryOp<scalar_conjugate_op<typename traits<T>::Scalar>,T> > {};
-
-} // end namespace internal
-
-template<typename MatrixType, unsigned int UpLo>
-template<typename DerivedU, typename DerivedV>
-SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
-::rankUpdate(const MatrixBase<DerivedU>& u, const MatrixBase<DerivedV>& v, Scalar alpha)
-{
- typedef internal::blas_traits<DerivedU> UBlasTraits;
- typedef typename UBlasTraits::DirectLinearAccessType ActualUType;
- typedef typename internal::remove_all<ActualUType>::type _ActualUType;
- const ActualUType actualU = UBlasTraits::extract(u.derived());
-
- typedef internal::blas_traits<DerivedV> VBlasTraits;
- typedef typename VBlasTraits::DirectLinearAccessType ActualVType;
- typedef typename internal::remove_all<ActualVType>::type _ActualVType;
- const ActualVType actualV = VBlasTraits::extract(v.derived());
-
- // If MatrixType is row major, then we use the routine for lower triangular in the upper triangular case and
- // vice versa, and take the complex conjugate of all coefficients and vector entries.
-
- enum { IsRowMajor = (internal::traits<MatrixType>::Flags&RowMajorBit) ? 1 : 0 };
- Scalar actualAlpha = alpha * UBlasTraits::extractScalarFactor(u.derived())
- * internal::conj(VBlasTraits::extractScalarFactor(v.derived()));
- if (IsRowMajor)
- actualAlpha = internal::conj(actualAlpha);
-
- internal::selfadjoint_rank2_update_selector<Scalar, Index,
- typename internal::remove_all<typename internal::conj_expr_if<IsRowMajor ^ UBlasTraits::NeedToConjugate,_ActualUType>::type>::type,
- typename internal::remove_all<typename internal::conj_expr_if<IsRowMajor ^ VBlasTraits::NeedToConjugate,_ActualVType>::type>::type,
- (IsRowMajor ? int(UpLo==Upper ? Lower : Upper) : UpLo)>
- ::run(_expression().const_cast_derived().data(),_expression().outerStride(),actualU,actualV,actualAlpha);
-
- return *this;
-}
-
-#endif // EIGEN_SELFADJOINTRANK2UPTADE_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h b/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h
deleted file mode 100644
index 0c48d2efb75..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h
+++ /dev/null
@@ -1,403 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_TRIANGULAR_MATRIX_MATRIX_H
-#define EIGEN_TRIANGULAR_MATRIX_MATRIX_H
-
-namespace internal {
-
-// template<typename Scalar, int mr, int StorageOrder, bool Conjugate, int Mode>
-// struct gemm_pack_lhs_triangular
-// {
-// Matrix<Scalar,mr,mr,
-// void operator()(Scalar* blockA, const EIGEN_RESTRICT Scalar* _lhs, int lhsStride, int depth, int rows)
-// {
-// conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
-// const_blas_data_mapper<Scalar, StorageOrder> lhs(_lhs,lhsStride);
-// int count = 0;
-// const int peeled_mc = (rows/mr)*mr;
-// for(int i=0; i<peeled_mc; i+=mr)
-// {
-// for(int k=0; k<depth; k++)
-// for(int w=0; w<mr; w++)
-// blockA[count++] = cj(lhs(i+w, k));
-// }
-// for(int i=peeled_mc; i<rows; i++)
-// {
-// for(int k=0; k<depth; k++)
-// blockA[count++] = cj(lhs(i, k));
-// }
-// }
-// };
-
-/* Optimized triangular matrix * matrix (_TRMM++) product built on top of
- * the general matrix matrix product.
- */
-template <typename Scalar, typename Index,
- int Mode, bool LhsIsTriangular,
- int LhsStorageOrder, bool ConjugateLhs,
- int RhsStorageOrder, bool ConjugateRhs,
- int ResStorageOrder>
-struct product_triangular_matrix_matrix;
-
-template <typename Scalar, typename Index,
- int Mode, bool LhsIsTriangular,
- int LhsStorageOrder, bool ConjugateLhs,
- int RhsStorageOrder, bool ConjugateRhs>
-struct product_triangular_matrix_matrix<Scalar,Index,Mode,LhsIsTriangular,
- LhsStorageOrder,ConjugateLhs,
- RhsStorageOrder,ConjugateRhs,RowMajor>
-{
- static EIGEN_STRONG_INLINE void run(
- Index rows, Index cols, Index depth,
- const Scalar* lhs, Index lhsStride,
- const Scalar* rhs, Index rhsStride,
- Scalar* res, Index resStride,
- Scalar alpha)
- {
- product_triangular_matrix_matrix<Scalar, Index,
- (Mode&(UnitDiag|ZeroDiag)) | ((Mode&Upper) ? Lower : Upper),
- (!LhsIsTriangular),
- RhsStorageOrder==RowMajor ? ColMajor : RowMajor,
- ConjugateRhs,
- LhsStorageOrder==RowMajor ? ColMajor : RowMajor,
- ConjugateLhs,
- ColMajor>
- ::run(cols, rows, depth, rhs, rhsStride, lhs, lhsStride, res, resStride, alpha);
- }
-};
-
-// implements col-major += alpha * op(triangular) * op(general)
-template <typename Scalar, typename Index, int Mode,
- int LhsStorageOrder, bool ConjugateLhs,
- int RhsStorageOrder, bool ConjugateRhs>
-struct product_triangular_matrix_matrix<Scalar,Index,Mode,true,
- LhsStorageOrder,ConjugateLhs,
- RhsStorageOrder,ConjugateRhs,ColMajor>
-{
-
- typedef gebp_traits<Scalar,Scalar> Traits;
- enum {
- SmallPanelWidth = EIGEN_PLAIN_ENUM_MAX(Traits::mr,Traits::nr),
- IsLower = (Mode&Lower) == Lower,
- SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1
- };
-
- static EIGEN_DONT_INLINE void run(
- Index _rows, Index _cols, Index _depth,
- const Scalar* _lhs, Index lhsStride,
- const Scalar* _rhs, Index rhsStride,
- Scalar* res, Index resStride,
- Scalar alpha)
- {
- // strip zeros
- Index diagSize = (std::min)(_rows,_depth);
- Index rows = IsLower ? _rows : diagSize;
- Index depth = IsLower ? diagSize : _depth;
- Index cols = _cols;
-
- const_blas_data_mapper<Scalar, Index, LhsStorageOrder> lhs(_lhs,lhsStride);
- const_blas_data_mapper<Scalar, Index, RhsStorageOrder> rhs(_rhs,rhsStride);
-
- Index kc = depth; // cache block size along the K direction
- Index mc = rows; // cache block size along the M direction
- Index nc = cols; // cache block size along the N direction
- computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc);
- std::size_t sizeW = kc*Traits::WorkSpaceFactor;
- std::size_t sizeB = sizeW + kc*cols;
- ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0);
- ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0);
- Scalar* blockB = allocatedBlockB + sizeW;
-
- Matrix<Scalar,SmallPanelWidth,SmallPanelWidth,LhsStorageOrder> triangularBuffer;
- triangularBuffer.setZero();
- if((Mode&ZeroDiag)==ZeroDiag)
- triangularBuffer.diagonal().setZero();
- else
- triangularBuffer.diagonal().setOnes();
-
- gebp_kernel<Scalar, Scalar, Index, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp_kernel;
- gemm_pack_lhs<Scalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder> pack_lhs;
- gemm_pack_rhs<Scalar, Index, Traits::nr,RhsStorageOrder> pack_rhs;
-
- for(Index k2=IsLower ? depth : 0;
- IsLower ? k2>0 : k2<depth;
- IsLower ? k2-=kc : k2+=kc)
- {
- Index actual_kc = (std::min)(IsLower ? k2 : depth-k2, kc);
- Index actual_k2 = IsLower ? k2-actual_kc : k2;
-
- // align blocks with the end of the triangular part for trapezoidal lhs
- if((!IsLower)&&(k2<rows)&&(k2+actual_kc>rows))
- {
- actual_kc = rows-k2;
- k2 = k2+actual_kc-kc;
- }
-
- pack_rhs(blockB, &rhs(actual_k2,0), rhsStride, actual_kc, cols);
-
- // the selected lhs's panel has to be split in three different parts:
- // 1 - the part which is zero => skip it
- // 2 - the diagonal block => special kernel
- // 3 - the dense panel below (lower case) or above (upper case) the diagonal block => GEPP
-
- // the block diagonal, if any:
- if(IsLower || actual_k2<rows)
- {
- // for each small vertical panels of lhs
- for (Index k1=0; k1<actual_kc; k1+=SmallPanelWidth)
- {
- Index actualPanelWidth = std::min<Index>(actual_kc-k1, SmallPanelWidth);
- Index lengthTarget = IsLower ? actual_kc-k1-actualPanelWidth : k1;
- Index startBlock = actual_k2+k1;
- Index blockBOffset = k1;
-
- // => GEBP with the micro triangular block
- // The trick is to pack this micro block while filling the opposite triangular part with zeros.
- // To this end we do an extra triangular copy to a small temporary buffer
- for (Index k=0;k<actualPanelWidth;++k)
- {
- if (SetDiag)
- triangularBuffer.coeffRef(k,k) = lhs(startBlock+k,startBlock+k);
- for (Index i=IsLower ? k+1 : 0; IsLower ? i<actualPanelWidth : i<k; ++i)
- triangularBuffer.coeffRef(i,k) = lhs(startBlock+i,startBlock+k);
- }
- pack_lhs(blockA, triangularBuffer.data(), triangularBuffer.outerStride(), actualPanelWidth, actualPanelWidth);
-
- gebp_kernel(res+startBlock, resStride, blockA, blockB, actualPanelWidth, actualPanelWidth, cols, alpha,
- actualPanelWidth, actual_kc, 0, blockBOffset);
-
- // GEBP with remaining micro panel
- if (lengthTarget>0)
- {
- Index startTarget = IsLower ? actual_k2+k1+actualPanelWidth : actual_k2;
-
- pack_lhs(blockA, &lhs(startTarget,startBlock), lhsStride, actualPanelWidth, lengthTarget);
-
- gebp_kernel(res+startTarget, resStride, blockA, blockB, lengthTarget, actualPanelWidth, cols, alpha,
- actualPanelWidth, actual_kc, 0, blockBOffset);
- }
- }
- }
- // the part below (lower case) or above (upper case) the diagonal => GEPP
- {
- Index start = IsLower ? k2 : 0;
- Index end = IsLower ? rows : (std::min)(actual_k2,rows);
- for(Index i2=start; i2<end; i2+=mc)
- {
- const Index actual_mc = (std::min)(i2+mc,end)-i2;
- gemm_pack_lhs<Scalar, Index, Traits::mr,Traits::LhsProgress, LhsStorageOrder,false>()
- (blockA, &lhs(i2, actual_k2), lhsStride, actual_kc, actual_mc);
-
- gebp_kernel(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha);
- }
- }
- }
- }
-};
-
-// implements col-major += alpha * op(general) * op(triangular)
-template <typename Scalar, typename Index, int Mode,
- int LhsStorageOrder, bool ConjugateLhs,
- int RhsStorageOrder, bool ConjugateRhs>
-struct product_triangular_matrix_matrix<Scalar,Index,Mode,false,
- LhsStorageOrder,ConjugateLhs,
- RhsStorageOrder,ConjugateRhs,ColMajor>
-{
- typedef gebp_traits<Scalar,Scalar> Traits;
- enum {
- SmallPanelWidth = EIGEN_PLAIN_ENUM_MAX(Traits::mr,Traits::nr),
- IsLower = (Mode&Lower) == Lower,
- SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1
- };
-
- static EIGEN_DONT_INLINE void run(
- Index _rows, Index _cols, Index _depth,
- const Scalar* _lhs, Index lhsStride,
- const Scalar* _rhs, Index rhsStride,
- Scalar* res, Index resStride,
- Scalar alpha)
- {
- // strip zeros
- Index diagSize = (std::min)(_cols,_depth);
- Index rows = _rows;
- Index depth = IsLower ? _depth : diagSize;
- Index cols = IsLower ? diagSize : _cols;
-
- const_blas_data_mapper<Scalar, Index, LhsStorageOrder> lhs(_lhs,lhsStride);
- const_blas_data_mapper<Scalar, Index, RhsStorageOrder> rhs(_rhs,rhsStride);
-
- Index kc = depth; // cache block size along the K direction
- Index mc = rows; // cache block size along the M direction
- Index nc = cols; // cache block size along the N direction
- computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc);
-
- std::size_t sizeW = kc*Traits::WorkSpaceFactor;
- std::size_t sizeB = sizeW + kc*cols;
- ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0);
- ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0);
- Scalar* blockB = allocatedBlockB + sizeW;
-
- Matrix<Scalar,SmallPanelWidth,SmallPanelWidth,RhsStorageOrder> triangularBuffer;
- triangularBuffer.setZero();
- if((Mode&ZeroDiag)==ZeroDiag)
- triangularBuffer.diagonal().setZero();
- else
- triangularBuffer.diagonal().setOnes();
-
- gebp_kernel<Scalar, Scalar, Index, Traits::mr, Traits::nr, ConjugateLhs, ConjugateRhs> gebp_kernel;
- gemm_pack_lhs<Scalar, Index, Traits::mr, Traits::LhsProgress, LhsStorageOrder> pack_lhs;
- gemm_pack_rhs<Scalar, Index, Traits::nr,RhsStorageOrder> pack_rhs;
- gemm_pack_rhs<Scalar, Index, Traits::nr,RhsStorageOrder,false,true> pack_rhs_panel;
-
- for(Index k2=IsLower ? 0 : depth;
- IsLower ? k2<depth : k2>0;
- IsLower ? k2+=kc : k2-=kc)
- {
- Index actual_kc = (std::min)(IsLower ? depth-k2 : k2, kc);
- Index actual_k2 = IsLower ? k2 : k2-actual_kc;
-
- // align blocks with the end of the triangular part for trapezoidal rhs
- if(IsLower && (k2<cols) && (actual_k2+actual_kc>cols))
- {
- actual_kc = cols-k2;
- k2 = actual_k2 + actual_kc - kc;
- }
-
- // remaining size
- Index rs = IsLower ? (std::min)(cols,actual_k2) : cols - k2;
- // size of the triangular part
- Index ts = (IsLower && actual_k2>=cols) ? 0 : actual_kc;
-
- Scalar* geb = blockB+ts*ts;
-
- pack_rhs(geb, &rhs(actual_k2,IsLower ? 0 : k2), rhsStride, actual_kc, rs);
-
- // pack the triangular part of the rhs padding the unrolled blocks with zeros
- if(ts>0)
- {
- for (Index j2=0; j2<actual_kc; j2+=SmallPanelWidth)
- {
- Index actualPanelWidth = std::min<Index>(actual_kc-j2, SmallPanelWidth);
- Index actual_j2 = actual_k2 + j2;
- Index panelOffset = IsLower ? j2+actualPanelWidth : 0;
- Index panelLength = IsLower ? actual_kc-j2-actualPanelWidth : j2;
- // general part
- pack_rhs_panel(blockB+j2*actual_kc,
- &rhs(actual_k2+panelOffset, actual_j2), rhsStride,
- panelLength, actualPanelWidth,
- actual_kc, panelOffset);
-
- // append the triangular part via a temporary buffer
- for (Index j=0;j<actualPanelWidth;++j)
- {
- if (SetDiag)
- triangularBuffer.coeffRef(j,j) = rhs(actual_j2+j,actual_j2+j);
- for (Index k=IsLower ? j+1 : 0; IsLower ? k<actualPanelWidth : k<j; ++k)
- triangularBuffer.coeffRef(k,j) = rhs(actual_j2+k,actual_j2+j);
- }
-
- pack_rhs_panel(blockB+j2*actual_kc,
- triangularBuffer.data(), triangularBuffer.outerStride(),
- actualPanelWidth, actualPanelWidth,
- actual_kc, j2);
- }
- }
-
- for (Index i2=0; i2<rows; i2+=mc)
- {
- const Index actual_mc = (std::min)(mc,rows-i2);
- pack_lhs(blockA, &lhs(i2, actual_k2), lhsStride, actual_kc, actual_mc);
-
- // triangular kernel
- if(ts>0)
- {
- for (Index j2=0; j2<actual_kc; j2+=SmallPanelWidth)
- {
- Index actualPanelWidth = std::min<Index>(actual_kc-j2, SmallPanelWidth);
- Index panelLength = IsLower ? actual_kc-j2 : j2+actualPanelWidth;
- Index blockOffset = IsLower ? j2 : 0;
-
- gebp_kernel(res+i2+(actual_k2+j2)*resStride, resStride,
- blockA, blockB+j2*actual_kc,
- actual_mc, panelLength, actualPanelWidth,
- alpha,
- actual_kc, actual_kc, // strides
- blockOffset, blockOffset,// offsets
- allocatedBlockB); // workspace
- }
- }
- gebp_kernel(res+i2+(IsLower ? 0 : k2)*resStride, resStride,
- blockA, geb, actual_mc, actual_kc, rs,
- alpha,
- -1, -1, 0, 0, allocatedBlockB);
- }
- }
- }
-};
-
-/***************************************************************************
-* Wrapper to product_triangular_matrix_matrix
-***************************************************************************/
-
-template<int Mode, bool LhsIsTriangular, typename Lhs, typename Rhs>
-struct traits<TriangularProduct<Mode,LhsIsTriangular,Lhs,false,Rhs,false> >
- : traits<ProductBase<TriangularProduct<Mode,LhsIsTriangular,Lhs,false,Rhs,false>, Lhs, Rhs> >
-{};
-
-} // end namespace internal
-
-template<int Mode, bool LhsIsTriangular, typename Lhs, typename Rhs>
-struct TriangularProduct<Mode,LhsIsTriangular,Lhs,false,Rhs,false>
- : public ProductBase<TriangularProduct<Mode,LhsIsTriangular,Lhs,false,Rhs,false>, Lhs, Rhs >
-{
- EIGEN_PRODUCT_PUBLIC_INTERFACE(TriangularProduct)
-
- TriangularProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {}
-
- template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
- {
- const ActualLhsType lhs = LhsBlasTraits::extract(m_lhs);
- const ActualRhsType rhs = RhsBlasTraits::extract(m_rhs);
-
- Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(m_lhs)
- * RhsBlasTraits::extractScalarFactor(m_rhs);
-
- internal::product_triangular_matrix_matrix<Scalar, Index,
- Mode, LhsIsTriangular,
- (internal::traits<_ActualLhsType>::Flags&RowMajorBit) ? RowMajor : ColMajor, LhsBlasTraits::NeedToConjugate,
- (internal::traits<_ActualRhsType>::Flags&RowMajorBit) ? RowMajor : ColMajor, RhsBlasTraits::NeedToConjugate,
- (internal::traits<Dest >::Flags&RowMajorBit) ? RowMajor : ColMajor>
- ::run(
- lhs.rows(), rhs.cols(), lhs.cols(),// LhsIsTriangular ? rhs.cols() : lhs.rows(), // sizes
- &lhs.coeffRef(0,0), lhs.outerStride(), // lhs info
- &rhs.coeffRef(0,0), rhs.outerStride(), // rhs info
- &dst.coeffRef(0,0), dst.outerStride(), // result info
- actualAlpha // alpha
- );
- }
-};
-
-
-#endif // EIGEN_TRIANGULAR_MATRIX_MATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h b/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h
deleted file mode 100644
index 71b4a52ab80..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h
+++ /dev/null
@@ -1,325 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_TRIANGULARMATRIXVECTOR_H
-#define EIGEN_TRIANGULARMATRIXVECTOR_H
-
-namespace internal {
-
-template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs, int StorageOrder>
-struct product_triangular_matrix_vector;
-
-template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs>
-struct product_triangular_matrix_vector<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,ColMajor>
-{
- typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
- enum {
- IsLower = ((Mode&Lower)==Lower),
- HasUnitDiag = (Mode & UnitDiag)==UnitDiag
- };
- static EIGEN_DONT_INLINE void run(Index rows, Index cols, const LhsScalar* _lhs, Index lhsStride,
- const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, ResScalar alpha)
- {
- static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
-
- typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,ColMajor>, 0, OuterStride<> > LhsMap;
- const LhsMap lhs(_lhs,rows,cols,OuterStride<>(lhsStride));
- typename conj_expr_if<ConjLhs,LhsMap>::type cjLhs(lhs);
-
- typedef Map<const Matrix<RhsScalar,Dynamic,1>, 0, InnerStride<> > RhsMap;
- const RhsMap rhs(_rhs,cols,InnerStride<>(rhsIncr));
- typename conj_expr_if<ConjRhs,RhsMap>::type cjRhs(rhs);
-
- typedef Map<Matrix<ResScalar,Dynamic,1> > ResMap;
- ResMap res(_res,rows);
-
- for (Index pi=0; pi<cols; pi+=PanelWidth)
- {
- Index actualPanelWidth = (std::min)(PanelWidth, cols-pi);
- for (Index k=0; k<actualPanelWidth; ++k)
- {
- Index i = pi + k;
- Index s = IsLower ? (HasUnitDiag ? i+1 : i ) : pi;
- Index r = IsLower ? actualPanelWidth-k : k+1;
- if ((!HasUnitDiag) || (--r)>0)
- res.segment(s,r) += (alpha * cjRhs.coeff(i)) * cjLhs.col(i).segment(s,r);
- if (HasUnitDiag)
- res.coeffRef(i) += alpha * cjRhs.coeff(i);
- }
- Index r = IsLower ? cols - pi - actualPanelWidth : pi;
- if (r>0)
- {
- Index s = IsLower ? pi+actualPanelWidth : 0;
- general_matrix_vector_product<Index,LhsScalar,ColMajor,ConjLhs,RhsScalar,ConjRhs>::run(
- r, actualPanelWidth,
- &lhs.coeffRef(s,pi), lhsStride,
- &rhs.coeffRef(pi), rhsIncr,
- &res.coeffRef(s), resIncr, alpha);
- }
- }
- }
-};
-
-template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs>
-struct product_triangular_matrix_vector<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,RowMajor>
-{
- typedef typename scalar_product_traits<LhsScalar, RhsScalar>::ReturnType ResScalar;
- enum {
- IsLower = ((Mode&Lower)==Lower),
- HasUnitDiag = (Mode & UnitDiag)==UnitDiag
- };
- static void run(Index rows, Index cols, const LhsScalar* _lhs, Index lhsStride,
- const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, ResScalar alpha)
- {
- static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
-
- typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,RowMajor>, 0, OuterStride<> > LhsMap;
- const LhsMap lhs(_lhs,rows,cols,OuterStride<>(lhsStride));
- typename conj_expr_if<ConjLhs,LhsMap>::type cjLhs(lhs);
-
- typedef Map<const Matrix<RhsScalar,Dynamic,1> > RhsMap;
- const RhsMap rhs(_rhs,cols);
- typename conj_expr_if<ConjRhs,RhsMap>::type cjRhs(rhs);
-
- typedef Map<Matrix<ResScalar,Dynamic,1>, 0, InnerStride<> > ResMap;
- ResMap res(_res,rows,InnerStride<>(resIncr));
-
- for (Index pi=0; pi<cols; pi+=PanelWidth)
- {
- Index actualPanelWidth = (std::min)(PanelWidth, cols-pi);
- for (Index k=0; k<actualPanelWidth; ++k)
- {
- Index i = pi + k;
- Index s = IsLower ? pi : (HasUnitDiag ? i+1 : i);
- Index r = IsLower ? k+1 : actualPanelWidth-k;
- if ((!HasUnitDiag) || (--r)>0)
- res.coeffRef(i) += alpha * (cjLhs.row(i).segment(s,r).cwiseProduct(cjRhs.segment(s,r).transpose())).sum();
- if (HasUnitDiag)
- res.coeffRef(i) += alpha * cjRhs.coeff(i);
- }
- Index r = IsLower ? pi : cols - pi - actualPanelWidth;
- if (r>0)
- {
- Index s = IsLower ? 0 : pi + actualPanelWidth;
- general_matrix_vector_product<Index,LhsScalar,RowMajor,ConjLhs,RhsScalar,ConjRhs>::run(
- actualPanelWidth, r,
- &lhs.coeffRef(pi,s), lhsStride,
- &rhs.coeffRef(s), rhsIncr,
- &res.coeffRef(pi), resIncr, alpha);
- }
- }
- }
-};
-
-/***************************************************************************
-* Wrapper to product_triangular_vector
-***************************************************************************/
-
-template<int Mode, bool LhsIsTriangular, typename Lhs, typename Rhs>
-struct traits<TriangularProduct<Mode,LhsIsTriangular,Lhs,false,Rhs,true> >
- : traits<ProductBase<TriangularProduct<Mode,LhsIsTriangular,Lhs,false,Rhs,true>, Lhs, Rhs> >
-{};
-
-template<int Mode, bool LhsIsTriangular, typename Lhs, typename Rhs>
-struct traits<TriangularProduct<Mode,LhsIsTriangular,Lhs,true,Rhs,false> >
- : traits<ProductBase<TriangularProduct<Mode,LhsIsTriangular,Lhs,true,Rhs,false>, Lhs, Rhs> >
-{};
-
-
-template<int StorageOrder>
-struct trmv_selector;
-
-} // end namespace internal
-
-template<int Mode, typename Lhs, typename Rhs>
-struct TriangularProduct<Mode,true,Lhs,false,Rhs,true>
- : public ProductBase<TriangularProduct<Mode,true,Lhs,false,Rhs,true>, Lhs, Rhs >
-{
- EIGEN_PRODUCT_PUBLIC_INTERFACE(TriangularProduct)
-
- TriangularProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {}
-
- template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
- {
- eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
-
- internal::trmv_selector<(int(internal::traits<Lhs>::Flags)&RowMajorBit) ? RowMajor : ColMajor>::run(*this, dst, alpha);
- }
-};
-
-template<int Mode, typename Lhs, typename Rhs>
-struct TriangularProduct<Mode,false,Lhs,true,Rhs,false>
- : public ProductBase<TriangularProduct<Mode,false,Lhs,true,Rhs,false>, Lhs, Rhs >
-{
- EIGEN_PRODUCT_PUBLIC_INTERFACE(TriangularProduct)
-
- TriangularProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) {}
-
- template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const
- {
- eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols());
-
- typedef TriangularProduct<(Mode & UnitDiag) | ((Mode & Lower) ? Upper : Lower),true,Transpose<const Rhs>,false,Transpose<const Lhs>,true> TriangularProductTranspose;
- Transpose<Dest> dstT(dst);
- internal::trmv_selector<(int(internal::traits<Rhs>::Flags)&RowMajorBit) ? ColMajor : RowMajor>::run(
- TriangularProductTranspose(m_rhs.transpose(),m_lhs.transpose()), dstT, alpha);
- }
-};
-
-namespace internal {
-
-// TODO: find a way to factorize this piece of code with gemv_selector since the logic is exactly the same.
-
-template<> struct trmv_selector<ColMajor>
-{
- template<int Mode, typename Lhs, typename Rhs, typename Dest>
- static void run(const TriangularProduct<Mode,true,Lhs,false,Rhs,true>& prod, Dest& dest, typename TriangularProduct<Mode,true,Lhs,false,Rhs,true>::Scalar alpha)
- {
- typedef TriangularProduct<Mode,true,Lhs,false,Rhs,true> ProductType;
- typedef typename ProductType::Index Index;
- typedef typename ProductType::LhsScalar LhsScalar;
- typedef typename ProductType::RhsScalar RhsScalar;
- typedef typename ProductType::Scalar ResScalar;
- typedef typename ProductType::RealScalar RealScalar;
- typedef typename ProductType::ActualLhsType ActualLhsType;
- typedef typename ProductType::ActualRhsType ActualRhsType;
- typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
- typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
- typedef Map<Matrix<ResScalar,Dynamic,1>, Aligned> MappedDest;
-
- const ActualLhsType actualLhs = LhsBlasTraits::extract(prod.lhs());
- const ActualRhsType actualRhs = RhsBlasTraits::extract(prod.rhs());
-
- ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
- * RhsBlasTraits::extractScalarFactor(prod.rhs());
-
- enum {
- // FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1
- // on, the other hand it is good for the cache to pack the vector anyways...
- EvalToDestAtCompileTime = Dest::InnerStrideAtCompileTime==1,
- ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
- MightCannotUseDest = (Dest::InnerStrideAtCompileTime!=1) || ComplexByReal
- };
-
- gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;
-
- bool alphaIsCompatible = (!ComplexByReal) || (imag(actualAlpha)==RealScalar(0));
- bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;
-
- RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);
-
- ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(),
- evalToDest ? dest.data() : static_dest.data());
-
- if(!evalToDest)
- {
- #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- int size = dest.size();
- EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- #endif
- if(!alphaIsCompatible)
- {
- MappedDest(actualDestPtr, dest.size()).setZero();
- compatibleAlpha = RhsScalar(1);
- }
- else
- MappedDest(actualDestPtr, dest.size()) = dest;
- }
-
- internal::product_triangular_matrix_vector
- <Index,Mode,
- LhsScalar, LhsBlasTraits::NeedToConjugate,
- RhsScalar, RhsBlasTraits::NeedToConjugate,
- ColMajor>
- ::run(actualLhs.rows(),actualLhs.cols(),
- actualLhs.data(),actualLhs.outerStride(),
- actualRhs.data(),actualRhs.innerStride(),
- actualDestPtr,1,compatibleAlpha);
-
- if (!evalToDest)
- {
- if(!alphaIsCompatible)
- dest += actualAlpha * MappedDest(actualDestPtr, dest.size());
- else
- dest = MappedDest(actualDestPtr, dest.size());
- }
- }
-};
-
-template<> struct trmv_selector<RowMajor>
-{
- template<int Mode, typename Lhs, typename Rhs, typename Dest>
- static void run(const TriangularProduct<Mode,true,Lhs,false,Rhs,true>& prod, Dest& dest, typename TriangularProduct<Mode,true,Lhs,false,Rhs,true>::Scalar alpha)
- {
- typedef TriangularProduct<Mode,true,Lhs,false,Rhs,true> ProductType;
- typedef typename ProductType::LhsScalar LhsScalar;
- typedef typename ProductType::RhsScalar RhsScalar;
- typedef typename ProductType::Scalar ResScalar;
- typedef typename ProductType::Index Index;
- typedef typename ProductType::ActualLhsType ActualLhsType;
- typedef typename ProductType::ActualRhsType ActualRhsType;
- typedef typename ProductType::_ActualRhsType _ActualRhsType;
- typedef typename ProductType::LhsBlasTraits LhsBlasTraits;
- typedef typename ProductType::RhsBlasTraits RhsBlasTraits;
-
- typename add_const<ActualLhsType>::type actualLhs = LhsBlasTraits::extract(prod.lhs());
- typename add_const<ActualRhsType>::type actualRhs = RhsBlasTraits::extract(prod.rhs());
-
- ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs())
- * RhsBlasTraits::extractScalarFactor(prod.rhs());
-
- enum {
- DirectlyUseRhs = _ActualRhsType::InnerStrideAtCompileTime==1
- };
-
- gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs;
-
- ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,actualRhs.size(),
- DirectlyUseRhs ? const_cast<RhsScalar*>(actualRhs.data()) : static_rhs.data());
-
- if(!DirectlyUseRhs)
- {
- #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- int size = actualRhs.size();
- EIGEN_DENSE_STORAGE_CTOR_PLUGIN
- #endif
- Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs;
- }
-
- internal::product_triangular_matrix_vector
- <Index,Mode,
- LhsScalar, LhsBlasTraits::NeedToConjugate,
- RhsScalar, RhsBlasTraits::NeedToConjugate,
- RowMajor>
- ::run(actualLhs.rows(),actualLhs.cols(),
- actualLhs.data(),actualLhs.outerStride(),
- actualRhsPtr,1,
- dest.data(),dest.innerStride(),
- actualAlpha);
- }
-};
-
-} // end namespace internal
-
-#endif // EIGEN_TRIANGULARMATRIXVECTOR_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h b/extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h
deleted file mode 100644
index 4dced6b0eb9..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h
+++ /dev/null
@@ -1,319 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_TRIANGULAR_SOLVER_MATRIX_H
-#define EIGEN_TRIANGULAR_SOLVER_MATRIX_H
-
-namespace internal {
-
-// if the rhs is row major, let's transpose the product
-template <typename Scalar, typename Index, int Side, int Mode, bool Conjugate, int TriStorageOrder>
-struct triangular_solve_matrix<Scalar,Index,Side,Mode,Conjugate,TriStorageOrder,RowMajor>
-{
- static EIGEN_DONT_INLINE void run(
- Index size, Index cols,
- const Scalar* tri, Index triStride,
- Scalar* _other, Index otherStride)
- {
- triangular_solve_matrix<
- Scalar, Index, Side==OnTheLeft?OnTheRight:OnTheLeft,
- (Mode&UnitDiag) | ((Mode&Upper) ? Lower : Upper),
- NumTraits<Scalar>::IsComplex && Conjugate,
- TriStorageOrder==RowMajor ? ColMajor : RowMajor, ColMajor>
- ::run(size, cols, tri, triStride, _other, otherStride);
- }
-};
-
-/* Optimized triangular solver with multiple right hand side and the triangular matrix on the left
- */
-template <typename Scalar, typename Index, int Mode, bool Conjugate, int TriStorageOrder>
-struct triangular_solve_matrix<Scalar,Index,OnTheLeft,Mode,Conjugate,TriStorageOrder,ColMajor>
-{
- static EIGEN_DONT_INLINE void run(
- Index size, Index otherSize,
- const Scalar* _tri, Index triStride,
- Scalar* _other, Index otherStride)
- {
- Index cols = otherSize;
- const_blas_data_mapper<Scalar, Index, TriStorageOrder> tri(_tri,triStride);
- blas_data_mapper<Scalar, Index, ColMajor> other(_other,otherStride);
-
- typedef gebp_traits<Scalar,Scalar> Traits;
- enum {
- SmallPanelWidth = EIGEN_PLAIN_ENUM_MAX(Traits::mr,Traits::nr),
- IsLower = (Mode&Lower) == Lower
- };
-
- Index kc = size; // cache block size along the K direction
- Index mc = size; // cache block size along the M direction
- Index nc = cols; // cache block size along the N direction
- computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc);
-
- std::size_t sizeW = kc*Traits::WorkSpaceFactor;
- std::size_t sizeB = sizeW + kc*cols;
- ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0);
- ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0);
- Scalar* blockB = allocatedBlockB + sizeW;
-
- conj_if<Conjugate> conj;
- gebp_kernel<Scalar, Scalar, Index, Traits::mr, Traits::nr, Conjugate, false> gebp_kernel;
- gemm_pack_lhs<Scalar, Index, Traits::mr, Traits::LhsProgress, TriStorageOrder> pack_lhs;
- gemm_pack_rhs<Scalar, Index, Traits::nr, ColMajor, false, true> pack_rhs;
-
- for(Index k2=IsLower ? 0 : size;
- IsLower ? k2<size : k2>0;
- IsLower ? k2+=kc : k2-=kc)
- {
- const Index actual_kc = (std::min)(IsLower ? size-k2 : k2, kc);
-
- // We have selected and packed a big horizontal panel R1 of rhs. Let B be the packed copy of this panel,
- // and R2 the remaining part of rhs. The corresponding vertical panel of lhs is split into
- // A11 (the triangular part) and A21 the remaining rectangular part.
- // Then the high level algorithm is:
- // - B = R1 => general block copy (done during the next step)
- // - R1 = L1^-1 B => tricky part
- // - update B from the new R1 => actually this has to be performed continuously during the above step
- // - R2 = L2 * B => GEPP
-
- // The tricky part: compute R1 = L1^-1 B while updating B from R1
- // The idea is to split L1 into multiple small vertical panels.
- // Each panel can be split into a small triangular part A1 which is processed without optimization,
- // and the remaining small part A2 which is processed using gebp with appropriate block strides
- {
- // for each small vertical panels of lhs
- for (Index k1=0; k1<actual_kc; k1+=SmallPanelWidth)
- {
- Index actualPanelWidth = std::min<Index>(actual_kc-k1, SmallPanelWidth);
- // tr solve
- for (Index k=0; k<actualPanelWidth; ++k)
- {
- // TODO write a small kernel handling this (can be shared with trsv)
- Index i = IsLower ? k2+k1+k : k2-k1-k-1;
- Index s = IsLower ? k2+k1 : i+1;
- Index rs = actualPanelWidth - k - 1; // remaining size
-
- Scalar a = (Mode & UnitDiag) ? Scalar(1) : Scalar(1)/conj(tri(i,i));
- for (Index j=0; j<cols; ++j)
- {
- if (TriStorageOrder==RowMajor)
- {
- Scalar b = 0;
- const Scalar* l = &tri(i,s);
- Scalar* r = &other(s,j);
- for (Index i3=0; i3<k; ++i3)
- b += conj(l[i3]) * r[i3];
-
- other(i,j) = (other(i,j) - b)*a;
- }
- else
- {
- Index s = IsLower ? i+1 : i-rs;
- Scalar b = (other(i,j) *= a);
- Scalar* r = &other(s,j);
- const Scalar* l = &tri(s,i);
- for (Index i3=0;i3<rs;++i3)
- r[i3] -= b * conj(l[i3]);
- }
- }
- }
-
- Index lengthTarget = actual_kc-k1-actualPanelWidth;
- Index startBlock = IsLower ? k2+k1 : k2-k1-actualPanelWidth;
- Index blockBOffset = IsLower ? k1 : lengthTarget;
-
- // update the respective rows of B from other
- pack_rhs(blockB, _other+startBlock, otherStride, actualPanelWidth, cols, actual_kc, blockBOffset);
-
- // GEBP
- if (lengthTarget>0)
- {
- Index startTarget = IsLower ? k2+k1+actualPanelWidth : k2-actual_kc;
-
- pack_lhs(blockA, &tri(startTarget,startBlock), triStride, actualPanelWidth, lengthTarget);
-
- gebp_kernel(_other+startTarget, otherStride, blockA, blockB, lengthTarget, actualPanelWidth, cols, Scalar(-1),
- actualPanelWidth, actual_kc, 0, blockBOffset);
- }
- }
- }
-
- // R2 = A2 * B => GEPP
- {
- Index start = IsLower ? k2+kc : 0;
- Index end = IsLower ? size : k2-kc;
- for(Index i2=start; i2<end; i2+=mc)
- {
- const Index actual_mc = (std::min)(mc,end-i2);
- if (actual_mc>0)
- {
- pack_lhs(blockA, &tri(i2, IsLower ? k2 : k2-kc), triStride, actual_kc, actual_mc);
-
- gebp_kernel(_other+i2, otherStride, blockA, blockB, actual_mc, actual_kc, cols, Scalar(-1));
- }
- }
- }
- }
- }
-};
-
-/* Optimized triangular solver with multiple left hand sides and the trinagular matrix on the right
- */
-template <typename Scalar, typename Index, int Mode, bool Conjugate, int TriStorageOrder>
-struct triangular_solve_matrix<Scalar,Index,OnTheRight,Mode,Conjugate,TriStorageOrder,ColMajor>
-{
- static EIGEN_DONT_INLINE void run(
- Index size, Index otherSize,
- const Scalar* _tri, Index triStride,
- Scalar* _other, Index otherStride)
- {
- Index rows = otherSize;
- const_blas_data_mapper<Scalar, Index, TriStorageOrder> rhs(_tri,triStride);
- blas_data_mapper<Scalar, Index, ColMajor> lhs(_other,otherStride);
-
- typedef gebp_traits<Scalar,Scalar> Traits;
- enum {
- RhsStorageOrder = TriStorageOrder,
- SmallPanelWidth = EIGEN_PLAIN_ENUM_MAX(Traits::mr,Traits::nr),
- IsLower = (Mode&Lower) == Lower
- };
-
-// Index kc = std::min<Index>(Traits::Max_kc/4,size); // cache block size along the K direction
-// Index mc = std::min<Index>(Traits::Max_mc,size); // cache block size along the M direction
- // check that !!!!
- Index kc = size; // cache block size along the K direction
- Index mc = size; // cache block size along the M direction
- Index nc = rows; // cache block size along the N direction
- computeProductBlockingSizes<Scalar,Scalar,4>(kc, mc, nc);
-
- std::size_t sizeW = kc*Traits::WorkSpaceFactor;
- std::size_t sizeB = sizeW + kc*size;
- ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0);
- ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0);
- Scalar* blockB = allocatedBlockB + sizeW;
-
- conj_if<Conjugate> conj;
- gebp_kernel<Scalar,Scalar, Index, Traits::mr, Traits::nr, false, Conjugate> gebp_kernel;
- gemm_pack_rhs<Scalar, Index, Traits::nr,RhsStorageOrder> pack_rhs;
- gemm_pack_rhs<Scalar, Index, Traits::nr,RhsStorageOrder,false,true> pack_rhs_panel;
- gemm_pack_lhs<Scalar, Index, Traits::mr, Traits::LhsProgress, ColMajor, false, true> pack_lhs_panel;
-
- for(Index k2=IsLower ? size : 0;
- IsLower ? k2>0 : k2<size;
- IsLower ? k2-=kc : k2+=kc)
- {
- const Index actual_kc = (std::min)(IsLower ? k2 : size-k2, kc);
- Index actual_k2 = IsLower ? k2-actual_kc : k2 ;
-
- Index startPanel = IsLower ? 0 : k2+actual_kc;
- Index rs = IsLower ? actual_k2 : size - actual_k2 - actual_kc;
- Scalar* geb = blockB+actual_kc*actual_kc;
-
- if (rs>0) pack_rhs(geb, &rhs(actual_k2,startPanel), triStride, actual_kc, rs);
-
- // triangular packing (we only pack the panels off the diagonal,
- // neglecting the blocks overlapping the diagonal
- {
- for (Index j2=0; j2<actual_kc; j2+=SmallPanelWidth)
- {
- Index actualPanelWidth = std::min<Index>(actual_kc-j2, SmallPanelWidth);
- Index actual_j2 = actual_k2 + j2;
- Index panelOffset = IsLower ? j2+actualPanelWidth : 0;
- Index panelLength = IsLower ? actual_kc-j2-actualPanelWidth : j2;
-
- if (panelLength>0)
- pack_rhs_panel(blockB+j2*actual_kc,
- &rhs(actual_k2+panelOffset, actual_j2), triStride,
- panelLength, actualPanelWidth,
- actual_kc, panelOffset);
- }
- }
-
- for(Index i2=0; i2<rows; i2+=mc)
- {
- const Index actual_mc = (std::min)(mc,rows-i2);
-
- // triangular solver kernel
- {
- // for each small block of the diagonal (=> vertical panels of rhs)
- for (Index j2 = IsLower
- ? (actual_kc - ((actual_kc%SmallPanelWidth) ? Index(actual_kc%SmallPanelWidth)
- : Index(SmallPanelWidth)))
- : 0;
- IsLower ? j2>=0 : j2<actual_kc;
- IsLower ? j2-=SmallPanelWidth : j2+=SmallPanelWidth)
- {
- Index actualPanelWidth = std::min<Index>(actual_kc-j2, SmallPanelWidth);
- Index absolute_j2 = actual_k2 + j2;
- Index panelOffset = IsLower ? j2+actualPanelWidth : 0;
- Index panelLength = IsLower ? actual_kc - j2 - actualPanelWidth : j2;
-
- // GEBP
- if(panelLength>0)
- {
- gebp_kernel(&lhs(i2,absolute_j2), otherStride,
- blockA, blockB+j2*actual_kc,
- actual_mc, panelLength, actualPanelWidth,
- Scalar(-1),
- actual_kc, actual_kc, // strides
- panelOffset, panelOffset, // offsets
- allocatedBlockB); // workspace
- }
-
- // unblocked triangular solve
- for (Index k=0; k<actualPanelWidth; ++k)
- {
- Index j = IsLower ? absolute_j2+actualPanelWidth-k-1 : absolute_j2+k;
-
- Scalar* r = &lhs(i2,j);
- for (Index k3=0; k3<k; ++k3)
- {
- Scalar b = conj(rhs(IsLower ? j+1+k3 : absolute_j2+k3,j));
- Scalar* a = &lhs(i2,IsLower ? j+1+k3 : absolute_j2+k3);
- 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;
- }
-
- // pack the just computed part of lhs to A
- pack_lhs_panel(blockA, _other+absolute_j2*otherStride+i2, otherStride,
- actualPanelWidth, actual_mc,
- actual_kc, j2);
- }
- }
-
- if (rs>0)
- gebp_kernel(_other+i2+startPanel*otherStride, otherStride, blockA, geb,
- actual_mc, actual_kc, rs, Scalar(-1),
- -1, -1, 0, 0, allocatedBlockB);
- }
- }
- }
-};
-
-} // end namespace internal
-
-#endif // EIGEN_TRIANGULAR_SOLVER_MATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h b/extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h
deleted file mode 100644
index 639d4a5b476..00000000000
--- a/extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h
+++ /dev/null
@@ -1,150 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_TRIANGULAR_SOLVER_VECTOR_H
-#define EIGEN_TRIANGULAR_SOLVER_VECTOR_H
-
-namespace internal {
-
-template<typename LhsScalar, typename RhsScalar, typename Index, int Mode, bool Conjugate, int StorageOrder>
-struct triangular_solve_vector<LhsScalar, RhsScalar, Index, OnTheRight, Mode, Conjugate, StorageOrder>
-{
- static void run(Index size, const LhsScalar* _lhs, Index lhsStride, RhsScalar* rhs)
- {
- triangular_solve_vector<LhsScalar,RhsScalar,Index,OnTheLeft,
- ((Mode&Upper)==Upper ? Lower : Upper) | (Mode&UnitDiag),
- Conjugate,StorageOrder==RowMajor?ColMajor:RowMajor
- >::run(size, _lhs, lhsStride, rhs);
- }
-};
-
-// forward and backward substitution, row-major, rhs is a vector
-template<typename LhsScalar, typename RhsScalar, typename Index, int Mode, bool Conjugate>
-struct triangular_solve_vector<LhsScalar, RhsScalar, Index, OnTheLeft, Mode, Conjugate, RowMajor>
-{
- enum {
- IsLower = ((Mode&Lower)==Lower)
- };
- static void run(Index size, const LhsScalar* _lhs, Index lhsStride, RhsScalar* rhs)
- {
- typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,RowMajor>, 0, OuterStride<> > LhsMap;
- const LhsMap lhs(_lhs,size,size,OuterStride<>(lhsStride));
- typename internal::conditional<
- Conjugate,
- const CwiseUnaryOp<typename internal::scalar_conjugate_op<LhsScalar>,LhsMap>,
- const LhsMap&>
- ::type cjLhs(lhs);
- static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
- for(Index pi=IsLower ? 0 : size;
- IsLower ? pi<size : pi>0;
- IsLower ? pi+=PanelWidth : pi-=PanelWidth)
- {
- Index actualPanelWidth = (std::min)(IsLower ? size - pi : pi, PanelWidth);
-
- Index r = IsLower ? pi : size - pi; // remaining size
- if (r > 0)
- {
- // let's directly call the low level product function because:
- // 1 - it is faster to compile
- // 2 - it is slighlty faster at runtime
- Index startRow = IsLower ? pi : pi-actualPanelWidth;
- Index startCol = IsLower ? 0 : pi;
-
- general_matrix_vector_product<Index,LhsScalar,RowMajor,Conjugate,RhsScalar,false>::run(
- actualPanelWidth, r,
- &lhs.coeffRef(startRow,startCol), lhsStride,
- rhs + startCol, 1,
- rhs + startRow, 1,
- RhsScalar(-1));
- }
-
- for(Index k=0; k<actualPanelWidth; ++k)
- {
- Index i = IsLower ? pi+k : pi-k-1;
- Index s = IsLower ? pi : i+1;
- if (k>0)
- rhs[i] -= (cjLhs.row(i).segment(s,k).transpose().cwiseProduct(Map<const Matrix<RhsScalar,Dynamic,1> >(rhs+s,k))).sum();
-
- if(!(Mode & UnitDiag))
- rhs[i] /= cjLhs(i,i);
- }
- }
- }
-};
-
-// forward and backward substitution, column-major, rhs is a vector
-template<typename LhsScalar, typename RhsScalar, typename Index, int Mode, bool Conjugate>
-struct triangular_solve_vector<LhsScalar, RhsScalar, Index, OnTheLeft, Mode, Conjugate, ColMajor>
-{
- enum {
- IsLower = ((Mode&Lower)==Lower)
- };
- static void run(Index size, const LhsScalar* _lhs, Index lhsStride, RhsScalar* rhs)
- {
- typedef Map<const Matrix<LhsScalar,Dynamic,Dynamic,ColMajor>, 0, OuterStride<> > LhsMap;
- const LhsMap lhs(_lhs,size,size,OuterStride<>(lhsStride));
- typename internal::conditional<Conjugate,
- const CwiseUnaryOp<typename internal::scalar_conjugate_op<LhsScalar>,LhsMap>,
- const LhsMap&
- >::type cjLhs(lhs);
- static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH;
-
- for(Index pi=IsLower ? 0 : size;
- IsLower ? pi<size : pi>0;
- IsLower ? pi+=PanelWidth : pi-=PanelWidth)
- {
- Index actualPanelWidth = (std::min)(IsLower ? size - pi : pi, PanelWidth);
- Index startBlock = IsLower ? pi : pi-actualPanelWidth;
- Index endBlock = IsLower ? pi + actualPanelWidth : 0;
-
- for(Index k=0; k<actualPanelWidth; ++k)
- {
- Index i = IsLower ? pi+k : pi-k-1;
- if(!(Mode & UnitDiag))
- rhs[i] /= cjLhs.coeff(i,i);
-
- Index r = actualPanelWidth - k - 1; // remaining size
- Index s = IsLower ? i+1 : i-r;
- if (r>0)
- Map<Matrix<RhsScalar,Dynamic,1> >(rhs+s,r) -= rhs[i] * cjLhs.col(i).segment(s,r);
- }
- Index r = IsLower ? size - endBlock : startBlock; // remaining size
- if (r > 0)
- {
- // let's directly call the low level product function because:
- // 1 - it is faster to compile
- // 2 - it is slighlty faster at runtime
- general_matrix_vector_product<Index,LhsScalar,ColMajor,Conjugate,RhsScalar,false>::run(
- r, actualPanelWidth,
- &lhs.coeffRef(endBlock,startBlock), lhsStride,
- rhs+startBlock, 1,
- rhs+endBlock, 1, RhsScalar(-1));
- }
- }
- }
-};
-
-} // end namespace internal
-
-#endif // EIGEN_TRIANGULAR_SOLVER_VECTOR_H
diff --git a/extern/Eigen3/Eigen/src/Core/util/BlasUtil.h b/extern/Eigen3/Eigen/src/Core/util/BlasUtil.h
deleted file mode 100644
index f1d93d2f8b9..00000000000
--- a/extern/Eigen3/Eigen/src/Core/util/BlasUtil.h
+++ /dev/null
@@ -1,271 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_BLASUTIL_H
-#define EIGEN_BLASUTIL_H
-
-// This file contains many lightweight helper classes used to
-// implement and control fast level 2 and level 3 BLAS-like routines.
-
-namespace internal {
-
-// forward declarations
-template<typename LhsScalar, typename RhsScalar, typename Index, int mr, int nr, bool ConjugateLhs=false, bool ConjugateRhs=false>
-struct gebp_kernel;
-
-template<typename Scalar, typename Index, int nr, int StorageOrder, bool Conjugate = false, bool PanelMode=false>
-struct gemm_pack_rhs;
-
-template<typename Scalar, typename Index, int Pack1, int Pack2, int StorageOrder, bool Conjugate = false, bool PanelMode = false>
-struct gemm_pack_lhs;
-
-template<
- typename Index,
- typename LhsScalar, int LhsStorageOrder, bool ConjugateLhs,
- typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs,
- int ResStorageOrder>
-struct general_matrix_matrix_product;
-
-template<typename Index, typename LhsScalar, int LhsStorageOrder, bool ConjugateLhs, typename RhsScalar, bool ConjugateRhs>
-struct general_matrix_vector_product;
-
-
-template<bool Conjugate> struct conj_if;
-
-template<> struct conj_if<true> {
- template<typename T>
- inline T operator()(const T& x) { return conj(x); }
-};
-
-template<> struct conj_if<false> {
- template<typename T>
- inline const T& operator()(const T& x) { return x; }
-};
-
-template<typename Scalar> struct conj_helper<Scalar,Scalar,false,false>
-{
- EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const { return internal::pmadd(x,y,c); }
- EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const { return internal::pmul(x,y); }
-};
-
-template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, false,true>
-{
- typedef std::complex<RealScalar> Scalar;
- EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const
- { return c + pmul(x,y); }
-
- EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
- { return Scalar(real(x)*real(y) + imag(x)*imag(y), imag(x)*real(y) - real(x)*imag(y)); }
-};
-
-template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, true,false>
-{
- typedef std::complex<RealScalar> Scalar;
- EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const
- { return c + pmul(x,y); }
-
- EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
- { return Scalar(real(x)*real(y) + imag(x)*imag(y), real(x)*imag(y) - imag(x)*real(y)); }
-};
-
-template<typename RealScalar> struct conj_helper<std::complex<RealScalar>, std::complex<RealScalar>, true,true>
-{
- typedef std::complex<RealScalar> Scalar;
- EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const
- { return c + pmul(x,y); }
-
- EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const
- { return Scalar(real(x)*real(y) - imag(x)*imag(y), - real(x)*imag(y) - imag(x)*real(y)); }
-};
-
-template<typename RealScalar,bool Conj> struct conj_helper<std::complex<RealScalar>, RealScalar, Conj,false>
-{
- typedef std::complex<RealScalar> Scalar;
- EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const RealScalar& y, const Scalar& c) const
- { return padd(c, pmul(x,y)); }
- EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const RealScalar& y) const
- { return conj_if<Conj>()(x)*y; }
-};
-
-template<typename RealScalar,bool Conj> struct conj_helper<RealScalar, std::complex<RealScalar>, false,Conj>
-{
- typedef std::complex<RealScalar> Scalar;
- EIGEN_STRONG_INLINE Scalar pmadd(const RealScalar& x, const Scalar& y, const Scalar& c) const
- { return padd(c, pmul(x,y)); }
- EIGEN_STRONG_INLINE Scalar pmul(const RealScalar& x, const Scalar& y) const
- { return x*conj_if<Conj>()(y); }
-};
-
-template<typename From,typename To> struct get_factor {
- EIGEN_STRONG_INLINE static To run(const From& x) { return x; }
-};
-
-template<typename Scalar> struct get_factor<Scalar,typename NumTraits<Scalar>::Real> {
- EIGEN_STRONG_INLINE static typename NumTraits<Scalar>::Real run(const Scalar& x) { return real(x); }
-};
-
-// Lightweight helper class to access matrix coefficients.
-// Yes, this is somehow redundant with Map<>, but this version is much much lighter,
-// and so I hope better compilation performance (time and code quality).
-template<typename Scalar, typename Index, int StorageOrder>
-class blas_data_mapper
-{
- public:
- blas_data_mapper(Scalar* data, Index stride) : m_data(data), m_stride(stride) {}
- EIGEN_STRONG_INLINE Scalar& operator()(Index i, Index j)
- { return m_data[StorageOrder==RowMajor ? j + i*m_stride : i + j*m_stride]; }
- protected:
- Scalar* EIGEN_RESTRICT m_data;
- Index m_stride;
-};
-
-// lightweight helper class to access matrix coefficients (const version)
-template<typename Scalar, typename Index, int StorageOrder>
-class const_blas_data_mapper
-{
- public:
- const_blas_data_mapper(const Scalar* data, Index stride) : m_data(data), m_stride(stride) {}
- EIGEN_STRONG_INLINE const Scalar& operator()(Index i, Index j) const
- { return m_data[StorageOrder==RowMajor ? j + i*m_stride : i + j*m_stride]; }
- protected:
- const Scalar* EIGEN_RESTRICT m_data;
- Index m_stride;
-};
-
-
-/* Helper class to analyze the factors of a Product expression.
- * In particular it allows to pop out operator-, scalar multiples,
- * and conjugate */
-template<typename XprType> struct blas_traits
-{
- typedef typename traits<XprType>::Scalar Scalar;
- typedef const XprType& ExtractType;
- typedef XprType _ExtractType;
- enum {
- IsComplex = NumTraits<Scalar>::IsComplex,
- IsTransposed = false,
- NeedToConjugate = false,
- HasUsableDirectAccess = ( (int(XprType::Flags)&DirectAccessBit)
- && ( bool(XprType::IsVectorAtCompileTime)
- || int(inner_stride_at_compile_time<XprType>::ret) == 1)
- ) ? 1 : 0
- };
- typedef typename conditional<bool(HasUsableDirectAccess),
- ExtractType,
- typename _ExtractType::PlainObject
- >::type DirectLinearAccessType;
- static inline const ExtractType extract(const XprType& x) { return x; }
- static inline const Scalar extractScalarFactor(const XprType&) { return Scalar(1); }
-};
-
-// pop conjugate
-template<typename Scalar, typename NestedXpr>
-struct blas_traits<CwiseUnaryOp<scalar_conjugate_op<Scalar>, NestedXpr> >
- : blas_traits<NestedXpr>
-{
- typedef blas_traits<NestedXpr> Base;
- typedef CwiseUnaryOp<scalar_conjugate_op<Scalar>, NestedXpr> XprType;
- typedef typename Base::ExtractType ExtractType;
-
- enum {
- IsComplex = NumTraits<Scalar>::IsComplex,
- NeedToConjugate = Base::NeedToConjugate ? 0 : IsComplex
- };
- static inline const ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
- static inline Scalar extractScalarFactor(const XprType& x) { return conj(Base::extractScalarFactor(x.nestedExpression())); }
-};
-
-// pop scalar multiple
-template<typename Scalar, typename NestedXpr>
-struct blas_traits<CwiseUnaryOp<scalar_multiple_op<Scalar>, NestedXpr> >
- : blas_traits<NestedXpr>
-{
- typedef blas_traits<NestedXpr> Base;
- typedef CwiseUnaryOp<scalar_multiple_op<Scalar>, NestedXpr> XprType;
- typedef typename Base::ExtractType ExtractType;
- static inline const ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
- static inline Scalar extractScalarFactor(const XprType& x)
- { return x.functor().m_other * Base::extractScalarFactor(x.nestedExpression()); }
-};
-
-// pop opposite
-template<typename Scalar, typename NestedXpr>
-struct blas_traits<CwiseUnaryOp<scalar_opposite_op<Scalar>, NestedXpr> >
- : blas_traits<NestedXpr>
-{
- typedef blas_traits<NestedXpr> Base;
- typedef CwiseUnaryOp<scalar_opposite_op<Scalar>, NestedXpr> XprType;
- typedef typename Base::ExtractType ExtractType;
- static inline const ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
- static inline Scalar extractScalarFactor(const XprType& x)
- { return - Base::extractScalarFactor(x.nestedExpression()); }
-};
-
-// pop/push transpose
-template<typename NestedXpr>
-struct blas_traits<Transpose<NestedXpr> >
- : blas_traits<NestedXpr>
-{
- typedef typename NestedXpr::Scalar Scalar;
- typedef blas_traits<NestedXpr> Base;
- typedef Transpose<NestedXpr> XprType;
- typedef Transpose<const typename Base::_ExtractType> ExtractType; // const to get rid of a compile error; anyway blas traits are only used on the RHS
- typedef Transpose<const typename Base::_ExtractType> _ExtractType;
- typedef typename conditional<bool(Base::HasUsableDirectAccess),
- ExtractType,
- typename ExtractType::PlainObject
- >::type DirectLinearAccessType;
- enum {
- IsTransposed = Base::IsTransposed ? 0 : 1
- };
- static inline const ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); }
- static inline Scalar extractScalarFactor(const XprType& x) { return Base::extractScalarFactor(x.nestedExpression()); }
-};
-
-template<typename T>
-struct blas_traits<const T>
- : blas_traits<T>
-{};
-
-template<typename T, bool HasUsableDirectAccess=blas_traits<T>::HasUsableDirectAccess>
-struct extract_data_selector {
- static const typename T::Scalar* run(const T& m)
- {
- return const_cast<typename T::Scalar*>(&blas_traits<T>::extract(m).coeffRef(0,0)); // FIXME this should be .data()
- }
-};
-
-template<typename T>
-struct extract_data_selector<T,false> {
- static typename T::Scalar* run(const T&) { return 0; }
-};
-
-template<typename T> const typename T::Scalar* extract_data(const T& m)
-{
- return extract_data_selector<T>::run(m);
-}
-
-} // end namespace internal
-
-#endif // EIGEN_BLASUTIL_H
diff --git a/extern/Eigen3/Eigen/src/Core/util/Constants.h b/extern/Eigen3/Eigen/src/Core/util/Constants.h
deleted file mode 100644
index c3dd3a09d00..00000000000
--- a/extern/Eigen3/Eigen/src/Core/util/Constants.h
+++ /dev/null
@@ -1,439 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_CONSTANTS_H
-#define EIGEN_CONSTANTS_H
-
-/** This value means that a quantity is not known at compile-time, and that instead the value is
- * stored in some runtime variable.
- *
- * Changing the value of Dynamic breaks the ABI, as Dynamic is often used as a template parameter for Matrix.
- */
-const int Dynamic = -1;
-
-/** This value means +Infinity; it is currently used only as the p parameter to MatrixBase::lpNorm<int>().
- * The value Infinity there means the L-infinity norm.
- */
-const int Infinity = -1;
-
-/** \defgroup flags Flags
- * \ingroup Core_Module
- *
- * These are the possible bits which can be OR'ed to constitute the flags of a matrix or
- * expression.
- *
- * It is important to note that these flags are a purely compile-time notion. They are a compile-time property of
- * an expression type, implemented as enum's. They are not stored in memory at runtime, and they do not incur any
- * runtime overhead.
- *
- * \sa MatrixBase::Flags
- */
-
-/** \ingroup flags
- *
- * for a matrix, this means that the storage order is row-major.
- * If this bit is not set, the storage order is column-major.
- * For an expression, this determines the storage order of
- * the matrix created by evaluation of that expression.
- * \sa \ref TopicStorageOrders */
-const unsigned int RowMajorBit = 0x1;
-
-/** \ingroup flags
- *
- * means the expression should be evaluated by the calling expression */
-const unsigned int EvalBeforeNestingBit = 0x2;
-
-/** \ingroup flags
- *
- * means the expression should be evaluated before any assignment */
-const unsigned int EvalBeforeAssigningBit = 0x4;
-
-/** \ingroup flags
- *
- * Short version: means the expression might be vectorized
- *
- * Long version: means that the coefficients can be handled by packets
- * and start at a memory location whose alignment meets the requirements
- * of the present CPU architecture for optimized packet access. In the fixed-size
- * case, there is the additional condition that it be possible to access all the
- * coefficients by packets (this implies the requirement that the size be a multiple of 16 bytes,
- * and that any nontrivial strides don't break the alignment). In the dynamic-size case,
- * there is no such condition on the total size and strides, so it might not be possible to access
- * all coeffs by packets.
- *
- * \note This bit can be set regardless of whether vectorization is actually enabled.
- * To check for actual vectorizability, see \a ActualPacketAccessBit.
- */
-const unsigned int PacketAccessBit = 0x8;
-
-#ifdef EIGEN_VECTORIZE
-/** \ingroup flags
- *
- * If vectorization is enabled (EIGEN_VECTORIZE is defined) this constant
- * is set to the value \a PacketAccessBit.
- *
- * If vectorization is not enabled (EIGEN_VECTORIZE is not defined) this constant
- * is set to the value 0.
- */
-const unsigned int ActualPacketAccessBit = PacketAccessBit;
-#else
-const unsigned int ActualPacketAccessBit = 0x0;
-#endif
-
-/** \ingroup flags
- *
- * Short version: means the expression can be seen as 1D vector.
- *
- * Long version: means that one can access the coefficients
- * of this expression by coeff(int), and coeffRef(int) in the case of a lvalue expression. These
- * index-based access methods are guaranteed
- * to not have to do any runtime computation of a (row, col)-pair from the index, so that it
- * is guaranteed that whenever it is available, index-based access is at least as fast as
- * (row,col)-based access. Expressions for which that isn't possible don't have the LinearAccessBit.
- *
- * If both PacketAccessBit and LinearAccessBit are set, then the
- * packets of this expression can be accessed by packet(int), and writePacket(int) in the case of a
- * lvalue expression.
- *
- * Typically, all vector expressions have the LinearAccessBit, but there is one exception:
- * Product expressions don't have it, because it would be troublesome for vectorization, even when the
- * Product is a vector expression. Thus, vector Product expressions allow index-based coefficient access but
- * not index-based packet access, so they don't have the LinearAccessBit.
- */
-const unsigned int LinearAccessBit = 0x10;
-
-/** \ingroup flags
- *
- * Means the expression has a coeffRef() method, i.e. is writable as its individual coefficients are directly addressable.
- * This rules out read-only expressions.
- *
- * Note that DirectAccessBit and LvalueBit are mutually orthogonal, as there are examples of expression having one but note
- * the other:
- * \li writable expressions that don't have a very simple memory layout as a strided array, have LvalueBit but not DirectAccessBit
- * \li Map-to-const expressions, for example Map<const Matrix>, have DirectAccessBit but not LvalueBit
- *
- * Expressions having LvalueBit also have their coeff() method returning a const reference instead of returning a new value.
- */
-const unsigned int LvalueBit = 0x20;
-
-/** \ingroup flags
- *
- * Means that the underlying array of coefficients can be directly accessed as a plain strided array. The memory layout
- * of the array of coefficients must be exactly the natural one suggested by rows(), cols(),
- * outerStride(), innerStride(), and the RowMajorBit. This rules out expressions such as Diagonal, whose coefficients,
- * though referencable, do not have such a regular memory layout.
- *
- * See the comment on LvalueBit for an explanation of how LvalueBit and DirectAccessBit are mutually orthogonal.
- */
-const unsigned int DirectAccessBit = 0x40;
-
-/** \ingroup flags
- *
- * means the first coefficient packet is guaranteed to be aligned */
-const unsigned int AlignedBit = 0x80;
-
-const unsigned int NestByRefBit = 0x100;
-
-// list of flags that are inherited by default
-const unsigned int HereditaryBits = RowMajorBit
- | EvalBeforeNestingBit
- | EvalBeforeAssigningBit;
-
-/** \defgroup enums Enumerations
- * \ingroup Core_Module
- *
- * Various enumerations used in %Eigen. Many of these are used as template parameters.
- */
-
-/** \ingroup enums
- * Enum containing possible values for the \p Mode parameter of
- * MatrixBase::selfadjointView() and MatrixBase::triangularView(). */
-enum {
- /** View matrix as a lower triangular matrix. */
- Lower=0x1,
- /** View matrix as an upper triangular matrix. */
- Upper=0x2,
- /** %Matrix has ones on the diagonal; to be used in combination with #Lower or #Upper. */
- UnitDiag=0x4,
- /** %Matrix has zeros on the diagonal; to be used in combination with #Lower or #Upper. */
- ZeroDiag=0x8,
- /** View matrix as a lower triangular matrix with ones on the diagonal. */
- UnitLower=UnitDiag|Lower,
- /** View matrix as an upper triangular matrix with ones on the diagonal. */
- UnitUpper=UnitDiag|Upper,
- /** View matrix as a lower triangular matrix with zeros on the diagonal. */
- StrictlyLower=ZeroDiag|Lower,
- /** View matrix as an upper triangular matrix with zeros on the diagonal. */
- StrictlyUpper=ZeroDiag|Upper,
- /** Used in BandMatrix and SelfAdjointView to indicate that the matrix is self-adjoint. */
- SelfAdjoint=0x10
-};
-
-/** \ingroup enums
- * Enum for indicating whether an object is aligned or not. */
-enum {
- /** Object is not correctly aligned for vectorization. */
- Unaligned=0,
- /** Object is aligned for vectorization. */
- Aligned=1
-};
-
-enum { ConditionalJumpCost = 5 };
-
-/** \ingroup enums
- * Enum used by DenseBase::corner() in Eigen2 compatibility mode. */
-// FIXME after the corner() API change, this was not needed anymore, except by AlignedBox
-// TODO: find out what to do with that. Adapt the AlignedBox API ?
-enum CornerType { TopLeft, TopRight, BottomLeft, BottomRight };
-
-/** \ingroup enums
- * Enum containing possible values for the \p Direction parameter of
- * Reverse, PartialReduxExpr and VectorwiseOp. */
-enum DirectionType {
- /** For Reverse, all columns are reversed;
- * for PartialReduxExpr and VectorwiseOp, act on columns. */
- Vertical,
- /** For Reverse, all rows are reversed;
- * for PartialReduxExpr and VectorwiseOp, act on rows. */
- Horizontal,
- /** For Reverse, both rows and columns are reversed;
- * not used for PartialReduxExpr and VectorwiseOp. */
- BothDirections
-};
-
-enum ProductEvaluationMode { NormalProduct, CacheFriendlyProduct };
-
-/** \internal \ingroup enums
- * Enum to specify how to traverse the entries of a matrix. */
-enum {
- /** \internal Default traversal, no vectorization, no index-based access */
- DefaultTraversal,
- /** \internal No vectorization, use index-based access to have only one for loop instead of 2 nested loops */
- LinearTraversal,
- /** \internal Equivalent to a slice vectorization for fixed-size matrices having good alignment
- * and good size */
- InnerVectorizedTraversal,
- /** \internal Vectorization path using a single loop plus scalar loops for the
- * unaligned boundaries */
- LinearVectorizedTraversal,
- /** \internal Generic vectorization path using one vectorized loop per row/column with some
- * scalar loops to handle the unaligned boundaries */
- SliceVectorizedTraversal,
- /** \internal Special case to properly handle incompatible scalar types or other defecting cases*/
- InvalidTraversal
-};
-
-/** \internal \ingroup enums
- * Enum to specify whether to unroll loops when traversing over the entries of a matrix. */
-enum {
- /** \internal Do not unroll loops. */
- NoUnrolling,
- /** \internal Unroll only the inner loop, but not the outer loop. */
- InnerUnrolling,
- /** \internal Unroll both the inner and the outer loop. If there is only one loop,
- * because linear traversal is used, then unroll that loop. */
- CompleteUnrolling
-};
-
-/** \ingroup enums
- * Enum containing possible values for the \p _Options template parameter of
- * Matrix, Array and BandMatrix. */
-enum {
- /** Storage order is column major (see \ref TopicStorageOrders). */
- ColMajor = 0,
- /** Storage order is row major (see \ref TopicStorageOrders). */
- RowMajor = 0x1, // it is only a coincidence that this is equal to RowMajorBit -- don't rely on that
- /** \internal Align the matrix itself if it is vectorizable fixed-size */
- AutoAlign = 0,
- /** \internal Don't require alignment for the matrix itself (the array of coefficients, if dynamically allocated, may still be requested to be aligned) */ // FIXME --- clarify the situation
- DontAlign = 0x2
-};
-
-/** \ingroup enums
- * Enum for specifying whether to apply or solve on the left or right. */
-enum {
- /** Apply transformation on the left. */
- OnTheLeft = 1,
- /** Apply transformation on the right. */
- OnTheRight = 2
-};
-
-/* the following could as well be written:
- * enum NoChange_t { NoChange };
- * but it feels dangerous to disambiguate overloaded functions on enum/integer types.
- * If on some platform it is really impossible to get rid of "unused variable" warnings, then
- * we can always come back to that solution.
- */
-struct NoChange_t {};
-namespace {
- EIGEN_UNUSED NoChange_t NoChange;
-}
-
-struct Sequential_t {};
-namespace {
- EIGEN_UNUSED Sequential_t Sequential;
-}
-
-struct Default_t {};
-namespace {
- EIGEN_UNUSED Default_t Default;
-}
-
-/** \internal \ingroup enums
- * Used in AmbiVector. */
-enum {
- IsDense = 0,
- IsSparse
-};
-
-/** \ingroup enums
- * Used as template parameter in DenseCoeffBase and MapBase to indicate
- * which accessors should be provided. */
-enum AccessorLevels {
- /** Read-only access via a member function. */
- ReadOnlyAccessors,
- /** Read/write access via member functions. */
- WriteAccessors,
- /** Direct read-only access to the coefficients. */
- DirectAccessors,
- /** Direct read/write access to the coefficients. */
- DirectWriteAccessors
-};
-
-/** \ingroup enums
- * Enum with options to give to various decompositions. */
-enum DecompositionOptions {
- /** \internal Not used (meant for LDLT?). */
- Pivoting = 0x01,
- /** \internal Not used (meant for LDLT?). */
- NoPivoting = 0x02,
- /** Used in JacobiSVD to indicate that the square matrix U is to be computed. */
- ComputeFullU = 0x04,
- /** Used in JacobiSVD to indicate that the thin matrix U is to be computed. */
- ComputeThinU = 0x08,
- /** Used in JacobiSVD to indicate that the square matrix V is to be computed. */
- ComputeFullV = 0x10,
- /** Used in JacobiSVD to indicate that the thin matrix V is to be computed. */
- ComputeThinV = 0x20,
- /** Used in SelfAdjointEigenSolver and GeneralizedSelfAdjointEigenSolver to specify
- * that only the eigenvalues are to be computed and not the eigenvectors. */
- EigenvaluesOnly = 0x40,
- /** Used in SelfAdjointEigenSolver and GeneralizedSelfAdjointEigenSolver to specify
- * that both the eigenvalues and the eigenvectors are to be computed. */
- ComputeEigenvectors = 0x80,
- /** \internal */
- EigVecMask = EigenvaluesOnly | ComputeEigenvectors,
- /** Used in GeneralizedSelfAdjointEigenSolver to indicate that it should
- * solve the generalized eigenproblem \f$ Ax = \lambda B x \f$. */
- Ax_lBx = 0x100,
- /** Used in GeneralizedSelfAdjointEigenSolver to indicate that it should
- * solve the generalized eigenproblem \f$ ABx = \lambda x \f$. */
- ABx_lx = 0x200,
- /** Used in GeneralizedSelfAdjointEigenSolver to indicate that it should
- * solve the generalized eigenproblem \f$ BAx = \lambda x \f$. */
- BAx_lx = 0x400,
- /** \internal */
- GenEigMask = Ax_lBx | ABx_lx | BAx_lx
-};
-
-/** \ingroup enums
- * Possible values for the \p QRPreconditioner template parameter of JacobiSVD. */
-enum QRPreconditioners {
- /** Do not specify what is to be done if the SVD of a non-square matrix is asked for. */
- NoQRPreconditioner,
- /** Use a QR decomposition without pivoting as the first step. */
- HouseholderQRPreconditioner,
- /** Use a QR decomposition with column pivoting as the first step. */
- ColPivHouseholderQRPreconditioner,
- /** Use a QR decomposition with full pivoting as the first step. */
- FullPivHouseholderQRPreconditioner
-};
-
-#ifdef Success
-#error The preprocessor symbol 'Success' is defined, possibly by the X11 header file X.h
-#endif
-
-/** \ingroups enums
- * Enum for reporting the status of a computation. */
-enum ComputationInfo {
- /** Computation was successful. */
- Success = 0,
- /** The provided data did not satisfy the prerequisites. */
- NumericalIssue = 1,
- /** Iterative procedure did not converge. */
- NoConvergence = 2
-};
-
-/** \ingroup enums
- * Enum used to specify how a particular transformation is stored in a matrix.
- * \sa Transform, Hyperplane::transform(). */
-enum TransformTraits {
- /** Transformation is an isometry. */
- Isometry = 0x1,
- /** Transformation is an affine transformation stored as a (Dim+1)^2 matrix whose last row is
- * assumed to be [0 ... 0 1]. */
- Affine = 0x2,
- /** Transformation is an affine transformation stored as a (Dim) x (Dim+1) matrix. */
- AffineCompact = 0x10 | Affine,
- /** Transformation is a general projective transformation stored as a (Dim+1)^2 matrix. */
- Projective = 0x20
-};
-
-/** \internal \ingroup enums
- * Enum used to choose between implementation depending on the computer architecture. */
-namespace Architecture
-{
- enum Type {
- Generic = 0x0,
- SSE = 0x1,
- AltiVec = 0x2,
-#if defined EIGEN_VECTORIZE_SSE
- Target = SSE
-#elif defined EIGEN_VECTORIZE_ALTIVEC
- Target = AltiVec
-#else
- Target = Generic
-#endif
- };
-}
-
-/** \internal \ingroup enums
- * Enum used as template parameter in GeneralProduct. */
-enum { CoeffBasedProductMode, LazyCoeffBasedProductMode, OuterProduct, InnerProduct, GemvProduct, GemmProduct };
-
-/** \internal \ingroup enums
- * Enum used in experimental parallel implementation. */
-enum Action {GetAction, SetAction};
-
-/** The type used to identify a dense storage. */
-struct Dense {};
-
-/** The type used to identify a matrix expression */
-struct MatrixXpr {};
-
-/** The type used to identify an array expression */
-struct ArrayXpr {};
-
-#endif // EIGEN_CONSTANTS_H
diff --git a/extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h b/extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h
deleted file mode 100644
index 00730524b26..00000000000
--- a/extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef EIGEN_WARNINGS_DISABLED
-#define EIGEN_WARNINGS_DISABLED
-
-#ifdef _MSC_VER
- // 4100 - unreferenced formal parameter (occurred e.g. in aligned_allocator::destroy(pointer p))
- // 4101 - unreferenced local variable
- // 4127 - conditional expression is constant
- // 4181 - qualifier applied to reference type ignored
- // 4211 - nonstandard extension used : redefined extern to static
- // 4244 - 'argument' : conversion from 'type1' to 'type2', possible loss of data
- // 4273 - QtAlignedMalloc, inconsistent DLL linkage
- // 4324 - structure was padded due to declspec(align())
- // 4512 - assignment operator could not be generated
- // 4522 - 'class' : multiple assignment operators specified
- // 4700 - uninitialized local variable 'xyz' used
- // 4717 - 'function' : recursive on all control paths, function will cause runtime stack overflow
- #ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS
- #pragma warning( push )
- #endif
- #pragma warning( disable : 4100 4101 4127 4181 4211 4244 4273 4324 4512 4522 4700 4717 )
-#elif defined __INTEL_COMPILER
- // 2196 - routine is both "inline" and "noinline" ("noinline" assumed)
- // ICC 12 generates this warning even without any inline keyword, when defining class methods 'inline' i.e. inside of class body
- // 2536 - type qualifiers are meaningless here
- // ICC 12 generates this warning when a function return type is const qualified, even if that type is a template-parameter-dependent
- // typedef that may be a reference type.
- // 279 - controlling expression is constant
- // ICC 12 generates this warning on assert(constant_expression_depending_on_template_params) and frankly this is a legitimate use case.
- #ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS
- #pragma warning push
- #endif
- #pragma warning disable 2196 2536 279
-#elif defined __clang__
- // -Wconstant-logical-operand - warning: use of logical && with constant operand; switch to bitwise & or remove constant
- // this is really a stupid warning as it warns on compile-time expressions involving enums
- #ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS
- #pragma clang diagnostic push
- #endif
- #pragma clang diagnostic ignored "-Wconstant-logical-operand"
-#endif
-
-#endif // not EIGEN_WARNINGS_DISABLED
diff --git a/extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h b/extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h
deleted file mode 100644
index 7fbccf98c2b..00000000000
--- a/extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h
+++ /dev/null
@@ -1,307 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2007-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_FORWARDDECLARATIONS_H
-#define EIGEN_FORWARDDECLARATIONS_H
-
-namespace internal {
-
-template<typename T> struct traits;
-
-// here we say once and for all that traits<const T> == traits<T>
-// When constness must affect traits, it has to be constness on template parameters on which T itself depends.
-// For example, traits<Map<const T> > != traits<Map<T> >, but
-// traits<const Map<T> > == traits<Map<T> >
-template<typename T> struct traits<const T> : traits<T> {};
-
-template<typename Derived> struct has_direct_access
-{
- enum { ret = (traits<Derived>::Flags & DirectAccessBit) ? 1 : 0 };
-};
-
-template<typename Derived> struct accessors_level
-{
- enum { has_direct_access = (traits<Derived>::Flags & DirectAccessBit) ? 1 : 0,
- has_write_access = (traits<Derived>::Flags & LvalueBit) ? 1 : 0,
- value = has_direct_access ? (has_write_access ? DirectWriteAccessors : DirectAccessors)
- : (has_write_access ? WriteAccessors : ReadOnlyAccessors)
- };
-};
-
-} // end namespace internal
-
-template<typename T> struct NumTraits;
-
-template<typename Derived> struct EigenBase;
-template<typename Derived> class DenseBase;
-template<typename Derived> class PlainObjectBase;
-
-
-template<typename Derived,
- int Level = internal::accessors_level<Derived>::value >
-class DenseCoeffsBase;
-
-template<typename _Scalar, int _Rows, int _Cols,
- int _Options = AutoAlign |
-#if defined(__GNUC__) && __GNUC__==3 && __GNUC_MINOR__==4
- // workaround a bug in at least gcc 3.4.6
- // the innermost ?: ternary operator is misparsed. We write it slightly
- // differently and this makes gcc 3.4.6 happy, but it's ugly.
- // The error would only show up with EIGEN_DEFAULT_TO_ROW_MAJOR is defined
- // (when EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION is RowMajor)
- ( (_Rows==1 && _Cols!=1) ? RowMajor
- : !(_Cols==1 && _Rows!=1) ? EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION
- : ColMajor ),
-#else
- ( (_Rows==1 && _Cols!=1) ? RowMajor
- : (_Cols==1 && _Rows!=1) ? ColMajor
- : EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ),
-#endif
- int _MaxRows = _Rows,
- int _MaxCols = _Cols
-> class Matrix;
-
-template<typename Derived> class MatrixBase;
-template<typename Derived> class ArrayBase;
-
-template<typename ExpressionType, unsigned int Added, unsigned int Removed> class Flagged;
-template<typename ExpressionType, template <typename> class StorageBase > class NoAlias;
-template<typename ExpressionType> class NestByValue;
-template<typename ExpressionType> class ForceAlignedAccess;
-template<typename ExpressionType> class SwapWrapper;
-
-template<typename XprType, int BlockRows=Dynamic, int BlockCols=Dynamic, bool InnerPanel = false,
- bool HasDirectAccess = internal::has_direct_access<XprType>::ret> class Block;
-
-template<typename MatrixType, int Size=Dynamic> class VectorBlock;
-template<typename MatrixType> class Transpose;
-template<typename MatrixType> class Conjugate;
-template<typename NullaryOp, typename MatrixType> class CwiseNullaryOp;
-template<typename UnaryOp, typename MatrixType> class CwiseUnaryOp;
-template<typename ViewOp, typename MatrixType> class CwiseUnaryView;
-template<typename BinaryOp, typename Lhs, typename Rhs> class CwiseBinaryOp;
-template<typename BinOp, typename Lhs, typename Rhs> class SelfCwiseBinaryOp;
-template<typename Derived, typename Lhs, typename Rhs> class ProductBase;
-template<typename Lhs, typename Rhs, int Mode> class GeneralProduct;
-template<typename Lhs, typename Rhs, int NestingFlags> class CoeffBasedProduct;
-
-template<typename Derived> class DiagonalBase;
-template<typename _DiagonalVectorType> class DiagonalWrapper;
-template<typename _Scalar, int SizeAtCompileTime, int MaxSizeAtCompileTime=SizeAtCompileTime> class DiagonalMatrix;
-template<typename MatrixType, typename DiagonalType, int ProductOrder> class DiagonalProduct;
-template<typename MatrixType, int Index = 0> class Diagonal;
-template<int SizeAtCompileTime, int MaxSizeAtCompileTime = SizeAtCompileTime, typename IndexType=int> class PermutationMatrix;
-template<int SizeAtCompileTime, int MaxSizeAtCompileTime = SizeAtCompileTime, typename IndexType=int> class Transpositions;
-template<typename Derived> class PermutationBase;
-template<typename Derived> class TranspositionsBase;
-template<typename _IndicesType> class PermutationWrapper;
-template<typename _IndicesType> class TranspositionsWrapper;
-
-template<typename Derived,
- int Level = internal::accessors_level<Derived>::has_write_access ? WriteAccessors : ReadOnlyAccessors
-> class MapBase;
-template<int InnerStrideAtCompileTime, int OuterStrideAtCompileTime> class Stride;
-template<typename MatrixType, int MapOptions=Unaligned, typename StrideType = Stride<0,0> > class Map;
-
-template<typename Derived> class TriangularBase;
-template<typename MatrixType, unsigned int Mode> class TriangularView;
-template<typename MatrixType, unsigned int Mode> class SelfAdjointView;
-template<typename MatrixType> class SparseView;
-template<typename ExpressionType> class WithFormat;
-template<typename MatrixType> struct CommaInitializer;
-template<typename Derived> class ReturnByValue;
-template<typename ExpressionType> class ArrayWrapper;
-
-namespace internal {
-template<typename DecompositionType, typename Rhs> struct solve_retval_base;
-template<typename DecompositionType, typename Rhs> struct solve_retval;
-template<typename DecompositionType> struct kernel_retval_base;
-template<typename DecompositionType> struct kernel_retval;
-template<typename DecompositionType> struct image_retval_base;
-template<typename DecompositionType> struct image_retval;
-} // end namespace internal
-
-namespace internal {
-template<typename _Scalar, int Rows=Dynamic, int Cols=Dynamic, int Supers=Dynamic, int Subs=Dynamic, int Options=0> class BandMatrix;
-}
-
-namespace internal {
-template<typename Lhs, typename Rhs> struct product_type;
-}
-
-template<typename Lhs, typename Rhs,
- int ProductType = internal::product_type<Lhs,Rhs>::value>
-struct ProductReturnType;
-
-// this is a workaround for sun CC
-template<typename Lhs, typename Rhs> struct LazyProductReturnType;
-
-namespace internal {
-
-// Provides scalar/packet-wise product and product with accumulation
-// with optional conjugation of the arguments.
-template<typename LhsScalar, typename RhsScalar, bool ConjLhs=false, bool ConjRhs=false> struct conj_helper;
-
-template<typename Scalar> struct scalar_sum_op;
-template<typename Scalar> struct scalar_difference_op;
-template<typename LhsScalar,typename RhsScalar> struct scalar_conj_product_op;
-template<typename Scalar> struct scalar_quotient_op;
-template<typename Scalar> struct scalar_opposite_op;
-template<typename Scalar> struct scalar_conjugate_op;
-template<typename Scalar> struct scalar_real_op;
-template<typename Scalar> struct scalar_imag_op;
-template<typename Scalar> struct scalar_abs_op;
-template<typename Scalar> struct scalar_abs2_op;
-template<typename Scalar> struct scalar_sqrt_op;
-template<typename Scalar> struct scalar_exp_op;
-template<typename Scalar> struct scalar_log_op;
-template<typename Scalar> struct scalar_cos_op;
-template<typename Scalar> struct scalar_sin_op;
-template<typename Scalar> struct scalar_acos_op;
-template<typename Scalar> struct scalar_asin_op;
-template<typename Scalar> struct scalar_tan_op;
-template<typename Scalar> struct scalar_pow_op;
-template<typename Scalar> struct scalar_inverse_op;
-template<typename Scalar> struct scalar_square_op;
-template<typename Scalar> struct scalar_cube_op;
-template<typename Scalar, typename NewType> struct scalar_cast_op;
-template<typename Scalar> struct scalar_multiple_op;
-template<typename Scalar> struct scalar_quotient1_op;
-template<typename Scalar> struct scalar_min_op;
-template<typename Scalar> struct scalar_max_op;
-template<typename Scalar> struct scalar_random_op;
-template<typename Scalar> struct scalar_add_op;
-template<typename Scalar> struct scalar_constant_op;
-template<typename Scalar> struct scalar_identity_op;
-
-template<typename LhsScalar,typename RhsScalar=LhsScalar> struct scalar_product_op;
-template<typename LhsScalar,typename RhsScalar> struct scalar_multiple2_op;
-
-} // end namespace internal
-
-struct IOFormat;
-
-// Array module
-template<typename _Scalar, int _Rows, int _Cols,
- int _Options = AutoAlign |
-#if defined(__GNUC__) && __GNUC__==3 && __GNUC_MINOR__==4
- // workaround a bug in at least gcc 3.4.6
- // the innermost ?: ternary operator is misparsed. We write it slightly
- // differently and this makes gcc 3.4.6 happy, but it's ugly.
- // The error would only show up with EIGEN_DEFAULT_TO_ROW_MAJOR is defined
- // (when EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION is RowMajor)
- ( (_Rows==1 && _Cols!=1) ? RowMajor
- : !(_Cols==1 && _Rows!=1) ? EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION
- : ColMajor ),
-#else
- ( (_Rows==1 && _Cols!=1) ? RowMajor
- : (_Cols==1 && _Rows!=1) ? ColMajor
- : EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ),
-#endif
- int _MaxRows = _Rows, int _MaxCols = _Cols> class Array;
-template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType> class Select;
-template<typename MatrixType, typename BinaryOp, int Direction> class PartialReduxExpr;
-template<typename ExpressionType, int Direction> class VectorwiseOp;
-template<typename MatrixType,int RowFactor,int ColFactor> class Replicate;
-template<typename MatrixType, int Direction = BothDirections> class Reverse;
-
-template<typename MatrixType> class FullPivLU;
-template<typename MatrixType> class PartialPivLU;
-namespace internal {
-template<typename MatrixType> struct inverse_impl;
-}
-template<typename MatrixType> class HouseholderQR;
-template<typename MatrixType> class ColPivHouseholderQR;
-template<typename MatrixType> class FullPivHouseholderQR;
-template<typename MatrixType, int QRPreconditioner = ColPivHouseholderQRPreconditioner> class JacobiSVD;
-template<typename MatrixType, int UpLo = Lower> class LLT;
-template<typename MatrixType, int UpLo = Lower> class LDLT;
-template<typename VectorsType, typename CoeffsType, int Side=OnTheLeft> class HouseholderSequence;
-template<typename Scalar> class JacobiRotation;
-
-// Geometry module:
-template<typename Derived, int _Dim> class RotationBase;
-template<typename Lhs, typename Rhs> class Cross;
-template<typename Derived> class QuaternionBase;
-template<typename Scalar> class Rotation2D;
-template<typename Scalar> class AngleAxis;
-template<typename Scalar,int Dim> class Translation;
-
-#ifdef EIGEN2_SUPPORT
-template<typename Derived, int _Dim> class eigen2_RotationBase;
-template<typename Lhs, typename Rhs> class eigen2_Cross;
-template<typename Scalar> class eigen2_Quaternion;
-template<typename Scalar> class eigen2_Rotation2D;
-template<typename Scalar> class eigen2_AngleAxis;
-template<typename Scalar,int Dim> class eigen2_Transform;
-template <typename _Scalar, int _AmbientDim> class eigen2_ParametrizedLine;
-template <typename _Scalar, int _AmbientDim> class eigen2_Hyperplane;
-template<typename Scalar,int Dim> class eigen2_Translation;
-template<typename Scalar,int Dim> class eigen2_Scaling;
-#endif
-
-#if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS
-template<typename Scalar> class Quaternion;
-template<typename Scalar,int Dim> class Transform;
-template <typename _Scalar, int _AmbientDim> class ParametrizedLine;
-template <typename _Scalar, int _AmbientDim> class Hyperplane;
-template<typename Scalar,int Dim> class Scaling;
-#endif
-
-#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
-template<typename Scalar, int Options = AutoAlign> class Quaternion;
-template<typename Scalar,int Dim,int Mode,int _Options=AutoAlign> class Transform;
-template <typename _Scalar, int _AmbientDim, int Options=AutoAlign> class ParametrizedLine;
-template <typename _Scalar, int _AmbientDim, int Options=AutoAlign> class Hyperplane;
-template<typename Scalar> class UniformScaling;
-template<typename MatrixType,int Direction> class Homogeneous;
-#endif
-
-// MatrixFunctions module
-template<typename Derived> struct MatrixExponentialReturnValue;
-template<typename Derived> class MatrixFunctionReturnValue;
-
-namespace internal {
-template <typename Scalar>
-struct stem_function
-{
- typedef std::complex<typename NumTraits<Scalar>::Real> ComplexScalar;
- typedef ComplexScalar type(ComplexScalar, int);
-};
-}
-
-
-#ifdef EIGEN2_SUPPORT
-template<typename ExpressionType> class Cwise;
-template<typename MatrixType> class Minor;
-template<typename MatrixType> class LU;
-template<typename MatrixType> class QR;
-template<typename MatrixType> class SVD;
-namespace internal {
-template<typename MatrixType, unsigned int Mode> struct eigen2_part_return_type;
-}
-#endif
-
-#endif // EIGEN_FORWARDDECLARATIONS_H
diff --git a/extern/Eigen3/Eigen/src/Core/util/Macros.h b/extern/Eigen3/Eigen/src/Core/util/Macros.h
deleted file mode 100644
index 6c3f1e421f0..00000000000
--- a/extern/Eigen3/Eigen/src/Core/util/Macros.h
+++ /dev/null
@@ -1,418 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_MACROS_H
-#define EIGEN_MACROS_H
-
-#define EIGEN_WORLD_VERSION 3
-#define EIGEN_MAJOR_VERSION 0
-#define EIGEN_MINOR_VERSION 2
-
-#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
- (EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
- EIGEN_MINOR_VERSION>=z))))
-#ifdef __GNUC__
- #define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__==x && __GNUC_MINOR__>=y) || __GNUC__>x)
-#else
- #define EIGEN_GNUC_AT_LEAST(x,y) 0
-#endif
-
-#ifdef __GNUC__
- #define EIGEN_GNUC_AT_MOST(x,y) ((__GNUC__==x && __GNUC_MINOR__<=y) || __GNUC__<x)
-#else
- #define EIGEN_GNUC_AT_MOST(x,y) 0
-#endif
-
-#if EIGEN_GNUC_AT_MOST(4,3)
- // see bug 89
- #define EIGEN_SAFE_TO_USE_STANDARD_ASSERT_MACRO 0
-#else
- #define EIGEN_SAFE_TO_USE_STANDARD_ASSERT_MACRO 1
-#endif
-
-#if defined(__GNUC__) && (__GNUC__ <= 3)
-#define EIGEN_GCC3_OR_OLDER 1
-#else
-#define EIGEN_GCC3_OR_OLDER 0
-#endif
-
-// 16 byte alignment is only useful for vectorization. Since it affects the ABI, we need to enable
-// 16 byte alignment on all platforms where vectorization might be enabled. In theory we could always
-// enable alignment, but it can be a cause of problems on some platforms, so we just disable it in
-// certain common platform (compiler+architecture combinations) to avoid these problems.
-// Only static alignment is really problematic (relies on nonstandard compiler extensions that don't
-// work everywhere, for example don't work on GCC/ARM), try to keep heap alignment even
-// when we have to disable static alignment.
-#if defined(__GNUC__) && !(defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__ppc__) || defined(__ia64__))
-#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_STACK_ALIGNMENT 1
-#else
-#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_STACK_ALIGNMENT 0
-#endif
-
-// static alignment is completely disabled with GCC 3, Sun Studio, and QCC/QNX
-#if !EIGEN_GCC_AND_ARCH_DOESNT_WANT_STACK_ALIGNMENT \
- && !EIGEN_GCC3_OR_OLDER \
- && !defined(__SUNPRO_CC) \
- && !defined(__QNXNTO__)
- #define EIGEN_ARCH_WANTS_STACK_ALIGNMENT 1
-#else
- #define EIGEN_ARCH_WANTS_STACK_ALIGNMENT 0
-#endif
-
-#ifdef EIGEN_DONT_ALIGN
- #ifndef EIGEN_DONT_ALIGN_STATICALLY
- #define EIGEN_DONT_ALIGN_STATICALLY
- #endif
- #define EIGEN_ALIGN 0
-#else
- #define EIGEN_ALIGN 1
-#endif
-
-// EIGEN_ALIGN_STATICALLY is the true test whether we want to align arrays on the stack or not. It takes into account both the user choice to explicitly disable
-// alignment (EIGEN_DONT_ALIGN_STATICALLY) and the architecture config (EIGEN_ARCH_WANTS_STACK_ALIGNMENT). Henceforth, only EIGEN_ALIGN_STATICALLY should be used.
-#if EIGEN_ARCH_WANTS_STACK_ALIGNMENT && !defined(EIGEN_DONT_ALIGN_STATICALLY)
- #define EIGEN_ALIGN_STATICALLY 1
-#else
- #define EIGEN_ALIGN_STATICALLY 0
- #ifndef EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
- #define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
- #endif
-#endif
-
-#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
-#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION RowMajor
-#else
-#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ColMajor
-#endif
-
-#ifndef EIGEN_DEFAULT_DENSE_INDEX_TYPE
-#define EIGEN_DEFAULT_DENSE_INDEX_TYPE std::ptrdiff_t
-#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:
- * - single precision Cwise::sin() and Cwise::cos() when SSE vectorization is enabled.
- */
-#ifndef EIGEN_FAST_MATH
-#define EIGEN_FAST_MATH 1
-#endif
-
-#define EIGEN_DEBUG_VAR(x) std::cerr << #x << " = " << x << std::endl;
-
-// concatenate two tokens
-#define EIGEN_CAT2(a,b) a ## b
-#define EIGEN_CAT(a,b) EIGEN_CAT2(a,b)
-
-// convert a token to a string
-#define EIGEN_MAKESTRING2(a) #a
-#define EIGEN_MAKESTRING(a) EIGEN_MAKESTRING2(a)
-
-// EIGEN_ALWAYS_INLINE_ATTRIB should be use in the declaration of function
-// which should be inlined even in debug mode.
-// FIXME with the always_inline attribute,
-// gcc 3.4.x reports the following compilation error:
-// Eval.h:91: sorry, unimplemented: inlining failed in call to 'const Eigen::Eval<Derived> Eigen::MatrixBase<Scalar, Derived>::eval() const'
-// : function body not available
-#if EIGEN_GNUC_AT_LEAST(4,0)
-#define EIGEN_ALWAYS_INLINE_ATTRIB __attribute__((always_inline))
-#else
-#define EIGEN_ALWAYS_INLINE_ATTRIB
-#endif
-
-#if EIGEN_GNUC_AT_LEAST(4,1) && !defined(__clang__) && !defined(__INTEL_COMPILER)
-#define EIGEN_FLATTEN_ATTRIB __attribute__((flatten))
-#else
-#define EIGEN_FLATTEN_ATTRIB
-#endif
-
-// EIGEN_FORCE_INLINE means "inline as much as possible"
-#if (defined _MSC_VER) || (defined __INTEL_COMPILER)
-#define EIGEN_STRONG_INLINE __forceinline
-#else
-#define EIGEN_STRONG_INLINE inline
-#endif
-
-#if (defined __GNUC__)
-#define EIGEN_DONT_INLINE __attribute__((noinline))
-#elif (defined _MSC_VER)
-#define EIGEN_DONT_INLINE __declspec(noinline)
-#else
-#define EIGEN_DONT_INLINE
-#endif
-
-// this macro allows to get rid of linking errors about multiply defined functions.
-// - static is not very good because it prevents definitions from different object files to be merged.
-// So static causes the resulting linked executable to be bloated with multiple copies of the same function.
-// - inline is not perfect either as it unwantedly hints the compiler toward inlining the function.
-#define EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
-#define EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS inline
-
-#ifdef NDEBUG
-# ifndef EIGEN_NO_DEBUG
-# define EIGEN_NO_DEBUG
-# endif
-#endif
-
-// eigen_plain_assert is where we implement the workaround for the assert() bug in GCC <= 4.3, see bug 89
-#ifdef EIGEN_NO_DEBUG
- #define eigen_plain_assert(x)
-#else
- #if EIGEN_SAFE_TO_USE_STANDARD_ASSERT_MACRO
- namespace Eigen {
- namespace internal {
- inline bool copy_bool(bool b) { return b; }
- }
- }
- #define eigen_plain_assert(x) assert(x)
- #else
- // work around bug 89
- #include <cstdlib> // for abort
- #include <iostream> // for std::cerr
-
- namespace Eigen {
- namespace internal {
- // trivial function copying a bool. Must be EIGEN_DONT_INLINE, so we implement it after including Eigen headers.
- // see bug 89.
- namespace {
- EIGEN_DONT_INLINE bool copy_bool(bool b) { return b; }
- }
- inline void assert_fail(const char *condition, const char *function, const char *file, int line)
- {
- std::cerr << "assertion failed: " << condition << " in function " << function << " at " << file << ":" << line << std::endl;
- abort();
- }
- }
- }
- #define eigen_plain_assert(x) \
- do { \
- if(!Eigen::internal::copy_bool(x)) \
- Eigen::internal::assert_fail(EIGEN_MAKESTRING(x), __PRETTY_FUNCTION__, __FILE__, __LINE__); \
- } while(false)
- #endif
-#endif
-
-// eigen_assert can be overridden
-#ifndef eigen_assert
-#define eigen_assert(x) eigen_plain_assert(x)
-#endif
-
-#ifdef EIGEN_INTERNAL_DEBUGGING
-#define eigen_internal_assert(x) eigen_assert(x)
-#else
-#define eigen_internal_assert(x)
-#endif
-
-#ifdef EIGEN_NO_DEBUG
-#define EIGEN_ONLY_USED_FOR_DEBUG(x) (void)x
-#else
-#define EIGEN_ONLY_USED_FOR_DEBUG(x)
-#endif
-
-#if (defined __GNUC__)
-#define EIGEN_DEPRECATED __attribute__((deprecated))
-#elif (defined _MSC_VER)
-#define EIGEN_DEPRECATED __declspec(deprecated)
-#else
-#define EIGEN_DEPRECATED
-#endif
-
-#if (defined __GNUC__)
-#define EIGEN_UNUSED __attribute__((unused))
-#else
-#define EIGEN_UNUSED
-#endif
-
-// Suppresses 'unused variable' warnings.
-#define EIGEN_UNUSED_VARIABLE(var) (void)var;
-
-#if (defined __GNUC__)
-#define EIGEN_ASM_COMMENT(X) asm("#"X)
-#else
-#define EIGEN_ASM_COMMENT(X)
-#endif
-
-/* EIGEN_ALIGN_TO_BOUNDARY(n) forces data to be n-byte aligned. This is used to satisfy SIMD requirements.
- * However, we do that EVEN if vectorization (EIGEN_VECTORIZE) is disabled,
- * so that vectorization doesn't affect binary compatibility.
- *
- * If we made alignment depend on whether or not EIGEN_VECTORIZE is defined, it would be impossible to link
- * vectorized and non-vectorized code.
- */
-#if (defined __GNUC__) || (defined __PGI) || (defined __IBMCPP__)
- #define EIGEN_ALIGN_TO_BOUNDARY(n) __attribute__((aligned(n)))
-#elif (defined _MSC_VER)
- #define EIGEN_ALIGN_TO_BOUNDARY(n) __declspec(align(n))
-#elif (defined __SUNPRO_CC)
- // FIXME not sure about this one:
- #define EIGEN_ALIGN_TO_BOUNDARY(n) __attribute__((aligned(n)))
-#else
- #error Please tell me what is the equivalent of __attribute__((aligned(n))) for your compiler
-#endif
-
-#define EIGEN_ALIGN16 EIGEN_ALIGN_TO_BOUNDARY(16)
-
-#if EIGEN_ALIGN_STATICALLY
-#define EIGEN_USER_ALIGN_TO_BOUNDARY(n) EIGEN_ALIGN_TO_BOUNDARY(n)
-#define EIGEN_USER_ALIGN16 EIGEN_ALIGN16
-#else
-#define EIGEN_USER_ALIGN_TO_BOUNDARY(n)
-#define EIGEN_USER_ALIGN16
-#endif
-
-#ifdef EIGEN_DONT_USE_RESTRICT_KEYWORD
- #define EIGEN_RESTRICT
-#endif
-#ifndef EIGEN_RESTRICT
- #define EIGEN_RESTRICT __restrict
-#endif
-
-#ifndef EIGEN_STACK_ALLOCATION_LIMIT
-#define EIGEN_STACK_ALLOCATION_LIMIT 20000
-#endif
-
-#ifndef EIGEN_DEFAULT_IO_FORMAT
-#ifdef EIGEN_MAKING_DOCS
-// format used in Eigen's documentation
-// needed to define it here as escaping characters in CMake add_definition's argument seems very problematic.
-#define EIGEN_DEFAULT_IO_FORMAT Eigen::IOFormat(3, 0, " ", "\n", "", "")
-#else
-#define EIGEN_DEFAULT_IO_FORMAT Eigen::IOFormat()
-#endif
-#endif
-
-// just an empty macro !
-#define EIGEN_EMPTY
-
-#if defined(_MSC_VER) && (!defined(__INTEL_COMPILER))
-#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
- using Base::operator =;
-#else
-#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
- using Base::operator =; \
- EIGEN_STRONG_INLINE Derived& operator=(const Derived& other) \
- { \
- Base::operator=(other); \
- return *this; \
- }
-#endif
-
-#define EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Derived) \
- EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived)
-
-/**
-* Just a side note. Commenting within defines works only by documenting
-* behind the object (via '!<'). Comments cannot be multi-line and thus
-* we have these extra long lines. What is confusing doxygen over here is
-* that we use '\' and basically have a bunch of typedefs with their
-* documentation in a single line.
-**/
-
-#define EIGEN_GENERIC_PUBLIC_INTERFACE(Derived) \
- typedef typename Eigen::internal::traits<Derived>::Scalar Scalar; /*!< \brief Numeric type, e.g. float, double, int or std::complex<float>. */ \
- typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; /*!< \brief The underlying numeric type for composed scalar types. \details In cases where Scalar is e.g. std::complex<T>, T were corresponding to RealScalar. */ \
- typedef typename Base::CoeffReturnType CoeffReturnType; /*!< \brief The return type for coefficient access. \details Depending on whether the object allows direct coefficient access (e.g. for a MatrixXd), this type is either 'const Scalar&' or simply 'Scalar' for objects that do not allow direct coefficient access. */ \
- typedef typename Eigen::internal::nested<Derived>::type Nested; \
- typedef typename Eigen::internal::traits<Derived>::StorageKind StorageKind; \
- typedef typename Eigen::internal::traits<Derived>::Index Index; \
- enum { RowsAtCompileTime = Eigen::internal::traits<Derived>::RowsAtCompileTime, \
- ColsAtCompileTime = Eigen::internal::traits<Derived>::ColsAtCompileTime, \
- Flags = Eigen::internal::traits<Derived>::Flags, \
- CoeffReadCost = Eigen::internal::traits<Derived>::CoeffReadCost, \
- SizeAtCompileTime = Base::SizeAtCompileTime, \
- MaxSizeAtCompileTime = Base::MaxSizeAtCompileTime, \
- IsVectorAtCompileTime = Base::IsVectorAtCompileTime };
-
-
-#define EIGEN_DENSE_PUBLIC_INTERFACE(Derived) \
- typedef typename Eigen::internal::traits<Derived>::Scalar Scalar; /*!< \brief Numeric type, e.g. float, double, int or std::complex<float>. */ \
- typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; /*!< \brief The underlying numeric type for composed scalar types. \details In cases where Scalar is e.g. std::complex<T>, T were corresponding to RealScalar. */ \
- typedef typename Base::PacketScalar PacketScalar; \
- typedef typename Base::CoeffReturnType CoeffReturnType; /*!< \brief The return type for coefficient access. \details Depending on whether the object allows direct coefficient access (e.g. for a MatrixXd), this type is either 'const Scalar&' or simply 'Scalar' for objects that do not allow direct coefficient access. */ \
- typedef typename Eigen::internal::nested<Derived>::type Nested; \
- typedef typename Eigen::internal::traits<Derived>::StorageKind StorageKind; \
- typedef typename Eigen::internal::traits<Derived>::Index Index; \
- enum { RowsAtCompileTime = Eigen::internal::traits<Derived>::RowsAtCompileTime, \
- ColsAtCompileTime = Eigen::internal::traits<Derived>::ColsAtCompileTime, \
- MaxRowsAtCompileTime = Eigen::internal::traits<Derived>::MaxRowsAtCompileTime, \
- MaxColsAtCompileTime = Eigen::internal::traits<Derived>::MaxColsAtCompileTime, \
- Flags = Eigen::internal::traits<Derived>::Flags, \
- CoeffReadCost = Eigen::internal::traits<Derived>::CoeffReadCost, \
- SizeAtCompileTime = Base::SizeAtCompileTime, \
- MaxSizeAtCompileTime = Base::MaxSizeAtCompileTime, \
- IsVectorAtCompileTime = Base::IsVectorAtCompileTime }; \
- using Base::derived; \
- using Base::const_cast_derived;
-
-
-#define EIGEN_PLAIN_ENUM_MIN(a,b) (((int)a <= (int)b) ? (int)a : (int)b)
-#define EIGEN_PLAIN_ENUM_MAX(a,b) (((int)a >= (int)b) ? (int)a : (int)b)
-
-// EIGEN_SIZE_MIN_PREFER_DYNAMIC gives the min between compile-time sizes. 0 has absolute priority, followed by 1,
-// followed by Dynamic, followed by other finite values. The reason for giving Dynamic the priority over
-// finite values is that min(3, Dynamic) should be Dynamic, since that could be anything between 0 and 3.
-#define EIGEN_SIZE_MIN_PREFER_DYNAMIC(a,b) (((int)a == 0 || (int)b == 0) ? 0 \
- : ((int)a == 1 || (int)b == 1) ? 1 \
- : ((int)a == Dynamic || (int)b == Dynamic) ? Dynamic \
- : ((int)a <= (int)b) ? (int)a : (int)b)
-
-// EIGEN_SIZE_MIN_PREFER_FIXED is a variant of EIGEN_SIZE_MIN_PREFER_DYNAMIC comparing MaxSizes. The difference is that finite values
-// now have priority over Dynamic, so that min(3, Dynamic) gives 3. Indeed, whatever the actual value is
-// (between 0 and 3), it is not more than 3.
-#define EIGEN_SIZE_MIN_PREFER_FIXED(a,b) (((int)a == 0 || (int)b == 0) ? 0 \
- : ((int)a == 1 || (int)b == 1) ? 1 \
- : ((int)a == Dynamic && (int)b == Dynamic) ? Dynamic \
- : ((int)a == Dynamic) ? (int)b \
- : ((int)b == Dynamic) ? (int)a \
- : ((int)a <= (int)b) ? (int)a : (int)b)
-
-// see EIGEN_SIZE_MIN_PREFER_DYNAMIC. No need for a separate variant for MaxSizes here.
-#define EIGEN_SIZE_MAX(a,b) (((int)a == Dynamic || (int)b == Dynamic) ? Dynamic \
- : ((int)a >= (int)b) ? (int)a : (int)b)
-
-#define EIGEN_LOGICAL_XOR(a,b) (((a) || (b)) && !((a) && (b)))
-
-#define EIGEN_IMPLIES(a,b) (!(a) || (b))
-
-#define EIGEN_MAKE_CWISE_BINARY_OP(METHOD,FUNCTOR) \
- template<typename OtherDerived> \
- EIGEN_STRONG_INLINE const CwiseBinaryOp<FUNCTOR<Scalar>, const Derived, const OtherDerived> \
- (METHOD)(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const \
- { \
- return CwiseBinaryOp<FUNCTOR<Scalar>, const Derived, const OtherDerived>(derived(), other.derived()); \
- }
-
-// the expression type of a cwise product
-#define EIGEN_CWISE_PRODUCT_RETURN_TYPE(LHS,RHS) \
- CwiseBinaryOp< \
- internal::scalar_product_op< \
- typename internal::traits<LHS>::Scalar, \
- typename internal::traits<RHS>::Scalar \
- >, \
- const LHS, \
- const RHS \
- >
-
-#endif // EIGEN_MACROS_H
diff --git a/extern/Eigen3/Eigen/src/Core/util/Memory.h b/extern/Eigen3/Eigen/src/Core/util/Memory.h
deleted file mode 100644
index a580b95ad0d..00000000000
--- a/extern/Eigen3/Eigen/src/Core/util/Memory.h
+++ /dev/null
@@ -1,911 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2008-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2009 Kenneth Riddile <kfriddile@yahoo.com>
-// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
-// Copyright (C) 2010 Thomas Capricelli <orzel@freehackers.org>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-
-/*****************************************************************************
-*** Platform checks for aligned malloc functions ***
-*****************************************************************************/
-
-#ifndef EIGEN_MEMORY_H
-#define EIGEN_MEMORY_H
-
-// On 64-bit systems, glibc's malloc returns 16-byte-aligned pointers, see:
-// http://www.gnu.org/s/libc/manual/html_node/Aligned-Memory-Blocks.html
-// This is true at least since glibc 2.8.
-// This leaves the question how to detect 64-bit. According to this document,
-// http://gcc.fyxm.net/summit/2003/Porting%20to%2064%20bit.pdf
-// page 114, "[The] LP64 model [...] is used by all 64-bit UNIX ports" so it's indeed
-// quite safe, at least within the context of glibc, to equate 64-bit with LP64.
-#if defined(__GLIBC__) && ((__GLIBC__>=2 && __GLIBC_MINOR__ >= 8) || __GLIBC__>2) \
- && defined(__LP64__)
- #define EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED 1
-#else
- #define EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED 0
-#endif
-
-// FreeBSD 6 seems to have 16-byte aligned malloc
-// See http://svn.freebsd.org/viewvc/base/stable/6/lib/libc/stdlib/malloc.c?view=markup
-// FreeBSD 7 seems to have 16-byte aligned malloc except on ARM and MIPS architectures
-// See http://svn.freebsd.org/viewvc/base/stable/7/lib/libc/stdlib/malloc.c?view=markup
-#if defined(__FreeBSD__) && !defined(__arm__) && !defined(__mips__)
- #define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 1
-#else
- #define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 0
-#endif
-
-#if defined(__APPLE__) \
- || defined(_WIN64) \
- || EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED \
- || EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED
- #define EIGEN_MALLOC_ALREADY_ALIGNED 1
-#else
- #define EIGEN_MALLOC_ALREADY_ALIGNED 0
-#endif
-
-#if ((defined __QNXNTO__) || (defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) \
- && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
- #define EIGEN_HAS_POSIX_MEMALIGN 1
-#else
- #define EIGEN_HAS_POSIX_MEMALIGN 0
-#endif
-
-#ifdef EIGEN_VECTORIZE_SSE
- #define EIGEN_HAS_MM_MALLOC 1
-#else
- #define EIGEN_HAS_MM_MALLOC 0
-#endif
-
-namespace internal {
-
-/*****************************************************************************
-*** Implementation of handmade aligned functions ***
-*****************************************************************************/
-
-/* ----- Hand made implementations of aligned malloc/free and realloc ----- */
-
-/** \internal Like malloc, but the returned pointer is guaranteed to be 16-byte aligned.
- * Fast, but wastes 16 additional bytes of memory. Does not throw any exception.
- */
-inline void* handmade_aligned_malloc(size_t size)
-{
- void *original = std::malloc(size+16);
- if (original == 0) return 0;
- void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
- *(reinterpret_cast<void**>(aligned) - 1) = original;
- return aligned;
-}
-
-/** \internal Frees memory allocated with handmade_aligned_malloc */
-inline void handmade_aligned_free(void *ptr)
-{
- if (ptr) std::free(*(reinterpret_cast<void**>(ptr) - 1));
-}
-
-/** \internal
- * \brief Reallocates aligned memory.
- * Since we know that our handmade version is based on std::realloc
- * we can use std::realloc to implement efficient reallocation.
- */
-inline void* handmade_aligned_realloc(void* ptr, size_t size, size_t = 0)
-{
- if (ptr == 0) return handmade_aligned_malloc(size);
- void *original = *(reinterpret_cast<void**>(ptr) - 1);
- original = std::realloc(original,size+16);
- if (original == 0) return 0;
- void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
- *(reinterpret_cast<void**>(aligned) - 1) = original;
- return aligned;
-}
-
-/*****************************************************************************
-*** Implementation of generic aligned realloc (when no realloc can be used)***
-*****************************************************************************/
-
-void* aligned_malloc(size_t size);
-void aligned_free(void *ptr);
-
-/** \internal
- * \brief Reallocates aligned memory.
- * Allows reallocation with aligned ptr types. This implementation will
- * always create a new memory chunk and copy the old data.
- */
-inline void* generic_aligned_realloc(void* ptr, size_t size, size_t old_size)
-{
- if (ptr==0)
- return aligned_malloc(size);
-
- if (size==0)
- {
- aligned_free(ptr);
- return 0;
- }
-
- void* newptr = aligned_malloc(size);
- if (newptr == 0)
- {
- #ifdef EIGEN_HAS_ERRNO
- errno = ENOMEM; // according to the standard
- #endif
- return 0;
- }
-
- if (ptr != 0)
- {
- std::memcpy(newptr, ptr, (std::min)(size,old_size));
- aligned_free(ptr);
- }
-
- return newptr;
-}
-
-/*****************************************************************************
-*** Implementation of portable aligned versions of malloc/free/realloc ***
-*****************************************************************************/
-
-#ifdef EIGEN_NO_MALLOC
-inline void check_that_malloc_is_allowed()
-{
- eigen_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
-}
-#elif defined EIGEN_RUNTIME_NO_MALLOC
-inline bool is_malloc_allowed_impl(bool update, bool new_value = false)
-{
- static bool value = true;
- if (update == 1)
- value = new_value;
- return value;
-}
-inline bool is_malloc_allowed() { return is_malloc_allowed_impl(false); }
-inline bool set_is_malloc_allowed(bool new_value) { return is_malloc_allowed_impl(true, new_value); }
-inline void check_that_malloc_is_allowed()
-{
- eigen_assert(is_malloc_allowed() && "heap allocation is forbidden (EIGEN_RUNTIME_NO_MALLOC is defined and g_is_malloc_allowed is false)");
-}
-#else
-inline void check_that_malloc_is_allowed()
-{}
-#endif
-
-/** \internal Allocates \a size bytes. The returned pointer is guaranteed to have 16 bytes alignment.
- * On allocation error, the returned pointer is null, and if exceptions are enabled then a std::bad_alloc is thrown.
- */
-inline void* aligned_malloc(size_t size)
-{
- check_that_malloc_is_allowed();
-
- void *result;
- #if !EIGEN_ALIGN
- result = std::malloc(size);
- #elif EIGEN_MALLOC_ALREADY_ALIGNED
- result = std::malloc(size);
- #elif EIGEN_HAS_POSIX_MEMALIGN
- if(posix_memalign(&result, 16, size)) result = 0;
- #elif EIGEN_HAS_MM_MALLOC
- result = _mm_malloc(size, 16);
- #elif (defined _MSC_VER)
- result = _aligned_malloc(size, 16);
- #else
- result = handmade_aligned_malloc(size);
- #endif
-
- #ifdef EIGEN_EXCEPTIONS
- if(result == 0)
- throw std::bad_alloc();
- #endif
- return result;
-}
-
-/** \internal Frees memory allocated with aligned_malloc. */
-inline void aligned_free(void *ptr)
-{
- #if !EIGEN_ALIGN
- std::free(ptr);
- #elif EIGEN_MALLOC_ALREADY_ALIGNED
- std::free(ptr);
- #elif EIGEN_HAS_POSIX_MEMALIGN
- std::free(ptr);
- #elif EIGEN_HAS_MM_MALLOC
- _mm_free(ptr);
- #elif defined(_MSC_VER)
- _aligned_free(ptr);
- #else
- handmade_aligned_free(ptr);
- #endif
-}
-
-/**
-* \internal
-* \brief Reallocates an aligned block of memory.
-* \throws std::bad_alloc if EIGEN_EXCEPTIONS are defined.
-**/
-inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size)
-{
- EIGEN_UNUSED_VARIABLE(old_size);
-
- void *result;
-#if !EIGEN_ALIGN
- result = std::realloc(ptr,new_size);
-#elif EIGEN_MALLOC_ALREADY_ALIGNED
- result = std::realloc(ptr,new_size);
-#elif EIGEN_HAS_POSIX_MEMALIGN
- result = generic_aligned_realloc(ptr,new_size,old_size);
-#elif EIGEN_HAS_MM_MALLOC
- // 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)
- result = _aligned_realloc(ptr,new_size,16);
- #else
- result = generic_aligned_realloc(ptr,new_size,old_size);
- #endif
-#elif defined(_MSC_VER)
- result = _aligned_realloc(ptr,new_size,16);
-#else
- result = handmade_aligned_realloc(ptr,new_size,old_size);
-#endif
-
-#ifdef EIGEN_EXCEPTIONS
- if (result==0 && new_size!=0)
- throw std::bad_alloc();
-#endif
- return result;
-}
-
-/*****************************************************************************
-*** Implementation of conditionally aligned functions ***
-*****************************************************************************/
-
-/** \internal Allocates \a size bytes. If Align is true, then the returned ptr is 16-byte-aligned.
- * On allocation error, the returned pointer is null, and if exceptions are enabled then a std::bad_alloc is thrown.
- */
-template<bool Align> inline void* conditional_aligned_malloc(size_t size)
-{
- return aligned_malloc(size);
-}
-
-template<> inline void* conditional_aligned_malloc<false>(size_t size)
-{
- check_that_malloc_is_allowed();
-
- void *result = std::malloc(size);
- #ifdef EIGEN_EXCEPTIONS
- if(!result) throw std::bad_alloc();
- #endif
- return result;
-}
-
-/** \internal Frees memory allocated with conditional_aligned_malloc */
-template<bool Align> inline void conditional_aligned_free(void *ptr)
-{
- aligned_free(ptr);
-}
-
-template<> inline void conditional_aligned_free<false>(void *ptr)
-{
- std::free(ptr);
-}
-
-template<bool Align> inline void* conditional_aligned_realloc(void* ptr, size_t new_size, size_t old_size)
-{
- return aligned_realloc(ptr, new_size, old_size);
-}
-
-template<> inline void* conditional_aligned_realloc<false>(void* ptr, size_t new_size, size_t)
-{
- return std::realloc(ptr, new_size);
-}
-
-/*****************************************************************************
-*** Construction/destruction of array elements ***
-*****************************************************************************/
-
-/** \internal Constructs the elements of an array.
- * The \a size parameter tells on how many objects to call the constructor of T.
- */
-template<typename T> inline T* construct_elements_of_array(T *ptr, size_t size)
-{
- for (size_t i=0; i < size; ++i) ::new (ptr + i) T;
- return ptr;
-}
-
-/** \internal Destructs the elements of an array.
- * The \a size parameters tells on how many objects to call the destructor of T.
- */
-template<typename T> inline void destruct_elements_of_array(T *ptr, size_t size)
-{
- // always destruct an array starting from the end.
- if(ptr)
- while(size) ptr[--size].~T();
-}
-
-/*****************************************************************************
-*** Implementation of aligned new/delete-like functions ***
-*****************************************************************************/
-
-/** \internal Allocates \a size objects of type T. The returned pointer is guaranteed to have 16 bytes alignment.
- * On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
- * The default constructor of T is called.
- */
-template<typename T> inline T* aligned_new(size_t size)
-{
- T *result = reinterpret_cast<T*>(aligned_malloc(sizeof(T)*size));
- return construct_elements_of_array(result, size);
-}
-
-template<typename T, bool Align> inline T* conditional_aligned_new(size_t size)
-{
- T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
- return construct_elements_of_array(result, size);
-}
-
-/** \internal Deletes objects constructed with aligned_new
- * The \a size parameters tells on how many objects to call the destructor of T.
- */
-template<typename T> inline void aligned_delete(T *ptr, size_t size)
-{
- destruct_elements_of_array<T>(ptr, size);
- aligned_free(ptr);
-}
-
-/** \internal Deletes objects constructed with conditional_aligned_new
- * The \a size parameters tells on how many objects to call the destructor of T.
- */
-template<typename T, bool Align> inline void conditional_aligned_delete(T *ptr, size_t size)
-{
- destruct_elements_of_array<T>(ptr, size);
- conditional_aligned_free<Align>(ptr);
-}
-
-template<typename T, bool Align> inline T* conditional_aligned_realloc_new(T* pts, size_t new_size, size_t old_size)
-{
- if(new_size < old_size)
- destruct_elements_of_array(pts+new_size, old_size-new_size);
- T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
- if(new_size > old_size)
- construct_elements_of_array(result+old_size, new_size-old_size);
- return result;
-}
-
-
-template<typename T, bool Align> inline T* conditional_aligned_new_auto(size_t size)
-{
- T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
- if(NumTraits<T>::RequireInitialization)
- construct_elements_of_array(result, size);
- return result;
-}
-
-template<typename T, bool Align> inline T* conditional_aligned_realloc_new_auto(T* pts, size_t new_size, size_t old_size)
-{
- if(NumTraits<T>::RequireInitialization && (new_size < old_size))
- destruct_elements_of_array(pts+new_size, old_size-new_size);
- T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
- if(NumTraits<T>::RequireInitialization && (new_size > old_size))
- construct_elements_of_array(result+old_size, new_size-old_size);
- return result;
-}
-
-template<typename T, bool Align> inline void conditional_aligned_delete_auto(T *ptr, size_t size)
-{
- if(NumTraits<T>::RequireInitialization)
- destruct_elements_of_array<T>(ptr, size);
- conditional_aligned_free<Align>(ptr);
-}
-
-/****************************************************************************/
-
-/** \internal Returns the index of the first element of the array that is well aligned for vectorization.
- *
- * \param array the address of the start of the array
- * \param size the size of the array
- *
- * \note If no element of the array is well aligned, the size of the array is returned. Typically,
- * for example with SSE, "well aligned" means 16-byte-aligned. If vectorization is disabled or if the
- * packet size for the given scalar type is 1, then everything is considered well-aligned.
- *
- * \note If the scalar type is vectorizable, we rely on the following assumptions: sizeof(Scalar) is a
- * power of 2, the packet size in bytes is also a power of 2, and is a multiple of sizeof(Scalar). On the
- * other hand, we do not assume that the array address is a multiple of sizeof(Scalar), as that fails for
- * example with Scalar=double on certain 32-bit platforms, see bug #79.
- *
- * There is also the variant first_aligned(const MatrixBase&) defined in DenseCoeffsBase.h.
- */
-template<typename Scalar, typename Index>
-inline static Index first_aligned(const Scalar* array, Index size)
-{
- typedef typename packet_traits<Scalar>::type Packet;
- enum { PacketSize = packet_traits<Scalar>::size,
- PacketAlignedMask = PacketSize-1
- };
-
- if(PacketSize==1)
- {
- // Either there is no vectorization, or a packet consists of exactly 1 scalar so that all elements
- // of the array have the same alignment.
- return 0;
- }
- else if(size_t(array) & (sizeof(Scalar)-1))
- {
- // There is vectorization for this scalar type, but the array is not aligned to the size of a single scalar.
- // Consequently, no element of the array is well aligned.
- return size;
- }
- else
- {
- return std::min<Index>( (PacketSize - (Index((size_t(array)/sizeof(Scalar))) & PacketAlignedMask))
- & PacketAlignedMask, size);
- }
-}
-
-} // end namespace internal
-
-/*****************************************************************************
-*** Implementation of runtime stack allocation (falling back to malloc) ***
-*****************************************************************************/
-
-// 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__)
- #define EIGEN_ALLOCA alloca
- #elif defined(_MSC_VER)
- #define EIGEN_ALLOCA _alloca
- #endif
-#endif
-
-namespace internal {
-
-// This helper class construct the allocated memory, and takes care of destructing and freeing the handled data
-// at destruction time. In practice this helper class is mainly useful to avoid memory leak in case of exceptions.
-template<typename T> class aligned_stack_memory_handler
-{
- public:
- /* Creates a stack_memory_handler responsible for the buffer \a ptr of size \a size.
- * Note that \a ptr can be 0 regardless of the other parameters.
- * This constructor takes care of constructing/initializing the elements of the buffer if required by the scalar type T (see NumTraits<T>::RequireInitialization).
- * In this case, the buffer elements will also be destructed when this handler will be destructed.
- * Finally, if \a dealloc is true, then the pointer \a ptr is freed.
- **/
- aligned_stack_memory_handler(T* ptr, size_t size, bool dealloc)
- : m_ptr(ptr), m_size(size), m_deallocate(dealloc)
- {
- if(NumTraits<T>::RequireInitialization && m_ptr)
- Eigen::internal::construct_elements_of_array(m_ptr, size);
- }
- ~aligned_stack_memory_handler()
- {
- if(NumTraits<T>::RequireInitialization && m_ptr)
- Eigen::internal::destruct_elements_of_array<T>(m_ptr, m_size);
- if(m_deallocate)
- Eigen::internal::aligned_free(m_ptr);
- }
- protected:
- T* m_ptr;
- size_t m_size;
- bool m_deallocate;
-};
-
-}
-
-/** \internal
- * Declares, allocates and construct an aligned buffer named NAME of SIZE elements of type TYPE on the stack
- * if SIZE is smaller than EIGEN_STACK_ALLOCATION_LIMIT, and if stack allocation is supported by the platform
- * (currently, this is Linux and Visual Studio only). Otherwise the memory is allocated on the heap.
- * The allocated buffer is automatically deleted when exiting the scope of this declaration.
- * If BUFFER is non nul, then the declared variable is simply an alias for BUFFER, and no allocation/deletion occurs.
- * Here is an example:
- * \code
- * {
- * ei_declare_aligned_stack_constructed_variable(float,data,size,0);
- * // use data[0] to data[size-1]
- * }
- * \endcode
- * The underlying stack allocation function can controlled with the EIGEN_ALLOCA preprocessor token.
- */
-#ifdef EIGEN_ALLOCA
-
- #ifdef __arm__
- #define EIGEN_ALIGNED_ALLOCA(SIZE) reinterpret_cast<void*>((reinterpret_cast<size_t>(EIGEN_ALLOCA(SIZE+16)) & ~(size_t(15))) + 16)
- #else
- #define EIGEN_ALIGNED_ALLOCA EIGEN_ALLOCA
- #endif
-
- #define ei_declare_aligned_stack_constructed_variable(TYPE,NAME,SIZE,BUFFER) \
- TYPE* NAME = (BUFFER)!=0 ? (BUFFER) \
- : reinterpret_cast<TYPE*>( \
- (sizeof(TYPE)*SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) ? EIGEN_ALIGNED_ALLOCA(sizeof(TYPE)*SIZE) \
- : Eigen::internal::aligned_malloc(sizeof(TYPE)*SIZE) ); \
- Eigen::internal::aligned_stack_memory_handler<TYPE> EIGEN_CAT(NAME,_stack_memory_destructor)((BUFFER)==0 ? NAME : 0,SIZE,sizeof(TYPE)*SIZE>EIGEN_STACK_ALLOCATION_LIMIT)
-
-#else
-
- #define ei_declare_aligned_stack_constructed_variable(TYPE,NAME,SIZE,BUFFER) \
- TYPE* NAME = (BUFFER)!=0 ? BUFFER : reinterpret_cast<TYPE*>(Eigen::internal::aligned_malloc(sizeof(TYPE)*SIZE)); \
- Eigen::internal::aligned_stack_memory_handler<TYPE> EIGEN_CAT(NAME,_stack_memory_destructor)((BUFFER)==0 ? NAME : 0,SIZE,true)
-
-#endif
-
-
-/*****************************************************************************
-*** Implementation of EIGEN_MAKE_ALIGNED_OPERATOR_NEW [_IF] ***
-*****************************************************************************/
-
-#if EIGEN_ALIGN
- #ifdef EIGEN_EXCEPTIONS
- #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
- 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) \
- void* operator new(size_t size, const std::nothrow_t&) throw() { \
- return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
- }
- #endif
-
- #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
- void *operator new(size_t size) { \
- return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
- } \
- void *operator new[](size_t size) { \
- return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
- } \
- void operator delete(void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
- void operator delete[](void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
- /* in-place new and delete. since (at least afaik) there is no actual */ \
- /* memory allocated we can safely let the default implementation handle */ \
- /* this particular case. */ \
- static void *operator new(size_t size, void *ptr) { return ::operator new(size,ptr); } \
- void operator delete(void * memory, void *ptr) throw() { return ::operator delete(memory,ptr); } \
- /* nothrow-new (returns zero instead of std::bad_alloc) */ \
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
- void operator delete(void *ptr, const std::nothrow_t&) throw() { \
- Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); \
- } \
- typedef void eigen_aligned_operator_new_marker_type;
-#else
- #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
-#endif
-
-#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(true)
-#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar,Size) \
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0))
-
-/****************************************************************************/
-
-/** \class aligned_allocator
-* \ingroup Core_Module
-*
-* \brief STL compatible allocator to use with with 16 byte aligned types
-*
-* Example:
-* \code
-* // Matrix4f requires 16 bytes alignment:
-* std::map< int, Matrix4f, std::less<int>,
-* aligned_allocator<std::pair<const int, Matrix4f> > > my_map_mat4;
-* // Vector3f does not require 16 bytes alignment, no need to use Eigen's allocator:
-* std::map< int, Vector3f > my_map_vec3;
-* \endcode
-*
-* \sa \ref TopicStlContainers.
-*/
-template<class T>
-class aligned_allocator
-{
-public:
- typedef size_t size_type;
- typedef std::ptrdiff_t difference_type;
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef T value_type;
-
- template<class U>
- struct rebind
- {
- typedef aligned_allocator<U> other;
- };
-
- pointer address( reference value ) const
- {
- return &value;
- }
-
- const_pointer address( const_reference value ) const
- {
- return &value;
- }
-
- aligned_allocator() throw()
- {
- }
-
- aligned_allocator( const aligned_allocator& ) throw()
- {
- }
-
- template<class U>
- aligned_allocator( const aligned_allocator<U>& ) throw()
- {
- }
-
- ~aligned_allocator() throw()
- {
- }
-
- size_type max_size() const throw()
- {
- return (std::numeric_limits<size_type>::max)();
- }
-
- pointer allocate( size_type num, const void* hint = 0 )
- {
- EIGEN_UNUSED_VARIABLE(hint);
- return static_cast<pointer>( internal::aligned_malloc( num * sizeof(T) ) );
- }
-
- void construct( pointer p, const T& value )
- {
- ::new( p ) T( value );
- }
-
- void destroy( pointer p )
- {
- p->~T();
- }
-
- void deallocate( pointer p, size_type /*num*/ )
- {
- internal::aligned_free( p );
- }
-
- bool operator!=(const aligned_allocator<T>& ) const
- { return false; }
-
- bool operator==(const aligned_allocator<T>& ) const
- { return true; }
-};
-
-//---------- Cache sizes ----------
-
-#if defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
-# if defined(__PIC__) && defined(__i386__)
- // Case for x86 with PIC
-# define EIGEN_CPUID(abcd,func,id) \
- __asm__ __volatile__ ("xchgl %%ebx, %%esi;cpuid; xchgl %%ebx,%%esi": "=a" (abcd[0]), "=S" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id));
-# else
- // Case for x86_64 or x86 w/o PIC
-# define EIGEN_CPUID(abcd,func,id) \
- __asm__ __volatile__ ("cpuid": "=a" (abcd[0]), "=b" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id) );
-# endif
-#elif defined(_MSC_VER)
-# if (_MSC_VER > 1500)
-# define EIGEN_CPUID(abcd,func,id) __cpuidex((int*)abcd,func,id)
-# endif
-#endif
-
-namespace internal {
-
-#ifdef EIGEN_CPUID
-
-inline bool cpuid_is_vendor(int abcd[4], const char* vendor)
-{
- return abcd[1]==((int*)(vendor))[0] && abcd[3]==((int*)(vendor))[1] && abcd[2]==((int*)(vendor))[2];
-}
-
-inline void queryCacheSizes_intel_direct(int& l1, int& l2, int& l3)
-{
- int abcd[4];
- l1 = l2 = l3 = 0;
- int cache_id = 0;
- int cache_type = 0;
- do {
- abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
- EIGEN_CPUID(abcd,0x4,cache_id);
- cache_type = (abcd[0] & 0x0F) >> 0;
- if(cache_type==1||cache_type==3) // data or unified cache
- {
- int cache_level = (abcd[0] & 0xE0) >> 5; // A[7:5]
- int ways = (abcd[1] & 0xFFC00000) >> 22; // B[31:22]
- int partitions = (abcd[1] & 0x003FF000) >> 12; // B[21:12]
- int line_size = (abcd[1] & 0x00000FFF) >> 0; // B[11:0]
- int sets = (abcd[2]); // C[31:0]
-
- int cache_size = (ways+1) * (partitions+1) * (line_size+1) * (sets+1);
-
- switch(cache_level)
- {
- case 1: l1 = cache_size; break;
- case 2: l2 = cache_size; break;
- case 3: l3 = cache_size; break;
- default: break;
- }
- }
- cache_id++;
- } while(cache_type>0 && cache_id<16);
-}
-
-inline void queryCacheSizes_intel_codes(int& l1, int& l2, int& l3)
-{
- int abcd[4];
- abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
- l1 = l2 = l3 = 0;
- EIGEN_CPUID(abcd,0x00000002,0);
- unsigned char * bytes = reinterpret_cast<unsigned char *>(abcd)+2;
- bool check_for_p2_core2 = false;
- for(int i=0; i<14; ++i)
- {
- switch(bytes[i])
- {
- case 0x0A: l1 = 8; break; // 0Ah data L1 cache, 8 KB, 2 ways, 32 byte lines
- case 0x0C: l1 = 16; break; // 0Ch data L1 cache, 16 KB, 4 ways, 32 byte lines
- case 0x0E: l1 = 24; break; // 0Eh data L1 cache, 24 KB, 6 ways, 64 byte lines
- case 0x10: l1 = 16; break; // 10h data L1 cache, 16 KB, 4 ways, 32 byte lines (IA-64)
- case 0x15: l1 = 16; break; // 15h code L1 cache, 16 KB, 4 ways, 32 byte lines (IA-64)
- case 0x2C: l1 = 32; break; // 2Ch data L1 cache, 32 KB, 8 ways, 64 byte lines
- case 0x30: l1 = 32; break; // 30h code L1 cache, 32 KB, 8 ways, 64 byte lines
- case 0x60: l1 = 16; break; // 60h data L1 cache, 16 KB, 8 ways, 64 byte lines, sectored
- case 0x66: l1 = 8; break; // 66h data L1 cache, 8 KB, 4 ways, 64 byte lines, sectored
- case 0x67: l1 = 16; break; // 67h data L1 cache, 16 KB, 4 ways, 64 byte lines, sectored
- case 0x68: l1 = 32; break; // 68h data L1 cache, 32 KB, 4 ways, 64 byte lines, sectored
- case 0x1A: l2 = 96; break; // code and data L2 cache, 96 KB, 6 ways, 64 byte lines (IA-64)
- case 0x22: l3 = 512; break; // code and data L3 cache, 512 KB, 4 ways (!), 64 byte lines, dual-sectored
- case 0x23: l3 = 1024; break; // code and data L3 cache, 1024 KB, 8 ways, 64 byte lines, dual-sectored
- case 0x25: l3 = 2048; break; // code and data L3 cache, 2048 KB, 8 ways, 64 byte lines, dual-sectored
- case 0x29: l3 = 4096; break; // code and data L3 cache, 4096 KB, 8 ways, 64 byte lines, dual-sectored
- case 0x39: l2 = 128; break; // code and data L2 cache, 128 KB, 4 ways, 64 byte lines, sectored
- case 0x3A: l2 = 192; break; // code and data L2 cache, 192 KB, 6 ways, 64 byte lines, sectored
- case 0x3B: l2 = 128; break; // code and data L2 cache, 128 KB, 2 ways, 64 byte lines, sectored
- case 0x3C: l2 = 256; break; // code and data L2 cache, 256 KB, 4 ways, 64 byte lines, sectored
- case 0x3D: l2 = 384; break; // code and data L2 cache, 384 KB, 6 ways, 64 byte lines, sectored
- case 0x3E: l2 = 512; break; // code and data L2 cache, 512 KB, 4 ways, 64 byte lines, sectored
- case 0x40: l2 = 0; break; // no integrated L2 cache (P6 core) or L3 cache (P4 core)
- case 0x41: l2 = 128; break; // code and data L2 cache, 128 KB, 4 ways, 32 byte lines
- case 0x42: l2 = 256; break; // code and data L2 cache, 256 KB, 4 ways, 32 byte lines
- case 0x43: l2 = 512; break; // code and data L2 cache, 512 KB, 4 ways, 32 byte lines
- case 0x44: l2 = 1024; break; // code and data L2 cache, 1024 KB, 4 ways, 32 byte lines
- case 0x45: l2 = 2048; break; // code and data L2 cache, 2048 KB, 4 ways, 32 byte lines
- case 0x46: l3 = 4096; break; // code and data L3 cache, 4096 KB, 4 ways, 64 byte lines
- case 0x47: l3 = 8192; break; // code and data L3 cache, 8192 KB, 8 ways, 64 byte lines
- case 0x48: l2 = 3072; break; // code and data L2 cache, 3072 KB, 12 ways, 64 byte lines
- case 0x49: if(l2!=0) l3 = 4096; else {check_for_p2_core2=true; l3 = l2 = 4096;} break;// code and data L3 cache, 4096 KB, 16 ways, 64 byte lines (P4) or L2 for core2
- case 0x4A: l3 = 6144; break; // code and data L3 cache, 6144 KB, 12 ways, 64 byte lines
- case 0x4B: l3 = 8192; break; // code and data L3 cache, 8192 KB, 16 ways, 64 byte lines
- case 0x4C: l3 = 12288; break; // code and data L3 cache, 12288 KB, 12 ways, 64 byte lines
- case 0x4D: l3 = 16384; break; // code and data L3 cache, 16384 KB, 16 ways, 64 byte lines
- case 0x4E: l2 = 6144; break; // code and data L2 cache, 6144 KB, 24 ways, 64 byte lines
- case 0x78: l2 = 1024; break; // code and data L2 cache, 1024 KB, 4 ways, 64 byte lines
- case 0x79: l2 = 128; break; // code and data L2 cache, 128 KB, 8 ways, 64 byte lines, dual-sectored
- case 0x7A: l2 = 256; break; // code and data L2 cache, 256 KB, 8 ways, 64 byte lines, dual-sectored
- case 0x7B: l2 = 512; break; // code and data L2 cache, 512 KB, 8 ways, 64 byte lines, dual-sectored
- case 0x7C: l2 = 1024; break; // code and data L2 cache, 1024 KB, 8 ways, 64 byte lines, dual-sectored
- case 0x7D: l2 = 2048; break; // code and data L2 cache, 2048 KB, 8 ways, 64 byte lines
- case 0x7E: l2 = 256; break; // code and data L2 cache, 256 KB, 8 ways, 128 byte lines, sect. (IA-64)
- case 0x7F: l2 = 512; break; // code and data L2 cache, 512 KB, 2 ways, 64 byte lines
- case 0x80: l2 = 512; break; // code and data L2 cache, 512 KB, 8 ways, 64 byte lines
- case 0x81: l2 = 128; break; // code and data L2 cache, 128 KB, 8 ways, 32 byte lines
- case 0x82: l2 = 256; break; // code and data L2 cache, 256 KB, 8 ways, 32 byte lines
- case 0x83: l2 = 512; break; // code and data L2 cache, 512 KB, 8 ways, 32 byte lines
- case 0x84: l2 = 1024; break; // code and data L2 cache, 1024 KB, 8 ways, 32 byte lines
- case 0x85: l2 = 2048; break; // code and data L2 cache, 2048 KB, 8 ways, 32 byte lines
- case 0x86: l2 = 512; break; // code and data L2 cache, 512 KB, 4 ways, 64 byte lines
- case 0x87: l2 = 1024; break; // code and data L2 cache, 1024 KB, 8 ways, 64 byte lines
- case 0x88: l3 = 2048; break; // code and data L3 cache, 2048 KB, 4 ways, 64 byte lines (IA-64)
- case 0x89: l3 = 4096; break; // code and data L3 cache, 4096 KB, 4 ways, 64 byte lines (IA-64)
- case 0x8A: l3 = 8192; break; // code and data L3 cache, 8192 KB, 4 ways, 64 byte lines (IA-64)
- case 0x8D: l3 = 3072; break; // code and data L3 cache, 3072 KB, 12 ways, 128 byte lines (IA-64)
-
- default: break;
- }
- }
- if(check_for_p2_core2 && l2 == l3)
- l3 = 0;
- l1 *= 1024;
- l2 *= 1024;
- l3 *= 1024;
-}
-
-inline void queryCacheSizes_intel(int& l1, int& l2, int& l3, int max_std_funcs)
-{
- if(max_std_funcs>=4)
- queryCacheSizes_intel_direct(l1,l2,l3);
- else
- queryCacheSizes_intel_codes(l1,l2,l3);
-}
-
-inline void queryCacheSizes_amd(int& l1, int& l2, int& l3)
-{
- int abcd[4];
- abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
- EIGEN_CPUID(abcd,0x80000005,0);
- l1 = (abcd[2] >> 24) * 1024; // C[31:24] = L1 size in KB
- abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
- EIGEN_CPUID(abcd,0x80000006,0);
- l2 = (abcd[2] >> 16) * 1024; // C[31;16] = l2 cache size in KB
- l3 = ((abcd[3] & 0xFFFC000) >> 18) * 512 * 1024; // D[31;18] = l3 cache size in 512KB
-}
-#endif
-
-/** \internal
- * Queries and returns the cache sizes in Bytes of the L1, L2, and L3 data caches respectively */
-inline void queryCacheSizes(int& l1, int& l2, int& l3)
-{
- #ifdef EIGEN_CPUID
- int abcd[4];
-
- // identify the CPU vendor
- EIGEN_CPUID(abcd,0x0,0);
- int max_std_funcs = abcd[1];
- 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!"))
- queryCacheSizes_amd(l1,l2,l3);
- else
- // by default let's use Intel's API
- queryCacheSizes_intel(l1,l2,l3,max_std_funcs);
-
- // here is the list of other vendors:
-// ||cpuid_is_vendor(abcd,"VIA VIA VIA ")
-// ||cpuid_is_vendor(abcd,"CyrixInstead")
-// ||cpuid_is_vendor(abcd,"CentaurHauls")
-// ||cpuid_is_vendor(abcd,"GenuineTMx86")
-// ||cpuid_is_vendor(abcd,"TransmetaCPU")
-// ||cpuid_is_vendor(abcd,"RiseRiseRise")
-// ||cpuid_is_vendor(abcd,"Geode by NSC")
-// ||cpuid_is_vendor(abcd,"SiS SiS SiS ")
-// ||cpuid_is_vendor(abcd,"UMC UMC UMC ")
-// ||cpuid_is_vendor(abcd,"NexGenDriven")
- #else
- l1 = l2 = l3 = -1;
- #endif
-}
-
-/** \internal
- * \returns the size in Bytes of the L1 data cache */
-inline int queryL1CacheSize()
-{
- int l1(-1), l2, l3;
- queryCacheSizes(l1,l2,l3);
- return l1;
-}
-
-/** \internal
- * \returns the size in Bytes of the L2 or L3 cache if this later is present */
-inline int queryTopLevelCacheSize()
-{
- int l1, l2(-1), l3(-1);
- queryCacheSizes(l1,l2,l3);
- return (std::max)(l2,l3);
-}
-
-} // end namespace internal
-
-#endif // EIGEN_MEMORY_H
diff --git a/extern/Eigen3/Eigen/src/Core/util/Meta.h b/extern/Eigen3/Eigen/src/Core/util/Meta.h
deleted file mode 100644
index 4518261efef..00000000000
--- a/extern/Eigen3/Eigen/src/Core/util/Meta.h
+++ /dev/null
@@ -1,229 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_META_H
-#define EIGEN_META_H
-
-namespace internal {
-
-/** \internal
- * \file Meta.h
- * This file contains generic metaprogramming classes which are not specifically related to Eigen.
- * \note In case you wonder, yes we're aware that Boost already provides all these features,
- * we however don't want to add a dependency to Boost.
- */
-
-struct true_type { enum { value = 1 }; };
-struct false_type { enum { value = 0 }; };
-
-template<bool Condition, typename Then, typename Else>
-struct conditional { typedef Then type; };
-
-template<typename Then, typename Else>
-struct conditional <false, Then, Else> { typedef Else type; };
-
-template<typename T, typename U> struct is_same { enum { value = 0 }; };
-template<typename T> struct is_same<T,T> { enum { value = 1 }; };
-
-template<typename T> struct remove_reference { typedef T type; };
-template<typename T> struct remove_reference<T&> { typedef T type; };
-
-template<typename T> struct remove_pointer { typedef T type; };
-template<typename T> struct remove_pointer<T*> { typedef T type; };
-template<typename T> struct remove_pointer<T*const> { typedef T type; };
-
-template <class T> struct remove_const { typedef T type; };
-template <class T> struct remove_const<const T> { typedef T type; };
-template <class T> struct remove_const<const T[]> { typedef T type[]; };
-template <class T, unsigned int Size> struct remove_const<const T[Size]> { typedef T type[Size]; };
-
-template<typename T> struct remove_all { typedef T type; };
-template<typename T> struct remove_all<const T> { typedef typename remove_all<T>::type type; };
-template<typename T> struct remove_all<T const&> { typedef typename remove_all<T>::type type; };
-template<typename T> struct remove_all<T&> { typedef typename remove_all<T>::type type; };
-template<typename T> struct remove_all<T const*> { typedef typename remove_all<T>::type type; };
-template<typename T> struct remove_all<T*> { typedef typename remove_all<T>::type type; };
-
-template<typename T> struct is_arithmetic { enum { value = false }; };
-template<> struct is_arithmetic<float> { enum { value = true }; };
-template<> struct is_arithmetic<double> { enum { value = true }; };
-template<> struct is_arithmetic<long double> { enum { value = true }; };
-template<> struct is_arithmetic<bool> { enum { value = true }; };
-template<> struct is_arithmetic<char> { enum { value = true }; };
-template<> struct is_arithmetic<signed char> { enum { value = true }; };
-template<> struct is_arithmetic<unsigned char> { enum { value = true }; };
-template<> struct is_arithmetic<signed short> { enum { value = true }; };
-template<> struct is_arithmetic<unsigned short>{ enum { value = true }; };
-template<> struct is_arithmetic<signed int> { enum { value = true }; };
-template<> struct is_arithmetic<unsigned int> { enum { value = true }; };
-template<> struct is_arithmetic<signed long> { enum { value = true }; };
-template<> struct is_arithmetic<unsigned long> { enum { value = true }; };
-template<> struct is_arithmetic<signed long long> { enum { value = true }; };
-template<> struct is_arithmetic<unsigned long long> { enum { value = true }; };
-
-template <typename T> struct add_const { typedef const T type; };
-template <typename T> struct add_const<T&> { typedef T& type; };
-
-template <typename T> struct is_const { enum { value = 0 }; };
-template <typename T> struct is_const<T const> { enum { value = 1 }; };
-
-template<typename T> struct add_const_on_value_type { typedef const T type; };
-template<typename T> struct add_const_on_value_type<T&> { typedef T const& type; };
-template<typename T> struct add_const_on_value_type<T*> { typedef T const* type; };
-template<typename T> struct add_const_on_value_type<T* const> { typedef T const* const type; };
-template<typename T> struct add_const_on_value_type<T const* const> { typedef T const* const type; };
-
-/** \internal Allows to enable/disable an overload
- * according to a compile time condition.
- */
-template<bool Condition, typename T> struct enable_if;
-
-template<typename T> struct enable_if<true,T>
-{ typedef T type; };
-
-/** \internal
- * Convenient struct to get the result type of a unary or binary functor.
- *
- * It supports both the current STL mechanism (using the result_type member) as well as
- * upcoming next STL generation (using a templated result member).
- * If none of these members is provided, then the type of the first argument is returned. FIXME, that behavior is a pretty bad hack.
- */
-template<typename T> struct result_of {};
-
-struct has_none {int a[1];};
-struct has_std_result_type {int a[2];};
-struct has_tr1_result {int a[3];};
-
-template<typename Func, typename ArgType, int SizeOf=sizeof(has_none)>
-struct unary_result_of_select {typedef ArgType type;};
-
-template<typename Func, typename ArgType>
-struct unary_result_of_select<Func, ArgType, sizeof(has_std_result_type)> {typedef typename Func::result_type type;};
-
-template<typename Func, typename ArgType>
-struct unary_result_of_select<Func, ArgType, sizeof(has_tr1_result)> {typedef typename Func::template result<Func(ArgType)>::type type;};
-
-template<typename Func, typename ArgType>
-struct result_of<Func(ArgType)> {
- template<typename T>
- static has_std_result_type testFunctor(T const *, typename T::result_type const * = 0);
- template<typename T>
- static has_tr1_result testFunctor(T const *, typename T::template result<T(ArgType)>::type const * = 0);
- static has_none testFunctor(...);
-
- // note that the following indirection is needed for gcc-3.3
- enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
- typedef typename unary_result_of_select<Func, ArgType, FunctorType>::type type;
-};
-
-template<typename Func, typename ArgType0, typename ArgType1, int SizeOf=sizeof(has_none)>
-struct binary_result_of_select {typedef ArgType0 type;};
-
-template<typename Func, typename ArgType0, typename ArgType1>
-struct binary_result_of_select<Func, ArgType0, ArgType1, sizeof(has_std_result_type)>
-{typedef typename Func::result_type type;};
-
-template<typename Func, typename ArgType0, typename ArgType1>
-struct binary_result_of_select<Func, ArgType0, ArgType1, sizeof(has_tr1_result)>
-{typedef typename Func::template result<Func(ArgType0,ArgType1)>::type type;};
-
-template<typename Func, typename ArgType0, typename ArgType1>
-struct result_of<Func(ArgType0,ArgType1)> {
- template<typename T>
- static has_std_result_type testFunctor(T const *, typename T::result_type const * = 0);
- template<typename T>
- static has_tr1_result testFunctor(T const *, typename T::template result<T(ArgType0,ArgType1)>::type const * = 0);
- static has_none testFunctor(...);
-
- // note that the following indirection is needed for gcc-3.3
- enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
- typedef typename binary_result_of_select<Func, ArgType0, ArgType1, FunctorType>::type type;
-};
-
-/** \internal In short, it computes int(sqrt(\a Y)) with \a Y an integer.
- * Usage example: \code meta_sqrt<1023>::ret \endcode
- */
-template<int Y,
- int InfX = 0,
- int SupX = ((Y==1) ? 1 : Y/2),
- bool Done = ((SupX-InfX)<=1 ? true : ((SupX*SupX <= Y) && ((SupX+1)*(SupX+1) > Y))) >
- // use ?: instead of || just to shut up a stupid gcc 4.3 warning
-class meta_sqrt
-{
- enum {
- MidX = (InfX+SupX)/2,
- TakeInf = MidX*MidX > Y ? 1 : 0,
- NewInf = int(TakeInf) ? InfX : int(MidX),
- NewSup = int(TakeInf) ? int(MidX) : SupX
- };
- public:
- enum { ret = meta_sqrt<Y,NewInf,NewSup>::ret };
-};
-
-template<int Y, int InfX, int SupX>
-class meta_sqrt<Y, InfX, SupX, true> { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
-
-/** \internal determines whether the product of two numeric types is allowed and what the return type is */
-template<typename T, typename U> struct scalar_product_traits;
-
-template<typename T> struct scalar_product_traits<T,T>
-{
- //enum { Cost = NumTraits<T>::MulCost };
- typedef T ReturnType;
-};
-
-template<typename T> struct scalar_product_traits<T,std::complex<T> >
-{
- //enum { Cost = 2*NumTraits<T>::MulCost };
- typedef std::complex<T> ReturnType;
-};
-
-template<typename T> struct scalar_product_traits<std::complex<T>, T>
-{
- //enum { Cost = 2*NumTraits<T>::MulCost };
- typedef std::complex<T> ReturnType;
-};
-
-// FIXME quick workaround around current limitation of result_of
-// template<typename Scalar, typename ArgType0, typename ArgType1>
-// struct result_of<scalar_product_op<Scalar>(ArgType0,ArgType1)> {
-// typedef typename scalar_product_traits<typename remove_all<ArgType0>::type, typename remove_all<ArgType1>::type>::ReturnType type;
-// };
-
-template<typename T> struct is_diagonal
-{ enum { ret = false }; };
-
-template<typename T> struct is_diagonal<DiagonalBase<T> >
-{ enum { ret = true }; };
-
-template<typename T> struct is_diagonal<DiagonalWrapper<T> >
-{ enum { ret = true }; };
-
-template<typename T, int S> struct is_diagonal<DiagonalMatrix<T,S> >
-{ enum { ret = true }; };
-
-} // end namespace internal
-
-#endif // EIGEN_META_H
diff --git a/extern/Eigen3/Eigen/src/Core/util/ReenableStupidWarnings.h b/extern/Eigen3/Eigen/src/Core/util/ReenableStupidWarnings.h
deleted file mode 100644
index 5ddfbd4aa68..00000000000
--- a/extern/Eigen3/Eigen/src/Core/util/ReenableStupidWarnings.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifdef EIGEN_WARNINGS_DISABLED
-#undef EIGEN_WARNINGS_DISABLED
-
-#ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS
- #ifdef _MSC_VER
- #pragma warning( pop )
- #elif defined __INTEL_COMPILER
- #pragma warning pop
- #elif defined __clang__
- #pragma clang diagnostic pop
- #endif
-#endif
-
-#endif // EIGEN_WARNINGS_DISABLED
diff --git a/extern/Eigen3/Eigen/src/Core/util/XprHelper.h b/extern/Eigen3/Eigen/src/Core/util/XprHelper.h
deleted file mode 100644
index 9047c5f8350..00000000000
--- a/extern/Eigen3/Eigen/src/Core/util/XprHelper.h
+++ /dev/null
@@ -1,460 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_XPRHELPER_H
-#define EIGEN_XPRHELPER_H
-
-// just a workaround because GCC seems to not really like empty structs
-// FIXME: gcc 4.3 generates bad code when strict-aliasing is enabled
-// so currently we simply disable this optimization for gcc 4.3
-#if (defined __GNUG__) && !((__GNUC__==4) && (__GNUC_MINOR__==3))
- #define EIGEN_EMPTY_STRUCT_CTOR(X) \
- EIGEN_STRONG_INLINE X() {} \
- EIGEN_STRONG_INLINE X(const X& ) {}
-#else
- #define EIGEN_EMPTY_STRUCT_CTOR(X)
-#endif
-
-typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex;
-
-namespace internal {
-
-//classes inheriting no_assignment_operator don't generate a default operator=.
-class no_assignment_operator
-{
- private:
- no_assignment_operator& operator=(const no_assignment_operator&);
-};
-
-/** \internal return the index type with the largest number of bits */
-template<typename I1, typename I2>
-struct promote_index_type
-{
- typedef typename conditional<(sizeof(I1)<sizeof(I2)), I2, I1>::type type;
-};
-
-/** \internal If the template parameter Value is Dynamic, this class is just a wrapper around a T variable that
- * can be accessed using value() and setValue().
- * Otherwise, this class is an empty structure and value() just returns the template parameter Value.
- */
-template<typename T, int Value> class variable_if_dynamic
-{
- public:
- EIGEN_EMPTY_STRUCT_CTOR(variable_if_dynamic)
- explicit variable_if_dynamic(T v) { EIGEN_ONLY_USED_FOR_DEBUG(v); assert(v == T(Value)); }
- static T value() { return T(Value); }
- void setValue(T) {}
-};
-
-template<typename T> class variable_if_dynamic<T, Dynamic>
-{
- T m_value;
- variable_if_dynamic() { assert(false); }
- public:
- explicit variable_if_dynamic(T value) : m_value(value) {}
- T value() const { return m_value; }
- void setValue(T value) { m_value = value; }
-};
-
-template<typename T> struct functor_traits
-{
- enum
- {
- Cost = 10,
- PacketAccess = false
- };
-};
-
-template<typename T> struct packet_traits;
-
-template<typename T> struct unpacket_traits
-{
- typedef T type;
- enum {size=1};
-};
-
-template<typename _Scalar, int _Rows, int _Cols,
- int _Options = AutoAlign |
- ( (_Rows==1 && _Cols!=1) ? RowMajor
- : (_Cols==1 && _Rows!=1) ? ColMajor
- : EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ),
- int _MaxRows = _Rows,
- int _MaxCols = _Cols
-> class make_proper_matrix_type
-{
- enum {
- IsColVector = _Cols==1 && _Rows!=1,
- IsRowVector = _Rows==1 && _Cols!=1,
- Options = IsColVector ? (_Options | ColMajor) & ~RowMajor
- : IsRowVector ? (_Options | RowMajor) & ~ColMajor
- : _Options
- };
- public:
- typedef Matrix<_Scalar, _Rows, _Cols, Options, _MaxRows, _MaxCols> type;
-};
-
-template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
-class compute_matrix_flags
-{
- enum {
- row_major_bit = Options&RowMajor ? RowMajorBit : 0,
- is_dynamic_size_storage = MaxRows==Dynamic || MaxCols==Dynamic,
-
- aligned_bit =
- (
- ((Options&DontAlign)==0)
- && packet_traits<Scalar>::Vectorizable
- && (
-#if EIGEN_ALIGN_STATICALLY
- ((!is_dynamic_size_storage) && (((MaxCols*MaxRows) % packet_traits<Scalar>::size) == 0))
-#else
- 0
-#endif
-
- ||
-
-#if EIGEN_ALIGN
- is_dynamic_size_storage
-#else
- 0
-#endif
-
- )
- ) ? AlignedBit : 0,
- packet_access_bit = packet_traits<Scalar>::Vectorizable && aligned_bit ? PacketAccessBit : 0
- };
-
- public:
- enum { ret = LinearAccessBit | LvalueBit | DirectAccessBit | NestByRefBit | packet_access_bit | row_major_bit | aligned_bit };
-};
-
-template<int _Rows, int _Cols> struct size_at_compile_time
-{
- enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols };
-};
-
-/* plain_matrix_type : the difference from eval is that plain_matrix_type is always a plain matrix type,
- * whereas eval is a const reference in the case of a matrix
- */
-
-template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct plain_matrix_type;
-template<typename T, typename BaseClassType> struct plain_matrix_type_dense;
-template<typename T> struct plain_matrix_type<T,Dense>
-{
- typedef typename plain_matrix_type_dense<T,typename traits<T>::XprKind>::type type;
-};
-
-template<typename T> struct plain_matrix_type_dense<T,MatrixXpr>
-{
- typedef Matrix<typename traits<T>::Scalar,
- traits<T>::RowsAtCompileTime,
- traits<T>::ColsAtCompileTime,
- AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
- traits<T>::MaxRowsAtCompileTime,
- traits<T>::MaxColsAtCompileTime
- > type;
-};
-
-template<typename T> struct plain_matrix_type_dense<T,ArrayXpr>
-{
- typedef Array<typename traits<T>::Scalar,
- traits<T>::RowsAtCompileTime,
- traits<T>::ColsAtCompileTime,
- AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
- traits<T>::MaxRowsAtCompileTime,
- traits<T>::MaxColsAtCompileTime
- > type;
-};
-
-/* eval : the return type of eval(). For matrices, this is just a const reference
- * in order to avoid a useless copy
- */
-
-template<typename T, typename StorageKind = typename traits<T>::StorageKind> struct eval;
-
-template<typename T> struct eval<T,Dense>
-{
- typedef typename plain_matrix_type<T>::type type;
-// typedef typename T::PlainObject type;
-// typedef T::Matrix<typename traits<T>::Scalar,
-// traits<T>::RowsAtCompileTime,
-// traits<T>::ColsAtCompileTime,
-// AutoAlign | (traits<T>::Flags&RowMajorBit ? RowMajor : ColMajor),
-// traits<T>::MaxRowsAtCompileTime,
-// traits<T>::MaxColsAtCompileTime
-// > type;
-};
-
-// for matrices, no need to evaluate, just use a const reference to avoid a useless copy
-template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
-struct eval<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
-{
- typedef const Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type;
-};
-
-template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
-struct eval<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>, Dense>
-{
- typedef const Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>& type;
-};
-
-
-
-/* plain_matrix_type_column_major : same as plain_matrix_type but guaranteed to be column-major
- */
-template<typename T> struct plain_matrix_type_column_major
-{
- enum { Rows = traits<T>::RowsAtCompileTime,
- Cols = traits<T>::ColsAtCompileTime,
- MaxRows = traits<T>::MaxRowsAtCompileTime,
- MaxCols = traits<T>::MaxColsAtCompileTime
- };
- typedef Matrix<typename traits<T>::Scalar,
- Rows,
- Cols,
- (MaxRows==1&&MaxCols!=1) ? RowMajor : ColMajor,
- MaxRows,
- MaxCols
- > type;
-};
-
-/* plain_matrix_type_row_major : same as plain_matrix_type but guaranteed to be row-major
- */
-template<typename T> struct plain_matrix_type_row_major
-{
- enum { Rows = traits<T>::RowsAtCompileTime,
- Cols = traits<T>::ColsAtCompileTime,
- MaxRows = traits<T>::MaxRowsAtCompileTime,
- MaxCols = traits<T>::MaxColsAtCompileTime
- };
- typedef Matrix<typename traits<T>::Scalar,
- Rows,
- Cols,
- (MaxCols==1&&MaxRows!=1) ? RowMajor : ColMajor,
- MaxRows,
- MaxCols
- > type;
-};
-
-// we should be able to get rid of this one too
-template<typename T> struct must_nest_by_value { enum { ret = false }; };
-
-template<class T>
-struct is_reference
-{
- enum { ret = false };
-};
-
-template<class T>
-struct is_reference<T&>
-{
- enum { ret = true };
-};
-
-/**
-* \internal The reference selector for template expressions. The idea is that we don't
-* need to use references for expressions since they are light weight proxy
-* objects which should generate no copying overhead.
-**/
-template <typename T>
-struct ref_selector
-{
- typedef typename conditional<
- bool(traits<T>::Flags & NestByRefBit),
- T const&,
- T
- >::type type;
-};
-
-/** \internal Determines how a given expression should be nested into another one.
- * For example, when you do a * (b+c), Eigen will determine how the expression b+c should be
- * nested into the bigger product expression. The choice is between nesting the expression b+c as-is, or
- * evaluating that expression b+c into a temporary variable d, and nest d so that the resulting expression is
- * a*d. Evaluating can be beneficial for example if every coefficient access in the resulting expression causes
- * many coefficient accesses in the nested expressions -- as is the case with matrix product for example.
- *
- * \param T the type of the expression being nested
- * \param n the number of coefficient accesses in the nested expression for each coefficient access in the bigger expression.
- *
- * Example. Suppose that a, b, and c are of type Matrix3d. The user forms the expression a*(b+c).
- * b+c is an expression "sum of matrices", which we will denote by S. In order to determine how to nest it,
- * the Product expression uses: nested<S, 3>::ret, which turns out to be Matrix3d because the internal logic of
- * nested determined that in this case it was better to evaluate the expression b+c into a temporary. On the other hand,
- * since a is of type Matrix3d, the Product expression nests it as nested<Matrix3d, 3>::ret, which turns out to be
- * const Matrix3d&, because the internal logic of nested determined that since a was already a matrix, there was no point
- * in copying it into another matrix.
- */
-template<typename T, int n=1, typename PlainObject = typename eval<T>::type> struct nested
-{
- enum {
- // for the purpose of this test, to keep it reasonably simple, we arbitrarily choose a value of Dynamic values.
- // the choice of 10000 makes it larger than any practical fixed value and even most dynamic values.
- // in extreme cases where these assumptions would be wrong, we would still at worst suffer performance issues
- // (poor choice of temporaries).
- // it's important that this value can still be squared without integer overflowing.
- DynamicAsInteger = 10000,
- ScalarReadCost = NumTraits<typename traits<T>::Scalar>::ReadCost,
- ScalarReadCostAsInteger = ScalarReadCost == Dynamic ? DynamicAsInteger : ScalarReadCost,
- CoeffReadCost = traits<T>::CoeffReadCost,
- CoeffReadCostAsInteger = CoeffReadCost == Dynamic ? DynamicAsInteger : CoeffReadCost,
- NAsInteger = n == Dynamic ? int(DynamicAsInteger) : n,
- CostEvalAsInteger = (NAsInteger+1) * ScalarReadCostAsInteger + CoeffReadCostAsInteger,
- CostNoEvalAsInteger = NAsInteger * CoeffReadCostAsInteger
- };
-
- typedef typename conditional<
- ( (int(traits<T>::Flags) & EvalBeforeNestingBit) ||
- int(CostEvalAsInteger) < int(CostNoEvalAsInteger)
- ),
- PlainObject,
- typename ref_selector<T>::type
- >::type type;
-};
-
-template<typename T>
-T* const_cast_ptr(const T* ptr)
-{
- return const_cast<T*>(ptr);
-}
-
-template<typename Derived, typename XprKind = typename traits<Derived>::XprKind>
-struct dense_xpr_base
-{
- /* dense_xpr_base should only ever be used on dense expressions, thus falling either into the MatrixXpr or into the ArrayXpr cases */
-};
-
-template<typename Derived>
-struct dense_xpr_base<Derived, MatrixXpr>
-{
- typedef MatrixBase<Derived> type;
-};
-
-template<typename Derived>
-struct dense_xpr_base<Derived, ArrayXpr>
-{
- typedef ArrayBase<Derived> type;
-};
-
-/** \internal Helper base class to add a scalar multiple operator
- * overloads for complex types */
-template<typename Derived,typename Scalar,typename OtherScalar,
- bool EnableIt = !is_same<Scalar,OtherScalar>::value >
-struct special_scalar_op_base : public DenseCoeffsBase<Derived>
-{
- // 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>
-{
- const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
- operator*(const OtherScalar& scalar) const
- {
- return CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
- (*static_cast<const Derived*>(this), scalar_multiple2_op<Scalar,OtherScalar>(scalar));
- }
-
- inline friend const CwiseUnaryOp<scalar_multiple2_op<Scalar,OtherScalar>, Derived>
- operator*(const OtherScalar& scalar, const Derived& matrix)
- { return static_cast<const special_scalar_op_base&>(matrix).operator*(scalar); }
-};
-
-template<typename XprType, typename CastType> struct cast_return_type
-{
- typedef typename XprType::Scalar CurrentScalarType;
- typedef typename remove_all<CastType>::type _CastType;
- typedef typename _CastType::Scalar NewScalarType;
- typedef typename conditional<is_same<CurrentScalarType,NewScalarType>::value,
- const XprType&,CastType>::type type;
-};
-
-template <typename A, typename B> struct promote_storage_type;
-
-template <typename A> struct promote_storage_type<A,A>
-{
- typedef A ret;
-};
-
-/** \internal gives the plain matrix or array type to store a row/column/diagonal of a matrix type.
- * \param Scalar optional parameter allowing to pass a different scalar type than the one of the MatrixType.
- */
-template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
-struct plain_row_type
-{
- typedef Matrix<Scalar, 1, ExpressionType::ColsAtCompileTime,
- ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> MatrixRowType;
- typedef Array<Scalar, 1, ExpressionType::ColsAtCompileTime,
- ExpressionType::PlainObject::Options | RowMajor, 1, ExpressionType::MaxColsAtCompileTime> ArrayRowType;
-
- typedef typename conditional<
- is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
- MatrixRowType,
- ArrayRowType
- >::type type;
-};
-
-template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
-struct plain_col_type
-{
- typedef Matrix<Scalar, ExpressionType::RowsAtCompileTime, 1,
- ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> MatrixColType;
- typedef Array<Scalar, ExpressionType::RowsAtCompileTime, 1,
- ExpressionType::PlainObject::Options & ~RowMajor, ExpressionType::MaxRowsAtCompileTime, 1> ArrayColType;
-
- typedef typename conditional<
- is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
- MatrixColType,
- ArrayColType
- >::type type;
-};
-
-template<typename ExpressionType, typename Scalar = typename ExpressionType::Scalar>
-struct plain_diag_type
-{
- enum { diag_size = EIGEN_SIZE_MIN_PREFER_DYNAMIC(ExpressionType::RowsAtCompileTime, ExpressionType::ColsAtCompileTime),
- max_diag_size = EIGEN_SIZE_MIN_PREFER_FIXED(ExpressionType::MaxRowsAtCompileTime, ExpressionType::MaxColsAtCompileTime)
- };
- typedef Matrix<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> MatrixDiagType;
- typedef Array<Scalar, diag_size, 1, ExpressionType::PlainObject::Options & ~RowMajor, max_diag_size, 1> ArrayDiagType;
-
- typedef typename conditional<
- is_same< typename traits<ExpressionType>::XprKind, MatrixXpr >::value,
- MatrixDiagType,
- ArrayDiagType
- >::type type;
-};
-
-template<typename ExpressionType>
-struct is_lvalue
-{
- enum { value = !bool(is_const<ExpressionType>::value) &&
- bool(traits<ExpressionType>::Flags & LvalueBit) };
-};
-
-} // end namespace internal
-
-#endif // EIGEN_XPRHELPER_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Block.h b/extern/Eigen3/Eigen/src/Eigen2Support/Block.h
deleted file mode 100644
index bc28051e017..00000000000
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Block.h
+++ /dev/null
@@ -1,137 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_BLOCK2_H
-#define EIGEN_BLOCK2_H
-
-/** \returns a dynamic-size expression of a corner of *this.
- *
- * \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight,
- * \a Eigen::BottomLeft, \a Eigen::BottomRight.
- * \param cRows the number of rows in the corner
- * \param cCols the number of columns in the corner
- *
- * Example: \include MatrixBase_corner_enum_int_int.cpp
- * Output: \verbinclude MatrixBase_corner_enum_int_int.out
- *
- * \note Even though the returned expression has dynamic size, in the case
- * when it is applied to a fixed-size matrix, it inherits a fixed maximal size,
- * which means that evaluating it does not cause a dynamic memory allocation.
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-template<typename Derived>
-inline Block<Derived> DenseBase<Derived>
- ::corner(CornerType type, Index cRows, Index cCols)
-{
- switch(type)
- {
- default:
- eigen_assert(false && "Bad corner type.");
- case TopLeft:
- return Block<Derived>(derived(), 0, 0, cRows, cCols);
- case TopRight:
- return Block<Derived>(derived(), 0, cols() - cCols, cRows, cCols);
- case BottomLeft:
- return Block<Derived>(derived(), rows() - cRows, 0, cRows, cCols);
- case BottomRight:
- return Block<Derived>(derived(), rows() - cRows, cols() - cCols, cRows, cCols);
- }
-}
-
-/** This is the const version of corner(CornerType, Index, Index).*/
-template<typename Derived>
-inline const Block<Derived>
-DenseBase<Derived>::corner(CornerType type, Index cRows, Index cCols) const
-{
- switch(type)
- {
- default:
- eigen_assert(false && "Bad corner type.");
- case TopLeft:
- return Block<Derived>(derived(), 0, 0, cRows, cCols);
- case TopRight:
- return Block<Derived>(derived(), 0, cols() - cCols, cRows, cCols);
- case BottomLeft:
- return Block<Derived>(derived(), rows() - cRows, 0, cRows, cCols);
- case BottomRight:
- return Block<Derived>(derived(), rows() - cRows, cols() - cCols, cRows, cCols);
- }
-}
-
-/** \returns a fixed-size expression of a corner of *this.
- *
- * \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight,
- * \a Eigen::BottomLeft, \a Eigen::BottomRight.
- *
- * The template parameters CRows and CCols arethe number of rows and columns in the corner.
- *
- * Example: \include MatrixBase_template_int_int_corner_enum.cpp
- * Output: \verbinclude MatrixBase_template_int_int_corner_enum.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-template<typename Derived>
-template<int CRows, int CCols>
-inline Block<Derived, CRows, CCols>
-DenseBase<Derived>::corner(CornerType type)
-{
- switch(type)
- {
- default:
- eigen_assert(false && "Bad corner type.");
- case TopLeft:
- return Block<Derived, CRows, CCols>(derived(), 0, 0);
- case TopRight:
- return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols);
- case BottomLeft:
- return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0);
- case BottomRight:
- return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols);
- }
-}
-
-/** This is the const version of corner<int, int>(CornerType).*/
-template<typename Derived>
-template<int CRows, int CCols>
-inline const Block<Derived, CRows, CCols>
-DenseBase<Derived>::corner(CornerType type) const
-{
- switch(type)
- {
- default:
- eigen_assert(false && "Bad corner type.");
- case TopLeft:
- return Block<Derived, CRows, CCols>(derived(), 0, 0);
- case TopRight:
- return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols);
- case BottomLeft:
- return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0);
- case BottomRight:
- return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols);
- }
-}
-
-#endif // EIGEN_BLOCK2_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h b/extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h
deleted file mode 100644
index 9c28559c329..00000000000
--- a/extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h
+++ /dev/null
@@ -1,309 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_ARRAY_CWISE_OPERATORS_H
-#define EIGEN_ARRAY_CWISE_OPERATORS_H
-
-/***************************************************************************
-* The following functions were defined in Core
-***************************************************************************/
-
-
-/** \deprecated ArrayBase::abs() */
-template<typename ExpressionType>
-EIGEN_STRONG_INLINE const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs_op)
-Cwise<ExpressionType>::abs() const
-{
- return _expression();
-}
-
-/** \deprecated ArrayBase::abs2() */
-template<typename ExpressionType>
-EIGEN_STRONG_INLINE const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs2_op)
-Cwise<ExpressionType>::abs2() const
-{
- return _expression();
-}
-
-/** \deprecated ArrayBase::exp() */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_exp_op)
-Cwise<ExpressionType>::exp() const
-{
- return _expression();
-}
-
-/** \deprecated ArrayBase::log() */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_log_op)
-Cwise<ExpressionType>::log() const
-{
- return _expression();
-}
-
-/** \deprecated ArrayBase::operator*() */
-template<typename ExpressionType>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE const EIGEN_CWISE_PRODUCT_RETURN_TYPE(ExpressionType,OtherDerived)
-Cwise<ExpressionType>::operator*(const MatrixBase<OtherDerived> &other) const
-{
- return EIGEN_CWISE_PRODUCT_RETURN_TYPE(ExpressionType,OtherDerived)(_expression(), other.derived());
-}
-
-/** \deprecated ArrayBase::operator/() */
-template<typename ExpressionType>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)
-Cwise<ExpressionType>::operator/(const MatrixBase<OtherDerived> &other) const
-{
- return EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)(_expression(), other.derived());
-}
-
-/** \deprecated ArrayBase::operator*=() */
-template<typename ExpressionType>
-template<typename OtherDerived>
-inline ExpressionType& Cwise<ExpressionType>::operator*=(const MatrixBase<OtherDerived> &other)
-{
- return m_matrix.const_cast_derived() = *this * other;
-}
-
-/** \deprecated ArrayBase::operator/=() */
-template<typename ExpressionType>
-template<typename OtherDerived>
-inline ExpressionType& Cwise<ExpressionType>::operator/=(const MatrixBase<OtherDerived> &other)
-{
- return m_matrix.const_cast_derived() = *this / other;
-}
-
-/***************************************************************************
-* The following functions were defined in Array
-***************************************************************************/
-
-// -- unary operators --
-
-/** \deprecated ArrayBase::sqrt() */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_sqrt_op)
-Cwise<ExpressionType>::sqrt() const
-{
- return _expression();
-}
-
-/** \deprecated ArrayBase::cos() */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_cos_op)
-Cwise<ExpressionType>::cos() const
-{
- return _expression();
-}
-
-
-/** \deprecated ArrayBase::sin() */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_sin_op)
-Cwise<ExpressionType>::sin() const
-{
- return _expression();
-}
-
-
-/** \deprecated ArrayBase::log() */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_pow_op)
-Cwise<ExpressionType>::pow(const Scalar& exponent) const
-{
- return EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_pow_op)(_expression(), internal::scalar_pow_op<Scalar>(exponent));
-}
-
-
-/** \deprecated ArrayBase::inverse() */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_inverse_op)
-Cwise<ExpressionType>::inverse() const
-{
- return _expression();
-}
-
-/** \deprecated ArrayBase::square() */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_square_op)
-Cwise<ExpressionType>::square() const
-{
- return _expression();
-}
-
-/** \deprecated ArrayBase::cube() */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_cube_op)
-Cwise<ExpressionType>::cube() const
-{
- return _expression();
-}
-
-
-// -- binary operators --
-
-/** \deprecated ArrayBase::operator<() */
-template<typename ExpressionType>
-template<typename OtherDerived>
-inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)
-Cwise<ExpressionType>::operator<(const MatrixBase<OtherDerived> &other) const
-{
- return EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)(_expression(), other.derived());
-}
-
-/** \deprecated ArrayBase::<=() */
-template<typename ExpressionType>
-template<typename OtherDerived>
-inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less_equal)
-Cwise<ExpressionType>::operator<=(const MatrixBase<OtherDerived> &other) const
-{
- return EIGEN_CWISE_BINOP_RETURN_TYPE(std::less_equal)(_expression(), other.derived());
-}
-
-/** \deprecated ArrayBase::operator>() */
-template<typename ExpressionType>
-template<typename OtherDerived>
-inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater)
-Cwise<ExpressionType>::operator>(const MatrixBase<OtherDerived> &other) const
-{
- return EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater)(_expression(), other.derived());
-}
-
-/** \deprecated ArrayBase::operator>=() */
-template<typename ExpressionType>
-template<typename OtherDerived>
-inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater_equal)
-Cwise<ExpressionType>::operator>=(const MatrixBase<OtherDerived> &other) const
-{
- return EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater_equal)(_expression(), other.derived());
-}
-
-/** \deprecated ArrayBase::operator==() */
-template<typename ExpressionType>
-template<typename OtherDerived>
-inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::equal_to)
-Cwise<ExpressionType>::operator==(const MatrixBase<OtherDerived> &other) const
-{
- return EIGEN_CWISE_BINOP_RETURN_TYPE(std::equal_to)(_expression(), other.derived());
-}
-
-/** \deprecated ArrayBase::operator!=() */
-template<typename ExpressionType>
-template<typename OtherDerived>
-inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::not_equal_to)
-Cwise<ExpressionType>::operator!=(const MatrixBase<OtherDerived> &other) const
-{
- return EIGEN_CWISE_BINOP_RETURN_TYPE(std::not_equal_to)(_expression(), other.derived());
-}
-
-// comparisons to scalar value
-
-/** \deprecated ArrayBase::operator<(Scalar) */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less)
-Cwise<ExpressionType>::operator<(Scalar s) const
-{
- return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less)(_expression(),
- typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
-}
-
-/** \deprecated ArrayBase::operator<=(Scalar) */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less_equal)
-Cwise<ExpressionType>::operator<=(Scalar s) const
-{
- return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less_equal)(_expression(),
- typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
-}
-
-/** \deprecated ArrayBase::operator>(Scalar) */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater)
-Cwise<ExpressionType>::operator>(Scalar s) const
-{
- return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater)(_expression(),
- typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
-}
-
-/** \deprecated ArrayBase::operator>=(Scalar) */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater_equal)
-Cwise<ExpressionType>::operator>=(Scalar s) const
-{
- return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater_equal)(_expression(),
- typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
-}
-
-/** \deprecated ArrayBase::operator==(Scalar) */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::equal_to)
-Cwise<ExpressionType>::operator==(Scalar s) const
-{
- return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::equal_to)(_expression(),
- typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
-}
-
-/** \deprecated ArrayBase::operator!=(Scalar) */
-template<typename ExpressionType>
-inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)
-Cwise<ExpressionType>::operator!=(Scalar s) const
-{
- return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)(_expression(),
- typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
-}
-
-// scalar addition
-
-/** \deprecated ArrayBase::operator+(Scalar) */
-template<typename ExpressionType>
-inline const typename Cwise<ExpressionType>::ScalarAddReturnType
-Cwise<ExpressionType>::operator+(const Scalar& scalar) const
-{
- return typename Cwise<ExpressionType>::ScalarAddReturnType(m_matrix, internal::scalar_add_op<Scalar>(scalar));
-}
-
-/** \deprecated ArrayBase::operator+=(Scalar) */
-template<typename ExpressionType>
-inline ExpressionType& Cwise<ExpressionType>::operator+=(const Scalar& scalar)
-{
- return m_matrix.const_cast_derived() = *this + scalar;
-}
-
-/** \deprecated ArrayBase::operator-(Scalar) */
-template<typename ExpressionType>
-inline const typename Cwise<ExpressionType>::ScalarAddReturnType
-Cwise<ExpressionType>::operator-(const Scalar& scalar) const
-{
- return *this + (-scalar);
-}
-
-/** \deprecated ArrayBase::operator-=(Scalar) */
-template<typename ExpressionType>
-inline ExpressionType& Cwise<ExpressionType>::operator-=(const Scalar& scalar)
-{
- return m_matrix.const_cast_derived() = *this - scalar;
-}
-
-#endif // EIGEN_ARRAY_CWISE_OPERATORS_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/All.h b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/All.h
deleted file mode 100644
index 9d8244b07a0..00000000000
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/All.h
+++ /dev/null
@@ -1,115 +0,0 @@
-#ifndef EIGEN2_GEOMETRY_MODULE_H
-#define EIGEN2_GEOMETRY_MODULE_H
-
-#include <limits>
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-#if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS
-#include "RotationBase.h"
-#include "Rotation2D.h"
-#include "Quaternion.h"
-#include "AngleAxis.h"
-#include "Transform.h"
-#include "Translation.h"
-#include "Scaling.h"
-#include "AlignedBox.h"
-#include "Hyperplane.h"
-#include "ParametrizedLine.h"
-#endif
-
-
-#define RotationBase eigen2_RotationBase
-#define Rotation2D eigen2_Rotation2D
-#define Rotation2Df eigen2_Rotation2Df
-#define Rotation2Dd eigen2_Rotation2Dd
-
-#define Quaternion eigen2_Quaternion
-#define Quaternionf eigen2_Quaternionf
-#define Quaterniond eigen2_Quaterniond
-
-#define AngleAxis eigen2_AngleAxis
-#define AngleAxisf eigen2_AngleAxisf
-#define AngleAxisd eigen2_AngleAxisd
-
-#define Transform eigen2_Transform
-#define Transform2f eigen2_Transform2f
-#define Transform2d eigen2_Transform2d
-#define Transform3f eigen2_Transform3f
-#define Transform3d eigen2_Transform3d
-
-#define Translation eigen2_Translation
-#define Translation2f eigen2_Translation2f
-#define Translation2d eigen2_Translation2d
-#define Translation3f eigen2_Translation3f
-#define Translation3d eigen2_Translation3d
-
-#define Scaling eigen2_Scaling
-#define Scaling2f eigen2_Scaling2f
-#define Scaling2d eigen2_Scaling2d
-#define Scaling3f eigen2_Scaling3f
-#define Scaling3d eigen2_Scaling3d
-
-#define AlignedBox eigen2_AlignedBox
-
-#define Hyperplane eigen2_Hyperplane
-#define ParametrizedLine eigen2_ParametrizedLine
-
-#define ei_toRotationMatrix eigen2_ei_toRotationMatrix
-#define ei_quaternion_assign_impl eigen2_ei_quaternion_assign_impl
-#define ei_transform_product_impl eigen2_ei_transform_product_impl
-
-#include "RotationBase.h"
-#include "Rotation2D.h"
-#include "Quaternion.h"
-#include "AngleAxis.h"
-#include "Transform.h"
-#include "Translation.h"
-#include "Scaling.h"
-#include "AlignedBox.h"
-#include "Hyperplane.h"
-#include "ParametrizedLine.h"
-
-#undef ei_toRotationMatrix
-#undef ei_quaternion_assign_impl
-#undef ei_transform_product_impl
-
-#undef RotationBase
-#undef Rotation2D
-#undef Rotation2Df
-#undef Rotation2Dd
-
-#undef Quaternion
-#undef Quaternionf
-#undef Quaterniond
-
-#undef AngleAxis
-#undef AngleAxisf
-#undef AngleAxisd
-
-#undef Transform
-#undef Transform2f
-#undef Transform2d
-#undef Transform3f
-#undef Transform3d
-
-#undef Translation
-#undef Translation2f
-#undef Translation2d
-#undef Translation3f
-#undef Translation3d
-
-#undef Scaling
-#undef Scaling2f
-#undef Scaling2d
-#undef Scaling3f
-#undef Scaling3d
-
-#undef AlignedBox
-
-#undef Hyperplane
-#undef ParametrizedLine
-
-#endif // EIGEN2_GEOMETRY_MODULE_H \ No newline at end of file
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/LU.h b/extern/Eigen3/Eigen/src/Eigen2Support/LU.h
deleted file mode 100644
index c23c11baa72..00000000000
--- a/extern/Eigen3/Eigen/src/Eigen2Support/LU.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN2_LU_H
-#define EIGEN2_LU_H
-
-template<typename MatrixType>
-class LU : public FullPivLU<MatrixType>
-{
- public:
-
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
- typedef Matrix<int, 1, MatrixType::ColsAtCompileTime, MatrixType::Options, 1, MatrixType::MaxColsAtCompileTime> IntRowVectorType;
- typedef Matrix<int, MatrixType::RowsAtCompileTime, 1, MatrixType::Options, MatrixType::MaxRowsAtCompileTime, 1> IntColVectorType;
- typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime, MatrixType::Options, 1, MatrixType::MaxColsAtCompileTime> RowVectorType;
- typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1, MatrixType::Options, MatrixType::MaxRowsAtCompileTime, 1> ColVectorType;
-
- typedef Matrix<typename MatrixType::Scalar,
- MatrixType::ColsAtCompileTime, // the number of rows in the "kernel matrix" is the number of cols of the original matrix
- // so that the product "matrix * kernel = zero" makes sense
- Dynamic, // we don't know at compile-time the dimension of the kernel
- MatrixType::Options,
- MatrixType::MaxColsAtCompileTime, // see explanation for 2nd template parameter
- MatrixType::MaxColsAtCompileTime // the kernel is a subspace of the domain space, whose dimension is the number
- // of columns of the original matrix
- > KernelResultType;
-
- typedef Matrix<typename MatrixType::Scalar,
- MatrixType::RowsAtCompileTime, // the image is a subspace of the destination space, whose dimension is the number
- // of rows of the original matrix
- Dynamic, // we don't know at compile time the dimension of the image (the rank)
- MatrixType::Options,
- MatrixType::MaxRowsAtCompileTime, // the image matrix will consist of columns from the original matrix,
- MatrixType::MaxColsAtCompileTime // so it has the same number of rows and at most as many columns.
- > ImageResultType;
-
- typedef FullPivLU<MatrixType> Base;
- LU() : Base() {}
-
- template<typename T>
- explicit LU(const T& t) : Base(t), m_originalMatrix(t) {}
-
- template<typename OtherDerived, typename ResultType>
- bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
- {
- *result = static_cast<const Base*>(this)->solve(b);
- return true;
- }
-
- template<typename ResultType>
- inline void computeInverse(ResultType *result) const
- {
- solve(MatrixType::Identity(this->rows(), this->cols()), result);
- }
-
- template<typename KernelMatrixType>
- void computeKernel(KernelMatrixType *result) const
- {
- *result = static_cast<const Base*>(this)->kernel();
- }
-
- template<typename ImageMatrixType>
- void computeImage(ImageMatrixType *result) const
- {
- *result = static_cast<const Base*>(this)->image(m_originalMatrix);
- }
-
- const ImageResultType image() const
- {
- return static_cast<const Base*>(this)->image(m_originalMatrix);
- }
-
- const MatrixType& m_originalMatrix;
-};
-
-#if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS
-/** \lu_module
- *
- * Synonym of partialPivLu().
- *
- * \return the partial-pivoting LU decomposition of \c *this.
- *
- * \sa class PartialPivLU
- */
-template<typename Derived>
-inline const LU<typename MatrixBase<Derived>::PlainObject>
-MatrixBase<Derived>::lu() const
-{
- return LU<PlainObject>(eval());
-}
-#endif
-
-#ifdef EIGEN2_SUPPORT
-/** \lu_module
- *
- * Synonym of partialPivLu().
- *
- * \return the partial-pivoting LU decomposition of \c *this.
- *
- * \sa class PartialPivLU
- */
-template<typename Derived>
-inline const LU<typename MatrixBase<Derived>::PlainObject>
-MatrixBase<Derived>::eigen2_lu() const
-{
- return LU<PlainObject>(eval());
-}
-#endif
-
-
-#endif // EIGEN2_LU_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h b/extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h
deleted file mode 100644
index c4288ede2ef..00000000000
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_LAZY_H
-#define EIGEN_LAZY_H
-
-/** \deprecated it is only used by lazy() which is deprecated
- *
- * \returns an expression of *this with added flags
- *
- * Example: \include MatrixBase_marked.cpp
- * Output: \verbinclude MatrixBase_marked.out
- *
- * \sa class Flagged, extract(), part()
- */
-template<typename Derived>
-template<unsigned int Added>
-inline const Flagged<Derived, Added, 0>
-MatrixBase<Derived>::marked() const
-{
- return derived();
-}
-
-/** \deprecated use MatrixBase::noalias()
- *
- * \returns an expression of *this with the EvalBeforeAssigningBit flag removed.
- *
- * Example: \include MatrixBase_lazy.cpp
- * Output: \verbinclude MatrixBase_lazy.out
- *
- * \sa class Flagged, marked()
- */
-template<typename Derived>
-inline const Flagged<Derived, 0, EvalBeforeAssigningBit>
-MatrixBase<Derived>::lazy() const
-{
- return derived();
-}
-
-
-/** \internal
- * Overloaded to perform an efficient C += (A*B).lazy() */
-template<typename Derived>
-template<typename ProductDerived, typename Lhs, typename Rhs>
-Derived& MatrixBase<Derived>::operator+=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0,
- EvalBeforeAssigningBit>& other)
-{
- other._expression().derived().addTo(derived()); return derived();
-}
-
-/** \internal
- * Overloaded to perform an efficient C -= (A*B).lazy() */
-template<typename Derived>
-template<typename ProductDerived, typename Lhs, typename Rhs>
-Derived& MatrixBase<Derived>::operator-=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0,
- EvalBeforeAssigningBit>& other)
-{
- other._expression().derived().subTo(derived()); return derived();
-}
-
-#endif // EIGEN_LAZY_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h b/extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h
deleted file mode 100644
index caa44e63f32..00000000000
--- a/extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN2_MATH_FUNCTIONS_H
-#define EIGEN2_MATH_FUNCTIONS_H
-
-template<typename T> inline typename NumTraits<T>::Real ei_real(const T& x) { return internal::real(x); }
-template<typename T> inline typename NumTraits<T>::Real ei_imag(const T& x) { return internal::imag(x); }
-template<typename T> inline T ei_conj(const T& x) { return internal::conj(x); }
-template<typename T> inline typename NumTraits<T>::Real ei_abs (const T& x) { return internal::abs(x); }
-template<typename T> inline typename NumTraits<T>::Real ei_abs2(const T& x) { return internal::abs2(x); }
-template<typename T> inline T ei_sqrt(const T& x) { return internal::sqrt(x); }
-template<typename T> inline T ei_exp (const T& x) { return internal::exp(x); }
-template<typename T> inline T ei_log (const T& x) { return internal::log(x); }
-template<typename T> inline T ei_sin (const T& x) { return internal::sin(x); }
-template<typename T> inline T ei_cos (const T& x) { return internal::cos(x); }
-template<typename T> inline T ei_atan2(const T& x,const T& y) { return internal::atan2(x,y); }
-template<typename T> inline T ei_pow (const T& x,const T& y) { return internal::pow(x,y); }
-template<typename T> inline T ei_random () { return internal::random<T>(); }
-template<typename T> inline T ei_random (const T& x, const T& y) { return internal::random(x, y); }
-
-template<typename T> inline T precision () { return NumTraits<T>::dummy_precision(); }
-template<typename T> inline T machine_epsilon () { return NumTraits<T>::epsilon(); }
-
-
-template<typename Scalar, typename OtherScalar>
-inline bool ei_isMuchSmallerThan(const Scalar& x, const OtherScalar& y,
- typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
-{
- return internal::isMuchSmallerThan(x, y, precision);
-}
-
-template<typename Scalar>
-inline bool ei_isApprox(const Scalar& x, const Scalar& y,
- typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
-{
- return internal::isApprox(x, y, precision);
-}
-
-template<typename Scalar>
-inline bool ei_isApproxOrLessThan(const Scalar& x, const Scalar& y,
- typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
-{
- return internal::isApproxOrLessThan(x, y, precision);
-}
-
-#endif // EIGEN2_MATH_FUNCTIONS_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Memory.h b/extern/Eigen3/Eigen/src/Eigen2Support/Memory.h
deleted file mode 100644
index 0283475419e..00000000000
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Memory.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN2_MEMORY_H
-#define EIGEN2_MEMORY_H
-
-inline void* ei_aligned_malloc(size_t size) { return internal::aligned_malloc(size); }
-inline void ei_aligned_free(void *ptr) { internal::aligned_free(ptr); }
-inline void* ei_aligned_realloc(void *ptr, size_t new_size, size_t old_size) { return internal::aligned_realloc(ptr, new_size, old_size); }
-inline void* ei_handmade_aligned_malloc(size_t size) { return internal::handmade_aligned_malloc(size); }
-inline void ei_handmade_aligned_free(void *ptr) { internal::handmade_aligned_free(ptr); }
-
-template<bool Align> inline void* ei_conditional_aligned_malloc(size_t size)
-{
- return internal::conditional_aligned_malloc<Align>(size);
-}
-template<bool Align> inline void ei_conditional_aligned_free(void *ptr)
-{
- internal::conditional_aligned_free<Align>(ptr);
-}
-template<bool Align> inline void* ei_conditional_aligned_realloc(void* ptr, size_t new_size, size_t old_size)
-{
- return internal::conditional_aligned_realloc<Align>(ptr, new_size, old_size);
-}
-
-template<typename T> inline T* ei_aligned_new(size_t size)
-{
- return internal::aligned_new<T>(size);
-}
-template<typename T> inline void ei_aligned_delete(T *ptr, size_t size)
-{
- return internal::aligned_delete(ptr, size);
-}
-
-
-
-#endif // EIGEN2_MACROS_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Meta.h b/extern/Eigen3/Eigen/src/Eigen2Support/Meta.h
deleted file mode 100644
index 6e500b79a2e..00000000000
--- a/extern/Eigen3/Eigen/src/Eigen2Support/Meta.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN2_META_H
-#define EIGEN2_META_H
-
-template<typename T>
-struct ei_traits : internal::traits<T>
-{};
-
-struct ei_meta_true { enum { ret = 1 }; };
-struct ei_meta_false { enum { ret = 0 }; };
-
-template<bool Condition, typename Then, typename Else>
-struct ei_meta_if { typedef Then ret; };
-
-template<typename Then, typename Else>
-struct ei_meta_if <false, Then, Else> { typedef Else ret; };
-
-template<typename T, typename U> struct ei_is_same_type { enum { ret = 0 }; };
-template<typename T> struct ei_is_same_type<T,T> { enum { ret = 1 }; };
-
-template<typename T> struct ei_unref { typedef T type; };
-template<typename T> struct ei_unref<T&> { typedef T type; };
-
-template<typename T> struct ei_unpointer { typedef T type; };
-template<typename T> struct ei_unpointer<T*> { typedef T type; };
-template<typename T> struct ei_unpointer<T*const> { typedef T type; };
-
-template<typename T> struct ei_unconst { typedef T type; };
-template<typename T> struct ei_unconst<const T> { typedef T type; };
-template<typename T> struct ei_unconst<T const &> { typedef T & type; };
-template<typename T> struct ei_unconst<T const *> { typedef T * type; };
-
-template<typename T> struct ei_cleantype { typedef T type; };
-template<typename T> struct ei_cleantype<const T> { typedef typename ei_cleantype<T>::type type; };
-template<typename T> struct ei_cleantype<const T&> { typedef typename ei_cleantype<T>::type type; };
-template<typename T> struct ei_cleantype<T&> { typedef typename ei_cleantype<T>::type type; };
-template<typename T> struct ei_cleantype<const T*> { typedef typename ei_cleantype<T>::type type; };
-template<typename T> struct ei_cleantype<T*> { typedef typename ei_cleantype<T>::type type; };
-
-/** \internal In short, it computes int(sqrt(\a Y)) with \a Y an integer.
- * Usage example: \code ei_meta_sqrt<1023>::ret \endcode
- */
-template<int Y,
- int InfX = 0,
- int SupX = ((Y==1) ? 1 : Y/2),
- bool Done = ((SupX-InfX)<=1 ? true : ((SupX*SupX <= Y) && ((SupX+1)*(SupX+1) > Y))) >
- // use ?: instead of || just to shut up a stupid gcc 4.3 warning
-class ei_meta_sqrt
-{
- enum {
- MidX = (InfX+SupX)/2,
- TakeInf = MidX*MidX > Y ? 1 : 0,
- NewInf = int(TakeInf) ? InfX : int(MidX),
- NewSup = int(TakeInf) ? int(MidX) : SupX
- };
- public:
- enum { ret = ei_meta_sqrt<Y,NewInf,NewSup>::ret };
-};
-
-template<int Y, int InfX, int SupX>
-class ei_meta_sqrt<Y, InfX, SupX, true> { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
-
-#endif // EIGEN2_META_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/QR.h b/extern/Eigen3/Eigen/src/Eigen2Support/QR.h
deleted file mode 100644
index 64f5d5ccb30..00000000000
--- a/extern/Eigen3/Eigen/src/Eigen2Support/QR.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
-// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN2_QR_H
-#define EIGEN2_QR_H
-
-template<typename MatrixType>
-class QR : public HouseholderQR<MatrixType>
-{
- public:
-
- typedef HouseholderQR<MatrixType> Base;
- typedef Block<const MatrixType, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> MatrixRBlockType;
-
- QR() : Base() {}
-
- template<typename T>
- explicit QR(const T& t) : Base(t) {}
-
- template<typename OtherDerived, typename ResultType>
- bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
- {
- *result = static_cast<const Base*>(this)->solve(b);
- return true;
- }
-
- MatrixType matrixQ(void) const {
- MatrixType ret = MatrixType::Identity(this->rows(), this->cols());
- ret = this->householderQ() * ret;
- return ret;
- }
-
- bool isFullRank() const {
- return true;
- }
-
- const TriangularView<MatrixRBlockType, UpperTriangular>
- matrixR(void) const
- {
- int cols = this->cols();
- return MatrixRBlockType(this->matrixQR(), 0, 0, cols, cols).template triangularView<UpperTriangular>();
- }
-};
-
-/** \return the QR decomposition of \c *this.
- *
- * \sa class QR
- */
-template<typename Derived>
-const QR<typename MatrixBase<Derived>::PlainObject>
-MatrixBase<Derived>::qr() const
-{
- return QR<PlainObject>(eval());
-}
-
-
-#endif // EIGEN2_QR_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h b/extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h
deleted file mode 100644
index e94e47a5093..00000000000
--- a/extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_TRIANGULAR_SOLVER2_H
-#define EIGEN_TRIANGULAR_SOLVER2_H
-
-const unsigned int UnitDiagBit = UnitDiag;
-const unsigned int SelfAdjointBit = SelfAdjoint;
-const unsigned int UpperTriangularBit = Upper;
-const unsigned int LowerTriangularBit = Lower;
-
-const unsigned int UpperTriangular = Upper;
-const unsigned int LowerTriangular = Lower;
-const unsigned int UnitUpperTriangular = UnitUpper;
-const unsigned int UnitLowerTriangular = UnitLower;
-
-template<typename ExpressionType, unsigned int Added, unsigned int Removed>
-template<typename OtherDerived>
-typename ExpressionType::PlainObject
-Flagged<ExpressionType,Added,Removed>::solveTriangular(const MatrixBase<OtherDerived>& other) const
-{
- return m_matrix.template triangularView<Added>().solve(other.derived());
-}
-
-template<typename ExpressionType, unsigned int Added, unsigned int Removed>
-template<typename OtherDerived>
-void Flagged<ExpressionType,Added,Removed>::solveTriangularInPlace(const MatrixBase<OtherDerived>& other) const
-{
- m_matrix.template triangularView<Added>().solveInPlace(other.derived());
-}
-
-#endif // EIGEN_TRIANGULAR_SOLVER2_H
diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h b/extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h
deleted file mode 100644
index 010031d1971..00000000000
--- a/extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN2_VECTORBLOCK_H
-#define EIGEN2_VECTORBLOCK_H
-
-/** \deprecated use DenseMase::head(Index) */
-template<typename Derived>
-inline VectorBlock<Derived>
-MatrixBase<Derived>::start(Index size)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return VectorBlock<Derived>(derived(), 0, size);
-}
-
-/** \deprecated use DenseMase::head(Index) */
-template<typename Derived>
-inline const VectorBlock<const Derived>
-MatrixBase<Derived>::start(Index size) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return VectorBlock<const Derived>(derived(), 0, size);
-}
-
-/** \deprecated use DenseMase::tail(Index) */
-template<typename Derived>
-inline VectorBlock<Derived>
-MatrixBase<Derived>::end(Index size)
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return VectorBlock<Derived>(derived(), this->size() - size, size);
-}
-
-/** \deprecated use DenseMase::tail(Index) */
-template<typename Derived>
-inline const VectorBlock<const Derived>
-MatrixBase<Derived>::end(Index size) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return VectorBlock<const Derived>(derived(), this->size() - size, size);
-}
-
-/** \deprecated use DenseMase::head() */
-template<typename Derived>
-template<int Size>
-inline VectorBlock<Derived,Size>
-MatrixBase<Derived>::start()
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return VectorBlock<Derived,Size>(derived(), 0);
-}
-
-/** \deprecated use DenseMase::head() */
-template<typename Derived>
-template<int Size>
-inline const VectorBlock<const Derived,Size>
-MatrixBase<Derived>::start() const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return VectorBlock<const Derived,Size>(derived(), 0);
-}
-
-/** \deprecated use DenseMase::tail() */
-template<typename Derived>
-template<int Size>
-inline VectorBlock<Derived,Size>
-MatrixBase<Derived>::end()
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return VectorBlock<Derived, Size>(derived(), size() - Size);
-}
-
-/** \deprecated use DenseMase::tail() */
-template<typename Derived>
-template<int Size>
-inline const VectorBlock<const Derived,Size>
-MatrixBase<Derived>::end() const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return VectorBlock<const Derived, Size>(derived(), size() - Size);
-}
-
-#endif // EIGEN2_VECTORBLOCK_H
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h b/extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h
deleted file mode 100644
index 57e00227d72..00000000000
--- a/extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h
+++ /dev/null
@@ -1,332 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Claire Maurice
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_COMPLEX_EIGEN_SOLVER_H
-#define EIGEN_COMPLEX_EIGEN_SOLVER_H
-
-#include "./EigenvaluesCommon.h"
-#include "./ComplexSchur.h"
-
-/** \eigenvalues_module \ingroup Eigenvalues_Module
- *
- *
- * \class ComplexEigenSolver
- *
- * \brief Computes eigenvalues and eigenvectors of general complex matrices
- *
- * \tparam _MatrixType the type of the matrix of which we are
- * computing the eigendecomposition; this is expected to be an
- * instantiation of the Matrix class template.
- *
- * The eigenvalues and eigenvectors of a matrix \f$ A \f$ are scalars
- * \f$ \lambda \f$ and vectors \f$ v \f$ such that \f$ Av = \lambda v
- * \f$. If \f$ D \f$ is a diagonal matrix with the eigenvalues on
- * the diagonal, and \f$ V \f$ is a matrix with the eigenvectors as
- * its columns, then \f$ A V = V D \f$. The matrix \f$ V \f$ is
- * almost always invertible, in which case we have \f$ A = V D V^{-1}
- * \f$. This is called the eigendecomposition.
- *
- * The main function in this class is compute(), which computes the
- * eigenvalues and eigenvectors of a given function. The
- * documentation for that function contains an example showing the
- * main features of the class.
- *
- * \sa class EigenSolver, class SelfAdjointEigenSolver
- */
-template<typename _MatrixType> class ComplexEigenSolver
-{
- public:
-
- /** \brief Synonym for the template parameter \p _MatrixType. */
- typedef _MatrixType MatrixType;
-
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- Options = MatrixType::Options,
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
- };
-
- /** \brief Scalar type for matrices of type #MatrixType. */
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef typename MatrixType::Index Index;
-
- /** \brief Complex scalar type for #MatrixType.
- *
- * This is \c std::complex<Scalar> if #Scalar is real (e.g.,
- * \c float or \c double) and just \c Scalar if #Scalar is
- * complex.
- */
- typedef std::complex<RealScalar> ComplexScalar;
-
- /** \brief Type for vector of eigenvalues as returned by eigenvalues().
- *
- * This is a column vector with entries of type #ComplexScalar.
- * The length of the vector is the size of #MatrixType.
- */
- typedef Matrix<ComplexScalar, ColsAtCompileTime, 1, Options&(~RowMajor), MaxColsAtCompileTime, 1> EigenvalueType;
-
- /** \brief Type for matrix of eigenvectors as returned by eigenvectors().
- *
- * This is a square matrix with entries of type #ComplexScalar.
- * The size is the same as the size of #MatrixType.
- */
- typedef Matrix<ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime> EigenvectorType;
-
- /** \brief Default constructor.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via compute().
- */
- ComplexEigenSolver()
- : m_eivec(),
- m_eivalues(),
- m_schur(),
- m_isInitialized(false),
- m_eigenvectorsOk(false),
- m_matX()
- {}
-
- /** \brief Default Constructor with memory preallocation
- *
- * Like the default constructor but with preallocation of the internal data
- * according to the specified problem \a size.
- * \sa ComplexEigenSolver()
- */
- ComplexEigenSolver(Index size)
- : m_eivec(size, size),
- m_eivalues(size),
- m_schur(size),
- m_isInitialized(false),
- m_eigenvectorsOk(false),
- m_matX(size, size)
- {}
-
- /** \brief Constructor; computes eigendecomposition of given matrix.
- *
- * \param[in] matrix Square matrix whose eigendecomposition is to be computed.
- * \param[in] computeEigenvectors If true, both the eigenvectors and the
- * eigenvalues are computed; if false, only the eigenvalues are
- * computed.
- *
- * This constructor calls compute() to compute the eigendecomposition.
- */
- ComplexEigenSolver(const MatrixType& matrix, bool computeEigenvectors = true)
- : m_eivec(matrix.rows(),matrix.cols()),
- m_eivalues(matrix.cols()),
- m_schur(matrix.rows()),
- m_isInitialized(false),
- m_eigenvectorsOk(false),
- m_matX(matrix.rows(),matrix.cols())
- {
- compute(matrix, computeEigenvectors);
- }
-
- /** \brief Returns the eigenvectors of given matrix.
- *
- * \returns A const reference to the matrix whose columns are the eigenvectors.
- *
- * \pre Either the constructor
- * ComplexEigenSolver(const MatrixType& matrix, bool) or the member
- * function compute(const MatrixType& matrix, bool) has been called before
- * to compute the eigendecomposition of a matrix, and
- * \p computeEigenvectors was set to true (the default).
- *
- * This function returns a matrix whose columns are the eigenvectors. Column
- * \f$ k \f$ is an eigenvector corresponding to eigenvalue number \f$ k
- * \f$ as returned by eigenvalues(). The eigenvectors are normalized to
- * have (Euclidean) norm equal to one. The matrix returned by this
- * function is the matrix \f$ V \f$ in the eigendecomposition \f$ A = V D
- * V^{-1} \f$, if it exists.
- *
- * Example: \include ComplexEigenSolver_eigenvectors.cpp
- * Output: \verbinclude ComplexEigenSolver_eigenvectors.out
- */
- const EigenvectorType& eigenvectors() const
- {
- eigen_assert(m_isInitialized && "ComplexEigenSolver is not initialized.");
- eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
- return m_eivec;
- }
-
- /** \brief Returns the eigenvalues of given matrix.
- *
- * \returns A const reference to the column vector containing the eigenvalues.
- *
- * \pre Either the constructor
- * ComplexEigenSolver(const MatrixType& matrix, bool) or the member
- * function compute(const MatrixType& matrix, bool) has been called before
- * to compute the eigendecomposition of a matrix.
- *
- * This function returns a column vector containing the
- * eigenvalues. Eigenvalues are repeated according to their
- * algebraic multiplicity, so there are as many eigenvalues as
- * rows in the matrix. The eigenvalues are not sorted in any particular
- * order.
- *
- * Example: \include ComplexEigenSolver_eigenvalues.cpp
- * Output: \verbinclude ComplexEigenSolver_eigenvalues.out
- */
- const EigenvalueType& eigenvalues() const
- {
- eigen_assert(m_isInitialized && "ComplexEigenSolver is not initialized.");
- return m_eivalues;
- }
-
- /** \brief Computes eigendecomposition of given matrix.
- *
- * \param[in] matrix Square matrix whose eigendecomposition is to be computed.
- * \param[in] computeEigenvectors If true, both the eigenvectors and the
- * eigenvalues are computed; if false, only the eigenvalues are
- * computed.
- * \returns Reference to \c *this
- *
- * This function computes the eigenvalues of the complex matrix \p matrix.
- * The eigenvalues() function can be used to retrieve them. If
- * \p computeEigenvectors is true, then the eigenvectors are also computed
- * and can be retrieved by calling eigenvectors().
- *
- * The matrix is first reduced to Schur form using the
- * ComplexSchur class. The Schur decomposition is then used to
- * compute the eigenvalues and eigenvectors.
- *
- * The cost of the computation is dominated by the cost of the
- * Schur decomposition, which is \f$ O(n^3) \f$ where \f$ n \f$
- * is the size of the matrix.
- *
- * Example: \include ComplexEigenSolver_compute.cpp
- * Output: \verbinclude ComplexEigenSolver_compute.out
- */
- ComplexEigenSolver& compute(const MatrixType& matrix, bool computeEigenvectors = true);
-
- /** \brief Reports whether previous computation was successful.
- *
- * \returns \c Success if computation was succesful, \c NoConvergence otherwise.
- */
- ComputationInfo info() const
- {
- eigen_assert(m_isInitialized && "ComplexEigenSolver is not initialized.");
- return m_schur.info();
- }
-
- protected:
- EigenvectorType m_eivec;
- EigenvalueType m_eivalues;
- ComplexSchur<MatrixType> m_schur;
- bool m_isInitialized;
- bool m_eigenvectorsOk;
- EigenvectorType m_matX;
-
- private:
- void doComputeEigenvectors(RealScalar matrixnorm);
- void sortEigenvalues(bool computeEigenvectors);
-};
-
-
-template<typename MatrixType>
-ComplexEigenSolver<MatrixType>& ComplexEigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvectors)
-{
- // this code is inspired from Jampack
- assert(matrix.cols() == matrix.rows());
-
- // Do a complex Schur decomposition, A = U T U^*
- // The eigenvalues are on the diagonal of T.
- m_schur.compute(matrix, computeEigenvectors);
-
- if(m_schur.info() == Success)
- {
- m_eivalues = m_schur.matrixT().diagonal();
- if(computeEigenvectors)
- doComputeEigenvectors(matrix.norm());
- sortEigenvalues(computeEigenvectors);
- }
-
- m_isInitialized = true;
- m_eigenvectorsOk = computeEigenvectors;
- return *this;
-}
-
-
-template<typename MatrixType>
-void ComplexEigenSolver<MatrixType>::doComputeEigenvectors(RealScalar matrixnorm)
-{
- const Index n = m_eivalues.size();
-
- // Compute X such that T = X D X^(-1), where D is the diagonal of T.
- // The matrix X is unit triangular.
- m_matX = EigenvectorType::Zero(n, n);
- for(Index k=n-1 ; k>=0 ; k--)
- {
- m_matX.coeffRef(k,k) = ComplexScalar(1.0,0.0);
- // Compute X(i,k) using the (i,k) entry of the equation X T = D X
- for(Index i=k-1 ; i>=0 ; i--)
- {
- m_matX.coeffRef(i,k) = -m_schur.matrixT().coeff(i,k);
- if(k-i-1>0)
- m_matX.coeffRef(i,k) -= (m_schur.matrixT().row(i).segment(i+1,k-i-1) * m_matX.col(k).segment(i+1,k-i-1)).value();
- ComplexScalar z = m_schur.matrixT().coeff(i,i) - m_schur.matrixT().coeff(k,k);
- if(z==ComplexScalar(0))
- {
- // If the i-th and k-th eigenvalue are equal, then z equals 0.
- // Use a small value instead, to prevent division by zero.
- internal::real_ref(z) = NumTraits<RealScalar>::epsilon() * matrixnorm;
- }
- m_matX.coeffRef(i,k) = m_matX.coeff(i,k) / z;
- }
- }
-
- // Compute V as V = U X; now A = U T U^* = U X D X^(-1) U^* = V D V^(-1)
- m_eivec.noalias() = m_schur.matrixU() * m_matX;
- // .. and normalize the eigenvectors
- for(Index k=0 ; k<n ; k++)
- {
- m_eivec.col(k).normalize();
- }
-}
-
-
-template<typename MatrixType>
-void ComplexEigenSolver<MatrixType>::sortEigenvalues(bool computeEigenvectors)
-{
- const Index n = m_eivalues.size();
- for (Index i=0; i<n; i++)
- {
- Index k;
- m_eivalues.cwiseAbs().tail(n-i).minCoeff(&k);
- if (k != 0)
- {
- k += i;
- std::swap(m_eivalues[k],m_eivalues[i]);
- if(computeEigenvectors)
- m_eivec.col(i).swap(m_eivec.col(k));
- }
- }
-}
-
-
-#endif // EIGEN_COMPLEX_EIGEN_SOLVER_H
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h b/extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h
deleted file mode 100644
index ec93af2e58a..00000000000
--- a/extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h
+++ /dev/null
@@ -1,448 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Claire Maurice
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_COMPLEX_SCHUR_H
-#define EIGEN_COMPLEX_SCHUR_H
-
-#include "./EigenvaluesCommon.h"
-#include "./HessenbergDecomposition.h"
-
-namespace internal {
-template<typename MatrixType, bool IsComplex> struct complex_schur_reduce_to_hessenberg;
-}
-
-/** \eigenvalues_module \ingroup Eigenvalues_Module
- *
- *
- * \class ComplexSchur
- *
- * \brief Performs a complex Schur decomposition of a real or complex square matrix
- *
- * \tparam _MatrixType the type of the matrix of which we are
- * computing the Schur decomposition; this is expected to be an
- * instantiation of the Matrix class template.
- *
- * Given a real or complex square matrix A, this class computes the
- * Schur decomposition: \f$ A = U T U^*\f$ where U is a unitary
- * complex matrix, and T is a complex upper triangular matrix. The
- * diagonal of the matrix T corresponds to the eigenvalues of the
- * matrix A.
- *
- * Call the function compute() to compute the Schur decomposition of
- * a given matrix. Alternatively, you can use the
- * ComplexSchur(const MatrixType&, bool) constructor which computes
- * the Schur decomposition at construction time. Once the
- * decomposition is computed, you can use the matrixU() and matrixT()
- * functions to retrieve the matrices U and V in the decomposition.
- *
- * \note This code is inspired from Jampack
- *
- * \sa class RealSchur, class EigenSolver, class ComplexEigenSolver
- */
-template<typename _MatrixType> class ComplexSchur
-{
- public:
- typedef _MatrixType MatrixType;
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- Options = MatrixType::Options,
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
- };
-
- /** \brief Scalar type for matrices of type \p _MatrixType. */
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef typename MatrixType::Index Index;
-
- /** \brief Complex scalar type for \p _MatrixType.
- *
- * This is \c std::complex<Scalar> if #Scalar is real (e.g.,
- * \c float or \c double) and just \c Scalar if #Scalar is
- * complex.
- */
- typedef std::complex<RealScalar> ComplexScalar;
-
- /** \brief Type for the matrices in the Schur decomposition.
- *
- * This is a square matrix with entries of type #ComplexScalar.
- * The size is the same as the size of \p _MatrixType.
- */
- typedef Matrix<ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime> ComplexMatrixType;
-
- /** \brief Default constructor.
- *
- * \param [in] size Positive integer, size of the matrix whose Schur decomposition will be computed.
- *
- * The default constructor is useful in cases in which the user
- * intends to perform decompositions via compute(). The \p size
- * parameter is only used as a hint. It is not an error to give a
- * wrong \p size, but it may impair performance.
- *
- * \sa compute() for an example.
- */
- ComplexSchur(Index size = RowsAtCompileTime==Dynamic ? 1 : RowsAtCompileTime)
- : m_matT(size,size),
- m_matU(size,size),
- m_hess(size),
- m_isInitialized(false),
- m_matUisUptodate(false)
- {}
-
- /** \brief Constructor; computes Schur decomposition of given matrix.
- *
- * \param[in] matrix Square matrix whose Schur decomposition is to be computed.
- * \param[in] computeU If true, both T and U are computed; if false, only T is computed.
- *
- * This constructor calls compute() to compute the Schur decomposition.
- *
- * \sa matrixT() and matrixU() for examples.
- */
- ComplexSchur(const MatrixType& matrix, bool computeU = true)
- : m_matT(matrix.rows(),matrix.cols()),
- m_matU(matrix.rows(),matrix.cols()),
- m_hess(matrix.rows()),
- m_isInitialized(false),
- m_matUisUptodate(false)
- {
- compute(matrix, computeU);
- }
-
- /** \brief Returns the unitary matrix in the Schur decomposition.
- *
- * \returns A const reference to the matrix U.
- *
- * It is assumed that either the constructor
- * ComplexSchur(const MatrixType& matrix, bool computeU) or the
- * member function compute(const MatrixType& matrix, bool computeU)
- * has been called before to compute the Schur decomposition of a
- * matrix, and that \p computeU was set to true (the default
- * value).
- *
- * Example: \include ComplexSchur_matrixU.cpp
- * Output: \verbinclude ComplexSchur_matrixU.out
- */
- const ComplexMatrixType& matrixU() const
- {
- eigen_assert(m_isInitialized && "ComplexSchur is not initialized.");
- eigen_assert(m_matUisUptodate && "The matrix U has not been computed during the ComplexSchur decomposition.");
- return m_matU;
- }
-
- /** \brief Returns the triangular matrix in the Schur decomposition.
- *
- * \returns A const reference to the matrix T.
- *
- * It is assumed that either the constructor
- * ComplexSchur(const MatrixType& matrix, bool computeU) or the
- * member function compute(const MatrixType& matrix, bool computeU)
- * has been called before to compute the Schur decomposition of a
- * matrix.
- *
- * Note that this function returns a plain square matrix. If you want to reference
- * only the upper triangular part, use:
- * \code schur.matrixT().triangularView<Upper>() \endcode
- *
- * Example: \include ComplexSchur_matrixT.cpp
- * Output: \verbinclude ComplexSchur_matrixT.out
- */
- const ComplexMatrixType& matrixT() const
- {
- eigen_assert(m_isInitialized && "ComplexSchur is not initialized.");
- return m_matT;
- }
-
- /** \brief Computes Schur decomposition of given matrix.
- *
- * \param[in] matrix Square matrix whose Schur decomposition is to be computed.
- * \param[in] computeU If true, both T and U are computed; if false, only T is computed.
- * \returns Reference to \c *this
- *
- * The Schur decomposition is computed by first reducing the
- * matrix to Hessenberg form using the class
- * HessenbergDecomposition. The Hessenberg matrix is then reduced
- * to triangular form by performing QR iterations with a single
- * shift. The cost of computing the Schur decomposition depends
- * on the number of iterations; as a rough guide, it may be taken
- * on the number of iterations; as a rough guide, it may be taken
- * to be \f$25n^3\f$ complex flops, or \f$10n^3\f$ complex flops
- * if \a computeU is false.
- *
- * Example: \include ComplexSchur_compute.cpp
- * Output: \verbinclude ComplexSchur_compute.out
- */
- ComplexSchur& compute(const MatrixType& matrix, bool computeU = true);
-
- /** \brief Reports whether previous computation was successful.
- *
- * \returns \c Success if computation was succesful, \c NoConvergence otherwise.
- */
- ComputationInfo info() const
- {
- eigen_assert(m_isInitialized && "RealSchur is not initialized.");
- return m_info;
- }
-
- /** \brief Maximum number of iterations.
- *
- * Maximum number of iterations allowed for an eigenvalue to converge.
- */
- static const int m_maxIterations = 30;
-
- protected:
- ComplexMatrixType m_matT, m_matU;
- HessenbergDecomposition<MatrixType> m_hess;
- ComputationInfo m_info;
- bool m_isInitialized;
- bool m_matUisUptodate;
-
- private:
- bool subdiagonalEntryIsNeglegible(Index i);
- ComplexScalar computeShift(Index iu, Index iter);
- void reduceToTriangularForm(bool computeU);
- friend struct internal::complex_schur_reduce_to_hessenberg<MatrixType, NumTraits<Scalar>::IsComplex>;
-};
-
-namespace internal {
-
-/** Computes the principal value of the square root of the complex \a z. */
-template<typename RealScalar>
-std::complex<RealScalar> sqrt(const std::complex<RealScalar> &z)
-{
- RealScalar t, tre, tim;
-
- t = abs(z);
-
- if (abs(real(z)) <= abs(imag(z)))
- {
- // No cancellation in these formulas
- tre = sqrt(RealScalar(0.5)*(t + real(z)));
- tim = sqrt(RealScalar(0.5)*(t - real(z)));
- }
- else
- {
- // Stable computation of the above formulas
- if (z.real() > RealScalar(0))
- {
- tre = t + z.real();
- tim = abs(imag(z))*sqrt(RealScalar(0.5)/tre);
- tre = sqrt(RealScalar(0.5)*tre);
- }
- else
- {
- tim = t - z.real();
- tre = abs(imag(z))*sqrt(RealScalar(0.5)/tim);
- tim = sqrt(RealScalar(0.5)*tim);
- }
- }
- if(z.imag() < RealScalar(0))
- tim = -tim;
-
- return (std::complex<RealScalar>(tre,tim));
-}
-} // end namespace internal
-
-
-/** If m_matT(i+1,i) is neglegible in floating point arithmetic
- * compared to m_matT(i,i) and m_matT(j,j), then set it to zero and
- * return true, else return false. */
-template<typename MatrixType>
-inline bool ComplexSchur<MatrixType>::subdiagonalEntryIsNeglegible(Index i)
-{
- RealScalar d = internal::norm1(m_matT.coeff(i,i)) + internal::norm1(m_matT.coeff(i+1,i+1));
- RealScalar sd = internal::norm1(m_matT.coeff(i+1,i));
- if (internal::isMuchSmallerThan(sd, d, NumTraits<RealScalar>::epsilon()))
- {
- m_matT.coeffRef(i+1,i) = ComplexScalar(0);
- return true;
- }
- return false;
-}
-
-
-/** Compute the shift in the current QR iteration. */
-template<typename MatrixType>
-typename ComplexSchur<MatrixType>::ComplexScalar ComplexSchur<MatrixType>::computeShift(Index iu, Index iter)
-{
- if (iter == 10 || iter == 20)
- {
- // exceptional shift, taken from http://www.netlib.org/eispack/comqr.f
- return internal::abs(internal::real(m_matT.coeff(iu,iu-1))) + internal::abs(internal::real(m_matT.coeff(iu-1,iu-2)));
- }
-
- // compute the shift as one of the eigenvalues of t, the 2x2
- // diagonal block on the bottom of the active submatrix
- Matrix<ComplexScalar,2,2> t = m_matT.template block<2,2>(iu-1,iu-1);
- RealScalar normt = t.cwiseAbs().sum();
- t /= normt; // the normalization by sf is to avoid under/overflow
-
- ComplexScalar b = t.coeff(0,1) * t.coeff(1,0);
- ComplexScalar c = t.coeff(0,0) - t.coeff(1,1);
- ComplexScalar disc = internal::sqrt(c*c + RealScalar(4)*b);
- ComplexScalar det = t.coeff(0,0) * t.coeff(1,1) - b;
- ComplexScalar trace = t.coeff(0,0) + t.coeff(1,1);
- ComplexScalar eival1 = (trace + disc) / RealScalar(2);
- ComplexScalar eival2 = (trace - disc) / RealScalar(2);
-
- if(internal::norm1(eival1) > internal::norm1(eival2))
- eival2 = det / eival1;
- else
- eival1 = det / eival2;
-
- // choose the eigenvalue closest to the bottom entry of the diagonal
- if(internal::norm1(eival1-t.coeff(1,1)) < internal::norm1(eival2-t.coeff(1,1)))
- return normt * eival1;
- else
- return normt * eival2;
-}
-
-
-template<typename MatrixType>
-ComplexSchur<MatrixType>& ComplexSchur<MatrixType>::compute(const MatrixType& matrix, bool computeU)
-{
- m_matUisUptodate = false;
- eigen_assert(matrix.cols() == matrix.rows());
-
- if(matrix.cols() == 1)
- {
- m_matT = matrix.template cast<ComplexScalar>();
- if(computeU) m_matU = ComplexMatrixType::Identity(1,1);
- m_info = Success;
- m_isInitialized = true;
- m_matUisUptodate = computeU;
- return *this;
- }
-
- internal::complex_schur_reduce_to_hessenberg<MatrixType, NumTraits<Scalar>::IsComplex>::run(*this, matrix, computeU);
- reduceToTriangularForm(computeU);
- return *this;
-}
-
-namespace internal {
-
-/* Reduce given matrix to Hessenberg form */
-template<typename MatrixType, bool IsComplex>
-struct complex_schur_reduce_to_hessenberg
-{
- // this is the implementation for the case IsComplex = true
- static void run(ComplexSchur<MatrixType>& _this, const MatrixType& matrix, bool computeU)
- {
- _this.m_hess.compute(matrix);
- _this.m_matT = _this.m_hess.matrixH();
- if(computeU) _this.m_matU = _this.m_hess.matrixQ();
- }
-};
-
-template<typename MatrixType>
-struct complex_schur_reduce_to_hessenberg<MatrixType, false>
-{
- static void run(ComplexSchur<MatrixType>& _this, const MatrixType& matrix, bool computeU)
- {
- typedef typename ComplexSchur<MatrixType>::ComplexScalar ComplexScalar;
- typedef typename ComplexSchur<MatrixType>::ComplexMatrixType ComplexMatrixType;
-
- // Note: m_hess is over RealScalar; m_matT and m_matU is over ComplexScalar
- _this.m_hess.compute(matrix);
- _this.m_matT = _this.m_hess.matrixH().template cast<ComplexScalar>();
- if(computeU)
- {
- // This may cause an allocation which seems to be avoidable
- MatrixType Q = _this.m_hess.matrixQ();
- _this.m_matU = Q.template cast<ComplexScalar>();
- }
- }
-};
-
-} // end namespace internal
-
-// Reduce the Hessenberg matrix m_matT to triangular form by QR iteration.
-template<typename MatrixType>
-void ComplexSchur<MatrixType>::reduceToTriangularForm(bool computeU)
-{
- // The matrix m_matT is divided in three parts.
- // Rows 0,...,il-1 are decoupled from the rest because m_matT(il,il-1) is zero.
- // Rows il,...,iu is the part we are working on (the active submatrix).
- // Rows iu+1,...,end are already brought in triangular form.
- Index iu = m_matT.cols() - 1;
- Index il;
- Index iter = 0; // number of iterations we are working on the (iu,iu) element
-
- while(true)
- {
- // find iu, the bottom row of the active submatrix
- while(iu > 0)
- {
- if(!subdiagonalEntryIsNeglegible(iu-1)) break;
- iter = 0;
- --iu;
- }
-
- // if iu is zero then we are done; the whole matrix is triangularized
- if(iu==0) break;
-
- // if we spent too many iterations on the current element, we give up
- iter++;
- if(iter > m_maxIterations) break;
-
- // find il, the top row of the active submatrix
- il = iu-1;
- while(il > 0 && !subdiagonalEntryIsNeglegible(il-1))
- {
- --il;
- }
-
- /* perform the QR step using Givens rotations. The first rotation
- creates a bulge; the (il+2,il) element becomes nonzero. This
- bulge is chased down to the bottom of the active submatrix. */
-
- ComplexScalar shift = computeShift(iu, iter);
- JacobiRotation<ComplexScalar> rot;
- rot.makeGivens(m_matT.coeff(il,il) - shift, m_matT.coeff(il+1,il));
- m_matT.rightCols(m_matT.cols()-il).applyOnTheLeft(il, il+1, rot.adjoint());
- m_matT.topRows((std::min)(il+2,iu)+1).applyOnTheRight(il, il+1, rot);
- if(computeU) m_matU.applyOnTheRight(il, il+1, rot);
-
- for(Index i=il+1 ; i<iu ; i++)
- {
- rot.makeGivens(m_matT.coeffRef(i,i-1), m_matT.coeffRef(i+1,i-1), &m_matT.coeffRef(i,i-1));
- m_matT.coeffRef(i+1,i-1) = ComplexScalar(0);
- m_matT.rightCols(m_matT.cols()-i).applyOnTheLeft(i, i+1, rot.adjoint());
- m_matT.topRows((std::min)(i+2,iu)+1).applyOnTheRight(i, i+1, rot);
- if(computeU) m_matU.applyOnTheRight(i, i+1, rot);
- }
- }
-
- if(iter <= m_maxIterations)
- m_info = Success;
- else
- m_info = NoConvergence;
-
- m_isInitialized = true;
- m_matUisUptodate = computeU;
-}
-
-#endif // EIGEN_COMPLEX_SCHUR_H
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h b/extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h
deleted file mode 100644
index ac4c4242dd4..00000000000
--- a/extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h
+++ /dev/null
@@ -1,588 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_EIGENSOLVER_H
-#define EIGEN_EIGENSOLVER_H
-
-#include "./EigenvaluesCommon.h"
-#include "./RealSchur.h"
-
-/** \eigenvalues_module \ingroup Eigenvalues_Module
- *
- *
- * \class EigenSolver
- *
- * \brief Computes eigenvalues and eigenvectors of general matrices
- *
- * \tparam _MatrixType the type of the matrix of which we are computing the
- * eigendecomposition; this is expected to be an instantiation of the Matrix
- * class template. Currently, only real matrices are supported.
- *
- * The eigenvalues and eigenvectors of a matrix \f$ A \f$ are scalars
- * \f$ \lambda \f$ and vectors \f$ v \f$ such that \f$ Av = \lambda v \f$. If
- * \f$ D \f$ is a diagonal matrix with the eigenvalues on the diagonal, and
- * \f$ V \f$ is a matrix with the eigenvectors as its columns, then \f$ A V =
- * V D \f$. The matrix \f$ V \f$ is almost always invertible, in which case we
- * have \f$ A = V D V^{-1} \f$. This is called the eigendecomposition.
- *
- * The eigenvalues and eigenvectors of a matrix may be complex, even when the
- * matrix is real. However, we can choose real matrices \f$ V \f$ and \f$ D
- * \f$ satisfying \f$ A V = V D \f$, just like the eigendecomposition, if the
- * matrix \f$ D \f$ is not required to be diagonal, but if it is allowed to
- * have blocks of the form
- * \f[ \begin{bmatrix} u & v \\ -v & u \end{bmatrix} \f]
- * (where \f$ u \f$ and \f$ v \f$ are real numbers) on the diagonal. These
- * blocks correspond to complex eigenvalue pairs \f$ u \pm iv \f$. We call
- * this variant of the eigendecomposition the pseudo-eigendecomposition.
- *
- * Call the function compute() to compute the eigenvalues and eigenvectors of
- * a given matrix. Alternatively, you can use the
- * EigenSolver(const MatrixType&, bool) constructor which computes the
- * eigenvalues and eigenvectors at construction time. Once the eigenvalue and
- * eigenvectors are computed, they can be retrieved with the eigenvalues() and
- * eigenvectors() functions. The pseudoEigenvalueMatrix() and
- * pseudoEigenvectors() methods allow the construction of the
- * pseudo-eigendecomposition.
- *
- * The documentation for EigenSolver(const MatrixType&, bool) contains an
- * example of the typical use of this class.
- *
- * \note The implementation is adapted from
- * <a href="http://math.nist.gov/javanumerics/jama/">JAMA</a> (public domain).
- * Their code is based on EISPACK.
- *
- * \sa MatrixBase::eigenvalues(), class ComplexEigenSolver, class SelfAdjointEigenSolver
- */
-template<typename _MatrixType> class EigenSolver
-{
- public:
-
- /** \brief Synonym for the template parameter \p _MatrixType. */
- typedef _MatrixType MatrixType;
-
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- Options = MatrixType::Options,
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
- };
-
- /** \brief Scalar type for matrices of type #MatrixType. */
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef typename MatrixType::Index Index;
-
- /** \brief Complex scalar type for #MatrixType.
- *
- * This is \c std::complex<Scalar> if #Scalar is real (e.g.,
- * \c float or \c double) and just \c Scalar if #Scalar is
- * complex.
- */
- typedef std::complex<RealScalar> ComplexScalar;
-
- /** \brief Type for vector of eigenvalues as returned by eigenvalues().
- *
- * This is a column vector with entries of type #ComplexScalar.
- * The length of the vector is the size of #MatrixType.
- */
- typedef Matrix<ComplexScalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> EigenvalueType;
-
- /** \brief Type for matrix of eigenvectors as returned by eigenvectors().
- *
- * This is a square matrix with entries of type #ComplexScalar.
- * The size is the same as the size of #MatrixType.
- */
- typedef Matrix<ComplexScalar, RowsAtCompileTime, ColsAtCompileTime, Options, MaxRowsAtCompileTime, MaxColsAtCompileTime> EigenvectorsType;
-
- /** \brief Default constructor.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via EigenSolver::compute(const MatrixType&, bool).
- *
- * \sa compute() for an example.
- */
- EigenSolver() : m_eivec(), m_eivalues(), m_isInitialized(false), m_realSchur(), m_matT(), m_tmp() {}
-
- /** \brief Default constructor with memory preallocation
- *
- * Like the default constructor but with preallocation of the internal data
- * according to the specified problem \a size.
- * \sa EigenSolver()
- */
- EigenSolver(Index size)
- : m_eivec(size, size),
- m_eivalues(size),
- m_isInitialized(false),
- m_eigenvectorsOk(false),
- m_realSchur(size),
- m_matT(size, size),
- m_tmp(size)
- {}
-
- /** \brief Constructor; computes eigendecomposition of given matrix.
- *
- * \param[in] matrix Square matrix whose eigendecomposition is to be computed.
- * \param[in] computeEigenvectors If true, both the eigenvectors and the
- * eigenvalues are computed; if false, only the eigenvalues are
- * computed.
- *
- * This constructor calls compute() to compute the eigenvalues
- * and eigenvectors.
- *
- * Example: \include EigenSolver_EigenSolver_MatrixType.cpp
- * Output: \verbinclude EigenSolver_EigenSolver_MatrixType.out
- *
- * \sa compute()
- */
- EigenSolver(const MatrixType& matrix, bool computeEigenvectors = true)
- : m_eivec(matrix.rows(), matrix.cols()),
- m_eivalues(matrix.cols()),
- m_isInitialized(false),
- m_eigenvectorsOk(false),
- m_realSchur(matrix.cols()),
- m_matT(matrix.rows(), matrix.cols()),
- m_tmp(matrix.cols())
- {
- compute(matrix, computeEigenvectors);
- }
-
- /** \brief Returns the eigenvectors of given matrix.
- *
- * \returns %Matrix whose columns are the (possibly complex) eigenvectors.
- *
- * \pre Either the constructor
- * EigenSolver(const MatrixType&,bool) or the member function
- * compute(const MatrixType&, bool) has been called before, and
- * \p computeEigenvectors was set to true (the default).
- *
- * Column \f$ k \f$ of the returned matrix is an eigenvector corresponding
- * to eigenvalue number \f$ k \f$ as returned by eigenvalues(). The
- * eigenvectors are normalized to have (Euclidean) norm equal to one. The
- * matrix returned by this function is the matrix \f$ V \f$ in the
- * eigendecomposition \f$ A = V D V^{-1} \f$, if it exists.
- *
- * Example: \include EigenSolver_eigenvectors.cpp
- * Output: \verbinclude EigenSolver_eigenvectors.out
- *
- * \sa eigenvalues(), pseudoEigenvectors()
- */
- EigenvectorsType eigenvectors() const;
-
- /** \brief Returns the pseudo-eigenvectors of given matrix.
- *
- * \returns Const reference to matrix whose columns are the pseudo-eigenvectors.
- *
- * \pre Either the constructor
- * EigenSolver(const MatrixType&,bool) or the member function
- * compute(const MatrixType&, bool) has been called before, and
- * \p computeEigenvectors was set to true (the default).
- *
- * The real matrix \f$ V \f$ returned by this function and the
- * block-diagonal matrix \f$ D \f$ returned by pseudoEigenvalueMatrix()
- * satisfy \f$ AV = VD \f$.
- *
- * Example: \include EigenSolver_pseudoEigenvectors.cpp
- * Output: \verbinclude EigenSolver_pseudoEigenvectors.out
- *
- * \sa pseudoEigenvalueMatrix(), eigenvectors()
- */
- const MatrixType& pseudoEigenvectors() const
- {
- eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
- eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
- return m_eivec;
- }
-
- /** \brief Returns the block-diagonal matrix in the pseudo-eigendecomposition.
- *
- * \returns A block-diagonal matrix.
- *
- * \pre Either the constructor
- * EigenSolver(const MatrixType&,bool) or the member function
- * compute(const MatrixType&, bool) has been called before.
- *
- * The matrix \f$ D \f$ returned by this function is real and
- * block-diagonal. The blocks on the diagonal are either 1-by-1 or 2-by-2
- * blocks of the form
- * \f$ \begin{bmatrix} u & v \\ -v & u \end{bmatrix} \f$.
- * These blocks are not sorted in any particular order.
- * The matrix \f$ D \f$ and the matrix \f$ V \f$ returned by
- * pseudoEigenvectors() satisfy \f$ AV = VD \f$.
- *
- * \sa pseudoEigenvectors() for an example, eigenvalues()
- */
- MatrixType pseudoEigenvalueMatrix() const;
-
- /** \brief Returns the eigenvalues of given matrix.
- *
- * \returns A const reference to the column vector containing the eigenvalues.
- *
- * \pre Either the constructor
- * EigenSolver(const MatrixType&,bool) or the member function
- * compute(const MatrixType&, bool) has been called before.
- *
- * The eigenvalues are repeated according to their algebraic multiplicity,
- * so there are as many eigenvalues as rows in the matrix. The eigenvalues
- * are not sorted in any particular order.
- *
- * Example: \include EigenSolver_eigenvalues.cpp
- * Output: \verbinclude EigenSolver_eigenvalues.out
- *
- * \sa eigenvectors(), pseudoEigenvalueMatrix(),
- * MatrixBase::eigenvalues()
- */
- const EigenvalueType& eigenvalues() const
- {
- eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
- return m_eivalues;
- }
-
- /** \brief Computes eigendecomposition of given matrix.
- *
- * \param[in] matrix Square matrix whose eigendecomposition is to be computed.
- * \param[in] computeEigenvectors If true, both the eigenvectors and the
- * eigenvalues are computed; if false, only the eigenvalues are
- * computed.
- * \returns Reference to \c *this
- *
- * This function computes the eigenvalues of the real matrix \p matrix.
- * The eigenvalues() function can be used to retrieve them. If
- * \p computeEigenvectors is true, then the eigenvectors are also computed
- * and can be retrieved by calling eigenvectors().
- *
- * The matrix is first reduced to real Schur form using the RealSchur
- * class. The Schur decomposition is then used to compute the eigenvalues
- * and eigenvectors.
- *
- * The cost of the computation is dominated by the cost of the
- * Schur decomposition, which is very approximately \f$ 25n^3 \f$
- * (where \f$ n \f$ is the size of the matrix) if \p computeEigenvectors
- * is true, and \f$ 10n^3 \f$ if \p computeEigenvectors is false.
- *
- * This method reuses of the allocated data in the EigenSolver object.
- *
- * Example: \include EigenSolver_compute.cpp
- * Output: \verbinclude EigenSolver_compute.out
- */
- EigenSolver& compute(const MatrixType& matrix, bool computeEigenvectors = true);
-
- ComputationInfo info() const
- {
- eigen_assert(m_isInitialized && "ComplexEigenSolver is not initialized.");
- return m_realSchur.info();
- }
-
- private:
- void doComputeEigenvectors();
-
- protected:
- MatrixType m_eivec;
- EigenvalueType m_eivalues;
- bool m_isInitialized;
- bool m_eigenvectorsOk;
- RealSchur<MatrixType> m_realSchur;
- MatrixType m_matT;
-
- typedef Matrix<Scalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> ColumnVectorType;
- ColumnVectorType m_tmp;
-};
-
-template<typename MatrixType>
-MatrixType EigenSolver<MatrixType>::pseudoEigenvalueMatrix() const
-{
- eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
- Index n = m_eivalues.rows();
- MatrixType matD = MatrixType::Zero(n,n);
- for (Index i=0; i<n; ++i)
- {
- if (internal::isMuchSmallerThan(internal::imag(m_eivalues.coeff(i)), internal::real(m_eivalues.coeff(i))))
- matD.coeffRef(i,i) = internal::real(m_eivalues.coeff(i));
- else
- {
- matD.template block<2,2>(i,i) << internal::real(m_eivalues.coeff(i)), internal::imag(m_eivalues.coeff(i)),
- -internal::imag(m_eivalues.coeff(i)), internal::real(m_eivalues.coeff(i));
- ++i;
- }
- }
- return matD;
-}
-
-template<typename MatrixType>
-typename EigenSolver<MatrixType>::EigenvectorsType EigenSolver<MatrixType>::eigenvectors() const
-{
- eigen_assert(m_isInitialized && "EigenSolver is not initialized.");
- eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
- Index n = m_eivec.cols();
- EigenvectorsType matV(n,n);
- for (Index j=0; j<n; ++j)
- {
- if (internal::isMuchSmallerThan(internal::imag(m_eivalues.coeff(j)), internal::real(m_eivalues.coeff(j))))
- {
- // we have a real eigen value
- matV.col(j) = m_eivec.col(j).template cast<ComplexScalar>();
- matV.col(j).normalize();
- }
- else
- {
- // we have a pair of complex eigen values
- for (Index i=0; i<n; ++i)
- {
- matV.coeffRef(i,j) = ComplexScalar(m_eivec.coeff(i,j), m_eivec.coeff(i,j+1));
- matV.coeffRef(i,j+1) = ComplexScalar(m_eivec.coeff(i,j), -m_eivec.coeff(i,j+1));
- }
- matV.col(j).normalize();
- matV.col(j+1).normalize();
- ++j;
- }
- }
- return matV;
-}
-
-template<typename MatrixType>
-EigenSolver<MatrixType>& EigenSolver<MatrixType>::compute(const MatrixType& matrix, bool computeEigenvectors)
-{
- assert(matrix.cols() == matrix.rows());
-
- // Reduce to real Schur form.
- m_realSchur.compute(matrix, computeEigenvectors);
- if (m_realSchur.info() == Success)
- {
- m_matT = m_realSchur.matrixT();
- if (computeEigenvectors)
- m_eivec = m_realSchur.matrixU();
-
- // Compute eigenvalues from matT
- m_eivalues.resize(matrix.cols());
- Index i = 0;
- while (i < matrix.cols())
- {
- if (i == matrix.cols() - 1 || m_matT.coeff(i+1, i) == Scalar(0))
- {
- m_eivalues.coeffRef(i) = m_matT.coeff(i, i);
- ++i;
- }
- else
- {
- Scalar p = Scalar(0.5) * (m_matT.coeff(i, i) - m_matT.coeff(i+1, i+1));
- Scalar z = internal::sqrt(internal::abs(p * p + m_matT.coeff(i+1, i) * m_matT.coeff(i, i+1)));
- m_eivalues.coeffRef(i) = ComplexScalar(m_matT.coeff(i+1, i+1) + p, z);
- m_eivalues.coeffRef(i+1) = ComplexScalar(m_matT.coeff(i+1, i+1) + p, -z);
- i += 2;
- }
- }
-
- // Compute eigenvectors.
- if (computeEigenvectors)
- doComputeEigenvectors();
- }
-
- m_isInitialized = true;
- m_eigenvectorsOk = computeEigenvectors;
-
- return *this;
-}
-
-// Complex scalar division.
-template<typename Scalar>
-std::complex<Scalar> cdiv(Scalar xr, Scalar xi, Scalar yr, Scalar yi)
-{
- Scalar r,d;
- if (internal::abs(yr) > internal::abs(yi))
- {
- r = yi/yr;
- d = yr + r*yi;
- return std::complex<Scalar>((xr + r*xi)/d, (xi - r*xr)/d);
- }
- else
- {
- r = yr/yi;
- d = yi + r*yr;
- return std::complex<Scalar>((r*xr + xi)/d, (r*xi - xr)/d);
- }
-}
-
-
-template<typename MatrixType>
-void EigenSolver<MatrixType>::doComputeEigenvectors()
-{
- const Index size = m_eivec.cols();
- const Scalar eps = NumTraits<Scalar>::epsilon();
-
- // inefficient! this is already computed in RealSchur
- Scalar norm = 0.0;
- for (Index j = 0; j < size; ++j)
- {
- norm += m_matT.row(j).segment((std::max)(j-1,Index(0)), size-(std::max)(j-1,Index(0))).cwiseAbs().sum();
- }
-
- // Backsubstitute to find vectors of upper triangular form
- if (norm == 0.0)
- {
- return;
- }
-
- for (Index n = size-1; n >= 0; n--)
- {
- Scalar p = m_eivalues.coeff(n).real();
- Scalar q = m_eivalues.coeff(n).imag();
-
- // Scalar vector
- if (q == Scalar(0))
- {
- Scalar lastr=0, lastw=0;
- Index l = n;
-
- m_matT.coeffRef(n,n) = 1.0;
- for (Index i = n-1; i >= 0; i--)
- {
- Scalar w = m_matT.coeff(i,i) - p;
- Scalar r = m_matT.row(i).segment(l,n-l+1).dot(m_matT.col(n).segment(l, n-l+1));
-
- if (m_eivalues.coeff(i).imag() < 0.0)
- {
- lastw = w;
- lastr = r;
- }
- else
- {
- l = i;
- if (m_eivalues.coeff(i).imag() == 0.0)
- {
- if (w != 0.0)
- m_matT.coeffRef(i,n) = -r / w;
- else
- m_matT.coeffRef(i,n) = -r / (eps * norm);
- }
- else // Solve real equations
- {
- Scalar x = m_matT.coeff(i,i+1);
- Scalar y = m_matT.coeff(i+1,i);
- Scalar denom = (m_eivalues.coeff(i).real() - p) * (m_eivalues.coeff(i).real() - p) + m_eivalues.coeff(i).imag() * m_eivalues.coeff(i).imag();
- Scalar t = (x * lastr - lastw * r) / denom;
- m_matT.coeffRef(i,n) = t;
- if (internal::abs(x) > internal::abs(lastw))
- m_matT.coeffRef(i+1,n) = (-r - w * t) / x;
- else
- m_matT.coeffRef(i+1,n) = (-lastr - y * t) / lastw;
- }
-
- // Overflow control
- Scalar t = internal::abs(m_matT.coeff(i,n));
- if ((eps * t) * t > Scalar(1))
- m_matT.col(n).tail(size-i) /= t;
- }
- }
- }
- else if (q < Scalar(0) && n > 0) // Complex vector
- {
- Scalar lastra=0, lastsa=0, lastw=0;
- Index l = n-1;
-
- // Last vector component imaginary so matrix is triangular
- if (internal::abs(m_matT.coeff(n,n-1)) > internal::abs(m_matT.coeff(n-1,n)))
- {
- m_matT.coeffRef(n-1,n-1) = q / m_matT.coeff(n,n-1);
- m_matT.coeffRef(n-1,n) = -(m_matT.coeff(n,n) - p) / m_matT.coeff(n,n-1);
- }
- else
- {
- std::complex<Scalar> cc = cdiv<Scalar>(0.0,-m_matT.coeff(n-1,n),m_matT.coeff(n-1,n-1)-p,q);
- m_matT.coeffRef(n-1,n-1) = internal::real(cc);
- m_matT.coeffRef(n-1,n) = internal::imag(cc);
- }
- m_matT.coeffRef(n,n-1) = 0.0;
- m_matT.coeffRef(n,n) = 1.0;
- for (Index i = n-2; i >= 0; i--)
- {
- Scalar ra = m_matT.row(i).segment(l, n-l+1).dot(m_matT.col(n-1).segment(l, n-l+1));
- Scalar sa = m_matT.row(i).segment(l, n-l+1).dot(m_matT.col(n).segment(l, n-l+1));
- Scalar w = m_matT.coeff(i,i) - p;
-
- if (m_eivalues.coeff(i).imag() < 0.0)
- {
- lastw = w;
- lastra = ra;
- lastsa = sa;
- }
- else
- {
- l = i;
- if (m_eivalues.coeff(i).imag() == RealScalar(0))
- {
- std::complex<Scalar> cc = cdiv(-ra,-sa,w,q);
- m_matT.coeffRef(i,n-1) = internal::real(cc);
- m_matT.coeffRef(i,n) = internal::imag(cc);
- }
- else
- {
- // Solve complex equations
- Scalar x = m_matT.coeff(i,i+1);
- Scalar y = m_matT.coeff(i+1,i);
- Scalar vr = (m_eivalues.coeff(i).real() - p) * (m_eivalues.coeff(i).real() - p) + m_eivalues.coeff(i).imag() * m_eivalues.coeff(i).imag() - q * q;
- Scalar vi = (m_eivalues.coeff(i).real() - p) * Scalar(2) * q;
- if ((vr == 0.0) && (vi == 0.0))
- vr = eps * norm * (internal::abs(w) + internal::abs(q) + internal::abs(x) + internal::abs(y) + internal::abs(lastw));
-
- std::complex<Scalar> cc = cdiv(x*lastra-lastw*ra+q*sa,x*lastsa-lastw*sa-q*ra,vr,vi);
- m_matT.coeffRef(i,n-1) = internal::real(cc);
- m_matT.coeffRef(i,n) = internal::imag(cc);
- if (internal::abs(x) > (internal::abs(lastw) + internal::abs(q)))
- {
- m_matT.coeffRef(i+1,n-1) = (-ra - w * m_matT.coeff(i,n-1) + q * m_matT.coeff(i,n)) / x;
- m_matT.coeffRef(i+1,n) = (-sa - w * m_matT.coeff(i,n) - q * m_matT.coeff(i,n-1)) / x;
- }
- else
- {
- cc = cdiv(-lastra-y*m_matT.coeff(i,n-1),-lastsa-y*m_matT.coeff(i,n),lastw,q);
- m_matT.coeffRef(i+1,n-1) = internal::real(cc);
- m_matT.coeffRef(i+1,n) = internal::imag(cc);
- }
- }
-
- // Overflow control
- using std::max;
- Scalar t = (max)(internal::abs(m_matT.coeff(i,n-1)),internal::abs(m_matT.coeff(i,n)));
- if ((eps * t) * t > Scalar(1))
- m_matT.block(i, n-1, size-i, 2) /= t;
-
- }
- }
- }
- else
- {
- eigen_assert("Internal bug in EigenSolver"); // this should not happen
- }
- }
-
- // Back transformation to get eigenvectors of original matrix
- for (Index j = size-1; j >= 0; j--)
- {
- m_tmp.noalias() = m_eivec.leftCols(j+1) * m_matT.col(j).segment(0, j+1);
- m_eivec.col(j) = m_tmp;
- }
-}
-
-#endif // EIGEN_EIGENSOLVER_H
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/EigenvaluesCommon.h b/extern/Eigen3/Eigen/src/Eigenvalues/EigenvaluesCommon.h
deleted file mode 100644
index 749bea79500..00000000000
--- a/extern/Eigen3/Eigen/src/Eigenvalues/EigenvaluesCommon.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_EIGENVALUES_COMMON_H
-#define EIGEN_EIGENVALUES_COMMON_H
-
-
-
-#endif // EIGEN_EIGENVALUES_COMMON_H
-
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h b/extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h
deleted file mode 100644
index 980af14ce71..00000000000
--- a/extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h
+++ /dev/null
@@ -1,239 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_GENERALIZEDSELFADJOINTEIGENSOLVER_H
-#define EIGEN_GENERALIZEDSELFADJOINTEIGENSOLVER_H
-
-#include "./EigenvaluesCommon.h"
-#include "./Tridiagonalization.h"
-
-/** \eigenvalues_module \ingroup Eigenvalues_Module
- *
- *
- * \class GeneralizedSelfAdjointEigenSolver
- *
- * \brief Computes eigenvalues and eigenvectors of the generalized selfadjoint eigen problem
- *
- * \tparam _MatrixType the type of the matrix of which we are computing the
- * eigendecomposition; this is expected to be an instantiation of the Matrix
- * class template.
- *
- * This class solves the generalized eigenvalue problem
- * \f$ Av = \lambda Bv \f$. In this case, the matrix \f$ A \f$ should be
- * selfadjoint and the matrix \f$ B \f$ should be positive definite.
- *
- * Only the \b lower \b triangular \b part of the input matrix is referenced.
- *
- * Call the function compute() to compute the eigenvalues and eigenvectors of
- * a given matrix. Alternatively, you can use the
- * GeneralizedSelfAdjointEigenSolver(const MatrixType&, const MatrixType&, int)
- * constructor which computes the eigenvalues and eigenvectors at construction time.
- * Once the eigenvalue and eigenvectors are computed, they can be retrieved with the eigenvalues()
- * and eigenvectors() functions.
- *
- * The documentation for GeneralizedSelfAdjointEigenSolver(const MatrixType&, const MatrixType&, int)
- * contains an example of the typical use of this class.
- *
- * \sa class SelfAdjointEigenSolver, class EigenSolver, class ComplexEigenSolver
- */
-template<typename _MatrixType>
-class GeneralizedSelfAdjointEigenSolver : public SelfAdjointEigenSolver<_MatrixType>
-{
- typedef SelfAdjointEigenSolver<_MatrixType> Base;
- public:
-
- typedef typename Base::Index Index;
- typedef _MatrixType MatrixType;
-
- /** \brief Default constructor for fixed-size matrices.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via compute(). This constructor
- * can only be used if \p _MatrixType is a fixed-size matrix; use
- * GeneralizedSelfAdjointEigenSolver(Index) for dynamic-size matrices.
- */
- GeneralizedSelfAdjointEigenSolver() : Base() {}
-
- /** \brief Constructor, pre-allocates memory for dynamic-size matrices.
- *
- * \param [in] size Positive integer, size of the matrix whose
- * eigenvalues and eigenvectors will be computed.
- *
- * This constructor is useful for dynamic-size matrices, when the user
- * intends to perform decompositions via compute(). The \p size
- * parameter is only used as a hint. It is not an error to give a wrong
- * \p size, but it may impair performance.
- *
- * \sa compute() for an example
- */
- GeneralizedSelfAdjointEigenSolver(Index size)
- : Base(size)
- {}
-
- /** \brief Constructor; computes generalized eigendecomposition of given matrix pencil.
- *
- * \param[in] matA Selfadjoint matrix in matrix pencil.
- * Only the lower triangular part of the matrix is referenced.
- * \param[in] matB Positive-definite matrix in matrix pencil.
- * Only the lower triangular part of the matrix is referenced.
- * \param[in] options A or-ed set of flags {#ComputeEigenvectors,#EigenvaluesOnly} | {#Ax_lBx,#ABx_lx,#BAx_lx}.
- * Default is #ComputeEigenvectors|#Ax_lBx.
- *
- * This constructor calls compute(const MatrixType&, const MatrixType&, int)
- * to compute the eigenvalues and (if requested) the eigenvectors of the
- * generalized eigenproblem \f$ Ax = \lambda B x \f$ with \a matA the
- * selfadjoint matrix \f$ A \f$ and \a matB the positive definite matrix
- * \f$ B \f$. Each eigenvector \f$ x \f$ satisfies the property
- * \f$ x^* B x = 1 \f$. The eigenvectors are computed if
- * \a options contains ComputeEigenvectors.
- *
- * In addition, the two following variants can be solved via \p options:
- * - \c ABx_lx: \f$ ABx = \lambda x \f$
- * - \c BAx_lx: \f$ BAx = \lambda x \f$
- *
- * Example: \include SelfAdjointEigenSolver_SelfAdjointEigenSolver_MatrixType2.cpp
- * Output: \verbinclude SelfAdjointEigenSolver_SelfAdjointEigenSolver_MatrixType2.out
- *
- * \sa compute(const MatrixType&, const MatrixType&, int)
- */
- GeneralizedSelfAdjointEigenSolver(const MatrixType& matA, const MatrixType& matB,
- int options = ComputeEigenvectors|Ax_lBx)
- : Base(matA.cols())
- {
- compute(matA, matB, options);
- }
-
- /** \brief Computes generalized eigendecomposition of given matrix pencil.
- *
- * \param[in] matA Selfadjoint matrix in matrix pencil.
- * Only the lower triangular part of the matrix is referenced.
- * \param[in] matB Positive-definite matrix in matrix pencil.
- * Only the lower triangular part of the matrix is referenced.
- * \param[in] options A or-ed set of flags {#ComputeEigenvectors,#EigenvaluesOnly} | {#Ax_lBx,#ABx_lx,#BAx_lx}.
- * Default is #ComputeEigenvectors|#Ax_lBx.
- *
- * \returns Reference to \c *this
- *
- * Accoring to \p options, this function computes eigenvalues and (if requested)
- * the eigenvectors of one of the following three generalized eigenproblems:
- * - \c Ax_lBx: \f$ Ax = \lambda B x \f$
- * - \c ABx_lx: \f$ ABx = \lambda x \f$
- * - \c BAx_lx: \f$ BAx = \lambda x \f$
- * with \a matA the selfadjoint matrix \f$ A \f$ and \a matB the positive definite
- * matrix \f$ B \f$.
- * In addition, each eigenvector \f$ x \f$ satisfies the property \f$ x^* B x = 1 \f$.
- *
- * The eigenvalues() function can be used to retrieve
- * the eigenvalues. If \p options contains ComputeEigenvectors, then the
- * eigenvectors are also computed and can be retrieved by calling
- * eigenvectors().
- *
- * The implementation uses LLT to compute the Cholesky decomposition
- * \f$ B = LL^* \f$ and computes the classical eigendecomposition
- * of the selfadjoint matrix \f$ L^{-1} A (L^*)^{-1} \f$ if \p options contains Ax_lBx
- * and of \f$ L^{*} A L \f$ otherwise. This solves the
- * generalized eigenproblem, because any solution of the generalized
- * eigenproblem \f$ Ax = \lambda B x \f$ corresponds to a solution
- * \f$ L^{-1} A (L^*)^{-1} (L^* x) = \lambda (L^* x) \f$ of the
- * eigenproblem for \f$ L^{-1} A (L^*)^{-1} \f$. Similar statements
- * can be made for the two other variants.
- *
- * Example: \include SelfAdjointEigenSolver_compute_MatrixType2.cpp
- * Output: \verbinclude SelfAdjointEigenSolver_compute_MatrixType2.out
- *
- * \sa GeneralizedSelfAdjointEigenSolver(const MatrixType&, const MatrixType&, int)
- */
- GeneralizedSelfAdjointEigenSolver& compute(const MatrixType& matA, const MatrixType& matB,
- int options = ComputeEigenvectors|Ax_lBx);
-
- protected:
-
-};
-
-
-template<typename MatrixType>
-GeneralizedSelfAdjointEigenSolver<MatrixType>& GeneralizedSelfAdjointEigenSolver<MatrixType>::
-compute(const MatrixType& matA, const MatrixType& matB, int options)
-{
- eigen_assert(matA.cols()==matA.rows() && matB.rows()==matA.rows() && matB.cols()==matB.rows());
- eigen_assert((options&~(EigVecMask|GenEigMask))==0
- && (options&EigVecMask)!=EigVecMask
- && ((options&GenEigMask)==0 || (options&GenEigMask)==Ax_lBx
- || (options&GenEigMask)==ABx_lx || (options&GenEigMask)==BAx_lx)
- && "invalid option parameter");
-
- bool computeEigVecs = ((options&EigVecMask)==0) || ((options&EigVecMask)==ComputeEigenvectors);
-
- // Compute the cholesky decomposition of matB = L L' = U'U
- LLT<MatrixType> cholB(matB);
-
- int type = (options&GenEigMask);
- if(type==0)
- type = Ax_lBx;
-
- if(type==Ax_lBx)
- {
- // compute C = inv(L) A inv(L')
- MatrixType matC = matA.template selfadjointView<Lower>();
- cholB.matrixL().template solveInPlace<OnTheLeft>(matC);
- cholB.matrixU().template solveInPlace<OnTheRight>(matC);
-
- Base::compute(matC, computeEigVecs ? ComputeEigenvectors : EigenvaluesOnly );
-
- // transform back the eigen vectors: evecs = inv(U) * evecs
- if(computeEigVecs)
- cholB.matrixU().solveInPlace(Base::m_eivec);
- }
- else if(type==ABx_lx)
- {
- // compute C = L' A L
- MatrixType matC = matA.template selfadjointView<Lower>();
- matC = matC * cholB.matrixL();
- matC = cholB.matrixU() * matC;
-
- Base::compute(matC, computeEigVecs ? ComputeEigenvectors : EigenvaluesOnly);
-
- // transform back the eigen vectors: evecs = inv(U) * evecs
- if(computeEigVecs)
- cholB.matrixU().solveInPlace(Base::m_eivec);
- }
- else if(type==BAx_lx)
- {
- // compute C = L' A L
- MatrixType matC = matA.template selfadjointView<Lower>();
- matC = matC * cholB.matrixL();
- matC = cholB.matrixU() * matC;
-
- Base::compute(matC, computeEigVecs ? ComputeEigenvectors : EigenvaluesOnly);
-
- // transform back the eigen vectors: evecs = L * evecs
- if(computeEigVecs)
- Base::m_eivec = cholB.matrixL() * Base::m_eivec;
- }
-
- return *this;
-}
-
-#endif // EIGEN_GENERALIZEDSELFADJOINTEIGENSOLVER_H
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h b/extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h
deleted file mode 100644
index c17f155a59b..00000000000
--- a/extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h
+++ /dev/null
@@ -1,384 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_HESSENBERGDECOMPOSITION_H
-#define EIGEN_HESSENBERGDECOMPOSITION_H
-
-namespace internal {
-
-template<typename MatrixType> struct HessenbergDecompositionMatrixHReturnType;
-template<typename MatrixType>
-struct traits<HessenbergDecompositionMatrixHReturnType<MatrixType> >
-{
- typedef MatrixType ReturnType;
-};
-
-}
-
-/** \eigenvalues_module \ingroup Eigenvalues_Module
- *
- *
- * \class HessenbergDecomposition
- *
- * \brief Reduces a square matrix to Hessenberg form by an orthogonal similarity transformation
- *
- * \tparam _MatrixType the type of the matrix of which we are computing the Hessenberg decomposition
- *
- * This class performs an Hessenberg decomposition of a matrix \f$ A \f$. In
- * the real case, the Hessenberg decomposition consists of an orthogonal
- * matrix \f$ Q \f$ and a Hessenberg matrix \f$ H \f$ such that \f$ A = Q H
- * Q^T \f$. An orthogonal matrix is a matrix whose inverse equals its
- * transpose (\f$ Q^{-1} = Q^T \f$). A Hessenberg matrix has zeros below the
- * subdiagonal, so it is almost upper triangular. The Hessenberg decomposition
- * of a complex matrix is \f$ A = Q H Q^* \f$ with \f$ Q \f$ unitary (that is,
- * \f$ Q^{-1} = Q^* \f$).
- *
- * Call the function compute() to compute the Hessenberg decomposition of a
- * given matrix. Alternatively, you can use the
- * HessenbergDecomposition(const MatrixType&) constructor which computes the
- * Hessenberg decomposition at construction time. Once the decomposition is
- * computed, you can use the matrixH() and matrixQ() functions to construct
- * the matrices H and Q in the decomposition.
- *
- * The documentation for matrixH() contains an example of the typical use of
- * this class.
- *
- * \sa class ComplexSchur, class Tridiagonalization, \ref QR_Module "QR Module"
- */
-template<typename _MatrixType> class HessenbergDecomposition
-{
- public:
-
- /** \brief Synonym for the template parameter \p _MatrixType. */
- typedef _MatrixType MatrixType;
-
- enum {
- Size = MatrixType::RowsAtCompileTime,
- SizeMinusOne = Size == Dynamic ? Dynamic : Size - 1,
- Options = MatrixType::Options,
- MaxSize = MatrixType::MaxRowsAtCompileTime,
- MaxSizeMinusOne = MaxSize == Dynamic ? Dynamic : MaxSize - 1
- };
-
- /** \brief Scalar type for matrices of type #MatrixType. */
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::Index Index;
-
- /** \brief Type for vector of Householder coefficients.
- *
- * This is column vector with entries of type #Scalar. The length of the
- * vector is one less than the size of #MatrixType, if it is a fixed-side
- * type.
- */
- typedef Matrix<Scalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> CoeffVectorType;
-
- /** \brief Return type of matrixQ() */
- typedef typename HouseholderSequence<MatrixType,CoeffVectorType>::ConjugateReturnType HouseholderSequenceType;
-
- typedef internal::HessenbergDecompositionMatrixHReturnType<MatrixType> MatrixHReturnType;
-
- /** \brief Default constructor; the decomposition will be computed later.
- *
- * \param [in] size The size of the matrix whose Hessenberg decomposition will be computed.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via compute(). The \p size parameter is only
- * used as a hint. It is not an error to give a wrong \p size, but it may
- * impair performance.
- *
- * \sa compute() for an example.
- */
- HessenbergDecomposition(Index size = Size==Dynamic ? 2 : Size)
- : m_matrix(size,size),
- m_temp(size),
- m_isInitialized(false)
- {
- if(size>1)
- m_hCoeffs.resize(size-1);
- }
-
- /** \brief Constructor; computes Hessenberg decomposition of given matrix.
- *
- * \param[in] matrix Square matrix whose Hessenberg decomposition is to be computed.
- *
- * This constructor calls compute() to compute the Hessenberg
- * decomposition.
- *
- * \sa matrixH() for an example.
- */
- HessenbergDecomposition(const MatrixType& matrix)
- : m_matrix(matrix),
- m_temp(matrix.rows()),
- m_isInitialized(false)
- {
- if(matrix.rows()<2)
- {
- m_isInitialized = true;
- return;
- }
- m_hCoeffs.resize(matrix.rows()-1,1);
- _compute(m_matrix, m_hCoeffs, m_temp);
- m_isInitialized = true;
- }
-
- /** \brief Computes Hessenberg decomposition of given matrix.
- *
- * \param[in] matrix Square matrix whose Hessenberg decomposition is to be computed.
- * \returns Reference to \c *this
- *
- * The Hessenberg decomposition is computed by bringing the columns of the
- * matrix successively in the required form using Householder reflections
- * (see, e.g., Algorithm 7.4.2 in Golub \& Van Loan, <i>%Matrix
- * Computations</i>). The cost is \f$ 10n^3/3 \f$ flops, where \f$ n \f$
- * denotes the size of the given matrix.
- *
- * This method reuses of the allocated data in the HessenbergDecomposition
- * object.
- *
- * Example: \include HessenbergDecomposition_compute.cpp
- * Output: \verbinclude HessenbergDecomposition_compute.out
- */
- HessenbergDecomposition& compute(const MatrixType& matrix)
- {
- m_matrix = matrix;
- if(matrix.rows()<2)
- {
- m_isInitialized = true;
- return *this;
- }
- m_hCoeffs.resize(matrix.rows()-1,1);
- _compute(m_matrix, m_hCoeffs, m_temp);
- m_isInitialized = true;
- return *this;
- }
-
- /** \brief Returns the Householder coefficients.
- *
- * \returns a const reference to the vector of Householder coefficients
- *
- * \pre Either the constructor HessenbergDecomposition(const MatrixType&)
- * or the member function compute(const MatrixType&) has been called
- * before to compute the Hessenberg decomposition of a matrix.
- *
- * The Householder coefficients allow the reconstruction of the matrix
- * \f$ Q \f$ in the Hessenberg decomposition from the packed data.
- *
- * \sa packedMatrix(), \ref Householder_Module "Householder module"
- */
- const CoeffVectorType& householderCoefficients() const
- {
- eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
- return m_hCoeffs;
- }
-
- /** \brief Returns the internal representation of the decomposition
- *
- * \returns a const reference to a matrix with the internal representation
- * of the decomposition.
- *
- * \pre Either the constructor HessenbergDecomposition(const MatrixType&)
- * or the member function compute(const MatrixType&) has been called
- * before to compute the Hessenberg decomposition of a matrix.
- *
- * The returned matrix contains the following information:
- * - the upper part and lower sub-diagonal represent the Hessenberg matrix H
- * - the rest of the lower part contains the Householder vectors that, combined with
- * Householder coefficients returned by householderCoefficients(),
- * allows to reconstruct the matrix Q as
- * \f$ Q = H_{N-1} \ldots H_1 H_0 \f$.
- * Here, the matrices \f$ H_i \f$ are the Householder transformations
- * \f$ H_i = (I - h_i v_i v_i^T) \f$
- * where \f$ h_i \f$ is the \f$ i \f$th Householder coefficient and
- * \f$ v_i \f$ is the Householder vector defined by
- * \f$ v_i = [ 0, \ldots, 0, 1, M(i+2,i), \ldots, M(N-1,i) ]^T \f$
- * with M the matrix returned by this function.
- *
- * See LAPACK for further details on this packed storage.
- *
- * Example: \include HessenbergDecomposition_packedMatrix.cpp
- * Output: \verbinclude HessenbergDecomposition_packedMatrix.out
- *
- * \sa householderCoefficients()
- */
- const MatrixType& packedMatrix() const
- {
- eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
- return m_matrix;
- }
-
- /** \brief Reconstructs the orthogonal matrix Q in the decomposition
- *
- * \returns object representing the matrix Q
- *
- * \pre Either the constructor HessenbergDecomposition(const MatrixType&)
- * or the member function compute(const MatrixType&) has been called
- * before to compute the Hessenberg decomposition of a matrix.
- *
- * This function returns a light-weight object of template class
- * HouseholderSequence. You can either apply it directly to a matrix or
- * you can convert it to a matrix of type #MatrixType.
- *
- * \sa matrixH() for an example, class HouseholderSequence
- */
- HouseholderSequenceType matrixQ() const
- {
- eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
- return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate())
- .setLength(m_matrix.rows() - 1)
- .setShift(1);
- }
-
- /** \brief Constructs the Hessenberg matrix H in the decomposition
- *
- * \returns expression object representing the matrix H
- *
- * \pre Either the constructor HessenbergDecomposition(const MatrixType&)
- * or the member function compute(const MatrixType&) has been called
- * before to compute the Hessenberg decomposition of a matrix.
- *
- * The object returned by this function constructs the Hessenberg matrix H
- * when it is assigned to a matrix or otherwise evaluated. The matrix H is
- * constructed from the packed matrix as returned by packedMatrix(): The
- * upper part (including the subdiagonal) of the packed matrix contains
- * the matrix H. It may sometimes be better to directly use the packed
- * matrix instead of constructing the matrix H.
- *
- * Example: \include HessenbergDecomposition_matrixH.cpp
- * Output: \verbinclude HessenbergDecomposition_matrixH.out
- *
- * \sa matrixQ(), packedMatrix()
- */
- MatrixHReturnType matrixH() const
- {
- eigen_assert(m_isInitialized && "HessenbergDecomposition is not initialized.");
- return MatrixHReturnType(*this);
- }
-
- private:
-
- typedef Matrix<Scalar, 1, Size, Options | RowMajor, 1, MaxSize> VectorType;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- static void _compute(MatrixType& matA, CoeffVectorType& hCoeffs, VectorType& temp);
-
- protected:
- MatrixType m_matrix;
- CoeffVectorType m_hCoeffs;
- VectorType m_temp;
- bool m_isInitialized;
-};
-
-/** \internal
- * Performs a tridiagonal decomposition of \a matA in place.
- *
- * \param matA the input selfadjoint matrix
- * \param hCoeffs returned Householder coefficients
- *
- * The result is written in the lower triangular part of \a matA.
- *
- * Implemented from Golub's "%Matrix Computations", algorithm 8.3.1.
- *
- * \sa packedMatrix()
- */
-template<typename MatrixType>
-void HessenbergDecomposition<MatrixType>::_compute(MatrixType& matA, CoeffVectorType& hCoeffs, VectorType& temp)
-{
- assert(matA.rows()==matA.cols());
- Index n = matA.rows();
- temp.resize(n);
- for (Index i = 0; i<n-1; ++i)
- {
- // let's consider the vector v = i-th column starting at position i+1
- Index remainingSize = n-i-1;
- RealScalar beta;
- Scalar h;
- matA.col(i).tail(remainingSize).makeHouseholderInPlace(h, beta);
- matA.col(i).coeffRef(i+1) = beta;
- hCoeffs.coeffRef(i) = h;
-
- // Apply similarity transformation to remaining columns,
- // i.e., compute A = H A H'
-
- // A = H A
- matA.bottomRightCorner(remainingSize, remainingSize)
- .applyHouseholderOnTheLeft(matA.col(i).tail(remainingSize-1), h, &temp.coeffRef(0));
-
- // A = A H'
- matA.rightCols(remainingSize)
- .applyHouseholderOnTheRight(matA.col(i).tail(remainingSize-1).conjugate(), internal::conj(h), &temp.coeffRef(0));
- }
-}
-
-namespace internal {
-
-/** \eigenvalues_module \ingroup Eigenvalues_Module
- *
- *
- * \brief Expression type for return value of HessenbergDecomposition::matrixH()
- *
- * \tparam MatrixType type of matrix in the Hessenberg decomposition
- *
- * Objects of this type represent the Hessenberg matrix in the Hessenberg
- * decomposition of some matrix. The object holds a reference to the
- * HessenbergDecomposition class until the it is assigned or evaluated for
- * some other reason (the reference should remain valid during the life time
- * of this object). This class is the return type of
- * HessenbergDecomposition::matrixH(); there is probably no other use for this
- * class.
- */
-template<typename MatrixType> struct HessenbergDecompositionMatrixHReturnType
-: public ReturnByValue<HessenbergDecompositionMatrixHReturnType<MatrixType> >
-{
- typedef typename MatrixType::Index Index;
- public:
- /** \brief Constructor.
- *
- * \param[in] hess Hessenberg decomposition
- */
- HessenbergDecompositionMatrixHReturnType(const HessenbergDecomposition<MatrixType>& hess) : m_hess(hess) { }
-
- /** \brief Hessenberg matrix in decomposition.
- *
- * \param[out] result Hessenberg matrix in decomposition \p hess which
- * was passed to the constructor
- */
- template <typename ResultType>
- inline void evalTo(ResultType& result) const
- {
- result = m_hess.packedMatrix();
- Index n = result.rows();
- if (n>2)
- result.bottomLeftCorner(n-2, n-2).template triangularView<Lower>().setZero();
- }
-
- Index rows() const { return m_hess.packedMatrix().rows(); }
- Index cols() const { return m_hess.packedMatrix().cols(); }
-
- protected:
- const HessenbergDecomposition<MatrixType>& m_hess;
-};
-
-}
-
-#endif // EIGEN_HESSENBERGDECOMPOSITION_H
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h b/extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h
deleted file mode 100644
index 5591519fb75..00000000000
--- a/extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h
+++ /dev/null
@@ -1,170 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_MATRIXBASEEIGENVALUES_H
-#define EIGEN_MATRIXBASEEIGENVALUES_H
-
-namespace internal {
-
-template<typename Derived, bool IsComplex>
-struct eigenvalues_selector
-{
- // this is the implementation for the case IsComplex = true
- static inline typename MatrixBase<Derived>::EigenvaluesReturnType const
- run(const MatrixBase<Derived>& m)
- {
- typedef typename Derived::PlainObject PlainObject;
- PlainObject m_eval(m);
- return ComplexEigenSolver<PlainObject>(m_eval, false).eigenvalues();
- }
-};
-
-template<typename Derived>
-struct eigenvalues_selector<Derived, false>
-{
- static inline typename MatrixBase<Derived>::EigenvaluesReturnType const
- run(const MatrixBase<Derived>& m)
- {
- typedef typename Derived::PlainObject PlainObject;
- PlainObject m_eval(m);
- return EigenSolver<PlainObject>(m_eval, false).eigenvalues();
- }
-};
-
-} // end namespace internal
-
-/** \brief Computes the eigenvalues of a matrix
- * \returns Column vector containing the eigenvalues.
- *
- * \eigenvalues_module
- * This function computes the eigenvalues with the help of the EigenSolver
- * class (for real matrices) or the ComplexEigenSolver class (for complex
- * matrices).
- *
- * The eigenvalues are repeated according to their algebraic multiplicity,
- * so there are as many eigenvalues as rows in the matrix.
- *
- * The SelfAdjointView class provides a better algorithm for selfadjoint
- * matrices.
- *
- * Example: \include MatrixBase_eigenvalues.cpp
- * Output: \verbinclude MatrixBase_eigenvalues.out
- *
- * \sa EigenSolver::eigenvalues(), ComplexEigenSolver::eigenvalues(),
- * SelfAdjointView::eigenvalues()
- */
-template<typename Derived>
-inline typename MatrixBase<Derived>::EigenvaluesReturnType
-MatrixBase<Derived>::eigenvalues() const
-{
- typedef typename internal::traits<Derived>::Scalar Scalar;
- return internal::eigenvalues_selector<Derived, NumTraits<Scalar>::IsComplex>::run(derived());
-}
-
-/** \brief Computes the eigenvalues of a matrix
- * \returns Column vector containing the eigenvalues.
- *
- * \eigenvalues_module
- * This function computes the eigenvalues with the help of the
- * SelfAdjointEigenSolver class. The eigenvalues are repeated according to
- * their algebraic multiplicity, so there are as many eigenvalues as rows in
- * the matrix.
- *
- * Example: \include SelfAdjointView_eigenvalues.cpp
- * Output: \verbinclude SelfAdjointView_eigenvalues.out
- *
- * \sa SelfAdjointEigenSolver::eigenvalues(), MatrixBase::eigenvalues()
- */
-template<typename MatrixType, unsigned int UpLo>
-inline typename SelfAdjointView<MatrixType, UpLo>::EigenvaluesReturnType
-SelfAdjointView<MatrixType, UpLo>::eigenvalues() const
-{
- typedef typename SelfAdjointView<MatrixType, UpLo>::PlainObject PlainObject;
- PlainObject thisAsMatrix(*this);
- return SelfAdjointEigenSolver<PlainObject>(thisAsMatrix, false).eigenvalues();
-}
-
-
-
-/** \brief Computes the L2 operator norm
- * \returns Operator norm of the matrix.
- *
- * \eigenvalues_module
- * This function computes the L2 operator norm of a matrix, which is also
- * known as the spectral norm. The norm of a matrix \f$ A \f$ is defined to be
- * \f[ \|A\|_2 = \max_x \frac{\|Ax\|_2}{\|x\|_2} \f]
- * where the maximum is over all vectors and the norm on the right is the
- * Euclidean vector norm. The norm equals the largest singular value, which is
- * the square root of the largest eigenvalue of the positive semi-definite
- * matrix \f$ A^*A \f$.
- *
- * The current implementation uses the eigenvalues of \f$ A^*A \f$, as computed
- * by SelfAdjointView::eigenvalues(), to compute the operator norm of a
- * matrix. The SelfAdjointView class provides a better algorithm for
- * selfadjoint matrices.
- *
- * Example: \include MatrixBase_operatorNorm.cpp
- * Output: \verbinclude MatrixBase_operatorNorm.out
- *
- * \sa SelfAdjointView::eigenvalues(), SelfAdjointView::operatorNorm()
- */
-template<typename Derived>
-inline typename MatrixBase<Derived>::RealScalar
-MatrixBase<Derived>::operatorNorm() const
-{
- typename Derived::PlainObject m_eval(derived());
- // FIXME if it is really guaranteed that the eigenvalues are already sorted,
- // then we don't need to compute a maxCoeff() here, comparing the 1st and last ones is enough.
- return internal::sqrt((m_eval*m_eval.adjoint())
- .eval()
- .template selfadjointView<Lower>()
- .eigenvalues()
- .maxCoeff()
- );
-}
-
-/** \brief Computes the L2 operator norm
- * \returns Operator norm of the matrix.
- *
- * \eigenvalues_module
- * This function computes the L2 operator norm of a self-adjoint matrix. For a
- * self-adjoint matrix, the operator norm is the largest eigenvalue.
- *
- * The current implementation uses the eigenvalues of the matrix, as computed
- * by eigenvalues(), to compute the operator norm of the matrix.
- *
- * Example: \include SelfAdjointView_operatorNorm.cpp
- * Output: \verbinclude SelfAdjointView_operatorNorm.out
- *
- * \sa eigenvalues(), MatrixBase::operatorNorm()
- */
-template<typename MatrixType, unsigned int UpLo>
-inline typename SelfAdjointView<MatrixType, UpLo>::RealScalar
-SelfAdjointView<MatrixType, UpLo>::operatorNorm() const
-{
- return eigenvalues().cwiseAbs().maxCoeff();
-}
-
-#endif
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h b/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h
deleted file mode 100644
index cc9af11c117..00000000000
--- a/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h
+++ /dev/null
@@ -1,474 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_REAL_SCHUR_H
-#define EIGEN_REAL_SCHUR_H
-
-#include "./EigenvaluesCommon.h"
-#include "./HessenbergDecomposition.h"
-
-/** \eigenvalues_module \ingroup Eigenvalues_Module
- *
- *
- * \class RealSchur
- *
- * \brief Performs a real Schur decomposition of a square matrix
- *
- * \tparam _MatrixType the type of the matrix of which we are computing the
- * real Schur decomposition; this is expected to be an instantiation of the
- * Matrix class template.
- *
- * Given a real square matrix A, this class computes the real Schur
- * decomposition: \f$ A = U T U^T \f$ where U is a real orthogonal matrix and
- * T is a real quasi-triangular matrix. An orthogonal matrix is a matrix whose
- * inverse is equal to its transpose, \f$ U^{-1} = U^T \f$. A quasi-triangular
- * matrix is a block-triangular matrix whose diagonal consists of 1-by-1
- * blocks and 2-by-2 blocks with complex eigenvalues. The eigenvalues of the
- * blocks on the diagonal of T are the same as the eigenvalues of the matrix
- * A, and thus the real Schur decomposition is used in EigenSolver to compute
- * the eigendecomposition of a matrix.
- *
- * Call the function compute() to compute the real Schur decomposition of a
- * given matrix. Alternatively, you can use the RealSchur(const MatrixType&, bool)
- * constructor which computes the real Schur decomposition at construction
- * time. Once the decomposition is computed, you can use the matrixU() and
- * matrixT() functions to retrieve the matrices U and T in the decomposition.
- *
- * The documentation of RealSchur(const MatrixType&, bool) contains an example
- * of the typical use of this class.
- *
- * \note The implementation is adapted from
- * <a href="http://math.nist.gov/javanumerics/jama/">JAMA</a> (public domain).
- * Their code is based on EISPACK.
- *
- * \sa class ComplexSchur, class EigenSolver, class ComplexEigenSolver
- */
-template<typename _MatrixType> class RealSchur
-{
- public:
- typedef _MatrixType MatrixType;
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- Options = MatrixType::Options,
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
- };
- typedef typename MatrixType::Scalar Scalar;
- typedef std::complex<typename NumTraits<Scalar>::Real> ComplexScalar;
- typedef typename MatrixType::Index Index;
-
- typedef Matrix<ComplexScalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> EigenvalueType;
- typedef Matrix<Scalar, ColsAtCompileTime, 1, Options & ~RowMajor, MaxColsAtCompileTime, 1> ColumnVectorType;
-
- /** \brief Default constructor.
- *
- * \param [in] size Positive integer, size of the matrix whose Schur decomposition will be computed.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via compute(). The \p size parameter is only
- * used as a hint. It is not an error to give a wrong \p size, but it may
- * impair performance.
- *
- * \sa compute() for an example.
- */
- RealSchur(Index size = RowsAtCompileTime==Dynamic ? 1 : RowsAtCompileTime)
- : m_matT(size, size),
- m_matU(size, size),
- m_workspaceVector(size),
- m_hess(size),
- m_isInitialized(false),
- m_matUisUptodate(false)
- { }
-
- /** \brief Constructor; computes real Schur decomposition of given matrix.
- *
- * \param[in] matrix Square matrix whose Schur decomposition is to be computed.
- * \param[in] computeU If true, both T and U are computed; if false, only T is computed.
- *
- * This constructor calls compute() to compute the Schur decomposition.
- *
- * Example: \include RealSchur_RealSchur_MatrixType.cpp
- * Output: \verbinclude RealSchur_RealSchur_MatrixType.out
- */
- RealSchur(const MatrixType& matrix, bool computeU = true)
- : m_matT(matrix.rows(),matrix.cols()),
- m_matU(matrix.rows(),matrix.cols()),
- m_workspaceVector(matrix.rows()),
- m_hess(matrix.rows()),
- m_isInitialized(false),
- m_matUisUptodate(false)
- {
- compute(matrix, computeU);
- }
-
- /** \brief Returns the orthogonal matrix in the Schur decomposition.
- *
- * \returns A const reference to the matrix U.
- *
- * \pre Either the constructor RealSchur(const MatrixType&, bool) or the
- * member function compute(const MatrixType&, bool) has been called before
- * to compute the Schur decomposition of a matrix, and \p computeU was set
- * to true (the default value).
- *
- * \sa RealSchur(const MatrixType&, bool) for an example
- */
- const MatrixType& matrixU() const
- {
- eigen_assert(m_isInitialized && "RealSchur is not initialized.");
- eigen_assert(m_matUisUptodate && "The matrix U has not been computed during the RealSchur decomposition.");
- return m_matU;
- }
-
- /** \brief Returns the quasi-triangular matrix in the Schur decomposition.
- *
- * \returns A const reference to the matrix T.
- *
- * \pre Either the constructor RealSchur(const MatrixType&, bool) or the
- * member function compute(const MatrixType&, bool) has been called before
- * to compute the Schur decomposition of a matrix.
- *
- * \sa RealSchur(const MatrixType&, bool) for an example
- */
- const MatrixType& matrixT() const
- {
- eigen_assert(m_isInitialized && "RealSchur is not initialized.");
- return m_matT;
- }
-
- /** \brief Computes Schur decomposition of given matrix.
- *
- * \param[in] matrix Square matrix whose Schur decomposition is to be computed.
- * \param[in] computeU If true, both T and U are computed; if false, only T is computed.
- * \returns Reference to \c *this
- *
- * The Schur decomposition is computed by first reducing the matrix to
- * Hessenberg form using the class HessenbergDecomposition. The Hessenberg
- * matrix is then reduced to triangular form by performing Francis QR
- * iterations with implicit double shift. The cost of computing the Schur
- * decomposition depends on the number of iterations; as a rough guide, it
- * may be taken to be \f$25n^3\f$ flops if \a computeU is true and
- * \f$10n^3\f$ flops if \a computeU is false.
- *
- * Example: \include RealSchur_compute.cpp
- * Output: \verbinclude RealSchur_compute.out
- */
- RealSchur& compute(const MatrixType& matrix, bool computeU = true);
-
- /** \brief Reports whether previous computation was successful.
- *
- * \returns \c Success if computation was succesful, \c NoConvergence otherwise.
- */
- ComputationInfo info() const
- {
- eigen_assert(m_isInitialized && "RealSchur is not initialized.");
- return m_info;
- }
-
- /** \brief Maximum number of iterations.
- *
- * Maximum number of iterations allowed for an eigenvalue to converge.
- */
- static const int m_maxIterations = 40;
-
- private:
-
- MatrixType m_matT;
- MatrixType m_matU;
- ColumnVectorType m_workspaceVector;
- HessenbergDecomposition<MatrixType> m_hess;
- ComputationInfo m_info;
- bool m_isInitialized;
- bool m_matUisUptodate;
-
- typedef Matrix<Scalar,3,1> Vector3s;
-
- Scalar computeNormOfT();
- Index findSmallSubdiagEntry(Index iu, Scalar norm);
- void splitOffTwoRows(Index iu, bool computeU, 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);
- void performFrancisQRStep(Index il, Index im, Index iu, bool computeU, const Vector3s& firstHouseholderVector, Scalar* workspace);
-};
-
-
-template<typename MatrixType>
-RealSchur<MatrixType>& RealSchur<MatrixType>::compute(const MatrixType& matrix, bool computeU)
-{
- assert(matrix.cols() == matrix.rows());
-
- // Step 1. Reduce to Hessenberg form
- m_hess.compute(matrix);
- m_matT = m_hess.matrixH();
- if (computeU)
- m_matU = m_hess.matrixQ();
-
- // Step 2. Reduce to real Schur form
- m_workspaceVector.resize(m_matT.cols());
- Scalar* workspace = &m_workspaceVector.coeffRef(0);
-
- // The matrix m_matT is divided in three parts.
- // Rows 0,...,il-1 are decoupled from the rest because m_matT(il,il-1) is zero.
- // Rows il,...,iu is the part we are working on (the active window).
- // Rows iu+1,...,end are already brought in triangular form.
- Index iu = m_matT.cols() - 1;
- Index iter = 0; // iteration count
- Scalar exshift = 0.0; // sum of exceptional shifts
- Scalar norm = computeNormOfT();
-
- while (iu >= 0)
- {
- Index il = findSmallSubdiagEntry(iu, norm);
-
- // Check for convergence
- if (il == iu) // One root found
- {
- m_matT.coeffRef(iu,iu) = m_matT.coeff(iu,iu) + exshift;
- if (iu > 0)
- m_matT.coeffRef(iu, iu-1) = Scalar(0);
- iu--;
- iter = 0;
- }
- else if (il == iu-1) // Two roots found
- {
- splitOffTwoRows(iu, computeU, exshift);
- iu -= 2;
- iter = 0;
- }
- else // No convergence yet
- {
- // The firstHouseholderVector vector has to be initialized to something to get rid of a silly GCC warning (-O1 -Wall -DNDEBUG )
- Vector3s firstHouseholderVector(0,0,0), shiftInfo;
- computeShift(iu, iter, exshift, shiftInfo);
- iter = iter + 1;
- if (iter > m_maxIterations) break;
- Index im;
- initFrancisQRStep(il, iu, shiftInfo, im, firstHouseholderVector);
- performFrancisQRStep(il, im, iu, computeU, firstHouseholderVector, workspace);
- }
- }
-
- if(iter <= m_maxIterations)
- m_info = Success;
- else
- m_info = NoConvergence;
-
- m_isInitialized = true;
- m_matUisUptodate = computeU;
- return *this;
-}
-
-/** \internal Computes and returns vector L1 norm of T */
-template<typename MatrixType>
-inline typename MatrixType::Scalar RealSchur<MatrixType>::computeNormOfT()
-{
- const Index size = m_matT.cols();
- // FIXME to be efficient the following would requires a triangular reduxion code
- // Scalar norm = m_matT.upper().cwiseAbs().sum()
- // + m_matT.bottomLeftCorner(size-1,size-1).diagonal().cwiseAbs().sum();
- Scalar norm = 0.0;
- for (Index j = 0; j < size; ++j)
- norm += m_matT.row(j).segment((std::max)(j-1,Index(0)), size-(std::max)(j-1,Index(0))).cwiseAbs().sum();
- return norm;
-}
-
-/** \internal Look for single small sub-diagonal element and returns its index */
-template<typename MatrixType>
-inline typename MatrixType::Index RealSchur<MatrixType>::findSmallSubdiagEntry(Index iu, Scalar norm)
-{
- Index res = iu;
- while (res > 0)
- {
- Scalar s = internal::abs(m_matT.coeff(res-1,res-1)) + internal::abs(m_matT.coeff(res,res));
- if (s == 0.0)
- s = norm;
- if (internal::abs(m_matT.coeff(res,res-1)) < NumTraits<Scalar>::epsilon() * s)
- break;
- res--;
- }
- return res;
-}
-
-/** \internal Update T given that rows iu-1 and iu decouple from the rest. */
-template<typename MatrixType>
-inline void RealSchur<MatrixType>::splitOffTwoRows(Index iu, bool computeU, Scalar exshift)
-{
- const Index size = m_matT.cols();
-
- // The eigenvalues of the 2x2 matrix [a b; c d] are
- // trace +/- sqrt(discr/4) where discr = tr^2 - 4*det, tr = a + d, det = ad - bc
- Scalar p = Scalar(0.5) * (m_matT.coeff(iu-1,iu-1) - m_matT.coeff(iu,iu));
- Scalar q = p * p + m_matT.coeff(iu,iu-1) * m_matT.coeff(iu-1,iu); // q = tr^2 / 4 - det = discr/4
- m_matT.coeffRef(iu,iu) += exshift;
- m_matT.coeffRef(iu-1,iu-1) += exshift;
-
- if (q >= Scalar(0)) // Two real eigenvalues
- {
- Scalar z = internal::sqrt(internal::abs(q));
- JacobiRotation<Scalar> rot;
- if (p >= Scalar(0))
- rot.makeGivens(p + z, m_matT.coeff(iu, iu-1));
- else
- rot.makeGivens(p - z, m_matT.coeff(iu, iu-1));
-
- m_matT.rightCols(size-iu+1).applyOnTheLeft(iu-1, iu, rot.adjoint());
- m_matT.topRows(iu+1).applyOnTheRight(iu-1, iu, rot);
- m_matT.coeffRef(iu, iu-1) = Scalar(0);
- if (computeU)
- m_matU.applyOnTheRight(iu-1, iu, rot);
- }
-
- if (iu > 1)
- m_matT.coeffRef(iu-1, iu-2) = Scalar(0);
-}
-
-/** \internal Form shift in shiftInfo, and update exshift if an exceptional shift is performed. */
-template<typename MatrixType>
-inline void RealSchur<MatrixType>::computeShift(Index iu, Index iter, Scalar& exshift, Vector3s& shiftInfo)
-{
- shiftInfo.coeffRef(0) = m_matT.coeff(iu,iu);
- shiftInfo.coeffRef(1) = m_matT.coeff(iu-1,iu-1);
- shiftInfo.coeffRef(2) = m_matT.coeff(iu,iu-1) * m_matT.coeff(iu-1,iu);
-
- // Wilkinson's original ad hoc shift
- if (iter == 10)
- {
- exshift += shiftInfo.coeff(0);
- for (Index i = 0; i <= iu; ++i)
- m_matT.coeffRef(i,i) -= shiftInfo.coeff(0);
- Scalar s = internal::abs(m_matT.coeff(iu,iu-1)) + internal::abs(m_matT.coeff(iu-1,iu-2));
- shiftInfo.coeffRef(0) = Scalar(0.75) * s;
- shiftInfo.coeffRef(1) = Scalar(0.75) * s;
- shiftInfo.coeffRef(2) = Scalar(-0.4375) * s * s;
- }
-
- // MATLAB's new ad hoc shift
- if (iter == 30)
- {
- Scalar s = (shiftInfo.coeff(1) - shiftInfo.coeff(0)) / Scalar(2.0);
- s = s * s + shiftInfo.coeff(2);
- if (s > Scalar(0))
- {
- s = internal::sqrt(s);
- if (shiftInfo.coeff(1) < shiftInfo.coeff(0))
- s = -s;
- s = s + (shiftInfo.coeff(1) - shiftInfo.coeff(0)) / Scalar(2.0);
- s = shiftInfo.coeff(0) - shiftInfo.coeff(2) / s;
- exshift += s;
- for (Index i = 0; i <= iu; ++i)
- m_matT.coeffRef(i,i) -= s;
- shiftInfo.setConstant(Scalar(0.964));
- }
- }
-}
-
-/** \internal Compute index im at which Francis QR step starts and the first Householder vector. */
-template<typename MatrixType>
-inline void RealSchur<MatrixType>::initFrancisQRStep(Index il, Index iu, const Vector3s& shiftInfo, Index& im, Vector3s& firstHouseholderVector)
-{
- Vector3s& v = firstHouseholderVector; // alias to save typing
-
- for (im = iu-2; im >= il; --im)
- {
- const Scalar Tmm = m_matT.coeff(im,im);
- const Scalar r = shiftInfo.coeff(0) - Tmm;
- const Scalar s = shiftInfo.coeff(1) - Tmm;
- v.coeffRef(0) = (r * s - shiftInfo.coeff(2)) / m_matT.coeff(im+1,im) + m_matT.coeff(im,im+1);
- v.coeffRef(1) = m_matT.coeff(im+1,im+1) - Tmm - r - s;
- v.coeffRef(2) = m_matT.coeff(im+2,im+1);
- if (im == il) {
- break;
- }
- const Scalar lhs = m_matT.coeff(im,im-1) * (internal::abs(v.coeff(1)) + internal::abs(v.coeff(2)));
- const Scalar rhs = v.coeff(0) * (internal::abs(m_matT.coeff(im-1,im-1)) + internal::abs(Tmm) + internal::abs(m_matT.coeff(im+1,im+1)));
- if (internal::abs(lhs) < NumTraits<Scalar>::epsilon() * rhs)
- {
- break;
- }
- }
-}
-
-/** \internal Perform a Francis QR step involving rows il:iu and columns im:iu. */
-template<typename MatrixType>
-inline void RealSchur<MatrixType>::performFrancisQRStep(Index il, Index im, Index iu, bool computeU, const Vector3s& firstHouseholderVector, Scalar* workspace)
-{
- assert(im >= il);
- assert(im <= iu-2);
-
- const Index size = m_matT.cols();
-
- for (Index k = im; k <= iu-2; ++k)
- {
- bool firstIteration = (k == im);
-
- Vector3s v;
- if (firstIteration)
- v = firstHouseholderVector;
- else
- v = m_matT.template block<3,1>(k,k-1);
-
- Scalar tau, beta;
- Matrix<Scalar, 2, 1> ess;
- v.makeHouseholder(ess, tau, beta);
-
- if (beta != Scalar(0)) // if v is not zero
- {
- if (firstIteration && k > il)
- m_matT.coeffRef(k,k-1) = -m_matT.coeff(k,k-1);
- else if (!firstIteration)
- m_matT.coeffRef(k,k-1) = beta;
-
- // These Householder transformations form the O(n^3) part of the algorithm
- m_matT.block(k, k, 3, size-k).applyHouseholderOnTheLeft(ess, tau, workspace);
- m_matT.block(0, k, (std::min)(iu,k+3) + 1, 3).applyHouseholderOnTheRight(ess, tau, workspace);
- if (computeU)
- m_matU.block(0, k, size, 3).applyHouseholderOnTheRight(ess, tau, workspace);
- }
- }
-
- Matrix<Scalar, 2, 1> v = m_matT.template block<2,1>(iu-1, iu-2);
- Scalar tau, beta;
- Matrix<Scalar, 1, 1> ess;
- v.makeHouseholder(ess, tau, beta);
-
- if (beta != Scalar(0)) // if v is not zero
- {
- m_matT.coeffRef(iu-1, iu-2) = beta;
- m_matT.block(iu-1, iu-1, 2, size-iu+1).applyHouseholderOnTheLeft(ess, tau, workspace);
- m_matT.block(0, iu-1, iu+1, 2).applyHouseholderOnTheRight(ess, tau, workspace);
- if (computeU)
- m_matU.block(0, iu-1, size, 2).applyHouseholderOnTheRight(ess, tau, workspace);
- }
-
- // clean up pollution due to round-off errors
- for (Index i = im+2; i <= iu; ++i)
- {
- m_matT.coeffRef(i,i-2) = Scalar(0);
- if (i > im+2)
- m_matT.coeffRef(i,i-3) = Scalar(0);
- }
-}
-
-#endif // EIGEN_REAL_SCHUR_H
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h b/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
deleted file mode 100644
index 965dda88bda..00000000000
--- a/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
+++ /dev/null
@@ -1,520 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SELFADJOINTEIGENSOLVER_H
-#define EIGEN_SELFADJOINTEIGENSOLVER_H
-
-#include "./EigenvaluesCommon.h"
-#include "./Tridiagonalization.h"
-
-template<typename _MatrixType>
-class GeneralizedSelfAdjointEigenSolver;
-
-/** \eigenvalues_module \ingroup Eigenvalues_Module
- *
- *
- * \class SelfAdjointEigenSolver
- *
- * \brief Computes eigenvalues and eigenvectors of selfadjoint matrices
- *
- * \tparam _MatrixType the type of the matrix of which we are computing the
- * eigendecomposition; this is expected to be an instantiation of the Matrix
- * class template.
- *
- * A matrix \f$ A \f$ is selfadjoint if it equals its adjoint. For real
- * matrices, this means that the matrix is symmetric: it equals its
- * transpose. This class computes the eigenvalues and eigenvectors of a
- * selfadjoint matrix. These are the scalars \f$ \lambda \f$ and vectors
- * \f$ v \f$ such that \f$ Av = \lambda v \f$. The eigenvalues of a
- * selfadjoint matrix are always real. If \f$ D \f$ is a diagonal matrix with
- * the eigenvalues on the diagonal, and \f$ V \f$ is a matrix with the
- * eigenvectors as its columns, then \f$ A = V D V^{-1} \f$ (for selfadjoint
- * matrices, the matrix \f$ V \f$ is always invertible). This is called the
- * eigendecomposition.
- *
- * The algorithm exploits the fact that the matrix is selfadjoint, making it
- * faster and more accurate than the general purpose eigenvalue algorithms
- * implemented in EigenSolver and ComplexEigenSolver.
- *
- * Only the \b lower \b triangular \b part of the input matrix is referenced.
- *
- * Call the function compute() to compute the eigenvalues and eigenvectors of
- * a given matrix. Alternatively, you can use the
- * SelfAdjointEigenSolver(const MatrixType&, int) constructor which computes
- * the eigenvalues and eigenvectors at construction time. Once the eigenvalue
- * and eigenvectors are computed, they can be retrieved with the eigenvalues()
- * and eigenvectors() functions.
- *
- * The documentation for SelfAdjointEigenSolver(const MatrixType&, int)
- * contains an example of the typical use of this class.
- *
- * To solve the \em generalized eigenvalue problem \f$ Av = \lambda Bv \f$ and
- * the likes, see the class GeneralizedSelfAdjointEigenSolver.
- *
- * \sa MatrixBase::eigenvalues(), class EigenSolver, class ComplexEigenSolver
- */
-template<typename _MatrixType> class SelfAdjointEigenSolver
-{
- public:
-
- typedef _MatrixType MatrixType;
- enum {
- Size = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- Options = MatrixType::Options,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
- };
-
- /** \brief Scalar type for matrices of type \p _MatrixType. */
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::Index Index;
-
- /** \brief Real scalar type for \p _MatrixType.
- *
- * This is just \c Scalar if #Scalar is real (e.g., \c float or
- * \c double), and the type of the real part of \c Scalar if #Scalar is
- * complex.
- */
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
- /** \brief Type for vector of eigenvalues as returned by eigenvalues().
- *
- * This is a column vector with entries of type #RealScalar.
- * The length of the vector is the size of \p _MatrixType.
- */
- typedef typename internal::plain_col_type<MatrixType, RealScalar>::type RealVectorType;
- typedef Tridiagonalization<MatrixType> TridiagonalizationType;
-
- /** \brief Default constructor for fixed-size matrices.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via compute(). This constructor
- * can only be used if \p _MatrixType is a fixed-size matrix; use
- * SelfAdjointEigenSolver(Index) for dynamic-size matrices.
- *
- * Example: \include SelfAdjointEigenSolver_SelfAdjointEigenSolver.cpp
- * Output: \verbinclude SelfAdjointEigenSolver_SelfAdjointEigenSolver.out
- */
- SelfAdjointEigenSolver()
- : m_eivec(),
- m_eivalues(),
- m_subdiag(),
- m_isInitialized(false)
- { }
-
- /** \brief Constructor, pre-allocates memory for dynamic-size matrices.
- *
- * \param [in] size Positive integer, size of the matrix whose
- * eigenvalues and eigenvectors will be computed.
- *
- * This constructor is useful for dynamic-size matrices, when the user
- * intends to perform decompositions via compute(). The \p size
- * parameter is only used as a hint. It is not an error to give a wrong
- * \p size, but it may impair performance.
- *
- * \sa compute() for an example
- */
- SelfAdjointEigenSolver(Index size)
- : m_eivec(size, size),
- m_eivalues(size),
- m_subdiag(size > 1 ? size - 1 : 1),
- m_isInitialized(false)
- {}
-
- /** \brief Constructor; computes eigendecomposition of given matrix.
- *
- * \param[in] matrix Selfadjoint matrix whose eigendecomposition is to
- * be computed. Only the lower triangular part of the matrix is referenced.
- * \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly.
- *
- * This constructor calls compute(const MatrixType&, int) to compute the
- * eigenvalues of the matrix \p matrix. The eigenvectors are computed if
- * \p options equals #ComputeEigenvectors.
- *
- * Example: \include SelfAdjointEigenSolver_SelfAdjointEigenSolver_MatrixType.cpp
- * Output: \verbinclude SelfAdjointEigenSolver_SelfAdjointEigenSolver_MatrixType.out
- *
- * \sa compute(const MatrixType&, int)
- */
- SelfAdjointEigenSolver(const MatrixType& matrix, int options = ComputeEigenvectors)
- : m_eivec(matrix.rows(), matrix.cols()),
- m_eivalues(matrix.cols()),
- m_subdiag(matrix.rows() > 1 ? matrix.rows() - 1 : 1),
- m_isInitialized(false)
- {
- compute(matrix, options);
- }
-
- /** \brief Computes eigendecomposition of given matrix.
- *
- * \param[in] matrix Selfadjoint matrix whose eigendecomposition is to
- * be computed. Only the lower triangular part of the matrix is referenced.
- * \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly.
- * \returns Reference to \c *this
- *
- * This function computes the eigenvalues of \p matrix. The eigenvalues()
- * function can be used to retrieve them. If \p options equals #ComputeEigenvectors,
- * then the eigenvectors are also computed and can be retrieved by
- * calling eigenvectors().
- *
- * This implementation uses a symmetric QR algorithm. The matrix is first
- * reduced to tridiagonal form using the Tridiagonalization class. The
- * tridiagonal matrix is then brought to diagonal form with implicit
- * symmetric QR steps with Wilkinson shift. Details can be found in
- * Section 8.3 of Golub \& Van Loan, <i>%Matrix Computations</i>.
- *
- * The cost of the computation is about \f$ 9n^3 \f$ if the eigenvectors
- * are required and \f$ 4n^3/3 \f$ if they are not required.
- *
- * This method reuses the memory in the SelfAdjointEigenSolver object that
- * was allocated when the object was constructed, if the size of the
- * matrix does not change.
- *
- * Example: \include SelfAdjointEigenSolver_compute_MatrixType.cpp
- * Output: \verbinclude SelfAdjointEigenSolver_compute_MatrixType.out
- *
- * \sa SelfAdjointEigenSolver(const MatrixType&, int)
- */
- SelfAdjointEigenSolver& compute(const MatrixType& matrix, int options = ComputeEigenvectors);
-
- /** \brief Returns the eigenvectors of given matrix.
- *
- * \returns A const reference to the matrix whose columns are the eigenvectors.
- *
- * \pre The eigenvectors have been computed before.
- *
- * Column \f$ k \f$ of the returned matrix is an eigenvector corresponding
- * to eigenvalue number \f$ k \f$ as returned by eigenvalues(). The
- * eigenvectors are normalized to have (Euclidean) norm equal to one. If
- * this object was used to solve the eigenproblem for the selfadjoint
- * matrix \f$ A \f$, then the matrix returned by this function is the
- * matrix \f$ V \f$ in the eigendecomposition \f$ A = V D V^{-1} \f$.
- *
- * Example: \include SelfAdjointEigenSolver_eigenvectors.cpp
- * Output: \verbinclude SelfAdjointEigenSolver_eigenvectors.out
- *
- * \sa eigenvalues()
- */
- const MatrixType& eigenvectors() const
- {
- eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
- eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
- return m_eivec;
- }
-
- /** \brief Returns the eigenvalues of given matrix.
- *
- * \returns A const reference to the column vector containing the eigenvalues.
- *
- * \pre The eigenvalues have been computed before.
- *
- * The eigenvalues are repeated according to their algebraic multiplicity,
- * so there are as many eigenvalues as rows in the matrix. The eigenvalues
- * are sorted in increasing order.
- *
- * Example: \include SelfAdjointEigenSolver_eigenvalues.cpp
- * Output: \verbinclude SelfAdjointEigenSolver_eigenvalues.out
- *
- * \sa eigenvectors(), MatrixBase::eigenvalues()
- */
- const RealVectorType& eigenvalues() const
- {
- eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
- return m_eivalues;
- }
-
- /** \brief Computes the positive-definite square root of the matrix.
- *
- * \returns the positive-definite square root of the matrix
- *
- * \pre The eigenvalues and eigenvectors of a positive-definite matrix
- * have been computed before.
- *
- * The square root of a positive-definite matrix \f$ A \f$ is the
- * positive-definite matrix whose square equals \f$ A \f$. This function
- * uses the eigendecomposition \f$ A = V D V^{-1} \f$ to compute the
- * square root as \f$ A^{1/2} = V D^{1/2} V^{-1} \f$.
- *
- * Example: \include SelfAdjointEigenSolver_operatorSqrt.cpp
- * Output: \verbinclude SelfAdjointEigenSolver_operatorSqrt.out
- *
- * \sa operatorInverseSqrt(),
- * \ref MatrixFunctions_Module "MatrixFunctions Module"
- */
- MatrixType operatorSqrt() const
- {
- eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
- eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
- return m_eivec * m_eivalues.cwiseSqrt().asDiagonal() * m_eivec.adjoint();
- }
-
- /** \brief Computes the inverse square root of the matrix.
- *
- * \returns the inverse positive-definite square root of the matrix
- *
- * \pre The eigenvalues and eigenvectors of a positive-definite matrix
- * have been computed before.
- *
- * This function uses the eigendecomposition \f$ A = V D V^{-1} \f$ to
- * compute the inverse square root as \f$ V D^{-1/2} V^{-1} \f$. This is
- * cheaper than first computing the square root with operatorSqrt() and
- * then its inverse with MatrixBase::inverse().
- *
- * Example: \include SelfAdjointEigenSolver_operatorInverseSqrt.cpp
- * Output: \verbinclude SelfAdjointEigenSolver_operatorInverseSqrt.out
- *
- * \sa operatorSqrt(), MatrixBase::inverse(),
- * \ref MatrixFunctions_Module "MatrixFunctions Module"
- */
- MatrixType operatorInverseSqrt() const
- {
- eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
- eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues.");
- return m_eivec * m_eivalues.cwiseInverse().cwiseSqrt().asDiagonal() * m_eivec.adjoint();
- }
-
- /** \brief Reports whether previous computation was successful.
- *
- * \returns \c Success if computation was succesful, \c NoConvergence otherwise.
- */
- ComputationInfo info() const
- {
- eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
- return m_info;
- }
-
- /** \brief Maximum number of iterations.
- *
- * Maximum number of iterations allowed for an eigenvalue to converge.
- */
- static const int m_maxIterations = 30;
-
- #ifdef EIGEN2_SUPPORT
- SelfAdjointEigenSolver(const MatrixType& matrix, bool computeEigenvectors)
- : m_eivec(matrix.rows(), matrix.cols()),
- m_eivalues(matrix.cols()),
- m_subdiag(matrix.rows() > 1 ? matrix.rows() - 1 : 1),
- m_isInitialized(false)
- {
- compute(matrix, computeEigenvectors);
- }
-
- SelfAdjointEigenSolver(const MatrixType& matA, const MatrixType& matB, bool computeEigenvectors = true)
- : m_eivec(matA.cols(), matA.cols()),
- m_eivalues(matA.cols()),
- m_subdiag(matA.cols() > 1 ? matA.cols() - 1 : 1),
- m_isInitialized(false)
- {
- static_cast<GeneralizedSelfAdjointEigenSolver<MatrixType>*>(this)->compute(matA, matB, computeEigenvectors ? ComputeEigenvectors : EigenvaluesOnly);
- }
-
- void compute(const MatrixType& matrix, bool computeEigenvectors)
- {
- compute(matrix, computeEigenvectors ? ComputeEigenvectors : EigenvaluesOnly);
- }
-
- void compute(const MatrixType& matA, const MatrixType& matB, bool computeEigenvectors = true)
- {
- compute(matA, matB, computeEigenvectors ? ComputeEigenvectors : EigenvaluesOnly);
- }
- #endif // EIGEN2_SUPPORT
-
- protected:
- MatrixType m_eivec;
- RealVectorType m_eivalues;
- typename TridiagonalizationType::SubDiagonalType m_subdiag;
- ComputationInfo m_info;
- bool m_isInitialized;
- bool m_eigenvectorsOk;
-};
-
-/** \internal
- *
- * \eigenvalues_module \ingroup Eigenvalues_Module
- *
- * Performs a QR step on a tridiagonal symmetric matrix represented as a
- * pair of two vectors \a diag and \a subdiag.
- *
- * \param matA the input selfadjoint matrix
- * \param hCoeffs returned Householder coefficients
- *
- * For compilation efficiency reasons, this procedure does not use eigen expression
- * for its arguments.
- *
- * Implemented from Golub's "Matrix Computations", algorithm 8.3.2:
- * "implicit symmetric QR step with Wilkinson shift"
- */
-namespace internal {
-template<int StorageOrder,typename RealScalar, typename Scalar, typename Index>
-static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n);
-}
-
-template<typename MatrixType>
-SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
-::compute(const MatrixType& matrix, int options)
-{
- eigen_assert(matrix.cols() == matrix.rows());
- eigen_assert((options&~(EigVecMask|GenEigMask))==0
- && (options&EigVecMask)!=EigVecMask
- && "invalid option parameter");
- bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors;
- Index n = matrix.cols();
- m_eivalues.resize(n,1);
-
- if(n==1)
- {
- m_eivalues.coeffRef(0,0) = internal::real(matrix.coeff(0,0));
- if(computeEigenvectors)
- m_eivec.setOnes(n,n);
- m_info = Success;
- m_isInitialized = true;
- m_eigenvectorsOk = computeEigenvectors;
- return *this;
- }
-
- // declare some aliases
- RealVectorType& diag = m_eivalues;
- MatrixType& mat = m_eivec;
-
- // map the matrix coefficients to [-1:1] to avoid over- and underflow.
- RealScalar scale = matrix.cwiseAbs().maxCoeff();
- if(scale==Scalar(0)) scale = 1;
- mat = matrix / scale;
- m_subdiag.resize(n-1);
- internal::tridiagonalization_inplace(mat, diag, m_subdiag, computeEigenvectors);
-
- Index end = n-1;
- Index start = 0;
- Index iter = 0; // number of iterations we are working on one element
-
- while (end>0)
- {
- for (Index i = start; i<end; ++i)
- if (internal::isMuchSmallerThan(internal::abs(m_subdiag[i]),(internal::abs(diag[i])+internal::abs(diag[i+1]))))
- m_subdiag[i] = 0;
-
- // find the largest unreduced block
- while (end>0 && m_subdiag[end-1]==0)
- {
- iter = 0;
- end--;
- }
- if (end<=0)
- break;
-
- // if we spent too many iterations on the current element, we give up
- iter++;
- if(iter > m_maxIterations) break;
-
- start = end - 1;
- 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);
- }
-
- if (iter <= m_maxIterations)
- m_info = Success;
- else
- m_info = NoConvergence;
-
- // Sort eigenvalues and corresponding vectors.
- // TODO make the sort optional ?
- // TODO use a better sort algorithm !!
- if (m_info == Success)
- {
- for (Index i = 0; i < n-1; ++i)
- {
- Index k;
- m_eivalues.segment(i,n-i).minCoeff(&k);
- if (k > 0)
- {
- std::swap(m_eivalues[i], m_eivalues[k+i]);
- if(computeEigenvectors)
- m_eivec.col(i).swap(m_eivec.col(k+i));
- }
- }
- }
-
- // scale back the eigen values
- m_eivalues *= scale;
-
- m_isInitialized = true;
- m_eigenvectorsOk = computeEigenvectors;
- return *this;
-}
-
-namespace internal {
-template<int StorageOrder,typename RealScalar, typename Scalar, typename Index>
-static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n)
-{
- // NOTE this version avoids over & underflow, however since the matrix is prescaled, overflow cannot occur,
- // and underflows should be meaningless anyway. So I don't any reason to enable this version, but I keep
- // it here for reference:
-// RealScalar td = (diag[end-1] - diag[end])*RealScalar(0.5);
-// RealScalar e = subdiag[end-1];
-// RealScalar mu = diag[end] - (e / (td + (td>0 ? 1 : -1))) * (e / hypot(td,e));
- RealScalar td = (diag[end-1] - diag[end])*RealScalar(0.5);
- RealScalar e2 = abs2(subdiag[end-1]);
- RealScalar mu = diag[end] - e2 / (td + (td>0 ? 1 : -1) * sqrt(td*td + e2));
- RealScalar x = diag[start] - mu;
- RealScalar z = subdiag[start];
- for (Index k = start; k < end; ++k)
- {
- JacobiRotation<RealScalar> rot;
- rot.makeGivens(x, z);
-
- // do T = G' T G
- RealScalar sdk = rot.s() * diag[k] + rot.c() * subdiag[k];
- RealScalar dkp1 = rot.s() * subdiag[k] + rot.c() * diag[k+1];
-
- diag[k] = rot.c() * (rot.c() * diag[k] - rot.s() * subdiag[k]) - rot.s() * (rot.c() * subdiag[k] - rot.s() * diag[k+1]);
- diag[k+1] = rot.s() * sdk + rot.c() * dkp1;
- subdiag[k] = rot.c() * sdk - rot.s() * dkp1;
-
-
- if (k > start)
- subdiag[k - 1] = rot.c() * subdiag[k-1] - rot.s() * z;
-
- x = subdiag[k];
-
- if (k < end - 1)
- {
- z = -rot.s() * subdiag[k+1];
- subdiag[k + 1] = rot.c() * subdiag[k+1];
- }
-
- // 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);
- q.applyOnTheRight(k,k+1,rot);
- }
- }
-}
-} // end namespace internal
-
-#endif // EIGEN_SELFADJOINTEIGENSOLVER_H
diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h b/extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h
deleted file mode 100644
index ae4cdce7aeb..00000000000
--- a/extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h
+++ /dev/null
@@ -1,568 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_TRIDIAGONALIZATION_H
-#define EIGEN_TRIDIAGONALIZATION_H
-
-namespace internal {
-
-template<typename MatrixType> struct TridiagonalizationMatrixTReturnType;
-template<typename MatrixType>
-struct traits<TridiagonalizationMatrixTReturnType<MatrixType> >
-{
- typedef typename MatrixType::PlainObject ReturnType;
-};
-
-template<typename MatrixType, typename CoeffVectorType>
-void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs);
-}
-
-/** \eigenvalues_module \ingroup Eigenvalues_Module
- *
- *
- * \class Tridiagonalization
- *
- * \brief Tridiagonal decomposition of a selfadjoint matrix
- *
- * \tparam _MatrixType the type of the matrix of which we are computing the
- * tridiagonal decomposition; this is expected to be an instantiation of the
- * Matrix class template.
- *
- * This class performs a tridiagonal decomposition of a selfadjoint matrix \f$ A \f$ such that:
- * \f$ A = Q T Q^* \f$ where \f$ Q \f$ is unitary and \f$ T \f$ a real symmetric tridiagonal matrix.
- *
- * A tridiagonal matrix is a matrix which has nonzero elements only on the
- * main diagonal and the first diagonal below and above it. The Hessenberg
- * decomposition of a selfadjoint matrix is in fact a tridiagonal
- * decomposition. This class is used in SelfAdjointEigenSolver to compute the
- * eigenvalues and eigenvectors of a selfadjoint matrix.
- *
- * Call the function compute() to compute the tridiagonal decomposition of a
- * given matrix. Alternatively, you can use the Tridiagonalization(const MatrixType&)
- * constructor which computes the tridiagonal Schur decomposition at
- * construction time. Once the decomposition is computed, you can use the
- * matrixQ() and matrixT() functions to retrieve the matrices Q and T in the
- * decomposition.
- *
- * The documentation of Tridiagonalization(const MatrixType&) contains an
- * example of the typical use of this class.
- *
- * \sa class HessenbergDecomposition, class SelfAdjointEigenSolver
- */
-template<typename _MatrixType> class Tridiagonalization
-{
- public:
-
- /** \brief Synonym for the template parameter \p _MatrixType. */
- typedef _MatrixType MatrixType;
-
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef typename MatrixType::Index Index;
-
- enum {
- Size = MatrixType::RowsAtCompileTime,
- SizeMinusOne = Size == Dynamic ? Dynamic : (Size > 1 ? Size - 1 : 1),
- Options = MatrixType::Options,
- MaxSize = MatrixType::MaxRowsAtCompileTime,
- MaxSizeMinusOne = MaxSize == Dynamic ? Dynamic : (MaxSize > 1 ? MaxSize - 1 : 1)
- };
-
- typedef Matrix<Scalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> CoeffVectorType;
- typedef typename internal::plain_col_type<MatrixType, RealScalar>::type DiagonalType;
- typedef Matrix<RealScalar, SizeMinusOne, 1, Options & ~RowMajor, MaxSizeMinusOne, 1> SubDiagonalType;
- typedef typename internal::remove_all<typename MatrixType::RealReturnType>::type MatrixTypeRealView;
- typedef internal::TridiagonalizationMatrixTReturnType<MatrixTypeRealView> MatrixTReturnType;
-
- typedef typename internal::conditional<NumTraits<Scalar>::IsComplex,
- const typename Diagonal<const MatrixType>::RealReturnType,
- const Diagonal<const MatrixType>
- >::type DiagonalReturnType;
-
- typedef typename internal::conditional<NumTraits<Scalar>::IsComplex,
- const typename Diagonal<
- Block<const MatrixType,SizeMinusOne,SizeMinusOne> >::RealReturnType,
- const Diagonal<
- Block<const MatrixType,SizeMinusOne,SizeMinusOne> >
- >::type SubDiagonalReturnType;
-
- /** \brief Return type of matrixQ() */
- typedef typename HouseholderSequence<MatrixType,CoeffVectorType>::ConjugateReturnType HouseholderSequenceType;
-
- /** \brief Default constructor.
- *
- * \param [in] size Positive integer, size of the matrix whose tridiagonal
- * decomposition will be computed.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via compute(). The \p size parameter is only
- * used as a hint. It is not an error to give a wrong \p size, but it may
- * impair performance.
- *
- * \sa compute() for an example.
- */
- Tridiagonalization(Index size = Size==Dynamic ? 2 : Size)
- : m_matrix(size,size),
- m_hCoeffs(size > 1 ? size-1 : 1),
- m_isInitialized(false)
- {}
-
- /** \brief Constructor; computes tridiagonal decomposition of given matrix.
- *
- * \param[in] matrix Selfadjoint matrix whose tridiagonal decomposition
- * is to be computed.
- *
- * This constructor calls compute() to compute the tridiagonal decomposition.
- *
- * Example: \include Tridiagonalization_Tridiagonalization_MatrixType.cpp
- * Output: \verbinclude Tridiagonalization_Tridiagonalization_MatrixType.out
- */
- Tridiagonalization(const MatrixType& matrix)
- : m_matrix(matrix),
- m_hCoeffs(matrix.cols() > 1 ? matrix.cols()-1 : 1),
- m_isInitialized(false)
- {
- internal::tridiagonalization_inplace(m_matrix, m_hCoeffs);
- m_isInitialized = true;
- }
-
- /** \brief Computes tridiagonal decomposition of given matrix.
- *
- * \param[in] matrix Selfadjoint matrix whose tridiagonal decomposition
- * is to be computed.
- * \returns Reference to \c *this
- *
- * The tridiagonal decomposition is computed by bringing the columns of
- * the matrix successively in the required form using Householder
- * reflections. The cost is \f$ 4n^3/3 \f$ flops, where \f$ n \f$ denotes
- * the size of the given matrix.
- *
- * This method reuses of the allocated data in the Tridiagonalization
- * object, if the size of the matrix does not change.
- *
- * Example: \include Tridiagonalization_compute.cpp
- * Output: \verbinclude Tridiagonalization_compute.out
- */
- Tridiagonalization& compute(const MatrixType& matrix)
- {
- m_matrix = matrix;
- m_hCoeffs.resize(matrix.rows()-1, 1);
- internal::tridiagonalization_inplace(m_matrix, m_hCoeffs);
- m_isInitialized = true;
- return *this;
- }
-
- /** \brief Returns the Householder coefficients.
- *
- * \returns a const reference to the vector of Householder coefficients
- *
- * \pre Either the constructor Tridiagonalization(const MatrixType&) or
- * the member function compute(const MatrixType&) has been called before
- * to compute the tridiagonal decomposition of a matrix.
- *
- * The Householder coefficients allow the reconstruction of the matrix
- * \f$ Q \f$ in the tridiagonal decomposition from the packed data.
- *
- * Example: \include Tridiagonalization_householderCoefficients.cpp
- * Output: \verbinclude Tridiagonalization_householderCoefficients.out
- *
- * \sa packedMatrix(), \ref Householder_Module "Householder module"
- */
- inline CoeffVectorType householderCoefficients() const
- {
- eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
- return m_hCoeffs;
- }
-
- /** \brief Returns the internal representation of the decomposition
- *
- * \returns a const reference to a matrix with the internal representation
- * of the decomposition.
- *
- * \pre Either the constructor Tridiagonalization(const MatrixType&) or
- * the member function compute(const MatrixType&) has been called before
- * to compute the tridiagonal decomposition of a matrix.
- *
- * The returned matrix contains the following information:
- * - the strict upper triangular part is equal to the input matrix A.
- * - the diagonal and lower sub-diagonal represent the real tridiagonal
- * symmetric matrix T.
- * - the rest of the lower part contains the Householder vectors that,
- * combined with Householder coefficients returned by
- * householderCoefficients(), allows to reconstruct the matrix Q as
- * \f$ Q = H_{N-1} \ldots H_1 H_0 \f$.
- * Here, the matrices \f$ H_i \f$ are the Householder transformations
- * \f$ H_i = (I - h_i v_i v_i^T) \f$
- * where \f$ h_i \f$ is the \f$ i \f$th Householder coefficient and
- * \f$ v_i \f$ is the Householder vector defined by
- * \f$ v_i = [ 0, \ldots, 0, 1, M(i+2,i), \ldots, M(N-1,i) ]^T \f$
- * with M the matrix returned by this function.
- *
- * See LAPACK for further details on this packed storage.
- *
- * Example: \include Tridiagonalization_packedMatrix.cpp
- * Output: \verbinclude Tridiagonalization_packedMatrix.out
- *
- * \sa householderCoefficients()
- */
- inline const MatrixType& packedMatrix() const
- {
- eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
- return m_matrix;
- }
-
- /** \brief Returns the unitary matrix Q in the decomposition
- *
- * \returns object representing the matrix Q
- *
- * \pre Either the constructor Tridiagonalization(const MatrixType&) or
- * the member function compute(const MatrixType&) has been called before
- * to compute the tridiagonal decomposition of a matrix.
- *
- * This function returns a light-weight object of template class
- * HouseholderSequence. You can either apply it directly to a matrix or
- * you can convert it to a matrix of type #MatrixType.
- *
- * \sa Tridiagonalization(const MatrixType&) for an example,
- * matrixT(), class HouseholderSequence
- */
- HouseholderSequenceType matrixQ() const
- {
- eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
- return HouseholderSequenceType(m_matrix, m_hCoeffs.conjugate())
- .setLength(m_matrix.rows() - 1)
- .setShift(1);
- }
-
- /** \brief Returns an expression of the tridiagonal matrix T in the decomposition
- *
- * \returns expression object representing the matrix T
- *
- * \pre Either the constructor Tridiagonalization(const MatrixType&) or
- * the member function compute(const MatrixType&) has been called before
- * to compute the tridiagonal decomposition of a matrix.
- *
- * Currently, this function can be used to extract the matrix T from internal
- * data and copy it to a dense matrix object. In most cases, it may be
- * sufficient to directly use the packed matrix or the vector expressions
- * returned by diagonal() and subDiagonal() instead of creating a new
- * dense copy matrix with this function.
- *
- * \sa Tridiagonalization(const MatrixType&) for an example,
- * matrixQ(), packedMatrix(), diagonal(), subDiagonal()
- */
- MatrixTReturnType matrixT() const
- {
- eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
- return MatrixTReturnType(m_matrix.real());
- }
-
- /** \brief Returns the diagonal of the tridiagonal matrix T in the decomposition.
- *
- * \returns expression representing the diagonal of T
- *
- * \pre Either the constructor Tridiagonalization(const MatrixType&) or
- * the member function compute(const MatrixType&) has been called before
- * to compute the tridiagonal decomposition of a matrix.
- *
- * Example: \include Tridiagonalization_diagonal.cpp
- * Output: \verbinclude Tridiagonalization_diagonal.out
- *
- * \sa matrixT(), subDiagonal()
- */
- DiagonalReturnType diagonal() const;
-
- /** \brief Returns the subdiagonal of the tridiagonal matrix T in the decomposition.
- *
- * \returns expression representing the subdiagonal of T
- *
- * \pre Either the constructor Tridiagonalization(const MatrixType&) or
- * the member function compute(const MatrixType&) has been called before
- * to compute the tridiagonal decomposition of a matrix.
- *
- * \sa diagonal() for an example, matrixT()
- */
- SubDiagonalReturnType subDiagonal() const;
-
- protected:
-
- MatrixType m_matrix;
- CoeffVectorType m_hCoeffs;
- bool m_isInitialized;
-};
-
-template<typename MatrixType>
-typename Tridiagonalization<MatrixType>::DiagonalReturnType
-Tridiagonalization<MatrixType>::diagonal() const
-{
- eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
- return m_matrix.diagonal();
-}
-
-template<typename MatrixType>
-typename Tridiagonalization<MatrixType>::SubDiagonalReturnType
-Tridiagonalization<MatrixType>::subDiagonal() const
-{
- eigen_assert(m_isInitialized && "Tridiagonalization is not initialized.");
- Index n = m_matrix.rows();
- return Block<const MatrixType,SizeMinusOne,SizeMinusOne>(m_matrix, 1, 0, n-1,n-1).diagonal();
-}
-
-namespace internal {
-
-/** \internal
- * Performs a tridiagonal decomposition of the selfadjoint matrix \a matA in-place.
- *
- * \param[in,out] matA On input the selfadjoint matrix. Only the \b lower triangular part is referenced.
- * On output, the strict upper part is left unchanged, and the lower triangular part
- * represents the T and Q matrices in packed format has detailed below.
- * \param[out] hCoeffs returned Householder coefficients (see below)
- *
- * On output, the tridiagonal selfadjoint matrix T is stored in the diagonal
- * and lower sub-diagonal of the matrix \a matA.
- * The unitary matrix Q is represented in a compact way as a product of
- * Householder reflectors \f$ H_i \f$ such that:
- * \f$ Q = H_{N-1} \ldots H_1 H_0 \f$.
- * The Householder reflectors are defined as
- * \f$ H_i = (I - h_i v_i v_i^T) \f$
- * where \f$ h_i = hCoeffs[i]\f$ is the \f$ i \f$th Householder coefficient and
- * \f$ v_i \f$ is the Householder vector defined by
- * \f$ v_i = [ 0, \ldots, 0, 1, matA(i+2,i), \ldots, matA(N-1,i) ]^T \f$.
- *
- * Implemented from Golub's "Matrix Computations", algorithm 8.3.1.
- *
- * \sa Tridiagonalization::packedMatrix()
- */
-template<typename MatrixType, typename CoeffVectorType>
-void tridiagonalization_inplace(MatrixType& matA, CoeffVectorType& hCoeffs)
-{
- typedef typename MatrixType::Index Index;
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
- Index n = matA.rows();
- eigen_assert(n==matA.cols());
- eigen_assert(n==hCoeffs.size()+1 || n==1);
-
- for (Index i = 0; i<n-1; ++i)
- {
- Index remainingSize = n-i-1;
- RealScalar beta;
- Scalar h;
- matA.col(i).tail(remainingSize).makeHouseholderInPlace(h, beta);
-
- // Apply similarity transformation to remaining columns,
- // i.e., A = H A H' where H = I - h v v' and v = matA.col(i).tail(n-i-1)
- matA.col(i).coeffRef(i+1) = 1;
-
- hCoeffs.tail(n-i-1).noalias() = (matA.bottomRightCorner(remainingSize,remainingSize).template selfadjointView<Lower>()
- * (conj(h) * matA.col(i).tail(remainingSize)));
-
- hCoeffs.tail(n-i-1) += (conj(h)*Scalar(-0.5)*(hCoeffs.tail(remainingSize).dot(matA.col(i).tail(remainingSize)))) * matA.col(i).tail(n-i-1);
-
- matA.bottomRightCorner(remainingSize, remainingSize).template selfadjointView<Lower>()
- .rankUpdate(matA.col(i).tail(remainingSize), hCoeffs.tail(remainingSize), -1);
-
- matA.col(i).coeffRef(i+1) = beta;
- hCoeffs.coeffRef(i) = h;
- }
-}
-
-// forward declaration, implementation at the end of this file
-template<typename MatrixType,
- int Size=MatrixType::ColsAtCompileTime,
- bool IsComplex=NumTraits<typename MatrixType::Scalar>::IsComplex>
-struct tridiagonalization_inplace_selector;
-
-/** \brief Performs a full tridiagonalization in place
- *
- * \param[in,out] mat On input, the selfadjoint matrix whose tridiagonal
- * decomposition is to be computed. Only the lower triangular part referenced.
- * The rest is left unchanged. On output, the orthogonal matrix Q
- * in the decomposition if \p extractQ is true.
- * \param[out] diag The diagonal of the tridiagonal matrix T in the
- * decomposition.
- * \param[out] subdiag The subdiagonal of the tridiagonal matrix T in
- * the decomposition.
- * \param[in] extractQ If true, the orthogonal matrix Q in the
- * decomposition is computed and stored in \p mat.
- *
- * Computes the tridiagonal decomposition of the selfadjoint matrix \p mat in place
- * such that \f$ mat = Q T Q^* \f$ where \f$ Q \f$ is unitary and \f$ T \f$ a real
- * symmetric tridiagonal matrix.
- *
- * The tridiagonal matrix T is passed to the output parameters \p diag and \p subdiag. If
- * \p extractQ is true, then the orthogonal matrix Q is passed to \p mat. Otherwise the lower
- * part of the matrix \p mat is destroyed.
- *
- * The vectors \p diag and \p subdiag are not resized. The function
- * assumes that they are already of the correct size. The length of the
- * vector \p diag should equal the number of rows in \p mat, and the
- * length of the vector \p subdiag should be one left.
- *
- * This implementation contains an optimized path for 3-by-3 matrices
- * which is especially useful for plane fitting.
- *
- * \note Currently, it requires two temporary vectors to hold the intermediate
- * Householder coefficients, and to reconstruct the matrix Q from the Householder
- * reflectors.
- *
- * Example (this uses the same matrix as the example in
- * Tridiagonalization::Tridiagonalization(const MatrixType&)):
- * \include Tridiagonalization_decomposeInPlace.cpp
- * Output: \verbinclude Tridiagonalization_decomposeInPlace.out
- *
- * \sa class Tridiagonalization
- */
-template<typename MatrixType, typename DiagonalType, typename SubDiagonalType>
-void tridiagonalization_inplace(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, bool extractQ)
-{
- typedef typename MatrixType::Index Index;
- //Index n = mat.rows();
- eigen_assert(mat.cols()==mat.rows() && diag.size()==mat.rows() && subdiag.size()==mat.rows()-1);
- tridiagonalization_inplace_selector<MatrixType>::run(mat, diag, subdiag, extractQ);
-}
-
-/** \internal
- * General full tridiagonalization
- */
-template<typename MatrixType, int Size, bool IsComplex>
-struct tridiagonalization_inplace_selector
-{
- typedef typename Tridiagonalization<MatrixType>::CoeffVectorType CoeffVectorType;
- typedef typename Tridiagonalization<MatrixType>::HouseholderSequenceType HouseholderSequenceType;
- typedef typename MatrixType::Index Index;
- template<typename DiagonalType, typename SubDiagonalType>
- static void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, bool extractQ)
- {
- CoeffVectorType hCoeffs(mat.cols()-1);
- tridiagonalization_inplace(mat,hCoeffs);
- diag = mat.diagonal().real();
- subdiag = mat.template diagonal<-1>().real();
- if(extractQ)
- mat = HouseholderSequenceType(mat, hCoeffs.conjugate())
- .setLength(mat.rows() - 1)
- .setShift(1);
- }
-};
-
-/** \internal
- * Specialization for 3x3 real matrices.
- * Especially useful for plane fitting.
- */
-template<typename MatrixType>
-struct tridiagonalization_inplace_selector<MatrixType,3,false>
-{
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
-
- template<typename DiagonalType, typename SubDiagonalType>
- static void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType& subdiag, bool extractQ)
- {
- diag[0] = mat(0,0);
- RealScalar v1norm2 = abs2(mat(2,0));
- if(v1norm2 == RealScalar(0))
- {
- diag[1] = mat(1,1);
- diag[2] = mat(2,2);
- subdiag[0] = mat(1,0);
- subdiag[1] = mat(2,1);
- if (extractQ)
- mat.setIdentity();
- }
- else
- {
- RealScalar beta = sqrt(abs2(mat(1,0)) + v1norm2);
- RealScalar invBeta = RealScalar(1)/beta;
- Scalar m01 = mat(1,0) * invBeta;
- Scalar m02 = mat(2,0) * invBeta;
- Scalar q = RealScalar(2)*m01*mat(2,1) + m02*(mat(2,2) - mat(1,1));
- diag[1] = mat(1,1) + m02*q;
- diag[2] = mat(2,2) - m02*q;
- subdiag[0] = beta;
- subdiag[1] = mat(2,1) - m01 * q;
- if (extractQ)
- {
- mat << 1, 0, 0,
- 0, m01, m02,
- 0, m02, -m01;
- }
- }
- }
-};
-
-/** \internal
- * Trivial specialization for 1x1 matrices
- */
-template<typename MatrixType, bool IsComplex>
-struct tridiagonalization_inplace_selector<MatrixType,1,IsComplex>
-{
- typedef typename MatrixType::Scalar Scalar;
-
- template<typename DiagonalType, typename SubDiagonalType>
- static void run(MatrixType& mat, DiagonalType& diag, SubDiagonalType&, bool extractQ)
- {
- diag(0,0) = real(mat(0,0));
- if(extractQ)
- mat(0,0) = Scalar(1);
- }
-};
-
-/** \internal
- * \eigenvalues_module \ingroup Eigenvalues_Module
- *
- * \brief Expression type for return value of Tridiagonalization::matrixT()
- *
- * \tparam MatrixType type of underlying dense matrix
- */
-template<typename MatrixType> struct TridiagonalizationMatrixTReturnType
-: public ReturnByValue<TridiagonalizationMatrixTReturnType<MatrixType> >
-{
- typedef typename MatrixType::Index Index;
- public:
- /** \brief Constructor.
- *
- * \param[in] mat The underlying dense matrix
- */
- TridiagonalizationMatrixTReturnType(const MatrixType& mat) : m_matrix(mat) { }
-
- template <typename ResultType>
- inline void evalTo(ResultType& result) const
- {
- result.setZero();
- result.template diagonal<1>() = m_matrix.template diagonal<-1>().conjugate();
- result.diagonal() = m_matrix.diagonal();
- result.template diagonal<-1>() = m_matrix.template diagonal<-1>();
- }
-
- Index rows() const { return m_matrix.rows(); }
- Index cols() const { return m_matrix.cols(); }
-
- protected:
- const typename MatrixType::Nested m_matrix;
-};
-
-} // end namespace internal
-
-#endif // EIGEN_TRIDIAGONALIZATION_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/AlignedBox.h b/extern/Eigen3/Eigen/src/Geometry/AlignedBox.h
deleted file mode 100644
index b51deb3f3c3..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/AlignedBox.h
+++ /dev/null
@@ -1,352 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_ALIGNEDBOX_H
-#define EIGEN_ALIGNEDBOX_H
-
-/** \geometry_module \ingroup Geometry_Module
- *
- *
- * \class AlignedBox
- *
- * \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.
- *
- * This class represents an axis aligned box as a pair of the minimal and maximal corners.
- */
-template <typename _Scalar, int _AmbientDim>
-class AlignedBox
-{
-public:
-EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
- enum { AmbientDimAtCompileTime = _AmbientDim };
- typedef _Scalar Scalar;
- typedef NumTraits<Scalar> ScalarTraits;
- typedef DenseIndex Index;
- typedef typename ScalarTraits::Real RealScalar;
- typedef typename ScalarTraits::NonInteger NonInteger;
- typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
-
- /** Define constants to name the corners of a 1D, 2D or 3D axis aligned bounding box */
- enum CornerType
- {
- /** 1D names */
- Min=0, Max=1,
-
- /** Added names for 2D */
- BottomLeft=0, BottomRight=1,
- TopLeft=2, TopRight=3,
-
- /** Added names for 3D */
- BottomLeftFloor=0, BottomRightFloor=1,
- TopLeftFloor=2, TopRightFloor=3,
- BottomLeftCeil=4, BottomRightCeil=5,
- TopLeftCeil=6, TopRightCeil=7
- };
-
-
- /** Default constructor initializing a null box. */
- inline explicit AlignedBox()
- { if (AmbientDimAtCompileTime!=Dynamic) setEmpty(); }
-
- /** Constructs a null box with \a _dim the dimension of the ambient space. */
- inline explicit AlignedBox(Index _dim) : m_min(_dim), m_max(_dim)
- { setEmpty(); }
-
- /** Constructs a box with extremities \a _min and \a _max. */
- 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)
- {
- const typename internal::nested<Derived,2>::type p(a_p.derived());
- m_min = p;
- m_max = p;
- }
-
- ~AlignedBox() {}
-
- /** \returns the dimension in which the box holds */
- inline Index dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size()-1 : Index(AmbientDimAtCompileTime); }
-
- /** \deprecated use isEmpty */
- inline bool isNull() const { return isEmpty(); }
-
- /** \deprecated use setEmpty */
- inline void setNull() { setEmpty(); }
-
- /** \returns true if the box is empty. */
- inline bool isEmpty() const { return (m_min.array() > m_max.array()).any(); }
-
- /** Makes \c *this an empty box. */
- inline void setEmpty()
- {
- m_min.setConstant( ScalarTraits::highest() );
- m_max.setConstant( ScalarTraits::lowest() );
- }
-
- /** \returns the minimal corner */
- inline const VectorType& (min)() const { return m_min; }
- /** \returns a non const reference to the minimal corner */
- inline VectorType& (min)() { return m_min; }
- /** \returns the maximal corner */
- inline const VectorType& (max)() const { return m_max; }
- /** \returns a non const reference to the maximal corner */
- inline VectorType& (max)() { return m_max; }
-
- /** \returns the center of the box */
- inline const CwiseUnaryOp<internal::scalar_quotient1_op<Scalar>,
- const CwiseBinaryOp<internal::scalar_sum_op<Scalar>, const VectorType, const VectorType> >
- center() const
- { return (m_min+m_max)/2; }
-
- /** \returns the lengths of the sides of the bounding box.
- * Note that this function does not get the same
- * result for integral or floating scalar types: see
- */
- inline const CwiseBinaryOp< internal::scalar_difference_op<Scalar>, const VectorType, const VectorType> sizes() const
- { return m_max - m_min; }
-
- /** \returns the volume of the bounding box */
- inline Scalar volume() const
- { return sizes().prod(); }
-
- /** \returns an expression for the bounding box diagonal vector
- * if the length of the diagonal is needed: diagonal().norm()
- * will provide it.
- */
- inline CwiseBinaryOp< internal::scalar_difference_op<Scalar>, const VectorType, const VectorType> diagonal() const
- { return sizes(); }
-
- /** \returns the vertex of the bounding box at the corner defined by
- * the corner-id corner. It works only for a 1D, 2D or 3D bounding box.
- * For 1D bounding boxes corners are named by 2 enum constants:
- * BottomLeft and BottomRight.
- * For 2D bounding boxes, corners are named by 4 enum constants:
- * BottomLeft, BottomRight, TopLeft, TopRight.
- * For 3D bounding boxes, the following names are added:
- * BottomLeftCeil, BottomRightCeil, TopLeftCeil, TopRightCeil.
- */
- inline VectorType corner(CornerType corner) const
- {
- EIGEN_STATIC_ASSERT(_AmbientDim <= 3, THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE);
-
- VectorType res;
-
- Index mult = 1;
- for(Index d=0; d<dim(); ++d)
- {
- if( mult & corner ) res[d] = m_max[d];
- else res[d] = m_min[d];
- mult *= 2;
- }
- return res;
- }
-
- /** \returns a random point inside the bounding box sampled with
- * a uniform distribution */
- inline VectorType sample() const
- {
- VectorType r;
- for(Index d=0; d<dim(); ++d)
- {
- if(!ScalarTraits::IsInteger)
- {
- r[d] = m_min[d] + (m_max[d]-m_min[d])
- * internal::random<Scalar>(Scalar(0), Scalar(1));
- }
- else
- r[d] = internal::random(m_min[d], m_max[d]);
- }
- return r;
- }
-
- /** \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
- {
- const typename internal::nested<Derived,2>::type p(a_p.derived());
- return (m_min.array()<=p.array()).all() && (p.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. */
- template<typename Derived>
- inline AlignedBox& extend(const MatrixBase<Derived>& a_p)
- {
- const typename internal::nested<Derived,2>::type p(a_p.derived());
- m_min = m_min.cwiseMin(p);
- m_max = m_max.cwiseMax(p);
- return *this;
- }
-
- /** Extends \c *this such that it contains the box \a b and returns a reference to \c *this. */
- inline AlignedBox& extend(const AlignedBox& b)
- {
- m_min = m_min.cwiseMin(b.m_min);
- m_max = m_max.cwiseMax(b.m_max);
- return *this;
- }
-
- /** Clamps \c *this by the box \a b and returns a reference to \c *this. */
- inline AlignedBox& clamp(const AlignedBox& b)
- {
- m_min = m_min.cwiseMax(b.m_min);
- m_max = m_max.cwiseMin(b.m_max);
- return *this;
- }
-
- /** Returns an AlignedBox that is the intersection of \a b and \c *this */
- 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 */
- inline AlignedBox merged(const AlignedBox& b) const
- { return AlignedBox(m_min.cwiseMin(b.m_min), m_max.cwiseMax(b.m_max)); }
-
- /** Translate \c *this by the vector \a t and returns a reference to \c *this. */
- template<typename Derived>
- inline AlignedBox& translate(const MatrixBase<Derived>& a_t)
- {
- const typename internal::nested<Derived,2>::type t(a_t.derived());
- m_min += t;
- m_max += t;
- return *this;
- }
-
- /** \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()
- */
- template<typename Derived>
- inline Scalar squaredExteriorDistance(const MatrixBase<Derived>& a_p) const;
-
- /** \returns the squared distance between the boxes \a b and \c *this,
- * and zero if the boxes intersect.
- * \sa exteriorDistance()
- */
- 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()
- */
- template<typename Derived>
- inline NonInteger exteriorDistance(const MatrixBase<Derived>& p) const
- { return internal::sqrt(NonInteger(squaredExteriorDistance(p))); }
-
- /** \returns the distance between the boxes \a b and \c *this,
- * and zero if the boxes intersect.
- * \sa squaredExteriorDistance()
- */
- inline NonInteger exteriorDistance(const AlignedBox& b) const
- { return internal::sqrt(NonInteger(squaredExteriorDistance(b))); }
-
- /** \returns \c *this with scalar type casted to \a NewScalarType
- *
- * Note that if \a NewScalarType is equal to the current scalar type of \c *this
- * then this function smartly returns a const reference to \c *this.
- */
- template<typename NewScalarType>
- inline typename internal::cast_return_type<AlignedBox,
- AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
- {
- return typename internal::cast_return_type<AlignedBox,
- AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
- }
-
- /** Copy constructor with scalar type conversion */
- template<typename OtherScalarType>
- inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime>& other)
- {
- m_min = (other.min)().template cast<Scalar>();
- m_max = (other.max)().template cast<Scalar>();
- }
-
- /** \returns \c true if \c *this is approximately equal to \a other, within the precision
- * determined by \a prec.
- *
- * \sa MatrixBase::isApprox() */
- bool isApprox(const AlignedBox& other, RealScalar prec = ScalarTraits::dummy_precision()) const
- { return m_min.isApprox(other.m_min, prec) && m_max.isApprox(other.m_max, prec); }
-
-protected:
-
- VectorType m_min, m_max;
-};
-
-
-
-template<typename Scalar,int AmbientDim>
-template<typename Derived>
-inline Scalar AlignedBox<Scalar,AmbientDim>::squaredExteriorDistance(const MatrixBase<Derived>& a_p) const
-{
- const typename internal::nested<Derived,2*AmbientDim>::type p(a_p.derived());
- Scalar dist2 = 0.;
- Scalar aux;
- for (Index k=0; k<dim(); ++k)
- {
- if( m_min[k] > p[k] )
- {
- aux = m_min[k] - p[k];
- dist2 += aux*aux;
- }
- else if( p[k] > m_max[k] )
- {
- aux = p[k] - m_max[k];
- dist2 += aux*aux;
- }
- }
- return dist2;
-}
-
-template<typename Scalar,int AmbientDim>
-inline Scalar AlignedBox<Scalar,AmbientDim>::squaredExteriorDistance(const AlignedBox& b) const
-{
- Scalar dist2 = 0.;
- Scalar aux;
- for (Index k=0; k<dim(); ++k)
- {
- if( m_min[k] > b.m_max[k] )
- {
- aux = m_min[k] - b.m_max[k];
- dist2 += aux*aux;
- }
- else if( b.m_min[k] > m_max[k] )
- {
- aux = b.m_min[k] - m_max[k];
- dist2 += aux*aux;
- }
- }
- return dist2;
-}
-
-#endif // EIGEN_ALIGNEDBOX_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/AngleAxis.h b/extern/Eigen3/Eigen/src/Geometry/AngleAxis.h
deleted file mode 100644
index 0ec4624cf98..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/AngleAxis.h
+++ /dev/null
@@ -1,241 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_ANGLEAXIS_H
-#define EIGEN_ANGLEAXIS_H
-
-/** \geometry_module \ingroup Geometry_Module
- *
- * \class AngleAxis
- *
- * \brief Represents a 3D rotation as a rotation angle around an arbitrary 3D axis
- *
- * \param _Scalar the scalar type, i.e., the type of the coefficients.
- *
- * \warning When setting up an AngleAxis object, the axis vector \b must \b be \b normalized.
- *
- * The following two typedefs are provided for convenience:
- * \li \c AngleAxisf for \c float
- * \li \c AngleAxisd for \c double
- *
- * Combined with MatrixBase::Unit{X,Y,Z}, AngleAxis can be used to easily
- * mimic Euler-angles. Here is an example:
- * \include AngleAxis_mimic_euler.cpp
- * Output: \verbinclude AngleAxis_mimic_euler.out
- *
- * \note This class is not aimed to be used to store a rotation transformation,
- * but rather to make easier the creation of other rotation (Quaternion, rotation Matrix)
- * and transformation objects.
- *
- * \sa class Quaternion, class Transform, MatrixBase::UnitX()
- */
-
-namespace internal {
-template<typename _Scalar> struct traits<AngleAxis<_Scalar> >
-{
- typedef _Scalar Scalar;
-};
-}
-
-template<typename _Scalar>
-class AngleAxis : public RotationBase<AngleAxis<_Scalar>,3>
-{
- typedef RotationBase<AngleAxis<_Scalar>,3> Base;
-
-public:
-
- using Base::operator*;
-
- enum { Dim = 3 };
- /** the scalar type of the coefficients */
- typedef _Scalar Scalar;
- typedef Matrix<Scalar,3,3> Matrix3;
- typedef Matrix<Scalar,3,1> Vector3;
- typedef Quaternion<Scalar> QuaternionType;
-
-protected:
-
- Vector3 m_axis;
- Scalar m_angle;
-
-public:
-
- /** Default constructor without initialization. */
- AngleAxis() {}
- /** Constructs and initialize the angle-axis rotation from an \a angle in radian
- * and an \a axis which \b must \b be \b normalized.
- *
- * \warning If the \a axis vector is not normalized, then the angle-axis object
- * represents an invalid rotation. */
- template<typename Derived>
- inline AngleAxis(Scalar angle, const MatrixBase<Derived>& axis) : m_axis(axis), m_angle(angle) {}
- /** Constructs and initialize the angle-axis rotation from a quaternion \a q. */
- template<typename QuatDerived> inline explicit AngleAxis(const QuaternionBase<QuatDerived>& q) { *this = q; }
- /** Constructs and initialize the angle-axis rotation from a 3x3 rotation matrix. */
- template<typename Derived>
- inline explicit AngleAxis(const MatrixBase<Derived>& m) { *this = m; }
-
- Scalar angle() const { return m_angle; }
- Scalar& angle() { return m_angle; }
-
- const Vector3& axis() const { return m_axis; }
- Vector3& axis() { return m_axis; }
-
- /** Concatenates two rotations */
- inline QuaternionType operator* (const AngleAxis& other) const
- { return QuaternionType(*this) * QuaternionType(other); }
-
- /** Concatenates two rotations */
- inline QuaternionType operator* (const QuaternionType& other) const
- { return QuaternionType(*this) * other; }
-
- /** Concatenates two rotations */
- friend inline QuaternionType operator* (const QuaternionType& a, const AngleAxis& b)
- { return a * QuaternionType(b); }
-
- /** \returns the inverse rotation, i.e., an angle-axis with opposite rotation angle */
- AngleAxis inverse() const
- { return AngleAxis(-m_angle, m_axis); }
-
- template<class QuatDerived>
- AngleAxis& operator=(const QuaternionBase<QuatDerived>& q);
- template<typename Derived>
- AngleAxis& operator=(const MatrixBase<Derived>& m);
-
- template<typename Derived>
- AngleAxis& fromRotationMatrix(const MatrixBase<Derived>& m);
- Matrix3 toRotationMatrix(void) const;
-
- /** \returns \c *this with scalar type casted to \a NewScalarType
- *
- * Note that if \a NewScalarType is equal to the current scalar type of \c *this
- * then this function smartly returns a const reference to \c *this.
- */
- template<typename NewScalarType>
- inline typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type cast() const
- { return typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type(*this); }
-
- /** Copy constructor with scalar type conversion */
- template<typename OtherScalarType>
- inline explicit AngleAxis(const AngleAxis<OtherScalarType>& other)
- {
- m_axis = other.axis().template cast<Scalar>();
- m_angle = Scalar(other.angle());
- }
-
- inline static const AngleAxis Identity() { return AngleAxis(0, Vector3::UnitX()); }
-
- /** \returns \c true if \c *this is approximately equal to \a other, within the precision
- * determined by \a prec.
- *
- * \sa MatrixBase::isApprox() */
- bool isApprox(const AngleAxis& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
- { return m_axis.isApprox(other.m_axis, prec) && internal::isApprox(m_angle,other.m_angle, prec); }
-};
-
-/** \ingroup Geometry_Module
- * single precision angle-axis type */
-typedef AngleAxis<float> AngleAxisf;
-/** \ingroup Geometry_Module
- * double precision angle-axis type */
-typedef AngleAxis<double> AngleAxisd;
-
-/** Set \c *this from a \b unit quaternion.
- * The axis is normalized.
- *
- * \warning As any other method dealing with quaternion, if the input quaternion
- * is not normalized then the result is undefined.
- */
-template<typename Scalar>
-template<typename QuatDerived>
-AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived>& q)
-{
- using std::acos;
- using std::min;
- using std::max;
- Scalar n2 = q.vec().squaredNorm();
- if (n2 < NumTraits<Scalar>::dummy_precision()*NumTraits<Scalar>::dummy_precision())
- {
- m_angle = 0;
- m_axis << 1, 0, 0;
- }
- else
- {
- m_angle = Scalar(2)*acos((min)((max)(Scalar(-1),q.w()),Scalar(1)));
- m_axis = q.vec() / internal::sqrt(n2);
- }
- return *this;
-}
-
-/** Set \c *this from a 3x3 rotation matrix \a mat.
- */
-template<typename Scalar>
-template<typename Derived>
-AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const MatrixBase<Derived>& mat)
-{
- // Since a direct conversion would not be really faster,
- // let's use the robust Quaternion implementation:
- return *this = QuaternionType(mat);
-}
-
-/**
-* \brief Sets \c *this from a 3x3 rotation matrix.
-**/
-template<typename Scalar>
-template<typename Derived>
-AngleAxis<Scalar>& AngleAxis<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat)
-{
- return *this = QuaternionType(mat);
-}
-
-/** Constructs and \returns an equivalent 3x3 rotation matrix.
- */
-template<typename Scalar>
-typename AngleAxis<Scalar>::Matrix3
-AngleAxis<Scalar>::toRotationMatrix(void) const
-{
- Matrix3 res;
- Vector3 sin_axis = internal::sin(m_angle) * m_axis;
- Scalar c = internal::cos(m_angle);
- Vector3 cos1_axis = (Scalar(1)-c) * m_axis;
-
- Scalar tmp;
- tmp = cos1_axis.x() * m_axis.y();
- res.coeffRef(0,1) = tmp - sin_axis.z();
- res.coeffRef(1,0) = tmp + sin_axis.z();
-
- tmp = cos1_axis.x() * m_axis.z();
- res.coeffRef(0,2) = tmp + sin_axis.y();
- res.coeffRef(2,0) = tmp - sin_axis.y();
-
- tmp = cos1_axis.y() * m_axis.z();
- res.coeffRef(1,2) = tmp - sin_axis.x();
- res.coeffRef(2,1) = tmp + sin_axis.x();
-
- res.diagonal() = (cos1_axis.cwiseProduct(m_axis)).array() + c;
-
- return res;
-}
-
-#endif // EIGEN_ANGLEAXIS_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/Homogeneous.h b/extern/Eigen3/Eigen/src/Geometry/Homogeneous.h
deleted file mode 100644
index 2bc4f7e87e3..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/Homogeneous.h
+++ /dev/null
@@ -1,318 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_HOMOGENEOUS_H
-#define EIGEN_HOMOGENEOUS_H
-
-/** \geometry_module \ingroup Geometry_Module
- *
- * \class Homogeneous
- *
- * \brief Expression of one (or a set of) homogeneous vector(s)
- *
- * \param MatrixType the type of the object in which we are making homogeneous
- *
- * This class represents an expression of one (or a set of) homogeneous vector(s).
- * It is the return type of MatrixBase::homogeneous() and most of the time
- * this is the only way it is used.
- *
- * \sa MatrixBase::homogeneous()
- */
-
-namespace internal {
-
-template<typename MatrixType,int Direction>
-struct traits<Homogeneous<MatrixType,Direction> >
- : traits<MatrixType>
-{
- typedef typename traits<MatrixType>::StorageKind StorageKind;
- typedef typename nested<MatrixType>::type MatrixTypeNested;
- typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
- enum {
- RowsPlusOne = (MatrixType::RowsAtCompileTime != Dynamic) ?
- int(MatrixType::RowsAtCompileTime) + 1 : Dynamic,
- ColsPlusOne = (MatrixType::ColsAtCompileTime != Dynamic) ?
- int(MatrixType::ColsAtCompileTime) + 1 : Dynamic,
- RowsAtCompileTime = Direction==Vertical ? RowsPlusOne : MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = Direction==Horizontal ? ColsPlusOne : MatrixType::ColsAtCompileTime,
- MaxRowsAtCompileTime = RowsAtCompileTime,
- MaxColsAtCompileTime = ColsAtCompileTime,
- TmpFlags = _MatrixTypeNested::Flags & HereditaryBits,
- Flags = ColsAtCompileTime==1 ? (TmpFlags & ~RowMajorBit)
- : RowsAtCompileTime==1 ? (TmpFlags | RowMajorBit)
- : TmpFlags,
- CoeffReadCost = _MatrixTypeNested::CoeffReadCost
- };
-};
-
-template<typename MatrixType,typename Lhs> struct homogeneous_left_product_impl;
-template<typename MatrixType,typename Rhs> struct homogeneous_right_product_impl;
-
-} // end namespace internal
-
-template<typename MatrixType,int _Direction> class Homogeneous
- : public MatrixBase<Homogeneous<MatrixType,_Direction> >
-{
- public:
-
- enum { Direction = _Direction };
-
- typedef MatrixBase<Homogeneous> Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(Homogeneous)
-
- inline Homogeneous(const MatrixType& matrix)
- : m_matrix(matrix)
- {}
-
- inline Index rows() const { return m_matrix.rows() + (int(Direction)==Vertical ? 1 : 0); }
- inline Index cols() const { return m_matrix.cols() + (int(Direction)==Horizontal ? 1 : 0); }
-
- inline Scalar coeff(Index row, Index col) const
- {
- if( (int(Direction)==Vertical && row==m_matrix.rows())
- || (int(Direction)==Horizontal && col==m_matrix.cols()))
- return 1;
- return m_matrix.coeff(row, col);
- }
-
- template<typename Rhs>
- inline const internal::homogeneous_right_product_impl<Homogeneous,Rhs>
- operator* (const MatrixBase<Rhs>& rhs) const
- {
- eigen_assert(int(Direction)==Horizontal);
- return internal::homogeneous_right_product_impl<Homogeneous,Rhs>(m_matrix,rhs.derived());
- }
-
- template<typename Lhs> friend
- inline const internal::homogeneous_left_product_impl<Homogeneous,Lhs>
- operator* (const MatrixBase<Lhs>& lhs, const Homogeneous& rhs)
- {
- eigen_assert(int(Direction)==Vertical);
- return internal::homogeneous_left_product_impl<Homogeneous,Lhs>(lhs.derived(),rhs.m_matrix);
- }
-
- template<typename Scalar, int Dim, int Mode, int Options> friend
- inline const internal::homogeneous_left_product_impl<Homogeneous,Transform<Scalar,Dim,Mode,Options> >
- operator* (const Transform<Scalar,Dim,Mode,Options>& lhs, const Homogeneous& rhs)
- {
- eigen_assert(int(Direction)==Vertical);
- return internal::homogeneous_left_product_impl<Homogeneous,Transform<Scalar,Dim,Mode,Options> >(lhs,rhs.m_matrix);
- }
-
- protected:
- const typename MatrixType::Nested m_matrix;
-};
-
-/** \geometry_module
- *
- * \return an expression of the equivalent homogeneous vector
- *
- * \only_for_vectors
- *
- * Example: \include MatrixBase_homogeneous.cpp
- * Output: \verbinclude MatrixBase_homogeneous.out
- *
- * \sa class Homogeneous
- */
-template<typename Derived>
-inline typename MatrixBase<Derived>::HomogeneousReturnType
-MatrixBase<Derived>::homogeneous() const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
- return derived();
-}
-
-/** \geometry_module
- *
- * \returns a matrix expression of homogeneous column (or row) vectors
- *
- * Example: \include VectorwiseOp_homogeneous.cpp
- * Output: \verbinclude VectorwiseOp_homogeneous.out
- *
- * \sa MatrixBase::homogeneous() */
-template<typename ExpressionType, int Direction>
-inline Homogeneous<ExpressionType,Direction>
-VectorwiseOp<ExpressionType,Direction>::homogeneous() const
-{
- return _expression();
-}
-
-/** \geometry_module
- *
- * \returns an expression of the homogeneous normalized vector of \c *this
- *
- * Example: \include MatrixBase_hnormalized.cpp
- * Output: \verbinclude MatrixBase_hnormalized.out
- *
- * \sa VectorwiseOp::hnormalized() */
-template<typename Derived>
-inline const typename MatrixBase<Derived>::HNormalizedReturnType
-MatrixBase<Derived>::hnormalized() const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
- return ConstStartMinusOne(derived(),0,0,
- ColsAtCompileTime==1?size()-1:1,
- ColsAtCompileTime==1?1:size()-1) / coeff(size()-1);
-}
-
-/** \geometry_module
- *
- * \returns an expression of the homogeneous normalized vector of \c *this
- *
- * Example: \include DirectionWise_hnormalized.cpp
- * Output: \verbinclude DirectionWise_hnormalized.out
- *
- * \sa MatrixBase::hnormalized() */
-template<typename ExpressionType, int Direction>
-inline const typename VectorwiseOp<ExpressionType,Direction>::HNormalizedReturnType
-VectorwiseOp<ExpressionType,Direction>::hnormalized() const
-{
- return HNormalized_Block(_expression(),0,0,
- Direction==Vertical ? _expression().rows()-1 : _expression().rows(),
- Direction==Horizontal ? _expression().cols()-1 : _expression().cols()).cwiseQuotient(
- Replicate<HNormalized_Factors,
- Direction==Vertical ? HNormalized_SizeMinusOne : 1,
- Direction==Horizontal ? HNormalized_SizeMinusOne : 1>
- (HNormalized_Factors(_expression(),
- Direction==Vertical ? _expression().rows()-1:0,
- Direction==Horizontal ? _expression().cols()-1:0,
- Direction==Vertical ? 1 : _expression().rows(),
- Direction==Horizontal ? 1 : _expression().cols()),
- Direction==Vertical ? _expression().rows()-1 : 1,
- Direction==Horizontal ? _expression().cols()-1 : 1));
-}
-
-namespace internal {
-
-template<typename MatrixOrTransformType>
-struct take_matrix_for_product
-{
- typedef MatrixOrTransformType type;
- static const type& run(const type &x) { return x; }
-};
-
-template<typename Scalar, int Dim, int Mode,int Options>
-struct take_matrix_for_product<Transform<Scalar, Dim, Mode, Options> >
-{
- typedef Transform<Scalar, Dim, Mode, Options> TransformType;
- typedef typename TransformType::ConstAffinePart type;
- static const type run (const TransformType& x) { return x.affine(); }
-};
-
-template<typename Scalar, int Dim, int Options>
-struct take_matrix_for_product<Transform<Scalar, Dim, Projective, Options> >
-{
- typedef Transform<Scalar, Dim, Projective, Options> TransformType;
- typedef typename TransformType::MatrixType type;
- static const type& run (const TransformType& x) { return x.matrix(); }
-};
-
-template<typename MatrixType,typename Lhs>
-struct traits<homogeneous_left_product_impl<Homogeneous<MatrixType,Vertical>,Lhs> >
-{
- typedef typename take_matrix_for_product<Lhs>::type LhsMatrixType;
- typedef typename remove_all<MatrixType>::type MatrixTypeCleaned;
- typedef typename remove_all<LhsMatrixType>::type LhsMatrixTypeCleaned;
- typedef typename make_proper_matrix_type<
- typename traits<MatrixTypeCleaned>::Scalar,
- LhsMatrixTypeCleaned::RowsAtCompileTime,
- MatrixTypeCleaned::ColsAtCompileTime,
- MatrixTypeCleaned::PlainObject::Options,
- LhsMatrixTypeCleaned::MaxRowsAtCompileTime,
- MatrixTypeCleaned::MaxColsAtCompileTime>::type ReturnType;
-};
-
-template<typename MatrixType,typename Lhs>
-struct homogeneous_left_product_impl<Homogeneous<MatrixType,Vertical>,Lhs>
- : public ReturnByValue<homogeneous_left_product_impl<Homogeneous<MatrixType,Vertical>,Lhs> >
-{
- typedef typename traits<homogeneous_left_product_impl>::LhsMatrixType LhsMatrixType;
- typedef typename remove_all<LhsMatrixType>::type LhsMatrixTypeCleaned;
- typedef typename remove_all<typename LhsMatrixTypeCleaned::Nested>::type LhsMatrixTypeNested;
- typedef typename MatrixType::Index Index;
- homogeneous_left_product_impl(const Lhs& lhs, const MatrixType& rhs)
- : m_lhs(take_matrix_for_product<Lhs>::run(lhs)),
- m_rhs(rhs)
- {}
-
- inline Index rows() const { return m_lhs.rows(); }
- inline Index cols() const { return m_rhs.cols(); }
-
- template<typename Dest> void evalTo(Dest& dst) const
- {
- // FIXME investigate how to allow lazy evaluation of this product when possible
- dst = Block<const LhsMatrixTypeNested,
- LhsMatrixTypeNested::RowsAtCompileTime,
- LhsMatrixTypeNested::ColsAtCompileTime==Dynamic?Dynamic:LhsMatrixTypeNested::ColsAtCompileTime-1>
- (m_lhs,0,0,m_lhs.rows(),m_lhs.cols()-1) * m_rhs;
- dst += m_lhs.col(m_lhs.cols()-1).rowwise()
- .template replicate<MatrixType::ColsAtCompileTime>(m_rhs.cols());
- }
-
- const typename LhsMatrixTypeCleaned::Nested m_lhs;
- const typename MatrixType::Nested m_rhs;
-};
-
-template<typename MatrixType,typename Rhs>
-struct traits<homogeneous_right_product_impl<Homogeneous<MatrixType,Horizontal>,Rhs> >
-{
- typedef typename make_proper_matrix_type<typename traits<MatrixType>::Scalar,
- MatrixType::RowsAtCompileTime,
- Rhs::ColsAtCompileTime,
- MatrixType::PlainObject::Options,
- MatrixType::MaxRowsAtCompileTime,
- Rhs::MaxColsAtCompileTime>::type ReturnType;
-};
-
-template<typename MatrixType,typename Rhs>
-struct homogeneous_right_product_impl<Homogeneous<MatrixType,Horizontal>,Rhs>
- : public ReturnByValue<homogeneous_right_product_impl<Homogeneous<MatrixType,Horizontal>,Rhs> >
-{
- typedef typename remove_all<typename Rhs::Nested>::type RhsNested;
- typedef typename MatrixType::Index Index;
- homogeneous_right_product_impl(const MatrixType& lhs, const Rhs& rhs)
- : m_lhs(lhs), m_rhs(rhs)
- {}
-
- inline Index rows() const { return m_lhs.rows(); }
- inline Index cols() const { return m_rhs.cols(); }
-
- template<typename Dest> void evalTo(Dest& dst) const
- {
- // FIXME investigate how to allow lazy evaluation of this product when possible
- dst = m_lhs * Block<const RhsNested,
- RhsNested::RowsAtCompileTime==Dynamic?Dynamic:RhsNested::RowsAtCompileTime-1,
- RhsNested::ColsAtCompileTime>
- (m_rhs,0,0,m_rhs.rows()-1,m_rhs.cols());
- dst += m_rhs.row(m_rhs.rows()-1).colwise()
- .template replicate<MatrixType::RowsAtCompileTime>(m_lhs.rows());
- }
-
- const typename MatrixType::Nested m_lhs;
- const typename Rhs::Nested m_rhs;
-};
-
-} // end namespace internal
-
-#endif // EIGEN_HOMOGENEOUS_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/Hyperplane.h b/extern/Eigen3/Eigen/src/Geometry/Hyperplane.h
deleted file mode 100644
index eb0a5877168..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/Hyperplane.h
+++ /dev/null
@@ -1,280 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_HYPERPLANE_H
-#define EIGEN_HYPERPLANE_H
-
-/** \geometry_module \ingroup Geometry_Module
- *
- * \class Hyperplane
- *
- * \brief A hyperplane
- *
- * A hyperplane is an affine subspace of dimension n-1 in a space of dimension n.
- * For example, a hyperplane in a plane is a line; a hyperplane in 3-space is a plane.
- *
- * \param _Scalar the scalar type, i.e., the type of the coefficients
- * \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
- * Notice that the dimension of the hyperplane is _AmbientDim-1.
- *
- * This class represents an hyperplane as the zero set of the implicit equation
- * \f$ n \cdot x + d = 0 \f$ where \f$ n \f$ is a unit normal vector of the plane (linear part)
- * and \f$ d \f$ is the distance (offset) to the origin.
- */
-template <typename _Scalar, int _AmbientDim, int _Options>
-class Hyperplane
-{
-public:
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1)
- enum {
- AmbientDimAtCompileTime = _AmbientDim,
- Options = _Options
- };
- typedef _Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef DenseIndex Index;
- typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
- typedef Matrix<Scalar,Index(AmbientDimAtCompileTime)==Dynamic
- ? Dynamic
- : Index(AmbientDimAtCompileTime)+1,1,Options> Coefficients;
- typedef Block<Coefficients,AmbientDimAtCompileTime,1> NormalReturnType;
- typedef const Block<const Coefficients,AmbientDimAtCompileTime,1> ConstNormalReturnType;
-
- /** Default constructor without initialization */
- inline explicit Hyperplane() {}
-
- template<int OtherOptions>
- Hyperplane(const Hyperplane<Scalar,AmbientDimAtCompileTime,OtherOptions>& other)
- : m_coeffs(other.coeffs())
- {}
-
- /** Constructs a dynamic-size hyperplane with \a _dim the dimension
- * of the ambient space */
- inline explicit Hyperplane(Index _dim) : m_coeffs(_dim+1) {}
-
- /** Construct a plane from its normal \a n and a point \a e onto the plane.
- * \warning the vector normal is assumed to be normalized.
- */
- inline Hyperplane(const VectorType& n, const VectorType& e)
- : m_coeffs(n.size()+1)
- {
- normal() = n;
- offset() = -n.dot(e);
- }
-
- /** Constructs a plane from its normal \a n and distance to the origin \a d
- * such that the algebraic equation of the plane is \f$ n \cdot x + d = 0 \f$.
- * \warning the vector normal is assumed to be normalized.
- */
- inline Hyperplane(const VectorType& n, Scalar d)
- : m_coeffs(n.size()+1)
- {
- normal() = n;
- offset() = d;
- }
-
- /** Constructs a hyperplane passing through the two points. If the dimension of the ambient space
- * is greater than 2, then there isn't uniqueness, so an arbitrary choice is made.
- */
- static inline Hyperplane Through(const VectorType& p0, const VectorType& p1)
- {
- Hyperplane result(p0.size());
- result.normal() = (p1 - p0).unitOrthogonal();
- result.offset() = -p0.dot(result.normal());
- return result;
- }
-
- /** Constructs a hyperplane passing through the three points. The dimension of the ambient space
- * is required to be exactly 3.
- */
- static inline Hyperplane Through(const VectorType& p0, const VectorType& p1, const VectorType& p2)
- {
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 3)
- Hyperplane result(p0.size());
- result.normal() = (p2 - p0).cross(p1 - p0).normalized();
- result.offset() = -p0.dot(result.normal());
- return result;
- }
-
- /** Constructs a hyperplane passing through the parametrized line \a parametrized.
- * If the dimension of the ambient space is greater than 2, then there isn't uniqueness,
- * so an arbitrary choice is made.
- */
- // FIXME to be consitent with the rest this could be implemented as a static Through function ??
- explicit Hyperplane(const ParametrizedLine<Scalar, AmbientDimAtCompileTime>& parametrized)
- {
- normal() = parametrized.direction().unitOrthogonal();
- offset() = -parametrized.origin().dot(normal());
- }
-
- ~Hyperplane() {}
-
- /** \returns the dimension in which the plane holds */
- inline Index dim() const { return AmbientDimAtCompileTime==Dynamic ? m_coeffs.size()-1 : Index(AmbientDimAtCompileTime); }
-
- /** normalizes \c *this */
- void normalize(void)
- {
- m_coeffs /= normal().norm();
- }
-
- /** \returns the signed distance between the plane \c *this and a point \a p.
- * \sa absDistance()
- */
- inline Scalar signedDistance(const VectorType& p) const { return normal().dot(p) + offset(); }
-
- /** \returns the absolute distance between the plane \c *this and a point \a p.
- * \sa signedDistance()
- */
- inline Scalar absDistance(const VectorType& p) const { return internal::abs(signedDistance(p)); }
-
- /** \returns the projection of a point \a p onto the plane \c *this.
- */
- inline VectorType projection(const VectorType& p) const { return p - signedDistance(p) * normal(); }
-
- /** \returns a constant reference to the unit normal vector of the plane, which corresponds
- * to the linear part of the implicit equation.
- */
- inline ConstNormalReturnType normal() const { return ConstNormalReturnType(m_coeffs,0,0,dim(),1); }
-
- /** \returns a non-constant reference to the unit normal vector of the plane, which corresponds
- * to the linear part of the implicit equation.
- */
- inline NormalReturnType normal() { return NormalReturnType(m_coeffs,0,0,dim(),1); }
-
- /** \returns the distance to the origin, which is also the "constant term" of the implicit equation
- * \warning the vector normal is assumed to be normalized.
- */
- inline const Scalar& offset() const { return m_coeffs.coeff(dim()); }
-
- /** \returns a non-constant reference to the distance to the origin, which is also the constant part
- * of the implicit equation */
- inline Scalar& offset() { return m_coeffs(dim()); }
-
- /** \returns a constant reference to the coefficients c_i of the plane equation:
- * \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
- */
- inline const Coefficients& coeffs() const { return m_coeffs; }
-
- /** \returns a non-constant reference to the coefficients c_i of the plane equation:
- * \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
- */
- inline Coefficients& coeffs() { return m_coeffs; }
-
- /** \returns the intersection of *this with \a other.
- *
- * \warning The ambient space must be a plane, i.e. have dimension 2, so that \c *this and \a other are lines.
- *
- * \note If \a other is approximately parallel to *this, this method will return any point on *this.
- */
- VectorType intersection(const Hyperplane& other) const
- {
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
- Scalar det = coeffs().coeff(0) * other.coeffs().coeff(1) - coeffs().coeff(1) * other.coeffs().coeff(0);
- // since the line equations ax+by=c are normalized with a^2+b^2=1, the following tests
- // whether the two lines are approximately parallel.
- if(internal::isMuchSmallerThan(det, Scalar(1)))
- { // special case where the two lines are approximately parallel. Pick any point on the first line.
- if(internal::abs(coeffs().coeff(1))>internal::abs(coeffs().coeff(0)))
- return VectorType(coeffs().coeff(1), -coeffs().coeff(2)/coeffs().coeff(1)-coeffs().coeff(0));
- else
- return VectorType(-coeffs().coeff(2)/coeffs().coeff(0)-coeffs().coeff(1), coeffs().coeff(0));
- }
- else
- { // general case
- Scalar invdet = Scalar(1) / det;
- return VectorType(invdet*(coeffs().coeff(1)*other.coeffs().coeff(2)-other.coeffs().coeff(1)*coeffs().coeff(2)),
- invdet*(other.coeffs().coeff(0)*coeffs().coeff(2)-coeffs().coeff(0)*other.coeffs().coeff(2)));
- }
- }
-
- /** Applies the transformation matrix \a mat to \c *this and returns a reference to \c *this.
- *
- * \param mat the Dim x Dim transformation matrix
- * \param traits specifies whether the matrix \a mat represents an #Isometry
- * or a more generic #Affine transformation. The default is #Affine.
- */
- template<typename XprType>
- inline Hyperplane& transform(const MatrixBase<XprType>& mat, TransformTraits traits = Affine)
- {
- if (traits==Affine)
- normal() = mat.inverse().transpose() * normal();
- else if (traits==Isometry)
- normal() = mat * normal();
- else
- {
- eigen_assert("invalid traits value in Hyperplane::transform()");
- }
- return *this;
- }
-
- /** Applies the transformation \a t to \c *this and returns a reference to \c *this.
- *
- * \param t the transformation of dimension Dim
- * \param traits specifies whether the transformation \a t represents an #Isometry
- * or a more generic #Affine transformation. The default is #Affine.
- * Other kind of transformations are not supported.
- */
- template<int TrOptions>
- inline Hyperplane& transform(const Transform<Scalar,AmbientDimAtCompileTime,Affine,TrOptions>& t,
- TransformTraits traits = Affine)
- {
- transform(t.linear(), traits);
- offset() -= normal().dot(t.translation());
- return *this;
- }
-
- /** \returns \c *this with scalar type casted to \a NewScalarType
- *
- * Note that if \a NewScalarType is equal to the current scalar type of \c *this
- * then this function smartly returns a const reference to \c *this.
- */
- template<typename NewScalarType>
- inline typename internal::cast_return_type<Hyperplane,
- Hyperplane<NewScalarType,AmbientDimAtCompileTime,Options> >::type cast() const
- {
- return typename internal::cast_return_type<Hyperplane,
- Hyperplane<NewScalarType,AmbientDimAtCompileTime,Options> >::type(*this);
- }
-
- /** Copy constructor with scalar type conversion */
- template<typename OtherScalarType,int OtherOptions>
- inline explicit Hyperplane(const Hyperplane<OtherScalarType,AmbientDimAtCompileTime,OtherOptions>& other)
- { m_coeffs = other.coeffs().template cast<Scalar>(); }
-
- /** \returns \c true if \c *this is approximately equal to \a other, within the precision
- * determined by \a prec.
- *
- * \sa MatrixBase::isApprox() */
- template<int OtherOptions>
- bool isApprox(const Hyperplane<Scalar,AmbientDimAtCompileTime,OtherOptions>& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
- { return m_coeffs.isApprox(other.m_coeffs, prec); }
-
-protected:
-
- Coefficients m_coeffs;
-};
-
-#endif // EIGEN_HYPERPLANE_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h b/extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h
deleted file mode 100644
index 52b46988196..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h
+++ /dev/null
@@ -1,229 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_ORTHOMETHODS_H
-#define EIGEN_ORTHOMETHODS_H
-
-/** \geometry_module
- *
- * \returns the cross product of \c *this and \a other
- *
- * Here is a very good explanation of cross-product: http://xkcd.com/199/
- * \sa MatrixBase::cross3()
- */
-template<typename Derived>
-template<typename OtherDerived>
-inline typename MatrixBase<Derived>::template cross_product_return_type<OtherDerived>::type
-MatrixBase<Derived>::cross(const MatrixBase<OtherDerived>& other) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,3)
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,3)
-
- // Note that there is no need for an expression here since the compiler
- // optimize such a small temporary very well (even within a complex expression)
- const typename internal::nested<Derived,2>::type lhs(derived());
- const typename internal::nested<OtherDerived,2>::type rhs(other.derived());
- return typename cross_product_return_type<OtherDerived>::type(
- internal::conj(lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1)),
- internal::conj(lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2)),
- internal::conj(lhs.coeff(0) * rhs.coeff(1) - lhs.coeff(1) * rhs.coeff(0))
- );
-}
-
-namespace internal {
-
-template< int Arch,typename VectorLhs,typename VectorRhs,
- typename Scalar = typename VectorLhs::Scalar,
- bool Vectorizable = (VectorLhs::Flags&VectorRhs::Flags)&PacketAccessBit>
-struct cross3_impl {
- inline static typename internal::plain_matrix_type<VectorLhs>::type
- run(const VectorLhs& lhs, const VectorRhs& rhs)
- {
- return typename internal::plain_matrix_type<VectorLhs>::type(
- internal::conj(lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1)),
- internal::conj(lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2)),
- internal::conj(lhs.coeff(0) * rhs.coeff(1) - lhs.coeff(1) * rhs.coeff(0)),
- 0
- );
- }
-};
-
-}
-
-/** \geometry_module
- *
- * \returns the cross product of \c *this and \a other using only the x, y, and z coefficients
- *
- * The size of \c *this and \a other must be four. This function is especially useful
- * when using 4D vectors instead of 3D ones to get advantage of SSE/AltiVec vectorization.
- *
- * \sa MatrixBase::cross()
- */
-template<typename Derived>
-template<typename OtherDerived>
-inline typename MatrixBase<Derived>::PlainObject
-MatrixBase<Derived>::cross3(const MatrixBase<OtherDerived>& other) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,4)
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,4)
-
- typedef typename internal::nested<Derived,2>::type DerivedNested;
- typedef typename internal::nested<OtherDerived,2>::type OtherDerivedNested;
- const DerivedNested lhs(derived());
- const OtherDerivedNested rhs(other.derived());
-
- return internal::cross3_impl<Architecture::Target,
- typename internal::remove_all<DerivedNested>::type,
- typename internal::remove_all<OtherDerivedNested>::type>::run(lhs,rhs);
-}
-
-/** \returns a matrix expression of the cross product of each column or row
- * of the referenced expression with the \a other vector.
- *
- * The referenced matrix must have one dimension equal to 3.
- * The result matrix has the same dimensions than the referenced one.
- *
- * \geometry_module
- *
- * \sa MatrixBase::cross() */
-template<typename ExpressionType, int Direction>
-template<typename OtherDerived>
-const typename VectorwiseOp<ExpressionType,Direction>::CrossReturnType
-VectorwiseOp<ExpressionType,Direction>::cross(const MatrixBase<OtherDerived>& other) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,3)
- EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
- YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
-
- CrossReturnType res(_expression().rows(),_expression().cols());
- if(Direction==Vertical)
- {
- eigen_assert(CrossReturnType::RowsAtCompileTime==3 && "the matrix must have exactly 3 rows");
- res.row(0) = (_expression().row(1) * other.coeff(2) - _expression().row(2) * other.coeff(1)).conjugate();
- res.row(1) = (_expression().row(2) * other.coeff(0) - _expression().row(0) * other.coeff(2)).conjugate();
- res.row(2) = (_expression().row(0) * other.coeff(1) - _expression().row(1) * other.coeff(0)).conjugate();
- }
- else
- {
- eigen_assert(CrossReturnType::ColsAtCompileTime==3 && "the matrix must have exactly 3 columns");
- res.col(0) = (_expression().col(1) * other.coeff(2) - _expression().col(2) * other.coeff(1)).conjugate();
- res.col(1) = (_expression().col(2) * other.coeff(0) - _expression().col(0) * other.coeff(2)).conjugate();
- res.col(2) = (_expression().col(0) * other.coeff(1) - _expression().col(1) * other.coeff(0)).conjugate();
- }
- return res;
-}
-
-namespace internal {
-
-template<typename Derived, int Size = Derived::SizeAtCompileTime>
-struct unitOrthogonal_selector
-{
- typedef typename plain_matrix_type<Derived>::type VectorType;
- typedef typename traits<Derived>::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef typename Derived::Index Index;
- typedef Matrix<Scalar,2,1> Vector2;
- inline static VectorType run(const Derived& src)
- {
- VectorType perp = VectorType::Zero(src.size());
- Index maxi = 0;
- Index sndi = 0;
- src.cwiseAbs().maxCoeff(&maxi);
- if (maxi==0)
- sndi = 1;
- RealScalar invnm = RealScalar(1)/(Vector2() << src.coeff(sndi),src.coeff(maxi)).finished().norm();
- perp.coeffRef(maxi) = -conj(src.coeff(sndi)) * invnm;
- perp.coeffRef(sndi) = conj(src.coeff(maxi)) * invnm;
-
- return perp;
- }
-};
-
-template<typename Derived>
-struct unitOrthogonal_selector<Derived,3>
-{
- typedef typename plain_matrix_type<Derived>::type VectorType;
- typedef typename traits<Derived>::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- inline static VectorType run(const Derived& src)
- {
- VectorType perp;
- /* Let us compute the crossed product of *this with a vector
- * that is not too close to being colinear to *this.
- */
-
- /* unless the x and y coords are both close to zero, we can
- * simply take ( -y, x, 0 ) and normalize it.
- */
- if((!isMuchSmallerThan(src.x(), src.z()))
- || (!isMuchSmallerThan(src.y(), src.z())))
- {
- RealScalar invnm = RealScalar(1)/src.template head<2>().norm();
- perp.coeffRef(0) = -conj(src.y())*invnm;
- perp.coeffRef(1) = conj(src.x())*invnm;
- perp.coeffRef(2) = 0;
- }
- /* if both x and y are close to zero, then the vector is close
- * to the z-axis, so it's far from colinear to the x-axis for instance.
- * So we take the crossed product with (1,0,0) and normalize it.
- */
- else
- {
- RealScalar invnm = RealScalar(1)/src.template tail<2>().norm();
- perp.coeffRef(0) = 0;
- perp.coeffRef(1) = -conj(src.z())*invnm;
- perp.coeffRef(2) = conj(src.y())*invnm;
- }
-
- return perp;
- }
-};
-
-template<typename Derived>
-struct unitOrthogonal_selector<Derived,2>
-{
- typedef typename plain_matrix_type<Derived>::type VectorType;
- inline static VectorType run(const Derived& src)
- { return VectorType(-conj(src.y()), conj(src.x())).normalized(); }
-};
-
-} // end namespace internal
-
-/** \returns a unit vector which is orthogonal to \c *this
- *
- * The size of \c *this must be at least 2. If the size is exactly 2,
- * then the returned vector is a counter clock wise rotation of \c *this, i.e., (-y,x).normalized().
- *
- * \sa cross()
- */
-template<typename Derived>
-typename MatrixBase<Derived>::PlainObject
-MatrixBase<Derived>::unitOrthogonal() const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
- return internal::unitOrthogonal_selector<Derived>::run(derived());
-}
-
-#endif // EIGEN_ORTHOMETHODS_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h b/extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h
deleted file mode 100644
index b90f9c088a2..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h
+++ /dev/null
@@ -1,168 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_PARAMETRIZEDLINE_H
-#define EIGEN_PARAMETRIZEDLINE_H
-
-/** \geometry_module \ingroup Geometry_Module
- *
- * \class ParametrizedLine
- *
- * \brief A parametrized line
- *
- * A parametrized line is defined by an origin point \f$ \mathbf{o} \f$ and a unit
- * direction vector \f$ \mathbf{d} \f$ such that the line corresponds to
- * the set \f$ l(t) = \mathbf{o} + t \mathbf{d} \f$, \f$ t \in \mathbf{R} \f$.
- *
- * \param _Scalar the scalar type, i.e., the type of the coefficients
- * \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
- */
-template <typename _Scalar, int _AmbientDim, int _Options>
-class ParametrizedLine
-{
-public:
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
- enum {
- AmbientDimAtCompileTime = _AmbientDim,
- Options = _Options
- };
- typedef _Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef DenseIndex Index;
- typedef Matrix<Scalar,AmbientDimAtCompileTime,1,Options> VectorType;
-
- /** Default constructor without initialization */
- inline explicit ParametrizedLine() {}
-
- template<int OtherOptions>
- ParametrizedLine(const ParametrizedLine<Scalar,AmbientDimAtCompileTime,OtherOptions>& other)
- : m_origin(other.origin()), m_direction(other.direction())
- {}
-
- /** Constructs a dynamic-size line with \a _dim the dimension
- * of the ambient space */
- inline explicit ParametrizedLine(Index _dim) : m_origin(_dim), m_direction(_dim) {}
-
- /** Initializes a parametrized line of direction \a direction and origin \a origin.
- * \warning the vector direction is assumed to be normalized.
- */
- ParametrizedLine(const VectorType& origin, const VectorType& direction)
- : m_origin(origin), m_direction(direction) {}
-
- template <int OtherOptions>
- explicit ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane);
-
- /** Constructs a parametrized line going from \a p0 to \a p1. */
- static inline ParametrizedLine Through(const VectorType& p0, const VectorType& p1)
- { return ParametrizedLine(p0, (p1-p0).normalized()); }
-
- ~ParametrizedLine() {}
-
- /** \returns the dimension in which the line holds */
- inline Index dim() const { return m_direction.size(); }
-
- const VectorType& origin() const { return m_origin; }
- VectorType& origin() { return m_origin; }
-
- const VectorType& direction() const { return m_direction; }
- VectorType& direction() { return m_direction; }
-
- /** \returns the squared distance of a point \a p to its projection onto the line \c *this.
- * \sa distance()
- */
- RealScalar squaredDistance(const VectorType& p) const
- {
- VectorType diff = p - origin();
- return (diff - direction().dot(diff) * direction()).squaredNorm();
- }
- /** \returns the distance of a point \a p to its projection onto the line \c *this.
- * \sa squaredDistance()
- */
- RealScalar distance(const VectorType& p) const { return internal::sqrt(squaredDistance(p)); }
-
- /** \returns the projection of a point \a p onto the line \c *this. */
- VectorType projection(const VectorType& p) const
- { return origin() + direction().dot(p-origin()) * direction(); }
-
- template <int OtherOptions>
- Scalar intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const;
-
- /** \returns \c *this with scalar type casted to \a NewScalarType
- *
- * Note that if \a NewScalarType is equal to the current scalar type of \c *this
- * then this function smartly returns a const reference to \c *this.
- */
- template<typename NewScalarType>
- inline typename internal::cast_return_type<ParametrizedLine,
- ParametrizedLine<NewScalarType,AmbientDimAtCompileTime,Options> >::type cast() const
- {
- return typename internal::cast_return_type<ParametrizedLine,
- ParametrizedLine<NewScalarType,AmbientDimAtCompileTime,Options> >::type(*this);
- }
-
- /** Copy constructor with scalar type conversion */
- template<typename OtherScalarType,int OtherOptions>
- inline explicit ParametrizedLine(const ParametrizedLine<OtherScalarType,AmbientDimAtCompileTime,OtherOptions>& other)
- {
- m_origin = other.origin().template cast<Scalar>();
- m_direction = other.direction().template cast<Scalar>();
- }
-
- /** \returns \c true if \c *this is approximately equal to \a other, within the precision
- * determined by \a prec.
- *
- * \sa MatrixBase::isApprox() */
- bool isApprox(const ParametrizedLine& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
- { return m_origin.isApprox(other.m_origin, prec) && m_direction.isApprox(other.m_direction, prec); }
-
-protected:
-
- VectorType m_origin, m_direction;
-};
-
-/** Constructs a parametrized line from a 2D hyperplane
- *
- * \warning the ambient space must have dimension 2 such that the hyperplane actually describes a line
- */
-template <typename _Scalar, int _AmbientDim, int _Options>
-template <int OtherOptions>
-inline ParametrizedLine<_Scalar, _AmbientDim,_Options>::ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim,OtherOptions>& hyperplane)
-{
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
- direction() = hyperplane.normal().unitOrthogonal();
- origin() = -hyperplane.normal()*hyperplane.offset();
-}
-
-/** \returns the parameter value of the intersection between \c *this and the given hyperplane
- */
-template <typename _Scalar, int _AmbientDim, int _Options>
-template <int OtherOptions>
-inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const
-{
- return -(hyperplane.offset()+hyperplane.normal().dot(origin()))
- / hyperplane.normal().dot(direction());
-}
-
-#endif // EIGEN_PARAMETRIZEDLINE_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/Quaternion.h b/extern/Eigen3/Eigen/src/Geometry/Quaternion.h
deleted file mode 100644
index 2662d60fed1..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/Quaternion.h
+++ /dev/null
@@ -1,751 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2009 Mathieu Gautier <mathieu.gautier@cea.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_QUATERNION_H
-#define EIGEN_QUATERNION_H
-
-/***************************************************************************
-* Definition of QuaternionBase<Derived>
-* The implementation is at the end of the file
-***************************************************************************/
-
-namespace internal {
-template<typename Other,
- int OtherRows=Other::RowsAtCompileTime,
- int OtherCols=Other::ColsAtCompileTime>
-struct quaternionbase_assign_impl;
-}
-
-template<class Derived>
-class QuaternionBase : public RotationBase<Derived, 3>
-{
- typedef RotationBase<Derived, 3> Base;
-public:
- using Base::operator*;
- using Base::derived;
-
- typedef typename internal::traits<Derived>::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef typename internal::traits<Derived>::Coefficients Coefficients;
- enum {
- Flags = Eigen::internal::traits<Derived>::Flags
- };
-
- // typedef typename Matrix<Scalar,4,1> Coefficients;
- /** the type of a 3D vector */
- typedef Matrix<Scalar,3,1> Vector3;
- /** the equivalent rotation matrix type */
- typedef Matrix<Scalar,3,3> Matrix3;
- /** the equivalent angle-axis type */
- typedef AngleAxis<Scalar> AngleAxisType;
-
-
-
- /** \returns the \c x coefficient */
- inline Scalar x() const { return this->derived().coeffs().coeff(0); }
- /** \returns the \c y coefficient */
- inline Scalar y() const { return this->derived().coeffs().coeff(1); }
- /** \returns the \c z coefficient */
- inline Scalar z() const { return this->derived().coeffs().coeff(2); }
- /** \returns the \c w coefficient */
- inline Scalar w() const { return this->derived().coeffs().coeff(3); }
-
- /** \returns a reference to the \c x coefficient */
- inline Scalar& x() { return this->derived().coeffs().coeffRef(0); }
- /** \returns a reference to the \c y coefficient */
- inline Scalar& y() { return this->derived().coeffs().coeffRef(1); }
- /** \returns a reference to the \c z coefficient */
- inline Scalar& z() { return this->derived().coeffs().coeffRef(2); }
- /** \returns a reference to the \c w coefficient */
- inline Scalar& w() { return this->derived().coeffs().coeffRef(3); }
-
- /** \returns a read-only vector expression of the imaginary part (x,y,z) */
- inline const VectorBlock<const Coefficients,3> vec() const { return coeffs().template head<3>(); }
-
- /** \returns a vector expression of the imaginary part (x,y,z) */
- inline VectorBlock<Coefficients,3> vec() { return coeffs().template head<3>(); }
-
- /** \returns a read-only vector expression of the coefficients (x,y,z,w) */
- inline const typename internal::traits<Derived>::Coefficients& coeffs() const { return derived().coeffs(); }
-
- /** \returns a vector expression of the coefficients (x,y,z,w) */
- inline typename internal::traits<Derived>::Coefficients& coeffs() { return derived().coeffs(); }
-
- EIGEN_STRONG_INLINE QuaternionBase<Derived>& operator=(const QuaternionBase<Derived>& other);
- template<class OtherDerived> EIGEN_STRONG_INLINE Derived& operator=(const QuaternionBase<OtherDerived>& other);
-
-// disabled this copy operator as it is giving very strange compilation errors when compiling
-// test_stdvector with GCC 4.4.2. This looks like a GCC bug though, so feel free to re-enable it if it's
-// useful; however notice that we already have the templated operator= above and e.g. in MatrixBase
-// we didn't have to add, in addition to templated operator=, such a non-templated copy operator.
-// Derived& operator=(const QuaternionBase& other)
-// { return operator=<Derived>(other); }
-
- Derived& operator=(const AngleAxisType& aa);
- template<class OtherDerived> Derived& operator=(const MatrixBase<OtherDerived>& m);
-
- /** \returns a quaternion representing an identity rotation
- * \sa MatrixBase::Identity()
- */
- inline static Quaternion<Scalar> Identity() { return Quaternion<Scalar>(1, 0, 0, 0); }
-
- /** \sa QuaternionBase::Identity(), MatrixBase::setIdentity()
- */
- inline QuaternionBase& setIdentity() { coeffs() << 0, 0, 0, 1; return *this; }
-
- /** \returns the squared norm of the quaternion's coefficients
- * \sa QuaternionBase::norm(), MatrixBase::squaredNorm()
- */
- inline Scalar squaredNorm() const { return coeffs().squaredNorm(); }
-
- /** \returns the norm of the quaternion's coefficients
- * \sa QuaternionBase::squaredNorm(), MatrixBase::norm()
- */
- inline Scalar norm() const { return coeffs().norm(); }
-
- /** Normalizes the quaternion \c *this
- * \sa normalized(), MatrixBase::normalize() */
- inline void normalize() { coeffs().normalize(); }
- /** \returns a normalized copy of \c *this
- * \sa normalize(), MatrixBase::normalized() */
- inline Quaternion<Scalar> normalized() const { return Quaternion<Scalar>(coeffs().normalized()); }
-
- /** \returns the dot product of \c *this and \a other
- * Geometrically speaking, the dot product of two unit quaternions
- * corresponds to the cosine of half the angle between the two rotations.
- * \sa angularDistance()
- */
- template<class OtherDerived> inline Scalar dot(const QuaternionBase<OtherDerived>& other) const { return coeffs().dot(other.coeffs()); }
-
- template<class OtherDerived> Scalar angularDistance(const QuaternionBase<OtherDerived>& other) const;
-
- /** \returns an equivalent 3x3 rotation matrix */
- Matrix3 toRotationMatrix() const;
-
- /** \returns the quaternion which transform \a a into \a b through a rotation */
- template<typename Derived1, typename Derived2>
- Derived& setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
-
- template<class OtherDerived> EIGEN_STRONG_INLINE Quaternion<Scalar> operator* (const QuaternionBase<OtherDerived>& q) const;
- template<class OtherDerived> EIGEN_STRONG_INLINE Derived& operator*= (const QuaternionBase<OtherDerived>& q);
-
- /** \returns the quaternion describing the inverse rotation */
- Quaternion<Scalar> inverse() const;
-
- /** \returns the conjugated quaternion */
- Quaternion<Scalar> conjugate() const;
-
- /** \returns an interpolation for a constant motion between \a other and \c *this
- * \a t in [0;1]
- * see http://en.wikipedia.org/wiki/Slerp
- */
- template<class OtherDerived> Quaternion<Scalar> slerp(Scalar t, const QuaternionBase<OtherDerived>& other) const;
-
- /** \returns \c true if \c *this is approximately equal to \a other, within the precision
- * determined by \a prec.
- *
- * \sa MatrixBase::isApprox() */
- template<class OtherDerived>
- bool isApprox(const QuaternionBase<OtherDerived>& other, RealScalar prec = NumTraits<Scalar>::dummy_precision()) const
- { return coeffs().isApprox(other.coeffs(), prec); }
-
- /** return the result vector of \a v through the rotation*/
- EIGEN_STRONG_INLINE Vector3 _transformVector(Vector3 v) const;
-
- /** \returns \c *this with scalar type casted to \a NewScalarType
- *
- * Note that if \a NewScalarType is equal to the current scalar type of \c *this
- * then this function smartly returns a const reference to \c *this.
- */
- template<typename NewScalarType>
- inline typename internal::cast_return_type<Derived,Quaternion<NewScalarType> >::type cast() const
- {
- return typename internal::cast_return_type<Derived,Quaternion<NewScalarType> >::type(
- coeffs().template cast<NewScalarType>());
- }
-
-#ifdef EIGEN_QUATERNIONBASE_PLUGIN
-# include EIGEN_QUATERNIONBASE_PLUGIN
-#endif
-};
-
-/***************************************************************************
-* Definition/implementation of Quaternion<Scalar>
-***************************************************************************/
-
-/** \geometry_module \ingroup Geometry_Module
- *
- * \class Quaternion
- *
- * \brief The quaternion class used to represent 3D orientations and rotations
- *
- * \param _Scalar the scalar type, i.e., the type of the coefficients
- *
- * This class represents a quaternion \f$ w+xi+yj+zk \f$ that is a convenient representation of
- * orientations and rotations of objects in three dimensions. Compared to other representations
- * like Euler angles or 3x3 matrices, quatertions offer the following advantages:
- * \li \b compact storage (4 scalars)
- * \li \b efficient to compose (28 flops),
- * \li \b stable spherical interpolation
- *
- * The following two typedefs are provided for convenience:
- * \li \c Quaternionf for \c float
- * \li \c Quaterniond for \c double
- *
- * \sa class AngleAxis, class Transform
- */
-
-namespace internal {
-template<typename _Scalar,int _Options>
-struct traits<Quaternion<_Scalar,_Options> >
-{
- typedef Quaternion<_Scalar,_Options> PlainObject;
- typedef _Scalar Scalar;
- typedef Matrix<_Scalar,4,1,_Options> Coefficients;
- enum{
- IsAligned = bool(EIGEN_ALIGN) && ((int(_Options)&Aligned)==Aligned),
- Flags = IsAligned ? (AlignedBit | LvalueBit) : LvalueBit
- };
-};
-}
-
-template<typename _Scalar, int _Options>
-class Quaternion : public QuaternionBase<Quaternion<_Scalar,_Options> >{
- typedef QuaternionBase<Quaternion<_Scalar,_Options> > Base;
-public:
- typedef _Scalar Scalar;
-
- EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Quaternion)
- using Base::operator*=;
-
- typedef typename internal::traits<Quaternion<Scalar,_Options> >::Coefficients Coefficients;
- typedef typename Base::AngleAxisType AngleAxisType;
-
- /** Default constructor leaving the quaternion uninitialized. */
- inline Quaternion() {}
-
- /** Constructs and initializes the quaternion \f$ w+xi+yj+zk \f$ from
- * its four coefficients \a w, \a x, \a y and \a z.
- *
- * \warning Note the order of the arguments: the real \a w coefficient first,
- * while internally the coefficients are stored in the following order:
- * [\c x, \c y, \c z, \c w]
- */
- inline Quaternion(Scalar w, Scalar x, Scalar y, Scalar z) : m_coeffs(x, y, z, w){}
-
- /** Constructs and initialize a quaternion from the array data */
- inline Quaternion(const Scalar* data) : m_coeffs(data) {}
-
- /** Copy constructor */
- template<class Derived> EIGEN_STRONG_INLINE Quaternion(const QuaternionBase<Derived>& other) { this->Base::operator=(other); }
-
- /** Constructs and initializes a quaternion from the angle-axis \a aa */
- explicit inline Quaternion(const AngleAxisType& aa) { *this = aa; }
-
- /** Constructs and initializes a quaternion from either:
- * - a rotation matrix expression,
- * - a 4D vector expression representing quaternion coefficients.
- */
- template<typename Derived>
- explicit inline Quaternion(const MatrixBase<Derived>& other) { *this = other; }
-
- inline Coefficients& coeffs() { return m_coeffs;}
- inline const Coefficients& coeffs() const { return m_coeffs;}
-
-protected:
- Coefficients m_coeffs;
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
- EIGEN_STRONG_INLINE static void _check_template_params()
- {
- EIGEN_STATIC_ASSERT( (_Options & DontAlign) == _Options,
- INVALID_MATRIX_TEMPLATE_PARAMETERS)
- }
-#endif
-};
-
-/** \ingroup Geometry_Module
- * single precision quaternion type */
-typedef Quaternion<float> Quaternionf;
-/** \ingroup Geometry_Module
- * double precision quaternion type */
-typedef Quaternion<double> Quaterniond;
-
-/***************************************************************************
-* Specialization of Map<Quaternion<Scalar>>
-***************************************************************************/
-
-namespace internal {
- template<typename _Scalar, int _Options>
- struct traits<Map<Quaternion<_Scalar>, _Options> >:
- traits<Quaternion<_Scalar, _Options> >
- {
- typedef _Scalar Scalar;
- typedef Map<Matrix<_Scalar,4,1>, _Options> Coefficients;
-
- typedef traits<Quaternion<_Scalar, _Options> > TraitsBase;
- enum {
- IsAligned = TraitsBase::IsAligned,
-
- Flags = TraitsBase::Flags
- };
- };
-}
-
-namespace internal {
- template<typename _Scalar, int _Options>
- struct traits<Map<const Quaternion<_Scalar>, _Options> >:
- traits<Quaternion<_Scalar> >
- {
- typedef _Scalar Scalar;
- typedef Map<const Matrix<_Scalar,4,1>, _Options> Coefficients;
-
- typedef traits<Quaternion<_Scalar, _Options> > TraitsBase;
- enum {
- IsAligned = TraitsBase::IsAligned,
- Flags = TraitsBase::Flags & ~LvalueBit
- };
- };
-}
-
-/** \brief Quaternion expression mapping a constant memory buffer
- *
- * \param _Scalar the type of the Quaternion coefficients
- * \param _Options see class Map
- *
- * This is a specialization of class Map for Quaternion. This class allows to view
- * a 4 scalar memory buffer as an Eigen's Quaternion object.
- *
- * \sa class Map, class Quaternion, class QuaternionBase
- */
-template<typename _Scalar, int _Options>
-class Map<const Quaternion<_Scalar>, _Options >
- : public QuaternionBase<Map<const Quaternion<_Scalar>, _Options> >
-{
- typedef QuaternionBase<Map<const Quaternion<_Scalar>, _Options> > Base;
-
- public:
- typedef _Scalar Scalar;
- typedef typename internal::traits<Map>::Coefficients Coefficients;
- EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(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:
- * \code *coeffs == {x, y, z, w} \endcode
- *
- * If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
- EIGEN_STRONG_INLINE Map(const Scalar* coeffs) : m_coeffs(coeffs) {}
-
- inline const Coefficients& coeffs() const { return m_coeffs;}
-
- protected:
- const Coefficients m_coeffs;
-};
-
-/** \brief Expression of a quaternion from a memory buffer
- *
- * \param _Scalar the type of the Quaternion coefficients
- * \param _Options see class Map
- *
- * This is a specialization of class Map for Quaternion. This class allows to view
- * a 4 scalar memory buffer as an Eigen's Quaternion object.
- *
- * \sa class Map, class Quaternion, class QuaternionBase
- */
-template<typename _Scalar, int _Options>
-class Map<Quaternion<_Scalar>, _Options >
- : public QuaternionBase<Map<Quaternion<_Scalar>, _Options> >
-{
- typedef QuaternionBase<Map<Quaternion<_Scalar>, _Options> > Base;
-
- public:
- typedef _Scalar Scalar;
- typedef typename internal::traits<Map>::Coefficients Coefficients;
- EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(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:
- * \code *coeffs == {x, y, z, w} \endcode
- *
- * If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
- EIGEN_STRONG_INLINE Map(Scalar* coeffs) : m_coeffs(coeffs) {}
-
- inline Coefficients& coeffs() { return m_coeffs; }
- inline const Coefficients& coeffs() const { return m_coeffs; }
-
- protected:
- Coefficients m_coeffs;
-};
-
-/** \ingroup Geometry_Module
- * Map an unaligned array of single precision scalar as a quaternion */
-typedef Map<Quaternion<float>, 0> QuaternionMapf;
-/** \ingroup Geometry_Module
- * Map an unaligned array of double precision scalar as a quaternion */
-typedef Map<Quaternion<double>, 0> QuaternionMapd;
-/** \ingroup Geometry_Module
- * Map a 16-bits aligned array of double precision scalars as a quaternion */
-typedef Map<Quaternion<float>, Aligned> QuaternionMapAlignedf;
-/** \ingroup Geometry_Module
- * Map a 16-bits aligned array of double precision scalars as a quaternion */
-typedef Map<Quaternion<double>, Aligned> QuaternionMapAlignedd;
-
-/***************************************************************************
-* Implementation of QuaternionBase methods
-***************************************************************************/
-
-// Generic Quaternion * Quaternion product
-// This product can be specialized for a given architecture via the Arch template argument.
-namespace internal {
-template<int Arch, class Derived1, class Derived2, typename Scalar, int _Options> struct quat_product
-{
- EIGEN_STRONG_INLINE static Quaternion<Scalar> run(const QuaternionBase<Derived1>& a, const QuaternionBase<Derived2>& b){
- return Quaternion<Scalar>
- (
- a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
- a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(),
- a.w() * b.y() + a.y() * b.w() + a.z() * b.x() - a.x() * b.z(),
- a.w() * b.z() + a.z() * b.w() + a.x() * b.y() - a.y() * b.x()
- );
- }
-};
-}
-
-/** \returns the concatenation of two rotations as a quaternion-quaternion product */
-template <class Derived>
-template <class OtherDerived>
-EIGEN_STRONG_INLINE Quaternion<typename internal::traits<Derived>::Scalar>
-QuaternionBase<Derived>::operator* (const QuaternionBase<OtherDerived>& other) const
-{
- EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename OtherDerived::Scalar>::value),
- YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
- return internal::quat_product<Architecture::Target, Derived, OtherDerived,
- typename internal::traits<Derived>::Scalar,
- internal::traits<Derived>::IsAligned && internal::traits<OtherDerived>::IsAligned>::run(*this, other);
-}
-
-/** \sa operator*(Quaternion) */
-template <class Derived>
-template <class OtherDerived>
-EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator*= (const QuaternionBase<OtherDerived>& other)
-{
- derived() = derived() * other.derived();
- return derived();
-}
-
-/** Rotation of a vector by a quaternion.
- * \remarks If the quaternion is used to rotate several points (>1)
- * then it is much more efficient to first convert it to a 3x3 Matrix.
- * Comparison of the operation cost for n transformations:
- * - Quaternion2: 30n
- * - Via a Matrix3: 24 + 15n
- */
-template <class Derived>
-EIGEN_STRONG_INLINE typename QuaternionBase<Derived>::Vector3
-QuaternionBase<Derived>::_transformVector(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
- // Vector3 as temporaries.
- Vector3 uv = this->vec().cross(v);
- uv += uv;
- return v + this->w() * uv + this->vec().cross(uv);
-}
-
-template<class Derived>
-EIGEN_STRONG_INLINE QuaternionBase<Derived>& QuaternionBase<Derived>::operator=(const QuaternionBase<Derived>& other)
-{
- coeffs() = other.coeffs();
- return derived();
-}
-
-template<class Derived>
-template<class OtherDerived>
-EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const QuaternionBase<OtherDerived>& other)
-{
- coeffs() = other.coeffs();
- return derived();
-}
-
-/** Set \c *this from an angle-axis \a aa and returns a reference to \c *this
- */
-template<class Derived>
-EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const AngleAxisType& aa)
-{
- Scalar ha = Scalar(0.5)*aa.angle(); // Scalar(0.5) to suppress precision loss warnings
- this->w() = internal::cos(ha);
- this->vec() = internal::sin(ha) * aa.axis();
- return derived();
-}
-
-/** Set \c *this from the expression \a xpr:
- * - if \a xpr is a 4x1 vector, then \a xpr is assumed to be a quaternion
- * - if \a xpr is a 3x3 matrix, then \a xpr is assumed to be rotation matrix
- * and \a xpr is converted to a quaternion
- */
-
-template<class Derived>
-template<class MatrixDerived>
-inline Derived& QuaternionBase<Derived>::operator=(const MatrixBase<MatrixDerived>& xpr)
-{
- EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename MatrixDerived::Scalar>::value),
- YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
- internal::quaternionbase_assign_impl<MatrixDerived>::run(*this, xpr.derived());
- return derived();
-}
-
-/** Convert the quaternion to a 3x3 rotation matrix. The quaternion is required to
- * be normalized, otherwise the result is undefined.
- */
-template<class Derived>
-inline typename QuaternionBase<Derived>::Matrix3
-QuaternionBase<Derived>::toRotationMatrix(void) const
-{
- // NOTE if inlined, then gcc 4.2 and 4.4 get rid of the temporary (not gcc 4.3 !!)
- // if not inlined then the cost of the return by value is huge ~ +35%,
- // however, not inlining this function is an order of magnitude slower, so
- // it has to be inlined, and so the return by value is not an issue
- Matrix3 res;
-
- const Scalar tx = 2*this->x();
- const Scalar ty = 2*this->y();
- const Scalar tz = 2*this->z();
- const Scalar twx = tx*this->w();
- const Scalar twy = ty*this->w();
- const Scalar twz = tz*this->w();
- const Scalar txx = tx*this->x();
- const Scalar txy = ty*this->x();
- const Scalar txz = tz*this->x();
- const Scalar tyy = ty*this->y();
- const Scalar tyz = tz*this->y();
- const Scalar tzz = tz*this->z();
-
- res.coeffRef(0,0) = 1-(tyy+tzz);
- res.coeffRef(0,1) = txy-twz;
- res.coeffRef(0,2) = txz+twy;
- res.coeffRef(1,0) = txy+twz;
- res.coeffRef(1,1) = 1-(txx+tzz);
- res.coeffRef(1,2) = tyz-twx;
- res.coeffRef(2,0) = txz-twy;
- res.coeffRef(2,1) = tyz+twx;
- res.coeffRef(2,2) = 1-(txx+tyy);
-
- return res;
-}
-
-/** Sets \c *this to be a quaternion representing a rotation between
- * the two arbitrary vectors \a a and \a b. In other words, the built
- * rotation represent a rotation sending the line of direction \a a
- * to the line of direction \a b, both lines passing through the origin.
- *
- * \returns a reference to \c *this.
- *
- * Note that the two input vectors do \b not have to be normalized, and
- * do not need to have the same norm.
- */
-template<class Derived>
-template<typename Derived1, typename Derived2>
-inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
-{
- using std::max;
- Vector3 v0 = a.normalized();
- Vector3 v1 = b.normalized();
- Scalar c = v1.dot(v0);
-
- // if dot == -1, vectors are nearly opposites
- // => accuraletly compute the rotation axis by computing the
- // intersection of the two planes. This is done by solving:
- // x^T v0 = 0
- // x^T v1 = 0
- // under the constraint:
- // ||x|| = 1
- // which yields a singular value problem
- if (c < Scalar(-1)+NumTraits<Scalar>::dummy_precision())
- {
- c = max<Scalar>(c,-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);
-
- Scalar w2 = (Scalar(1)+c)*Scalar(0.5);
- this->w() = internal::sqrt(w2);
- this->vec() = axis * internal::sqrt(Scalar(1) - w2);
- return derived();
- }
- Vector3 axis = v0.cross(v1);
- Scalar s = internal::sqrt((Scalar(1)+c)*Scalar(2));
- Scalar invs = Scalar(1)/s;
- this->vec() = axis * invs;
- this->w() = s * Scalar(0.5);
-
- return derived();
-}
-
-/** \returns the multiplicative inverse of \c *this
- * Note that in most cases, i.e., if you simply want the opposite rotation,
- * and/or the quaternion is normalized, then it is enough to use the conjugate.
- *
- * \sa QuaternionBase::conjugate()
- */
-template <class Derived>
-inline Quaternion<typename internal::traits<Derived>::Scalar> QuaternionBase<Derived>::inverse() const
-{
- // FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite() ??
- Scalar n2 = this->squaredNorm();
- if (n2 > 0)
- return Quaternion<Scalar>(conjugate().coeffs() / n2);
- else
- {
- // return an invalid result to flag the error
- return Quaternion<Scalar>(Coefficients::Zero());
- }
-}
-
-/** \returns the conjugate of the \c *this which is equal to the multiplicative inverse
- * if the quaternion is normalized.
- * The conjugate of a quaternion represents the opposite rotation.
- *
- * \sa Quaternion2::inverse()
- */
-template <class Derived>
-inline Quaternion<typename internal::traits<Derived>::Scalar>
-QuaternionBase<Derived>::conjugate() const
-{
- return Quaternion<Scalar>(this->w(),-this->x(),-this->y(),-this->z());
-}
-
-/** \returns the angle (in radian) between two rotations
- * \sa dot()
- */
-template <class Derived>
-template <class OtherDerived>
-inline typename internal::traits<Derived>::Scalar
-QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
-{
- using std::acos;
- double d = internal::abs(this->dot(other));
- if (d>=1.0)
- return Scalar(0);
- return static_cast<Scalar>(2 * acos(d));
-}
-
-/** \returns the spherical linear interpolation between the two quaternions
- * \c *this and \a other at the parameter \a t
- */
-template <class Derived>
-template <class OtherDerived>
-Quaternion<typename internal::traits<Derived>::Scalar>
-QuaternionBase<Derived>::slerp(Scalar t, const QuaternionBase<OtherDerived>& other) const
-{
- using std::acos;
- static const Scalar one = Scalar(1) - NumTraits<Scalar>::epsilon();
- Scalar d = this->dot(other);
- Scalar absD = internal::abs(d);
-
- Scalar scale0;
- Scalar scale1;
-
- if (absD>=one)
- {
- scale0 = Scalar(1) - t;
- scale1 = t;
- }
- else
- {
- // theta is the angle between the 2 quaternions
- Scalar theta = acos(absD);
- Scalar sinTheta = internal::sin(theta);
-
- scale0 = internal::sin( ( Scalar(1) - t ) * theta) / sinTheta;
- scale1 = internal::sin( ( t * theta) ) / sinTheta;
- if (d<0)
- scale1 = -scale1;
- }
-
- return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
-}
-
-namespace internal {
-
-// set from a rotation matrix
-template<typename Other>
-struct quaternionbase_assign_impl<Other,3,3>
-{
- typedef typename Other::Scalar Scalar;
- typedef DenseIndex Index;
- template<class Derived> inline static void run(QuaternionBase<Derived>& q, const Other& mat)
- {
- // This algorithm comes from "Quaternion Calculus and Fast Animation",
- // Ken Shoemake, 1987 SIGGRAPH course notes
- Scalar t = mat.trace();
- if (t > Scalar(0))
- {
- t = sqrt(t + Scalar(1.0));
- q.w() = Scalar(0.5)*t;
- t = Scalar(0.5)/t;
- q.x() = (mat.coeff(2,1) - mat.coeff(1,2)) * t;
- q.y() = (mat.coeff(0,2) - mat.coeff(2,0)) * t;
- q.z() = (mat.coeff(1,0) - mat.coeff(0,1)) * t;
- }
- else
- {
- DenseIndex i = 0;
- if (mat.coeff(1,1) > mat.coeff(0,0))
- i = 1;
- if (mat.coeff(2,2) > mat.coeff(i,i))
- i = 2;
- DenseIndex j = (i+1)%3;
- DenseIndex k = (j+1)%3;
-
- t = sqrt(mat.coeff(i,i)-mat.coeff(j,j)-mat.coeff(k,k) + Scalar(1.0));
- q.coeffs().coeffRef(i) = Scalar(0.5) * t;
- t = Scalar(0.5)/t;
- q.w() = (mat.coeff(k,j)-mat.coeff(j,k))*t;
- q.coeffs().coeffRef(j) = (mat.coeff(j,i)+mat.coeff(i,j))*t;
- q.coeffs().coeffRef(k) = (mat.coeff(k,i)+mat.coeff(i,k))*t;
- }
- }
-};
-
-// set from a vector of coefficients assumed to be a quaternion
-template<typename Other>
-struct quaternionbase_assign_impl<Other,4,1>
-{
- typedef typename Other::Scalar Scalar;
- template<class Derived> inline static void run(QuaternionBase<Derived>& q, const Other& vec)
- {
- q.coeffs() = vec;
- }
-};
-
-} // end namespace internal
-
-#endif // EIGEN_QUATERNION_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/Rotation2D.h b/extern/Eigen3/Eigen/src/Geometry/Rotation2D.h
deleted file mode 100644
index e1214bd3ebb..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/Rotation2D.h
+++ /dev/null
@@ -1,165 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_ROTATION2D_H
-#define EIGEN_ROTATION2D_H
-
-/** \geometry_module \ingroup Geometry_Module
- *
- * \class Rotation2D
- *
- * \brief Represents a rotation/orientation in a 2 dimensional space.
- *
- * \param _Scalar the scalar type, i.e., the type of the coefficients
- *
- * This class is equivalent to a single scalar representing a counter clock wise rotation
- * as a single angle in radian. It provides some additional features such as the automatic
- * conversion from/to a 2x2 rotation matrix. Moreover this class aims to provide a similar
- * interface to Quaternion in order to facilitate the writing of generic algorithms
- * dealing with rotations.
- *
- * \sa class Quaternion, class Transform
- */
-
-namespace internal {
-
-template<typename _Scalar> struct traits<Rotation2D<_Scalar> >
-{
- typedef _Scalar Scalar;
-};
-} // end namespace internal
-
-template<typename _Scalar>
-class Rotation2D : public RotationBase<Rotation2D<_Scalar>,2>
-{
- typedef RotationBase<Rotation2D<_Scalar>,2> Base;
-
-public:
-
- using Base::operator*;
-
- enum { Dim = 2 };
- /** the scalar type of the coefficients */
- typedef _Scalar Scalar;
- typedef Matrix<Scalar,2,1> Vector2;
- typedef Matrix<Scalar,2,2> Matrix2;
-
-protected:
-
- Scalar m_angle;
-
-public:
-
- /** Construct a 2D counter clock wise rotation from the angle \a a in radian. */
- inline Rotation2D(Scalar a) : m_angle(a) {}
-
- /** \returns the rotation angle */
- inline Scalar angle() const { return m_angle; }
-
- /** \returns a read-write reference to the rotation angle */
- inline Scalar& angle() { return m_angle; }
-
- /** \returns the inverse rotation */
- inline Rotation2D inverse() const { return -m_angle; }
-
- /** Concatenates two rotations */
- inline Rotation2D operator*(const Rotation2D& other) const
- { return m_angle + other.m_angle; }
-
- /** Concatenates two rotations */
- inline Rotation2D& operator*=(const Rotation2D& other)
- { return m_angle += other.m_angle; return *this; }
-
- /** 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;
-
- /** \returns the spherical interpolation between \c *this and \a other using
- * parameter \a t. It is in fact equivalent to a linear interpolation.
- */
- inline Rotation2D slerp(Scalar t, const Rotation2D& other) const
- { return m_angle * (1-t) + other.angle() * t; }
-
- /** \returns \c *this with scalar type casted to \a NewScalarType
- *
- * Note that if \a NewScalarType is equal to the current scalar type of \c *this
- * then this function smartly returns a const reference to \c *this.
- */
- template<typename NewScalarType>
- inline typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type cast() const
- { return typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type(*this); }
-
- /** Copy constructor with scalar type conversion */
- template<typename OtherScalarType>
- inline explicit Rotation2D(const Rotation2D<OtherScalarType>& other)
- {
- m_angle = Scalar(other.angle());
- }
-
- inline static Rotation2D Identity() { return Rotation2D(0); }
-
- /** \returns \c true if \c *this is approximately equal to \a other, within the precision
- * determined by \a prec.
- *
- * \sa MatrixBase::isApprox() */
- bool isApprox(const Rotation2D& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
- { return internal::isApprox(m_angle,other.m_angle, prec); }
-};
-
-/** \ingroup Geometry_Module
- * single precision 2D rotation type */
-typedef Rotation2D<float> Rotation2Df;
-/** \ingroup Geometry_Module
- * double precision 2D rotation type */
-typedef Rotation2D<double> Rotation2Dd;
-
-/** Set \c *this from a 2x2 rotation matrix \a mat.
- * In other words, this function extract the rotation angle
- * from the rotation matrix.
- */
-template<typename Scalar>
-template<typename Derived>
-Rotation2D<Scalar>& Rotation2D<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat)
-{
- EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime==2 && Derived::ColsAtCompileTime==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
- m_angle = internal::atan2(mat.coeff(1,0), mat.coeff(0,0));
- return *this;
-}
-
-/** Constructs and \returns an equivalent 2x2 rotation matrix.
- */
-template<typename Scalar>
-typename Rotation2D<Scalar>::Matrix2
-Rotation2D<Scalar>::toRotationMatrix(void) const
-{
- Scalar sinA = internal::sin(m_angle);
- Scalar cosA = internal::cos(m_angle);
- return (Matrix2() << cosA, -sinA, sinA, cosA).finished();
-}
-
-#endif // EIGEN_ROTATION2D_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/RotationBase.h b/extern/Eigen3/Eigen/src/Geometry/RotationBase.h
deleted file mode 100644
index 1abf06bb640..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/RotationBase.h
+++ /dev/null
@@ -1,217 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_ROTATIONBASE_H
-#define EIGEN_ROTATIONBASE_H
-
-// forward declaration
-namespace internal {
-template<typename RotationDerived, typename MatrixType, bool IsVector=MatrixType::IsVectorAtCompileTime>
-struct rotation_base_generic_product_selector;
-}
-
-/** \class RotationBase
- *
- * \brief Common base class for compact rotation representations
- *
- * \param Derived is the derived type, i.e., a rotation type
- * \param _Dim the dimension of the space
- */
-template<typename Derived, int _Dim>
-class RotationBase
-{
- public:
- enum { Dim = _Dim };
- /** the scalar type of the coefficients */
- typedef typename internal::traits<Derived>::Scalar Scalar;
-
- /** corresponding linear transformation matrix type */
- typedef Matrix<Scalar,Dim,Dim> RotationMatrixType;
- typedef Matrix<Scalar,Dim,1> VectorType;
-
- public:
- inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
- inline Derived& derived() { return *static_cast<Derived*>(this); }
-
- /** \returns an equivalent rotation matrix */
- inline RotationMatrixType toRotationMatrix() const { return derived().toRotationMatrix(); }
-
- /** \returns an equivalent rotation matrix
- * This function is added to be conform with the Transform class' naming scheme.
- */
- inline RotationMatrixType matrix() const { return derived().toRotationMatrix(); }
-
- /** \returns the inverse rotation */
- inline Derived inverse() const { return derived().inverse(); }
-
- /** \returns the concatenation of the rotation \c *this with a translation \a t */
- inline Transform<Scalar,Dim,Isometry> operator*(const Translation<Scalar,Dim>& t) const
- { return Transform<Scalar,Dim,Isometry>(*this) * t; }
-
- /** \returns the concatenation of the rotation \c *this with a uniform scaling \a s */
- inline RotationMatrixType operator*(const UniformScaling<Scalar>& s) const
- { return toRotationMatrix() * s.factor(); }
-
- /** \returns the concatenation of the rotation \c *this with a generic expression \a e
- * \a e can be:
- * - a DimxDim linear transformation matrix
- * - a DimxDim diagonal matrix (axis aligned scaling)
- * - a vector of size Dim
- */
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE typename internal::rotation_base_generic_product_selector<Derived,OtherDerived,OtherDerived::IsVectorAtCompileTime>::ReturnType
- operator*(const EigenBase<OtherDerived>& e) const
- { return internal::rotation_base_generic_product_selector<Derived,OtherDerived>::run(derived(), e.derived()); }
-
- /** \returns the concatenation of a linear transformation \a l with the rotation \a r */
- template<typename OtherDerived> friend
- inline RotationMatrixType operator*(const EigenBase<OtherDerived>& l, const Derived& r)
- { return l.derived() * r.toRotationMatrix(); }
-
- /** \returns the concatenation of a scaling \a l with the rotation \a r */
- friend inline Transform<Scalar,Dim,Affine> operator*(const DiagonalMatrix<Scalar,Dim>& l, const Derived& r)
- {
- Transform<Scalar,Dim,Affine> res(r);
- res.linear().applyOnTheLeft(l);
- return res;
- }
-
- /** \returns the concatenation of the rotation \c *this with a transformation \a t */
- template<int Mode, int Options>
- inline Transform<Scalar,Dim,Mode> operator*(const Transform<Scalar,Dim,Mode,Options>& t) const
- { return toRotationMatrix() * t; }
-
- template<typename OtherVectorType>
- inline VectorType _transformVector(const OtherVectorType& v) const
- { return toRotationMatrix() * v; }
-};
-
-namespace internal {
-
-// implementation of the generic product rotation * matrix
-template<typename RotationDerived, typename MatrixType>
-struct rotation_base_generic_product_selector<RotationDerived,MatrixType,false>
-{
- enum { Dim = RotationDerived::Dim };
- typedef Matrix<typename RotationDerived::Scalar,Dim,Dim> ReturnType;
- inline static ReturnType run(const RotationDerived& r, const MatrixType& m)
- { return r.toRotationMatrix() * m; }
-};
-
-template<typename RotationDerived, typename Scalar, int Dim, int MaxDim>
-struct rotation_base_generic_product_selector< RotationDerived, DiagonalMatrix<Scalar,Dim,MaxDim>, false >
-{
- typedef Transform<Scalar,Dim,Affine> ReturnType;
- inline static ReturnType run(const RotationDerived& r, const DiagonalMatrix<Scalar,Dim,MaxDim>& m)
- {
- ReturnType res(r);
- res.linear() *= m;
- return res;
- }
-};
-
-template<typename RotationDerived,typename OtherVectorType>
-struct rotation_base_generic_product_selector<RotationDerived,OtherVectorType,true>
-{
- enum { Dim = RotationDerived::Dim };
- typedef Matrix<typename RotationDerived::Scalar,Dim,1> ReturnType;
- EIGEN_STRONG_INLINE static ReturnType run(const RotationDerived& r, const OtherVectorType& v)
- {
- return r._transformVector(v);
- }
-};
-
-} // end namespace internal
-
-/** \geometry_module
- *
- * \brief Constructs a Dim x Dim rotation matrix from the rotation \a r
- */
-template<typename _Scalar, int _Rows, int _Cols, int _Storage, int _MaxRows, int _MaxCols>
-template<typename OtherDerived>
-Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
-::Matrix(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
-{
- EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim))
- *this = r.toRotationMatrix();
-}
-
-/** \geometry_module
- *
- * \brief Set a Dim x Dim rotation matrix from the rotation \a r
- */
-template<typename _Scalar, int _Rows, int _Cols, int _Storage, int _MaxRows, int _MaxCols>
-template<typename OtherDerived>
-Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>&
-Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
-::operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
-{
- EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim))
- return *this = r.toRotationMatrix();
-}
-
-namespace internal {
-
-/** \internal
- *
- * Helper function to return an arbitrary rotation object to a rotation matrix.
- *
- * \param Scalar the numeric type of the matrix coefficients
- * \param Dim the dimension of the current space
- *
- * It returns a Dim x Dim fixed size matrix.
- *
- * Default specializations are provided for:
- * - any scalar type (2D),
- * - any matrix expression,
- * - any type based on RotationBase (e.g., Quaternion, AngleAxis, Rotation2D)
- *
- * Currently toRotationMatrix is only used by Transform.
- *
- * \sa class Transform, class Rotation2D, class Quaternion, class AngleAxis
- */
-template<typename Scalar, int Dim>
-inline static Matrix<Scalar,2,2> toRotationMatrix(const Scalar& s)
-{
- EIGEN_STATIC_ASSERT(Dim==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
- return Rotation2D<Scalar>(s).toRotationMatrix();
-}
-
-template<typename Scalar, int Dim, typename OtherDerived>
-inline static Matrix<Scalar,Dim,Dim> toRotationMatrix(const RotationBase<OtherDerived,Dim>& r)
-{
- return r.toRotationMatrix();
-}
-
-template<typename Scalar, int Dim, typename OtherDerived>
-inline static const MatrixBase<OtherDerived>& toRotationMatrix(const MatrixBase<OtherDerived>& mat)
-{
- EIGEN_STATIC_ASSERT(OtherDerived::RowsAtCompileTime==Dim && OtherDerived::ColsAtCompileTime==Dim,
- YOU_MADE_A_PROGRAMMING_MISTAKE)
- return mat;
-}
-
-} // end namespace internal
-
-#endif // EIGEN_ROTATIONBASE_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/Scaling.h b/extern/Eigen3/Eigen/src/Geometry/Scaling.h
deleted file mode 100644
index c911d13e1d3..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/Scaling.h
+++ /dev/null
@@ -1,182 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SCALING_H
-#define EIGEN_SCALING_H
-
-/** \geometry_module \ingroup Geometry_Module
- *
- * \class Scaling
- *
- * \brief Represents a generic uniform scaling transformation
- *
- * \param _Scalar the scalar type, i.e., the type of the coefficients.
- *
- * This class represent a uniform scaling transformation. It is the return
- * type of Scaling(Scalar), and most of the time this is the only way it
- * is used. In particular, this class is not aimed to be used to store a scaling transformation,
- * but rather to make easier the constructions and updates of Transform objects.
- *
- * To represent an axis aligned scaling, use the DiagonalMatrix class.
- *
- * \sa Scaling(), class DiagonalMatrix, MatrixBase::asDiagonal(), class Translation, class Transform
- */
-template<typename _Scalar>
-class UniformScaling
-{
-public:
- /** the scalar type of the coefficients */
- typedef _Scalar Scalar;
-
-protected:
-
- Scalar m_factor;
-
-public:
-
- /** Default constructor without initialization. */
- UniformScaling() {}
- /** Constructs and initialize a uniform scaling transformation */
- explicit inline UniformScaling(const Scalar& s) : m_factor(s) {}
-
- inline const Scalar& factor() const { return m_factor; }
- inline Scalar& factor() { return m_factor; }
-
- /** Concatenates two uniform scaling */
- inline UniformScaling operator* (const UniformScaling& other) const
- { return UniformScaling(m_factor * other.factor()); }
-
- /** Concatenates a uniform scaling and a translation */
- template<int Dim>
- inline Transform<Scalar,Dim,Affine> operator* (const Translation<Scalar,Dim>& t) const;
-
- /** Concatenates a uniform scaling and an affine transformation */
- template<int Dim, int Mode, int Options>
- inline Transform<Scalar,Dim,Mode> operator* (const Transform<Scalar,Dim, Mode, Options>& t) const;
-
- /** Concatenates a uniform scaling and a linear transformation matrix */
- // TODO returns an expression
- template<typename Derived>
- inline typename internal::plain_matrix_type<Derived>::type operator* (const MatrixBase<Derived>& other) const
- { return other * m_factor; }
-
- template<typename Derived,int Dim>
- inline Matrix<Scalar,Dim,Dim> operator*(const RotationBase<Derived,Dim>& r) const
- { return r.toRotationMatrix() * m_factor; }
-
- /** \returns the inverse scaling */
- inline UniformScaling inverse() const
- { return UniformScaling(Scalar(1)/m_factor); }
-
- /** \returns \c *this with scalar type casted to \a NewScalarType
- *
- * Note that if \a NewScalarType is equal to the current scalar type of \c *this
- * then this function smartly returns a const reference to \c *this.
- */
- template<typename NewScalarType>
- inline UniformScaling<NewScalarType> cast() const
- { return UniformScaling<NewScalarType>(NewScalarType(m_factor)); }
-
- /** Copy constructor with scalar type conversion */
- template<typename OtherScalarType>
- inline explicit UniformScaling(const UniformScaling<OtherScalarType>& other)
- { m_factor = Scalar(other.factor()); }
-
- /** \returns \c true if \c *this is approximately equal to \a other, within the precision
- * determined by \a prec.
- *
- * \sa MatrixBase::isApprox() */
- bool isApprox(const UniformScaling& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
- { return internal::isApprox(m_factor, other.factor(), prec); }
-
-};
-
-/** Concatenates a linear transformation matrix and a uniform scaling */
-// NOTE this operator is defiend in MatrixBase and not as a friend function
-// of UniformScaling to fix an internal crash of Intel's ICC
-template<typename Derived> typename MatrixBase<Derived>::ScalarMultipleReturnType
-MatrixBase<Derived>::operator*(const UniformScaling<Scalar>& s) const
-{ return derived() * s.factor(); }
-
-/** Constructs a uniform scaling from scale factor \a s */
-static inline UniformScaling<float> Scaling(float s) { return UniformScaling<float>(s); }
-/** Constructs a uniform scaling from scale factor \a s */
-static inline UniformScaling<double> Scaling(double s) { return UniformScaling<double>(s); }
-/** Constructs a uniform scaling from scale factor \a s */
-template<typename RealScalar>
-static inline UniformScaling<std::complex<RealScalar> > Scaling(const std::complex<RealScalar>& s)
-{ return UniformScaling<std::complex<RealScalar> >(s); }
-
-/** Constructs a 2D axis aligned scaling */
-template<typename Scalar>
-static inline DiagonalMatrix<Scalar,2> Scaling(Scalar sx, Scalar sy)
-{ return DiagonalMatrix<Scalar,2>(sx, sy); }
-/** Constructs a 3D axis aligned scaling */
-template<typename Scalar>
-static inline DiagonalMatrix<Scalar,3> Scaling(Scalar sx, Scalar sy, Scalar sz)
-{ return DiagonalMatrix<Scalar,3>(sx, sy, sz); }
-
-/** Constructs an axis aligned scaling expression from vector expression \a coeffs
- * This is an alias for coeffs.asDiagonal()
- */
-template<typename Derived>
-static inline const DiagonalWrapper<const Derived> Scaling(const MatrixBase<Derived>& coeffs)
-{ return coeffs.asDiagonal(); }
-
-/** \addtogroup Geometry_Module */
-//@{
-/** \deprecated */
-typedef DiagonalMatrix<float, 2> AlignedScaling2f;
-/** \deprecated */
-typedef DiagonalMatrix<double,2> AlignedScaling2d;
-/** \deprecated */
-typedef DiagonalMatrix<float, 3> AlignedScaling3f;
-/** \deprecated */
-typedef DiagonalMatrix<double,3> AlignedScaling3d;
-//@}
-
-template<typename Scalar>
-template<int Dim>
-inline Transform<Scalar,Dim,Affine>
-UniformScaling<Scalar>::operator* (const Translation<Scalar,Dim>& t) const
-{
- Transform<Scalar,Dim,Affine> res;
- res.matrix().setZero();
- res.linear().diagonal().fill(factor());
- res.translation() = factor() * t.vector();
- res(Dim,Dim) = Scalar(1);
- return res;
-}
-
-template<typename Scalar>
-template<int Dim,int Mode,int Options>
-inline Transform<Scalar,Dim,Mode>
-UniformScaling<Scalar>::operator* (const Transform<Scalar,Dim, Mode, Options>& t) const
-{
- Transform<Scalar,Dim,Mode> res = t;
- res.prescale(factor());
- return res;
-}
-
-#endif // EIGEN_SCALING_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/Transform.h b/extern/Eigen3/Eigen/src/Geometry/Transform.h
deleted file mode 100644
index 19d012572d4..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/Transform.h
+++ /dev/null
@@ -1,1396 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_TRANSFORM_H
-#define EIGEN_TRANSFORM_H
-
-namespace internal {
-
-template<typename Transform>
-struct transform_traits
-{
- enum
- {
- Dim = Transform::Dim,
- HDim = Transform::HDim,
- Mode = Transform::Mode,
- IsProjective = (Mode==Projective)
- };
-};
-
-template< typename TransformType,
- typename MatrixType,
- int Case = transform_traits<TransformType>::IsProjective ? 0
- : int(MatrixType::RowsAtCompileTime) == int(transform_traits<TransformType>::HDim) ? 1
- : 2>
-struct transform_right_product_impl;
-
-template< typename Other,
- int Mode,
- int Options,
- int Dim,
- int HDim,
- int OtherRows=Other::RowsAtCompileTime,
- int OtherCols=Other::ColsAtCompileTime>
-struct transform_left_product_impl;
-
-template< typename Lhs,
- typename Rhs,
- bool AnyProjective =
- transform_traits<Lhs>::IsProjective ||
- transform_traits<Lhs>::IsProjective>
-struct transform_transform_product_impl;
-
-template< typename Other,
- int Mode,
- int Options,
- int Dim,
- int HDim,
- int OtherRows=Other::RowsAtCompileTime,
- int OtherCols=Other::ColsAtCompileTime>
-struct transform_construct_from_matrix;
-
-template<typename TransformType> struct transform_take_affine_part;
-
-} // end namespace internal
-
-/** \geometry_module \ingroup Geometry_Module
- *
- * \class Transform
- *
- * \brief Represents an homogeneous transformation in a N dimensional space
- *
- * \tparam _Scalar the scalar type, i.e., the type of the coefficients
- * \tparam _Dim the dimension of the space
- * \tparam _Mode the type of the transformation. Can be:
- * - #Affine: the transformation is stored as a (Dim+1)^2 matrix,
- * where the last row is assumed to be [0 ... 0 1].
- * - #AffineCompact: the transformation is stored as a (Dim)x(Dim+1) matrix.
- * - #Projective: the transformation is stored as a (Dim+1)^2 matrix
- * without any assumption.
- * \tparam _Options has the same meaning as in class Matrix. It allows to specify DontAlign and/or RowMajor.
- * These Options are passed directly to the underlying matrix type.
- *
- * The homography is internally represented and stored by a matrix which
- * is available through the matrix() method. To understand the behavior of
- * this class you have to think a Transform object as its internal
- * matrix representation. The chosen convention is right multiply:
- *
- * \code v' = T * v \endcode
- *
- * Therefore, an affine transformation matrix M is shaped like this:
- *
- * \f$ \left( \begin{array}{cc}
- * linear & translation\\
- * 0 ... 0 & 1
- * \end{array} \right) \f$
- *
- * Note that for a projective transformation the last row can be anything,
- * and then the interpretation of different parts might be sightly different.
- *
- * However, unlike a plain matrix, the Transform class provides many features
- * simplifying both its assembly and usage. In particular, it can be composed
- * with any other transformations (Transform,Translation,RotationBase,Matrix)
- * and can be directly used to transform implicit homogeneous vectors. All these
- * operations are handled via the operator*. For the composition of transformations,
- * its principle consists to first convert the right/left hand sides of the product
- * to a compatible (Dim+1)^2 matrix and then perform a pure matrix product.
- * Of course, internally, operator* tries to perform the minimal number of operations
- * according to the nature of each terms. Likewise, when applying the transform
- * to non homogeneous vectors, the latters are automatically promoted to homogeneous
- * one before doing the matrix product. The convertions to homogeneous representations
- * are performed as follow:
- *
- * \b Translation t (Dim)x(1):
- * \f$ \left( \begin{array}{cc}
- * I & t \\
- * 0\,...\,0 & 1
- * \end{array} \right) \f$
- *
- * \b Rotation R (Dim)x(Dim):
- * \f$ \left( \begin{array}{cc}
- * R & 0\\
- * 0\,...\,0 & 1
- * \end{array} \right) \f$
- *
- * \b Linear \b Matrix L (Dim)x(Dim):
- * \f$ \left( \begin{array}{cc}
- * L & 0\\
- * 0\,...\,0 & 1
- * \end{array} \right) \f$
- *
- * \b Affine \b Matrix A (Dim)x(Dim+1):
- * \f$ \left( \begin{array}{c}
- * A\\
- * 0\,...\,0\,1
- * \end{array} \right) \f$
- *
- * \b Column \b vector v (Dim)x(1):
- * \f$ \left( \begin{array}{c}
- * v\\
- * 1
- * \end{array} \right) \f$
- *
- * \b Set \b of \b column \b vectors V1...Vn (Dim)x(n):
- * \f$ \left( \begin{array}{ccc}
- * v_1 & ... & v_n\\
- * 1 & ... & 1
- * \end{array} \right) \f$
- *
- * The concatenation of a Transform object with any kind of other transformation
- * always returns a Transform object.
- *
- * A little exception to the "as pure matrix product" rule is the case of the
- * transformation of non homogeneous vectors by an affine transformation. In
- * that case the last matrix row can be ignored, and the product returns non
- * homogeneous vectors.
- *
- * Since, for instance, a Dim x Dim matrix is interpreted as a linear transformation,
- * it is not possible to directly transform Dim vectors stored in a Dim x Dim matrix.
- * The solution is either to use a Dim x Dynamic matrix or explicitly request a
- * vector transformation by making the vector homogeneous:
- * \code
- * m' = T * m.colwise().homogeneous();
- * \endcode
- * Note that there is zero overhead.
- *
- * Conversion methods from/to Qt's QMatrix and QTransform are available if the
- * preprocessor token EIGEN_QT_SUPPORT is defined.
- *
- * 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_TRANSFORM_PLUGIN.
- *
- * \sa class Matrix, class Quaternion
- */
-template<typename _Scalar, int _Dim, int _Mode, int _Options>
-class Transform
-{
-public:
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1))
- enum {
- Mode = _Mode,
- Options = _Options,
- Dim = _Dim, ///< space dimension in which the transformation holds
- HDim = _Dim+1, ///< size of a respective homogeneous vector
- Rows = int(Mode)==(AffineCompact) ? Dim : HDim
- };
- /** the scalar type of the coefficients */
- typedef _Scalar Scalar;
- typedef DenseIndex Index;
- /** type of the matrix used to represent the transformation */
- typedef typename internal::make_proper_matrix_type<Scalar,Rows,HDim,Options>::type MatrixType;
- /** constified MatrixType */
- typedef const MatrixType ConstMatrixType;
- /** 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> LinearPart;
- /** type of read reference to the linear part of the transformation */
- typedef const Block<ConstMatrixType,Dim,Dim> ConstLinearPart;
- /** type of read/write reference to the affine part of the transformation */
- typedef typename internal::conditional<int(Mode)==int(AffineCompact),
- MatrixType&,
- Block<MatrixType,Dim,HDim> >::type AffinePart;
- /** type of read reference to the affine part of the transformation */
- typedef typename internal::conditional<int(Mode)==int(AffineCompact),
- const MatrixType&,
- const Block<const MatrixType,Dim,HDim> >::type ConstAffinePart;
- /** type of a vector */
- typedef Matrix<Scalar,Dim,1> VectorType;
- /** type of a read/write reference to the translation part of the rotation */
- typedef Block<MatrixType,Dim,1> TranslationPart;
- /** type of a read reference to the translation part of the rotation */
- typedef const Block<ConstMatrixType,Dim,1> ConstTranslationPart;
- /** corresponding translation type */
- typedef Translation<Scalar,Dim> TranslationType;
-
- // this intermediate enum is needed to avoid an ICE with gcc 3.4 and 4.0
- enum { TransformTimeDiagonalMode = ((Mode==int(Isometry))?Affine:int(Mode)) };
- /** The return type of the product between a diagonal matrix and a transform */
- typedef Transform<Scalar,Dim,TransformTimeDiagonalMode> TransformTimeDiagonalReturnType;
-
-protected:
-
- MatrixType m_matrix;
-
-public:
-
- /** Default constructor without initialization of the meaningful coefficients.
- * If Mode==Affine, then the last row is set to [0 ... 0 1] */
- inline Transform()
- {
- check_template_params();
- if (int(Mode)==Affine)
- makeAffine();
- }
-
- inline Transform(const Transform& other)
- {
- check_template_params();
- m_matrix = other.m_matrix;
- }
-
- inline explicit Transform(const TranslationType& t)
- {
- check_template_params();
- *this = t;
- }
- inline explicit Transform(const UniformScaling<Scalar>& s)
- {
- check_template_params();
- *this = s;
- }
- template<typename Derived>
- inline explicit Transform(const RotationBase<Derived, Dim>& r)
- {
- check_template_params();
- *this = r;
- }
-
- inline Transform& operator=(const Transform& other)
- { m_matrix = other.m_matrix; return *this; }
-
- typedef internal::transform_take_affine_part<Transform> take_affine_part;
-
- /** Constructs and initializes a transformation from a Dim^2 or a (Dim+1)^2 matrix. */
- template<typename OtherDerived>
- inline explicit Transform(const EigenBase<OtherDerived>& other)
- {
- check_template_params();
- internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived());
- }
-
- /** Set \c *this from a Dim^2 or (Dim+1)^2 matrix. */
- template<typename OtherDerived>
- inline Transform& operator=(const EigenBase<OtherDerived>& other)
- {
- internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived());
- return *this;
- }
-
- template<int OtherOptions>
- inline Transform(const Transform<Scalar,Dim,Mode,OtherOptions>& other)
- {
- check_template_params();
- // only the options change, we can directly copy the matrices
- m_matrix = other.matrix();
- }
-
- template<int OtherMode,int OtherOptions>
- inline Transform(const Transform<Scalar,Dim,OtherMode,OtherOptions>& other)
- {
- check_template_params();
- // prevent conversions as:
- // Affine | AffineCompact | Isometry = Projective
- EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Projective), Mode==int(Projective)),
- YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
-
- // prevent conversions as:
- // Isometry = Affine | AffineCompact
- EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Affine)||OtherMode==int(AffineCompact), Mode!=int(Isometry)),
- YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
-
- enum { ModeIsAffineCompact = Mode == int(AffineCompact),
- OtherModeIsAffineCompact = OtherMode == int(AffineCompact)
- };
-
- if(ModeIsAffineCompact == OtherModeIsAffineCompact)
- {
- // We need the block expression because the code is compiled for all
- // combinations of transformations and will trigger a compile time error
- // if one tries to assign the matrices directly
- m_matrix.template block<Dim,Dim+1>(0,0) = other.matrix().template block<Dim,Dim+1>(0,0);
- makeAffine();
- }
- else if(OtherModeIsAffineCompact)
- {
- typedef typename Transform<Scalar,Dim,OtherMode,OtherOptions>::MatrixType OtherMatrixType;
- internal::transform_construct_from_matrix<OtherMatrixType,Mode,Options,Dim,HDim>::run(this, other.matrix());
- }
- else
- {
- // here we know that Mode == AffineCompact and OtherMode != AffineCompact.
- // if OtherMode were Projective, the static assert above would already have caught it.
- // So the only possibility is that OtherMode == Affine
- linear() = other.linear();
- translation() = other.translation();
- }
- }
-
- template<typename OtherDerived>
- Transform(const ReturnByValue<OtherDerived>& other)
- {
- check_template_params();
- other.evalTo(*this);
- }
-
- template<typename OtherDerived>
- Transform& operator=(const ReturnByValue<OtherDerived>& other)
- {
- other.evalTo(*this);
- return *this;
- }
-
- #ifdef EIGEN_QT_SUPPORT
- inline Transform(const QMatrix& other);
- inline Transform& operator=(const QMatrix& other);
- inline QMatrix toQMatrix(void) const;
- inline Transform(const QTransform& other);
- inline Transform& operator=(const QTransform& other);
- inline QTransform toQTransform(void) const;
- #endif
-
- /** shortcut for m_matrix(row,col);
- * \sa MatrixBase::operator(Index,Index) const */
- inline Scalar operator() (Index row, Index col) const { return m_matrix(row,col); }
- /** shortcut for m_matrix(row,col);
- * \sa MatrixBase::operator(Index,Index) */
- inline Scalar& operator() (Index row, Index col) { return m_matrix(row,col); }
-
- /** \returns a read-only expression of the transformation matrix */
- inline const MatrixType& matrix() const { return m_matrix; }
- /** \returns a writable expression of the transformation matrix */
- inline MatrixType& matrix() { return m_matrix; }
-
- /** \returns a read-only expression of the linear part of the transformation */
- inline ConstLinearPart linear() const { return m_matrix.template block<Dim,Dim>(0,0); }
- /** \returns a writable expression of the linear part of the transformation */
- inline LinearPart linear() { return m_matrix.template block<Dim,Dim>(0,0); }
-
- /** \returns a read-only expression of the Dim x HDim affine part of the transformation */
- inline ConstAffinePart affine() const { return take_affine_part::run(m_matrix); }
- /** \returns a writable expression of the Dim x HDim affine part of the transformation */
- inline AffinePart affine() { return take_affine_part::run(m_matrix); }
-
- /** \returns a read-only expression of the translation vector of the transformation */
- inline ConstTranslationPart translation() const { return m_matrix.template block<Dim,1>(0,Dim); }
- /** \returns a writable expression of the translation vector of the transformation */
- inline TranslationPart translation() { return m_matrix.template block<Dim,1>(0,Dim); }
-
- /** \returns an expression of the product between the transform \c *this and a matrix expression \a other
- *
- * The right hand side \a other might be either:
- * \li a vector of size Dim,
- * \li an homogeneous vector of size Dim+1,
- * \li a set of vectors of size Dim x Dynamic,
- * \li a set of homogeneous vectors of size Dim+1 x Dynamic,
- * \li a linear transformation matrix of size Dim x Dim,
- * \li an affine transformation matrix of size Dim x Dim+1,
- * \li a transformation matrix of size Dim+1 x Dim+1.
- */
- // note: this function is defined here because some compilers cannot find the respective declaration
- template<typename OtherDerived>
- EIGEN_STRONG_INLINE const typename internal::transform_right_product_impl<Transform, OtherDerived>::ResultType
- operator * (const EigenBase<OtherDerived> &other) const
- { return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); }
-
- /** \returns the product expression of a transformation matrix \a a times a transform \a b
- *
- * The left hand side \a other might be either:
- * \li a linear transformation matrix of size Dim x Dim,
- * \li an affine transformation matrix of size Dim x Dim+1,
- * \li a general transformation matrix of size Dim+1 x Dim+1.
- */
- template<typename OtherDerived> friend
- inline const typename internal::transform_left_product_impl<OtherDerived,Mode,Options,_Dim,_Dim+1>::ResultType
- operator * (const EigenBase<OtherDerived> &a, const Transform &b)
- { return internal::transform_left_product_impl<OtherDerived,Mode,Options,Dim,HDim>::run(a.derived(),b); }
-
- /** \returns The product expression of a transform \a a times a diagonal matrix \a b
- *
- * The rhs diagonal matrix is interpreted as an affine scaling transformation. The
- * product results in a Transform of the same type (mode) as the lhs only if the lhs
- * mode is no isometry. In that case, the returned transform is an affinity.
- */
- template<typename DiagonalDerived>
- inline const TransformTimeDiagonalReturnType
- operator * (const DiagonalBase<DiagonalDerived> &b) const
- {
- TransformTimeDiagonalReturnType res(*this);
- res.linear() *= b;
- return res;
- }
-
- /** \returns The product expression of a diagonal matrix \a a times a transform \a b
- *
- * The lhs diagonal matrix is interpreted as an affine scaling transformation. The
- * product results in a Transform of the same type (mode) as the lhs only if the lhs
- * mode is no isometry. In that case, the returned transform is an affinity.
- */
- template<typename DiagonalDerived>
- friend inline TransformTimeDiagonalReturnType
- operator * (const DiagonalBase<DiagonalDerived> &a, const Transform &b)
- {
- TransformTimeDiagonalReturnType res;
- res.linear().noalias() = a*b.linear();
- res.translation().noalias() = a*b.translation();
- if (Mode!=int(AffineCompact))
- res.matrix().row(Dim) = b.matrix().row(Dim);
- return res;
- }
-
- template<typename OtherDerived>
- inline Transform& operator*=(const EigenBase<OtherDerived>& other) { return *this = *this * other; }
-
- /** Concatenates two transformations */
- inline const Transform operator * (const Transform& other) const
- {
- return internal::transform_transform_product_impl<Transform,Transform>::run(*this,other);
- }
-
- /** Concatenates two different transformations */
- template<int OtherMode,int OtherOptions>
- inline const typename internal::transform_transform_product_impl<
- Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::ResultType
- operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
- {
- return internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::run(*this,other);
- }
-
- /** \sa MatrixBase::setIdentity() */
- void setIdentity() { m_matrix.setIdentity(); }
-
- /**
- * \brief Returns an identity transformation.
- * \todo In the future this function should be returning a Transform expression.
- */
- static const Transform Identity()
- {
- return Transform(MatrixType::Identity());
- }
-
- template<typename OtherDerived>
- inline Transform& scale(const MatrixBase<OtherDerived> &other);
-
- template<typename OtherDerived>
- inline Transform& prescale(const MatrixBase<OtherDerived> &other);
-
- inline Transform& scale(Scalar s);
- inline Transform& prescale(Scalar s);
-
- template<typename OtherDerived>
- inline Transform& translate(const MatrixBase<OtherDerived> &other);
-
- template<typename OtherDerived>
- inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
-
- template<typename RotationType>
- inline Transform& rotate(const RotationType& rotation);
-
- template<typename RotationType>
- inline Transform& prerotate(const RotationType& rotation);
-
- Transform& shear(Scalar sx, Scalar sy);
- Transform& preshear(Scalar sx, Scalar sy);
-
- inline Transform& operator=(const TranslationType& t);
- inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
- inline Transform operator*(const TranslationType& t) const;
-
- inline Transform& operator=(const UniformScaling<Scalar>& t);
- inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
- inline Transform operator*(const UniformScaling<Scalar>& s) const;
-
- inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linear() *= s; return *this; }
-
- template<typename Derived>
- inline Transform& operator=(const RotationBase<Derived,Dim>& r);
- template<typename Derived>
- inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
- template<typename Derived>
- inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
-
- const LinearMatrixType rotation() const;
- template<typename RotationMatrixType, typename ScalingMatrixType>
- void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
- template<typename ScalingMatrixType, typename RotationMatrixType>
- void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
-
- template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
- Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
- const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
-
- inline Transform inverse(TransformTraits traits = (TransformTraits)Mode) const;
-
- /** \returns a const pointer to the column major internal matrix */
- const Scalar* data() const { return m_matrix.data(); }
- /** \returns a non-const pointer to the column major internal matrix */
- Scalar* data() { return m_matrix.data(); }
-
- /** \returns \c *this with scalar type casted to \a NewScalarType
- *
- * Note that if \a NewScalarType is equal to the current scalar type of \c *this
- * then this function smartly returns a const reference to \c *this.
- */
- template<typename NewScalarType>
- inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type cast() const
- { return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type(*this); }
-
- /** Copy constructor with scalar type conversion */
- template<typename OtherScalarType>
- inline explicit Transform(const Transform<OtherScalarType,Dim,Mode,Options>& other)
- {
- check_template_params();
- m_matrix = other.matrix().template cast<Scalar>();
- }
-
- /** \returns \c true if \c *this is approximately equal to \a other, within the precision
- * determined by \a prec.
- *
- * \sa MatrixBase::isApprox() */
- bool isApprox(const Transform& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
- { return m_matrix.isApprox(other.m_matrix, prec); }
-
- /** Sets the last row to [0 ... 0 1]
- */
- void makeAffine()
- {
- if(int(Mode)!=int(AffineCompact))
- {
- matrix().template block<1,Dim>(Dim,0).setZero();
- matrix().coeffRef(Dim,Dim) = 1;
- }
- }
-
- /** \internal
- * \returns the Dim x Dim linear part if the transformation is affine,
- * and the HDim x Dim part for projective transformations.
- */
- inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt()
- { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
- /** \internal
- * \returns the Dim x Dim linear part if the transformation is affine,
- * and the HDim x Dim part for projective transformations.
- */
- inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt() const
- { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
-
- /** \internal
- * \returns the translation part if the transformation is affine,
- * and the last column for projective transformations.
- */
- inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt()
- { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
- /** \internal
- * \returns the translation part if the transformation is affine,
- * and the last column for projective transformations.
- */
- inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt() const
- { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
-
-
- #ifdef EIGEN_TRANSFORM_PLUGIN
- #include EIGEN_TRANSFORM_PLUGIN
- #endif
-
-protected:
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- EIGEN_STRONG_INLINE static void check_template_params()
- {
- EIGEN_STATIC_ASSERT((Options & (DontAlign|RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS)
- }
- #endif
-
-};
-
-/** \ingroup Geometry_Module */
-typedef Transform<float,2,Isometry> Isometry2f;
-/** \ingroup Geometry_Module */
-typedef Transform<float,3,Isometry> Isometry3f;
-/** \ingroup Geometry_Module */
-typedef Transform<double,2,Isometry> Isometry2d;
-/** \ingroup Geometry_Module */
-typedef Transform<double,3,Isometry> Isometry3d;
-
-/** \ingroup Geometry_Module */
-typedef Transform<float,2,Affine> Affine2f;
-/** \ingroup Geometry_Module */
-typedef Transform<float,3,Affine> Affine3f;
-/** \ingroup Geometry_Module */
-typedef Transform<double,2,Affine> Affine2d;
-/** \ingroup Geometry_Module */
-typedef Transform<double,3,Affine> Affine3d;
-
-/** \ingroup Geometry_Module */
-typedef Transform<float,2,AffineCompact> AffineCompact2f;
-/** \ingroup Geometry_Module */
-typedef Transform<float,3,AffineCompact> AffineCompact3f;
-/** \ingroup Geometry_Module */
-typedef Transform<double,2,AffineCompact> AffineCompact2d;
-/** \ingroup Geometry_Module */
-typedef Transform<double,3,AffineCompact> AffineCompact3d;
-
-/** \ingroup Geometry_Module */
-typedef Transform<float,2,Projective> Projective2f;
-/** \ingroup Geometry_Module */
-typedef Transform<float,3,Projective> Projective3f;
-/** \ingroup Geometry_Module */
-typedef Transform<double,2,Projective> Projective2d;
-/** \ingroup Geometry_Module */
-typedef Transform<double,3,Projective> Projective3d;
-
-/**************************
-*** Optional QT support ***
-**************************/
-
-#ifdef EIGEN_QT_SUPPORT
-/** Initializes \c *this from a QMatrix assuming the dimension is 2.
- *
- * This function is available only if the token EIGEN_QT_SUPPORT is defined.
- */
-template<typename Scalar, int Dim, int Mode,int Options>
-Transform<Scalar,Dim,Mode,Options>::Transform(const QMatrix& other)
-{
- check_template_params();
- *this = other;
-}
-
-/** Set \c *this from a QMatrix assuming the dimension is 2.
- *
- * This function is available only if the token EIGEN_QT_SUPPORT is defined.
- */
-template<typename Scalar, int Dim, int Mode,int Options>
-Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QMatrix& other)
-{
- EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
- m_matrix << other.m11(), other.m21(), other.dx(),
- other.m12(), other.m22(), other.dy(),
- 0, 0, 1;
- return *this;
-}
-
-/** \returns a QMatrix from \c *this assuming the dimension is 2.
- *
- * \warning this conversion might loss data if \c *this is not affine
- *
- * This function is available only if the token EIGEN_QT_SUPPORT is defined.
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-QMatrix Transform<Scalar,Dim,Mode,Options>::toQMatrix(void) const
-{
- check_template_params();
- EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
- return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
- m_matrix.coeff(0,1), m_matrix.coeff(1,1),
- m_matrix.coeff(0,2), m_matrix.coeff(1,2));
-}
-
-/** Initializes \c *this from a QTransform assuming the dimension is 2.
- *
- * This function is available only if the token EIGEN_QT_SUPPORT is defined.
- */
-template<typename Scalar, int Dim, int Mode,int Options>
-Transform<Scalar,Dim,Mode,Options>::Transform(const QTransform& other)
-{
- check_template_params();
- *this = other;
-}
-
-/** Set \c *this from a QTransform assuming the dimension is 2.
- *
- * This function is available only if the token EIGEN_QT_SUPPORT is defined.
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QTransform& other)
-{
- check_template_params();
- EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
- if (Mode == int(AffineCompact))
- m_matrix << other.m11(), other.m21(), other.dx(),
- other.m12(), other.m22(), other.dy();
- else
- m_matrix << other.m11(), other.m21(), other.dx(),
- other.m12(), other.m22(), other.dy(),
- other.m13(), other.m23(), other.m33();
- return *this;
-}
-
-/** \returns a QTransform from \c *this assuming the dimension is 2.
- *
- * This function is available only if the token EIGEN_QT_SUPPORT is defined.
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-QTransform Transform<Scalar,Dim,Mode,Options>::toQTransform(void) const
-{
- EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
- if (Mode == int(AffineCompact))
- return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
- m_matrix.coeff(0,1), m_matrix.coeff(1,1),
- m_matrix.coeff(0,2), m_matrix.coeff(1,2));
- else
- return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
- m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
- m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
-}
-#endif
-
-/*********************
-*** Procedural API ***
-*********************/
-
-/** Applies on the right the non uniform scale transformation represented
- * by the vector \a other to \c *this and returns a reference to \c *this.
- * \sa prescale()
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-template<typename OtherDerived>
-Transform<Scalar,Dim,Mode,Options>&
-Transform<Scalar,Dim,Mode,Options>::scale(const MatrixBase<OtherDerived> &other)
-{
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
- EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
- linearExt().noalias() = (linearExt() * other.asDiagonal());
- return *this;
-}
-
-/** Applies on the right a uniform scale of a factor \a c to \c *this
- * and returns a reference to \c *this.
- * \sa prescale(Scalar)
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::scale(Scalar s)
-{
- EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
- linearExt() *= s;
- return *this;
-}
-
-/** Applies on the left the non uniform scale transformation represented
- * by the vector \a other to \c *this and returns a reference to \c *this.
- * \sa scale()
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-template<typename OtherDerived>
-Transform<Scalar,Dim,Mode,Options>&
-Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &other)
-{
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
- EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
- m_matrix.template block<Dim,HDim>(0,0).noalias() = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0));
- return *this;
-}
-
-/** Applies on the left a uniform scale of a factor \a c to \c *this
- * and returns a reference to \c *this.
- * \sa scale(Scalar)
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::prescale(Scalar s)
-{
- EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
- m_matrix.template topRows<Dim>() *= s;
- return *this;
-}
-
-/** Applies on the right the translation matrix represented by the vector \a other
- * to \c *this and returns a reference to \c *this.
- * \sa pretranslate()
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-template<typename OtherDerived>
-Transform<Scalar,Dim,Mode,Options>&
-Transform<Scalar,Dim,Mode,Options>::translate(const MatrixBase<OtherDerived> &other)
-{
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
- translationExt() += linearExt() * other;
- return *this;
-}
-
-/** Applies on the left the translation matrix represented by the vector \a other
- * to \c *this and returns a reference to \c *this.
- * \sa translate()
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-template<typename OtherDerived>
-Transform<Scalar,Dim,Mode,Options>&
-Transform<Scalar,Dim,Mode,Options>::pretranslate(const MatrixBase<OtherDerived> &other)
-{
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
- if(int(Mode)==int(Projective))
- affine() += other * m_matrix.row(Dim);
- else
- translation() += other;
- return *this;
-}
-
-/** Applies on the right the rotation represented by the rotation \a rotation
- * to \c *this and returns a reference to \c *this.
- *
- * The template parameter \a RotationType is the type of the rotation which
- * must be known by internal::toRotationMatrix<>.
- *
- * Natively supported types includes:
- * - any scalar (2D),
- * - a Dim x Dim matrix expression,
- * - a Quaternion (3D),
- * - a AngleAxis (3D)
- *
- * This mechanism is easily extendable to support user types such as Euler angles,
- * or a pair of Quaternion for 4D rotations.
- *
- * \sa rotate(Scalar), class Quaternion, class AngleAxis, prerotate(RotationType)
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-template<typename RotationType>
-Transform<Scalar,Dim,Mode,Options>&
-Transform<Scalar,Dim,Mode,Options>::rotate(const RotationType& rotation)
-{
- linearExt() *= internal::toRotationMatrix<Scalar,Dim>(rotation);
- return *this;
-}
-
-/** Applies on the left the rotation represented by the rotation \a rotation
- * to \c *this and returns a reference to \c *this.
- *
- * See rotate() for further details.
- *
- * \sa rotate()
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-template<typename RotationType>
-Transform<Scalar,Dim,Mode,Options>&
-Transform<Scalar,Dim,Mode,Options>::prerotate(const RotationType& rotation)
-{
- m_matrix.template block<Dim,HDim>(0,0) = internal::toRotationMatrix<Scalar,Dim>(rotation)
- * m_matrix.template block<Dim,HDim>(0,0);
- return *this;
-}
-
-/** Applies on the right the shear transformation represented
- * by the vector \a other to \c *this and returns a reference to \c *this.
- * \warning 2D only.
- * \sa preshear()
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-Transform<Scalar,Dim,Mode,Options>&
-Transform<Scalar,Dim,Mode,Options>::shear(Scalar sx, Scalar sy)
-{
- EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
- EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
- VectorType tmp = linear().col(0)*sy + linear().col(1);
- linear() << linear().col(0) + linear().col(1)*sx, tmp;
- return *this;
-}
-
-/** Applies on the left the shear transformation represented
- * by the vector \a other to \c *this and returns a reference to \c *this.
- * \warning 2D only.
- * \sa shear()
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-Transform<Scalar,Dim,Mode,Options>&
-Transform<Scalar,Dim,Mode,Options>::preshear(Scalar sx, Scalar sy)
-{
- EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
- EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
- m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
- return *this;
-}
-
-/******************************************************
-*** Scaling, Translation and Rotation compatibility ***
-******************************************************/
-
-template<typename Scalar, int Dim, int Mode, int Options>
-inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const TranslationType& t)
-{
- linear().setIdentity();
- translation() = t.vector();
- makeAffine();
- return *this;
-}
-
-template<typename Scalar, int Dim, int Mode, int Options>
-inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const TranslationType& t) const
-{
- Transform res = *this;
- res.translate(t.vector());
- return res;
-}
-
-template<typename Scalar, int Dim, int Mode, int Options>
-inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const UniformScaling<Scalar>& s)
-{
- m_matrix.setZero();
- linear().diagonal().fill(s.factor());
- makeAffine();
- return *this;
-}
-
-template<typename Scalar, int Dim, int Mode, int Options>
-inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const UniformScaling<Scalar>& s) const
-{
- Transform res = *this;
- res.scale(s.factor());
- return res;
-}
-
-template<typename Scalar, int Dim, int Mode, int Options>
-template<typename Derived>
-inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const RotationBase<Derived,Dim>& r)
-{
- linear() = internal::toRotationMatrix<Scalar,Dim>(r);
- translation().setZero();
- makeAffine();
- return *this;
-}
-
-template<typename Scalar, int Dim, int Mode, int Options>
-template<typename Derived>
-inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const RotationBase<Derived,Dim>& r) const
-{
- Transform res = *this;
- res.rotate(r.derived());
- return res;
-}
-
-/************************
-*** Special functions ***
-************************/
-
-/** \returns the rotation part of the transformation
- *
- *
- * \svd_module
- *
- * \sa computeRotationScaling(), computeScalingRotation(), class SVD
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-const typename Transform<Scalar,Dim,Mode,Options>::LinearMatrixType
-Transform<Scalar,Dim,Mode,Options>::rotation() const
-{
- LinearMatrixType result;
- computeRotationScaling(&result, (LinearMatrixType*)0);
- return result;
-}
-
-
-/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
- * not necessarily positive.
- *
- * If either pointer is zero, the corresponding computation is skipped.
- *
- *
- *
- * \svd_module
- *
- * \sa computeScalingRotation(), rotation(), class SVD
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-template<typename RotationMatrixType, typename ScalingMatrixType>
-void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
-{
- JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
-
- Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
- VectorType sv(svd.singularValues());
- sv.coeffRef(0) *= x;
- if(scaling) scaling->lazyAssign(svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint());
- if(rotation)
- {
- LinearMatrixType m(svd.matrixU());
- m.col(0) /= x;
- rotation->lazyAssign(m * svd.matrixV().adjoint());
- }
-}
-
-/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
- * not necessarily positive.
- *
- * If either pointer is zero, the corresponding computation is skipped.
- *
- *
- *
- * \svd_module
- *
- * \sa computeRotationScaling(), rotation(), class SVD
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-template<typename ScalingMatrixType, typename RotationMatrixType>
-void Transform<Scalar,Dim,Mode,Options>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
-{
- JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
-
- Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
- VectorType sv(svd.singularValues());
- sv.coeffRef(0) *= x;
- if(scaling) scaling->lazyAssign(svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint());
- if(rotation)
- {
- LinearMatrixType m(svd.matrixU());
- m.col(0) /= x;
- rotation->lazyAssign(m * svd.matrixV().adjoint());
- }
-}
-
-/** Convenient method to set \c *this from a position, orientation and scale
- * of a 3D object.
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
-Transform<Scalar,Dim,Mode,Options>&
-Transform<Scalar,Dim,Mode,Options>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
- const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
-{
- linear() = internal::toRotationMatrix<Scalar,Dim>(orientation);
- linear() *= scale.asDiagonal();
- translation() = position;
- makeAffine();
- return *this;
-}
-
-namespace internal {
-
-// selector needed to avoid taking the inverse of a 3x4 matrix
-template<typename TransformType, int Mode=TransformType::Mode>
-struct projective_transform_inverse
-{
- static inline void run(const TransformType&, TransformType&)
- {}
-};
-
-template<typename TransformType>
-struct projective_transform_inverse<TransformType, Projective>
-{
- static inline void run(const TransformType& m, TransformType& res)
- {
- res.matrix() = m.matrix().inverse();
- }
-};
-
-} // end namespace internal
-
-
-/**
- *
- * \returns the inverse transformation according to some given knowledge
- * on \c *this.
- *
- * \param hint allows to optimize the inversion process when the transformation
- * is known to be not a general transformation (optional). The possible values are:
- * - #Projective if the transformation is not necessarily affine, i.e., if the
- * last row is not guaranteed to be [0 ... 0 1]
- * - #Affine if the last row can be assumed to be [0 ... 0 1]
- * - #Isometry if the transformation is only a concatenations of translations
- * and rotations.
- * The default is the template class parameter \c Mode.
- *
- * \warning unless \a traits is always set to NoShear or NoScaling, this function
- * requires the generic inverse method of MatrixBase defined in the LU module. If
- * you forget to include this module, then you will get hard to debug linking errors.
- *
- * \sa MatrixBase::inverse()
- */
-template<typename Scalar, int Dim, int Mode, int Options>
-Transform<Scalar,Dim,Mode,Options>
-Transform<Scalar,Dim,Mode,Options>::inverse(TransformTraits hint) const
-{
- Transform res;
- if (hint == Projective)
- {
- internal::projective_transform_inverse<Transform>::run(*this, res);
- }
- else
- {
- if (hint == Isometry)
- {
- res.matrix().template topLeftCorner<Dim,Dim>() = linear().transpose();
- }
- else if(hint&Affine)
- {
- res.matrix().template topLeftCorner<Dim,Dim>() = linear().inverse();
- }
- else
- {
- eigen_assert(false && "Invalid transform traits in Transform::Inverse");
- }
- // translation and remaining parts
- res.matrix().template topRightCorner<Dim,1>()
- = - res.matrix().template topLeftCorner<Dim,Dim>() * translation();
- res.makeAffine(); // we do need this, because in the beginning res is uninitialized
- }
- return res;
-}
-
-namespace internal {
-
-/*****************************************************
-*** Specializations of take affine part ***
-*****************************************************/
-
-template<typename TransformType> struct transform_take_affine_part {
- typedef typename TransformType::MatrixType MatrixType;
- typedef typename TransformType::AffinePart AffinePart;
- typedef typename TransformType::ConstAffinePart ConstAffinePart;
- static inline AffinePart run(MatrixType& m)
- { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
- static inline ConstAffinePart run(const MatrixType& m)
- { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
-};
-
-template<typename Scalar, int Dim, int Options>
-struct transform_take_affine_part<Transform<Scalar,Dim,AffineCompact, Options> > {
- typedef typename Transform<Scalar,Dim,AffineCompact,Options>::MatrixType MatrixType;
- static inline MatrixType& run(MatrixType& m) { return m; }
- static inline const MatrixType& run(const MatrixType& m) { return m; }
-};
-
-/*****************************************************
-*** Specializations of construct from matrix ***
-*****************************************************/
-
-template<typename Other, int Mode, int Options, int Dim, int HDim>
-struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,Dim>
-{
- static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
- {
- transform->linear() = other;
- transform->translation().setZero();
- transform->makeAffine();
- }
-};
-
-template<typename Other, int Mode, int Options, int Dim, int HDim>
-struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,HDim>
-{
- static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
- {
- transform->affine() = other;
- transform->makeAffine();
- }
-};
-
-template<typename Other, int Mode, int Options, int Dim, int HDim>
-struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, HDim,HDim>
-{
- static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
- { transform->matrix() = other; }
-};
-
-template<typename Other, int Options, int Dim, int HDim>
-struct transform_construct_from_matrix<Other, AffineCompact,Options,Dim,HDim, HDim,HDim>
-{
- static inline void run(Transform<typename Other::Scalar,Dim,AffineCompact,Options> *transform, const Other& other)
- { transform->matrix() = other.template block<Dim,HDim>(0,0); }
-};
-
-/**********************************************************
-*** Specializations of operator* with rhs EigenBase ***
-**********************************************************/
-
-template<int LhsMode,int RhsMode>
-struct transform_product_result
-{
- enum
- {
- Mode =
- (LhsMode == (int)Projective || RhsMode == (int)Projective ) ? Projective :
- (LhsMode == (int)Affine || RhsMode == (int)Affine ) ? Affine :
- (LhsMode == (int)AffineCompact || RhsMode == (int)AffineCompact ) ? AffineCompact :
- (LhsMode == (int)Isometry || RhsMode == (int)Isometry ) ? Isometry : Projective
- };
-};
-
-template< typename TransformType, typename MatrixType >
-struct transform_right_product_impl< TransformType, MatrixType, 0 >
-{
- typedef typename MatrixType::PlainObject ResultType;
-
- EIGEN_STRONG_INLINE static ResultType run(const TransformType& T, const MatrixType& other)
- {
- return T.matrix() * other;
- }
-};
-
-template< typename TransformType, typename MatrixType >
-struct transform_right_product_impl< TransformType, MatrixType, 1 >
-{
- enum {
- Dim = TransformType::Dim,
- HDim = TransformType::HDim,
- OtherRows = MatrixType::RowsAtCompileTime,
- OtherCols = MatrixType::ColsAtCompileTime
- };
-
- typedef typename MatrixType::PlainObject ResultType;
-
- EIGEN_STRONG_INLINE static ResultType run(const TransformType& T, const MatrixType& other)
- {
- EIGEN_STATIC_ASSERT(OtherRows==HDim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
-
- typedef Block<ResultType, Dim, OtherCols> TopLeftLhs;
-
- ResultType res(other.rows(),other.cols());
- TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.affine() * other;
- res.row(OtherRows-1) = other.row(OtherRows-1);
-
- return res;
- }
-};
-
-template< typename TransformType, typename MatrixType >
-struct transform_right_product_impl< TransformType, MatrixType, 2 >
-{
- enum {
- Dim = TransformType::Dim,
- HDim = TransformType::HDim,
- OtherRows = MatrixType::RowsAtCompileTime,
- OtherCols = MatrixType::ColsAtCompileTime
- };
-
- typedef typename MatrixType::PlainObject ResultType;
-
- EIGEN_STRONG_INLINE static ResultType run(const TransformType& T, const MatrixType& other)
- {
- EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
-
- typedef Block<ResultType, Dim, OtherCols> TopLeftLhs;
-
- ResultType res(other.rows(),other.cols());
- TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.linear() * other;
- TopLeftLhs(res, 0, 0, Dim, other.cols()).colwise() += T.translation();
-
- return res;
- }
-};
-
-/**********************************************************
-*** Specializations of operator* with lhs EigenBase ***
-**********************************************************/
-
-// generic HDim x HDim matrix * T => Projective
-template<typename Other,int Mode, int Options, int Dim, int HDim>
-struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, HDim,HDim>
-{
- typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
- typedef typename TransformType::MatrixType MatrixType;
- typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
- static ResultType run(const Other& other,const TransformType& tr)
- { return ResultType(other * tr.matrix()); }
-};
-
-// generic HDim x HDim matrix * AffineCompact => Projective
-template<typename Other, int Options, int Dim, int HDim>
-struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, HDim,HDim>
-{
- typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
- typedef typename TransformType::MatrixType MatrixType;
- typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
- static ResultType run(const Other& other,const TransformType& tr)
- {
- ResultType res;
- res.matrix().noalias() = other.template block<HDim,Dim>(0,0) * tr.matrix();
- res.matrix().col(Dim) += other.col(Dim);
- return res;
- }
-};
-
-// affine matrix * T
-template<typename Other,int Mode, int Options, int Dim, int HDim>
-struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,HDim>
-{
- typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
- typedef typename TransformType::MatrixType MatrixType;
- typedef TransformType ResultType;
- static ResultType run(const Other& other,const TransformType& tr)
- {
- ResultType res;
- res.affine().noalias() = other * tr.matrix();
- res.matrix().row(Dim) = tr.matrix().row(Dim);
- return res;
- }
-};
-
-// affine matrix * AffineCompact
-template<typename Other, int Options, int Dim, int HDim>
-struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, Dim,HDim>
-{
- typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
- typedef typename TransformType::MatrixType MatrixType;
- typedef TransformType ResultType;
- static ResultType run(const Other& other,const TransformType& tr)
- {
- ResultType res;
- res.matrix().noalias() = other.template block<Dim,Dim>(0,0) * tr.matrix();
- res.translation() += other.col(Dim);
- return res;
- }
-};
-
-// linear matrix * T
-template<typename Other,int Mode, int Options, int Dim, int HDim>
-struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,Dim>
-{
- typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
- typedef typename TransformType::MatrixType MatrixType;
- typedef TransformType ResultType;
- static ResultType run(const Other& other, const TransformType& tr)
- {
- TransformType res;
- if(Mode!=int(AffineCompact))
- res.matrix().row(Dim) = tr.matrix().row(Dim);
- res.matrix().template topRows<Dim>().noalias()
- = other * tr.matrix().template topRows<Dim>();
- return res;
- }
-};
-
-/**********************************************************
-*** Specializations of operator* with another Transform ***
-**********************************************************/
-
-template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
-struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,false >
-{
- enum { ResultMode = transform_product_result<LhsMode,RhsMode>::Mode };
- typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
- typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
- typedef Transform<Scalar,Dim,ResultMode,LhsOptions> ResultType;
- static ResultType run(const Lhs& lhs, const Rhs& rhs)
- {
- ResultType res;
- res.linear() = lhs.linear() * rhs.linear();
- res.translation() = lhs.linear() * rhs.translation() + lhs.translation();
- res.makeAffine();
- return res;
- }
-};
-
-template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
-struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,true >
-{
- typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
- typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
- typedef Transform<Scalar,Dim,Projective> ResultType;
- static ResultType run(const Lhs& lhs, const Rhs& rhs)
- {
- return ResultType( lhs.matrix() * rhs.matrix() );
- }
-};
-
-} // end namespace internal
-
-#endif // EIGEN_TRANSFORM_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/Translation.h b/extern/Eigen3/Eigen/src/Geometry/Translation.h
deleted file mode 100644
index d8fe50f987e..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/Translation.h
+++ /dev/null
@@ -1,215 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_TRANSLATION_H
-#define EIGEN_TRANSLATION_H
-
-/** \geometry_module \ingroup Geometry_Module
- *
- * \class Translation
- *
- * \brief Represents a translation transformation
- *
- * \param _Scalar the scalar type, i.e., the type of the coefficients.
- * \param _Dim the dimension of the space, can be a compile time value or Dynamic
- *
- * \note This class is not aimed to be used to store a translation transformation,
- * but rather to make easier the constructions and updates of Transform objects.
- *
- * \sa class Scaling, class Transform
- */
-template<typename _Scalar, int _Dim>
-class Translation
-{
-public:
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim)
- /** dimension of the space */
- enum { Dim = _Dim };
- /** the scalar type of the coefficients */
- typedef _Scalar Scalar;
- /** corresponding vector type */
- typedef Matrix<Scalar,Dim,1> VectorType;
- /** corresponding linear transformation matrix type */
- typedef Matrix<Scalar,Dim,Dim> LinearMatrixType;
- /** corresponding affine transformation type */
- typedef Transform<Scalar,Dim,Affine> AffineTransformType;
-
-protected:
-
- VectorType m_coeffs;
-
-public:
-
- /** Default constructor without initialization. */
- Translation() {}
- /** */
- inline Translation(const Scalar& sx, const Scalar& sy)
- {
- eigen_assert(Dim==2);
- m_coeffs.x() = sx;
- m_coeffs.y() = sy;
- }
- /** */
- inline Translation(const Scalar& sx, const Scalar& sy, const Scalar& sz)
- {
- eigen_assert(Dim==3);
- m_coeffs.x() = sx;
- m_coeffs.y() = sy;
- m_coeffs.z() = sz;
- }
- /** Constructs and initialize the translation transformation from a vector of translation coefficients */
- explicit inline Translation(const VectorType& vector) : m_coeffs(vector) {}
-
- /** \brief Retruns the x-translation by value. **/
- inline Scalar x() const { return m_coeffs.x(); }
- /** \brief Retruns the y-translation by value. **/
- inline Scalar y() const { return m_coeffs.y(); }
- /** \brief Retruns the z-translation by value. **/
- inline Scalar z() const { return m_coeffs.z(); }
-
- /** \brief Retruns the x-translation as a reference. **/
- inline Scalar& x() { return m_coeffs.x(); }
- /** \brief Retruns the y-translation as a reference. **/
- inline Scalar& y() { return m_coeffs.y(); }
- /** \brief Retruns the z-translation as a reference. **/
- inline Scalar& z() { return m_coeffs.z(); }
-
- const VectorType& vector() const { return m_coeffs; }
- VectorType& vector() { return m_coeffs; }
-
- const VectorType& translation() const { return m_coeffs; }
- VectorType& translation() { return m_coeffs; }
-
- /** Concatenates two translation */
- inline Translation operator* (const Translation& other) const
- { return Translation(m_coeffs + other.m_coeffs); }
-
- /** Concatenates a translation and a uniform scaling */
- inline AffineTransformType operator* (const UniformScaling<Scalar>& other) const;
-
- /** Concatenates a translation and a linear transformation */
- template<typename OtherDerived>
- inline AffineTransformType operator* (const EigenBase<OtherDerived>& linear) const;
-
- /** Concatenates a translation and a rotation */
- template<typename Derived>
- inline AffineTransformType operator*(const RotationBase<Derived,Dim>& r) const
- { return *this * r.toRotationMatrix(); }
-
- /** \returns the concatenation of a linear transformation \a l with the translation \a t */
- // its a nightmare to define a templated friend function outside its declaration
- template<typename OtherDerived> friend
- inline AffineTransformType operator*(const EigenBase<OtherDerived>& linear, const Translation& t)
- {
- AffineTransformType res;
- res.matrix().setZero();
- res.linear() = linear.derived();
- res.translation() = linear.derived() * t.m_coeffs;
- res.matrix().row(Dim).setZero();
- res(Dim,Dim) = Scalar(1);
- return res;
- }
-
- /** Concatenates a translation and a transformation */
- template<int Mode, int Options>
- inline Transform<Scalar,Dim,Mode> operator* (const Transform<Scalar,Dim,Mode,Options>& t) const
- {
- Transform<Scalar,Dim,Mode> res = t;
- res.pretranslate(m_coeffs);
- return res;
- }
-
- /** Applies translation to vector */
- inline VectorType operator* (const VectorType& other) const
- { return m_coeffs + other; }
-
- /** \returns the inverse translation (opposite) */
- Translation inverse() const { return Translation(-m_coeffs); }
-
- Translation& operator=(const Translation& other)
- {
- m_coeffs = other.m_coeffs;
- return *this;
- }
-
- static const Translation Identity() { return Translation(VectorType::Zero()); }
-
- /** \returns \c *this with scalar type casted to \a NewScalarType
- *
- * Note that if \a NewScalarType is equal to the current scalar type of \c *this
- * then this function smartly returns a const reference to \c *this.
- */
- template<typename NewScalarType>
- inline typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type cast() const
- { return typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type(*this); }
-
- /** Copy constructor with scalar type conversion */
- template<typename OtherScalarType>
- inline explicit Translation(const Translation<OtherScalarType,Dim>& other)
- { m_coeffs = other.vector().template cast<Scalar>(); }
-
- /** \returns \c true if \c *this is approximately equal to \a other, within the precision
- * determined by \a prec.
- *
- * \sa MatrixBase::isApprox() */
- bool isApprox(const Translation& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
- { return m_coeffs.isApprox(other.m_coeffs, prec); }
-
-};
-
-/** \addtogroup Geometry_Module */
-//@{
-typedef Translation<float, 2> Translation2f;
-typedef Translation<double,2> Translation2d;
-typedef Translation<float, 3> Translation3f;
-typedef Translation<double,3> Translation3d;
-//@}
-
-template<typename Scalar, int Dim>
-inline typename Translation<Scalar,Dim>::AffineTransformType
-Translation<Scalar,Dim>::operator* (const UniformScaling<Scalar>& other) const
-{
- AffineTransformType res;
- res.matrix().setZero();
- res.linear().diagonal().fill(other.factor());
- res.translation() = m_coeffs;
- res(Dim,Dim) = Scalar(1);
- return res;
-}
-
-template<typename Scalar, int Dim>
-template<typename OtherDerived>
-inline typename Translation<Scalar,Dim>::AffineTransformType
-Translation<Scalar,Dim>::operator* (const EigenBase<OtherDerived>& linear) const
-{
- AffineTransformType res;
- res.matrix().setZero();
- res.linear() = linear.derived();
- res.translation() = m_coeffs;
- res.matrix().row(Dim).setZero();
- res(Dim,Dim) = Scalar(1);
- return res;
-}
-
-#endif // EIGEN_TRANSLATION_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/Umeyama.h b/extern/Eigen3/Eigen/src/Geometry/Umeyama.h
deleted file mode 100644
index b50f461730e..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/Umeyama.h
+++ /dev/null
@@ -1,183 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Hauke Heibel <hauke.heibel@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_UMEYAMA_H
-#define EIGEN_UMEYAMA_H
-
-// This file requires the user to include
-// * Eigen/Core
-// * Eigen/LU
-// * Eigen/SVD
-// * Eigen/Array
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
-
-// These helpers are required since it allows to use mixed types as parameters
-// for the Umeyama. The problem with mixed parameters is that the return type
-// cannot trivially be deduced when float and double types are mixed.
-namespace internal {
-
-// Compile time return type deduction for different MatrixBase types.
-// Different means here different alignment and parameters but the same underlying
-// real scalar type.
-template<typename MatrixType, typename OtherMatrixType>
-struct umeyama_transform_matrix_type
-{
- enum {
- MinRowsAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(MatrixType::RowsAtCompileTime, OtherMatrixType::RowsAtCompileTime),
-
- // When possible we want to choose some small fixed size value since the result
- // is likely to fit on the stack. So here, EIGEN_SIZE_MIN_PREFER_DYNAMIC is not what we want.
- HomogeneousDimension = int(MinRowsAtCompileTime) == Dynamic ? Dynamic : int(MinRowsAtCompileTime)+1
- };
-
- typedef Matrix<typename traits<MatrixType>::Scalar,
- HomogeneousDimension,
- HomogeneousDimension,
- AutoAlign | (traits<MatrixType>::Flags & RowMajorBit ? RowMajor : ColMajor),
- HomogeneousDimension,
- HomogeneousDimension
- > type;
-};
-
-}
-
-#endif
-
-/**
-* \geometry_module \ingroup Geometry_Module
-*
-* \brief Returns the transformation between two point sets.
-*
-* The algorithm is based on:
-* "Least-squares estimation of transformation parameters between two point patterns",
-* Shinji Umeyama, PAMI 1991, DOI: 10.1109/34.88573
-*
-* It estimates parameters \f$ c, \mathbf{R}, \f$ and \f$ \mathbf{t} \f$ such that
-* \f{align*}
-* \frac{1}{n} \sum_{i=1}^n \vert\vert y_i - (c\mathbf{R}x_i + \mathbf{t}) \vert\vert_2^2
-* \f}
-* is minimized.
-*
-* The algorithm is based on the analysis of the covariance matrix
-* \f$ \Sigma_{\mathbf{x}\mathbf{y}} \in \mathbb{R}^{d \times d} \f$
-* of the input point sets \f$ \mathbf{x} \f$ and \f$ \mathbf{y} \f$ where
-* \f$d\f$ is corresponding to the dimension (which is typically small).
-* The analysis is involving the SVD having a complexity of \f$O(d^3)\f$
-* though the actual computational effort lies in the covariance
-* matrix computation which has an asymptotic lower bound of \f$O(dm)\f$ when
-* the input point sets have dimension \f$d \times m\f$.
-*
-* Currently the method is working only for floating point matrices.
-*
-* \todo Should the return type of umeyama() become a Transform?
-*
-* \param src Source points \f$ \mathbf{x} = \left( x_1, \hdots, x_n \right) \f$.
-* \param dst Destination points \f$ \mathbf{y} = \left( y_1, \hdots, y_n \right) \f$.
-* \param with_scaling Sets \f$ c=1 \f$ when <code>false</code> is passed.
-* \return The homogeneous transformation
-* \f{align*}
-* T = \begin{bmatrix} c\mathbf{R} & \mathbf{t} \\ \mathbf{0} & 1 \end{bmatrix}
-* \f}
-* minimizing the resudiual above. This transformation is always returned as an
-* Eigen::Matrix.
-*/
-template <typename Derived, typename OtherDerived>
-typename internal::umeyama_transform_matrix_type<Derived, OtherDerived>::type
-umeyama(const MatrixBase<Derived>& src, const MatrixBase<OtherDerived>& dst, bool with_scaling = true)
-{
- typedef typename internal::umeyama_transform_matrix_type<Derived, OtherDerived>::type TransformationMatrixType;
- typedef typename internal::traits<TransformationMatrixType>::Scalar Scalar;
- typedef typename NumTraits<Scalar>::Real RealScalar;
- typedef typename Derived::Index Index;
-
- EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL)
- EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename internal::traits<OtherDerived>::Scalar>::value),
- YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
-
- enum { Dimension = EIGEN_SIZE_MIN_PREFER_DYNAMIC(Derived::RowsAtCompileTime, OtherDerived::RowsAtCompileTime) };
-
- typedef Matrix<Scalar, Dimension, 1> VectorType;
- typedef Matrix<Scalar, Dimension, Dimension> MatrixType;
- typedef typename internal::plain_matrix_type_row_major<Derived>::type RowMajorMatrixType;
-
- const Index m = src.rows(); // dimension
- const Index n = src.cols(); // number of measurements
-
- // required for demeaning ...
- const RealScalar one_over_n = 1 / static_cast<RealScalar>(n);
-
- // computation of mean
- const VectorType src_mean = src.rowwise().sum() * one_over_n;
- const VectorType dst_mean = dst.rowwise().sum() * one_over_n;
-
- // demeaning of src and dst points
- const RowMajorMatrixType src_demean = src.colwise() - src_mean;
- const RowMajorMatrixType dst_demean = dst.colwise() - dst_mean;
-
- // Eq. (36)-(37)
- const Scalar src_var = src_demean.rowwise().squaredNorm().sum() * one_over_n;
-
- // Eq. (38)
- const MatrixType sigma = one_over_n * dst_demean * src_demean.transpose();
-
- JacobiSVD<MatrixType> svd(sigma, ComputeFullU | ComputeFullV);
-
- // Initialize the resulting transformation with an identity matrix...
- TransformationMatrixType Rt = TransformationMatrixType::Identity(m+1,m+1);
-
- // Eq. (39)
- VectorType S = VectorType::Ones(m);
- if (sigma.determinant()<0) S(m-1) = -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 ) {
- Rt.block(0,0,m,m).noalias() = svd.matrixU()*svd.matrixV().transpose();
- } else {
- const Scalar s = S(m-1); S(m-1) = -1;
- Rt.block(0,0,m,m).noalias() = svd.matrixU() * S.asDiagonal() * svd.matrixV().transpose();
- S(m-1) = s;
- }
- } else {
- Rt.block(0,0,m,m).noalias() = svd.matrixU() * S.asDiagonal() * svd.matrixV().transpose();
- }
-
- // Eq. (42)
- const Scalar c = 1/src_var * svd.singularValues().dot(S);
-
- // Eq. (41)
- // Note that we first assign dst_mean to the destination so that there no need
- // for a temporary.
- Rt.col(m).head(m) = dst_mean;
- Rt.col(m).head(m).noalias() -= c*Rt.topLeftCorner(m,m)*src_mean;
-
- if (with_scaling) Rt.block(0,0,m,m) *= c;
-
- return Rt;
-}
-
-#endif // EIGEN_UMEYAMA_H
diff --git a/extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h b/extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h
deleted file mode 100644
index cbe695c7259..00000000000
--- a/extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Rohit Garg <rpg.314@gmail.com>
-// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_GEOMETRY_SSE_H
-#define EIGEN_GEOMETRY_SSE_H
-
-namespace internal {
-
-template<class Derived, class OtherDerived>
-struct quat_product<Architecture::SSE, Derived, OtherDerived, float, Aligned>
-{
- inline static Quaternion<float> run(const QuaternionBase<Derived>& _a, const QuaternionBase<OtherDerived>& _b)
- {
- const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0,0,0,0x80000000));
- Quaternion<float> res;
- __m128 a = _a.coeffs().template packet<Aligned>(0);
- __m128 b = _b.coeffs().template packet<Aligned>(0);
- __m128 flip1 = _mm_xor_ps(_mm_mul_ps(vec4f_swizzle1(a,1,2,0,2),
- vec4f_swizzle1(b,2,0,1,2)),mask);
- __m128 flip2 = _mm_xor_ps(_mm_mul_ps(vec4f_swizzle1(a,3,3,3,1),
- vec4f_swizzle1(b,0,1,2,1)),mask);
- pstore(&res.x(),
- _mm_add_ps(_mm_sub_ps(_mm_mul_ps(a,vec4f_swizzle1(b,3,3,3,3)),
- _mm_mul_ps(vec4f_swizzle1(a,2,0,1,0),
- vec4f_swizzle1(b,1,2,0,0))),
- _mm_add_ps(flip1,flip2)));
- return res;
- }
-};
-
-template<typename VectorLhs,typename VectorRhs>
-struct cross3_impl<Architecture::SSE,VectorLhs,VectorRhs,float,true>
-{
- inline static typename plain_matrix_type<VectorLhs>::type
- run(const VectorLhs& lhs, const VectorRhs& rhs)
- {
- __m128 a = lhs.template packet<VectorLhs::Flags&AlignedBit ? Aligned : Unaligned>(0);
- __m128 b = rhs.template packet<VectorRhs::Flags&AlignedBit ? Aligned : Unaligned>(0);
- __m128 mul1=_mm_mul_ps(vec4f_swizzle1(a,1,2,0,3),vec4f_swizzle1(b,2,0,1,3));
- __m128 mul2=_mm_mul_ps(vec4f_swizzle1(a,2,0,1,3),vec4f_swizzle1(b,1,2,0,3));
- typename plain_matrix_type<VectorLhs>::type res;
- pstore(&res.x(),_mm_sub_ps(mul1,mul2));
- return res;
- }
-};
-
-
-
-
-template<class Derived, class OtherDerived>
-struct quat_product<Architecture::SSE, Derived, OtherDerived, double, Aligned>
-{
- inline static Quaternion<double> run(const QuaternionBase<Derived>& _a, const QuaternionBase<OtherDerived>& _b)
- {
- const Packet2d mask = _mm_castsi128_pd(_mm_set_epi32(0x0,0x0,0x80000000,0x0));
-
- Quaternion<double> res;
-
- const double* a = _a.coeffs().data();
- Packet2d b_xy = _b.coeffs().template packet<Aligned>(0);
- Packet2d b_zw = _b.coeffs().template packet<Aligned>(2);
- Packet2d a_xx = pset1<Packet2d>(a[0]);
- Packet2d a_yy = pset1<Packet2d>(a[1]);
- Packet2d a_zz = pset1<Packet2d>(a[2]);
- Packet2d a_ww = pset1<Packet2d>(a[3]);
-
- // two temporaries:
- Packet2d t1, t2;
-
- /*
- * t1 = ww*xy + yy*zw
- * t2 = zz*xy - xx*zw
- * res.xy = t1 +/- swap(t2)
- */
- t1 = padd(pmul(a_ww, b_xy), pmul(a_yy, b_zw));
- t2 = psub(pmul(a_zz, b_xy), pmul(a_xx, b_zw));
-#ifdef __SSE3__
- EIGEN_UNUSED_VARIABLE(mask)
- pstore(&res.x(), _mm_addsub_pd(t1, preverse(t2)));
-#else
- pstore(&res.x(), padd(t1, pxor(mask,preverse(t2))));
-#endif
-
- /*
- * t1 = ww*zw - yy*xy
- * t2 = zz*zw + xx*xy
- * res.zw = t1 -/+ swap(t2) = swap( swap(t1) +/- t2)
- */
- t1 = psub(pmul(a_ww, b_zw), pmul(a_yy, b_xy));
- t2 = padd(pmul(a_zz, b_zw), pmul(a_xx, b_xy));
-#ifdef __SSE3__
- EIGEN_UNUSED_VARIABLE(mask)
- pstore(&res.z(), preverse(_mm_addsub_pd(preverse(t1), t2)));
-#else
- pstore(&res.z(), psub(t1, pxor(mask,preverse(t2))));
-#endif
-
- return res;
-}
-};
-
-} // end namespace internal
-
-#endif // EIGEN_GEOMETRY_SSE_H
diff --git a/extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h b/extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h
deleted file mode 100644
index 23ce1bfbd46..00000000000
--- a/extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010 Vincent Lejeune
-// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_BLOCK_HOUSEHOLDER_H
-#define EIGEN_BLOCK_HOUSEHOLDER_H
-
-// This file contains some helper function to deal with block householder reflectors
-
-namespace internal {
-
-/** \internal */
-template<typename TriangularFactorType,typename VectorsType,typename CoeffsType>
-void make_block_householder_triangular_factor(TriangularFactorType& triFactor, const VectorsType& vectors, const CoeffsType& hCoeffs)
-{
- typedef typename TriangularFactorType::Index Index;
- typedef typename VectorsType::Scalar Scalar;
- const Index nbVecs = vectors.cols();
- eigen_assert(triFactor.rows() == nbVecs && triFactor.cols() == nbVecs && vectors.rows()>=nbVecs);
-
- for(Index i = 0; i < nbVecs; i++)
- {
- Index rs = vectors.rows() - i;
- Scalar Vii = vectors(i,i);
- vectors.const_cast_derived().coeffRef(i,i) = Scalar(1);
- triFactor.col(i).head(i).noalias() = -hCoeffs(i) * vectors.block(i, 0, rs, i).adjoint()
- * vectors.col(i).tail(rs);
- vectors.const_cast_derived().coeffRef(i, i) = Vii;
- // FIXME add .noalias() once the triangular product can work inplace
- triFactor.col(i).head(i) = triFactor.block(0,0,i,i).template triangularView<Upper>()
- * triFactor.col(i).head(i);
- triFactor(i,i) = hCoeffs(i);
- }
-}
-
-/** \internal */
-template<typename MatrixType,typename VectorsType,typename CoeffsType>
-void apply_block_householder_on_the_left(MatrixType& mat, const VectorsType& vectors, const CoeffsType& hCoeffs)
-{
- typedef typename MatrixType::Index Index;
- enum { TFactorSize = MatrixType::ColsAtCompileTime };
- Index nbVecs = vectors.cols();
- Matrix<typename MatrixType::Scalar, TFactorSize, TFactorSize> T(nbVecs,nbVecs);
- make_block_householder_triangular_factor(T, vectors, hCoeffs);
-
- const TriangularView<VectorsType, UnitLower>& V(vectors);
-
- // A -= V T V^* A
- Matrix<typename MatrixType::Scalar,VectorsType::ColsAtCompileTime,MatrixType::ColsAtCompileTime,0,
- VectorsType::MaxColsAtCompileTime,MatrixType::MaxColsAtCompileTime> tmp = V.adjoint() * mat;
- // FIXME add .noalias() once the triangular product can work inplace
- tmp = T.template triangularView<Upper>().adjoint() * tmp;
- mat.noalias() -= V * tmp;
-}
-
-} // end namespace internal
-
-#endif // EIGEN_BLOCK_HOUSEHOLDER_H
diff --git a/extern/Eigen3/Eigen/src/Householder/Householder.h b/extern/Eigen3/Eigen/src/Householder/Householder.h
deleted file mode 100644
index 74139c0dcce..00000000000
--- a/extern/Eigen3/Eigen/src/Householder/Householder.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_HOUSEHOLDER_H
-#define EIGEN_HOUSEHOLDER_H
-
-namespace internal {
-template<int n> struct decrement_size
-{
- enum {
- ret = n==Dynamic ? n : n-1
- };
-};
-}
-
-template<typename Derived>
-void MatrixBase<Derived>::makeHouseholderInPlace(Scalar& tau, RealScalar& beta)
-{
- VectorBlock<Derived, internal::decrement_size<Base::SizeAtCompileTime>::ret> essentialPart(derived(), 1, size()-1);
- makeHouseholder(essentialPart, tau, beta);
-}
-
-/** Computes the elementary reflector H such that:
- * \f$ H *this = [ beta 0 ... 0]^T \f$
- * where the transformation H is:
- * \f$ H = I - tau v v^*\f$
- * and the vector v is:
- * \f$ v^T = [1 essential^T] \f$
- *
- * On output:
- * \param essential the essential part of the vector \c v
- * \param tau the scaling factor of the householder transformation
- * \param beta the result of H * \c *this
- *
- * \sa MatrixBase::makeHouseholderInPlace(), MatrixBase::applyHouseholderOnTheLeft(),
- * MatrixBase::applyHouseholderOnTheRight()
- */
-template<typename Derived>
-template<typename EssentialPart>
-void MatrixBase<Derived>::makeHouseholder(
- EssentialPart& essential,
- Scalar& tau,
- RealScalar& beta) const
-{
- EIGEN_STATIC_ASSERT_VECTOR_ONLY(EssentialPart)
- VectorBlock<const Derived, EssentialPart::SizeAtCompileTime> tail(derived(), 1, size()-1);
-
- RealScalar tailSqNorm = size()==1 ? RealScalar(0) : tail.squaredNorm();
- Scalar c0 = coeff(0);
-
- if(tailSqNorm == RealScalar(0) && internal::imag(c0)==RealScalar(0))
- {
- tau = RealScalar(0);
- beta = internal::real(c0);
- essential.setZero();
- }
- else
- {
- beta = internal::sqrt(internal::abs2(c0) + tailSqNorm);
- if (internal::real(c0)>=RealScalar(0))
- beta = -beta;
- essential = tail / (c0 - beta);
- tau = internal::conj((beta - c0) / beta);
- }
-}
-
-template<typename Derived>
-template<typename EssentialPart>
-void MatrixBase<Derived>::applyHouseholderOnTheLeft(
- const EssentialPart& essential,
- const Scalar& tau,
- Scalar* workspace)
-{
- if(rows() == 1)
- {
- *this *= Scalar(1)-tau;
- }
- else
- {
- Map<typename internal::plain_row_type<PlainObject>::type> tmp(workspace,cols());
- Block<Derived, EssentialPart::SizeAtCompileTime, Derived::ColsAtCompileTime> bottom(derived(), 1, 0, rows()-1, cols());
- tmp.noalias() = essential.adjoint() * bottom;
- tmp += this->row(0);
- this->row(0) -= tau * tmp;
- bottom.noalias() -= tau * essential * tmp;
- }
-}
-
-template<typename Derived>
-template<typename EssentialPart>
-void MatrixBase<Derived>::applyHouseholderOnTheRight(
- const EssentialPart& essential,
- const Scalar& tau,
- Scalar* workspace)
-{
- if(cols() == 1)
- {
- *this *= Scalar(1)-tau;
- }
- else
- {
- Map<typename internal::plain_col_type<PlainObject>::type> tmp(workspace,rows());
- Block<Derived, Derived::RowsAtCompileTime, EssentialPart::SizeAtCompileTime> right(derived(), 0, 1, rows(), cols()-1);
- tmp.noalias() = right * essential.conjugate();
- tmp += this->col(0);
- this->col(0) -= tau * tmp;
- right.noalias() -= tau * tmp * essential.transpose();
- }
-}
-
-#endif // EIGEN_HOUSEHOLDER_H
diff --git a/extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h b/extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h
deleted file mode 100644
index 717f29c99e9..00000000000
--- a/extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h
+++ /dev/null
@@ -1,429 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_HOUSEHOLDER_SEQUENCE_H
-#define EIGEN_HOUSEHOLDER_SEQUENCE_H
-
-/** \ingroup Householder_Module
- * \householder_module
- * \class HouseholderSequence
- * \brief Sequence of Householder reflections acting on subspaces with decreasing size
- * \tparam VectorsType type of matrix containing the Householder vectors
- * \tparam CoeffsType type of vector containing the Householder coefficients
- * \tparam Side either OnTheLeft (the default) or OnTheRight
- *
- * This class represents a product sequence of Householder reflections where the first Householder reflection
- * acts on the whole space, the second Householder reflection leaves the one-dimensional subspace spanned by
- * the first unit vector invariant, the third Householder reflection leaves the two-dimensional subspace
- * spanned by the first two unit vectors invariant, and so on up to the last reflection which leaves all but
- * one dimensions invariant and acts only on the last dimension. Such sequences of Householder reflections
- * are used in several algorithms to zero out certain parts of a matrix. Indeed, the methods
- * HessenbergDecomposition::matrixQ(), Tridiagonalization::matrixQ(), HouseholderQR::householderQ(),
- * and ColPivHouseholderQR::householderQ() all return a %HouseholderSequence.
- *
- * More precisely, the class %HouseholderSequence represents an \f$ n \times n \f$ matrix \f$ H \f$ of the
- * form \f$ H = \prod_{i=0}^{n-1} H_i \f$ where the i-th Householder reflection is \f$ H_i = I - h_i v_i
- * v_i^* \f$. The i-th Householder coefficient \f$ h_i \f$ is a scalar and the i-th Householder vector \f$
- * v_i \f$ is a vector of the form
- * \f[
- * v_i = [\underbrace{0, \ldots, 0}_{i-1\mbox{ zeros}}, 1, \underbrace{*, \ldots,*}_{n-i\mbox{ arbitrary entries}} ].
- * \f]
- * The last \f$ n-i \f$ entries of \f$ v_i \f$ are called the essential part of the Householder vector.
- *
- * Typical usages are listed below, where H is a HouseholderSequence:
- * \code
- * A.applyOnTheRight(H); // A = A * H
- * A.applyOnTheLeft(H); // A = H * A
- * A.applyOnTheRight(H.adjoint()); // A = A * H^*
- * A.applyOnTheLeft(H.adjoint()); // A = H^* * A
- * MatrixXd Q = H; // conversion to a dense matrix
- * \endcode
- * In addition to the adjoint, you can also apply the inverse (=adjoint), the transpose, and the conjugate operators.
- *
- * See the documentation for HouseholderSequence(const VectorsType&, const CoeffsType&) for an example.
- *
- * \sa MatrixBase::applyOnTheLeft(), MatrixBase::applyOnTheRight()
- */
-
-namespace internal {
-
-template<typename VectorsType, typename CoeffsType, int Side>
-struct traits<HouseholderSequence<VectorsType,CoeffsType,Side> >
-{
- typedef typename VectorsType::Scalar Scalar;
- typedef typename VectorsType::Index Index;
- typedef typename VectorsType::StorageKind StorageKind;
- enum {
- RowsAtCompileTime = Side==OnTheLeft ? traits<VectorsType>::RowsAtCompileTime
- : traits<VectorsType>::ColsAtCompileTime,
- ColsAtCompileTime = RowsAtCompileTime,
- MaxRowsAtCompileTime = Side==OnTheLeft ? traits<VectorsType>::MaxRowsAtCompileTime
- : traits<VectorsType>::MaxColsAtCompileTime,
- MaxColsAtCompileTime = MaxRowsAtCompileTime,
- Flags = 0
- };
-};
-
-template<typename VectorsType, typename CoeffsType, int Side>
-struct hseq_side_dependent_impl
-{
- typedef Block<const VectorsType, Dynamic, 1> EssentialVectorType;
- typedef HouseholderSequence<VectorsType, CoeffsType, OnTheLeft> HouseholderSequenceType;
- typedef typename VectorsType::Index Index;
- static inline const EssentialVectorType essentialVector(const HouseholderSequenceType& h, Index k)
- {
- Index start = k+1+h.m_shift;
- return Block<const VectorsType,Dynamic,1>(h.m_vectors, start, k, h.rows()-start, 1);
- }
-};
-
-template<typename VectorsType, typename CoeffsType>
-struct hseq_side_dependent_impl<VectorsType, CoeffsType, OnTheRight>
-{
- typedef Transpose<Block<const VectorsType, 1, Dynamic> > EssentialVectorType;
- typedef HouseholderSequence<VectorsType, CoeffsType, OnTheRight> HouseholderSequenceType;
- typedef typename VectorsType::Index Index;
- static inline const EssentialVectorType essentialVector(const HouseholderSequenceType& h, Index k)
- {
- Index start = k+1+h.m_shift;
- return Block<const VectorsType,1,Dynamic>(h.m_vectors, k, start, 1, h.rows()-start).transpose();
- }
-};
-
-template<typename OtherScalarType, typename MatrixType> struct matrix_type_times_scalar_type
-{
- typedef typename scalar_product_traits<OtherScalarType, typename MatrixType::Scalar>::ReturnType
- ResultScalar;
- typedef Matrix<ResultScalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime,
- 0, MatrixType::MaxRowsAtCompileTime, MatrixType::MaxColsAtCompileTime> Type;
-};
-
-} // end namespace internal
-
-template<typename VectorsType, typename CoeffsType, int Side> class HouseholderSequence
- : public EigenBase<HouseholderSequence<VectorsType,CoeffsType,Side> >
-{
- enum {
- RowsAtCompileTime = internal::traits<HouseholderSequence>::RowsAtCompileTime,
- ColsAtCompileTime = internal::traits<HouseholderSequence>::ColsAtCompileTime,
- MaxRowsAtCompileTime = internal::traits<HouseholderSequence>::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = internal::traits<HouseholderSequence>::MaxColsAtCompileTime
- };
- typedef typename internal::traits<HouseholderSequence>::Scalar Scalar;
- typedef typename VectorsType::Index Index;
-
- typedef typename internal::hseq_side_dependent_impl<VectorsType,CoeffsType,Side>::EssentialVectorType
- EssentialVectorType;
-
- public:
-
- typedef HouseholderSequence<
- VectorsType,
- typename internal::conditional<NumTraits<Scalar>::IsComplex,
- typename internal::remove_all<typename CoeffsType::ConjugateReturnType>::type,
- CoeffsType>::type,
- Side
- > ConjugateReturnType;
-
- /** \brief Constructor.
- * \param[in] v %Matrix containing the essential parts of the Householder vectors
- * \param[in] h Vector containing the Householder coefficients
- *
- * Constructs the Householder sequence with coefficients given by \p h and vectors given by \p v. The
- * i-th Householder coefficient \f$ h_i \f$ is given by \p h(i) and the essential part of the i-th
- * Householder vector \f$ v_i \f$ is given by \p v(k,i) with \p k > \p i (the subdiagonal part of the
- * i-th column). If \p v has fewer columns than rows, then the Householder sequence contains as many
- * Householder reflections as there are columns.
- *
- * \note The %HouseholderSequence object stores \p v and \p h by reference.
- *
- * Example: \include HouseholderSequence_HouseholderSequence.cpp
- * Output: \verbinclude HouseholderSequence_HouseholderSequence.out
- *
- * \sa setLength(), setShift()
- */
- HouseholderSequence(const VectorsType& v, const CoeffsType& h)
- : m_vectors(v), m_coeffs(h), m_trans(false), m_length(v.diagonalSize()),
- m_shift(0)
- {
- }
-
- /** \brief Copy constructor. */
- HouseholderSequence(const HouseholderSequence& other)
- : m_vectors(other.m_vectors),
- m_coeffs(other.m_coeffs),
- m_trans(other.m_trans),
- m_length(other.m_length),
- m_shift(other.m_shift)
- {
- }
-
- /** \brief Number of rows of transformation viewed as a matrix.
- * \returns Number of rows
- * \details This equals the dimension of the space that the transformation acts on.
- */
- Index rows() const { return Side==OnTheLeft ? m_vectors.rows() : m_vectors.cols(); }
-
- /** \brief Number of columns of transformation viewed as a matrix.
- * \returns Number of columns
- * \details This equals the dimension of the space that the transformation acts on.
- */
- Index cols() const { return rows(); }
-
- /** \brief Essential part of a Householder vector.
- * \param[in] k Index of Householder reflection
- * \returns Vector containing non-trivial entries of k-th Householder vector
- *
- * This function returns the essential part of the Householder vector \f$ v_i \f$. This is a vector of
- * length \f$ n-i \f$ containing the last \f$ n-i \f$ entries of the vector
- * \f[
- * v_i = [\underbrace{0, \ldots, 0}_{i-1\mbox{ zeros}}, 1, \underbrace{*, \ldots,*}_{n-i\mbox{ arbitrary entries}} ].
- * \f]
- * The index \f$ i \f$ equals \p k + shift(), corresponding to the k-th column of the matrix \p v
- * passed to the constructor.
- *
- * \sa setShift(), shift()
- */
- const EssentialVectorType essentialVector(Index k) const
- {
- eigen_assert(k >= 0 && k < m_length);
- return internal::hseq_side_dependent_impl<VectorsType,CoeffsType,Side>::essentialVector(*this, k);
- }
-
- /** \brief %Transpose of the Householder sequence. */
- HouseholderSequence transpose() const
- {
- return HouseholderSequence(*this).setTrans(!m_trans);
- }
-
- /** \brief Complex conjugate of the Householder sequence. */
- ConjugateReturnType conjugate() const
- {
- return ConjugateReturnType(m_vectors, m_coeffs.conjugate())
- .setTrans(m_trans)
- .setLength(m_length)
- .setShift(m_shift);
- }
-
- /** \brief Adjoint (conjugate transpose) of the Householder sequence. */
- ConjugateReturnType adjoint() const
- {
- return conjugate().setTrans(!m_trans);
- }
-
- /** \brief Inverse of the Householder sequence (equals the adjoint). */
- ConjugateReturnType inverse() const { return adjoint(); }
-
- /** \internal */
- template<typename DestType> void evalTo(DestType& dst) const
- {
- Index vecs = m_length;
- // FIXME find a way to pass this temporary if the user wants to
- Matrix<Scalar, DestType::RowsAtCompileTime, 1,
- AutoAlign|ColMajor, DestType::MaxRowsAtCompileTime, 1> temp(rows());
- if( internal::is_same<typename internal::remove_all<VectorsType>::type,DestType>::value
- && internal::extract_data(dst) == internal::extract_data(m_vectors))
- {
- // in-place
- dst.diagonal().setOnes();
- dst.template triangularView<StrictlyUpper>().setZero();
- for(Index k = vecs-1; k >= 0; --k)
- {
- Index cornerSize = rows() - k - m_shift;
- if(m_trans)
- dst.bottomRightCorner(cornerSize, cornerSize)
- .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), &temp.coeffRef(0));
- else
- dst.bottomRightCorner(cornerSize, cornerSize)
- .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), &temp.coeffRef(0));
-
- // clear the off diagonal vector
- dst.col(k).tail(rows()-k-1).setZero();
- }
- // clear the remaining columns if needed
- for(Index k = 0; k<cols()-vecs ; ++k)
- dst.col(k).tail(rows()-k-1).setZero();
- }
- else
- {
- dst.setIdentity(rows(), rows());
- for(Index k = vecs-1; k >= 0; --k)
- {
- Index cornerSize = rows() - k - m_shift;
- if(m_trans)
- dst.bottomRightCorner(cornerSize, cornerSize)
- .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), &temp.coeffRef(0));
- else
- dst.bottomRightCorner(cornerSize, cornerSize)
- .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), &temp.coeffRef(0));
- }
- }
- }
-
- /** \internal */
- template<typename Dest> inline void applyThisOnTheRight(Dest& dst) const
- {
- Matrix<Scalar,1,Dest::RowsAtCompileTime> temp(dst.rows());
- for(Index k = 0; k < m_length; ++k)
- {
- Index actual_k = m_trans ? m_length-k-1 : k;
- dst.rightCols(rows()-m_shift-actual_k)
- .applyHouseholderOnTheRight(essentialVector(actual_k), m_coeffs.coeff(actual_k), &temp.coeffRef(0));
- }
- }
-
- /** \internal */
- template<typename Dest> inline void applyThisOnTheLeft(Dest& dst) const
- {
- Matrix<Scalar,1,Dest::ColsAtCompileTime> temp(dst.cols());
- for(Index k = 0; k < m_length; ++k)
- {
- Index actual_k = m_trans ? k : m_length-k-1;
- dst.bottomRows(rows()-m_shift-actual_k)
- .applyHouseholderOnTheLeft(essentialVector(actual_k), m_coeffs.coeff(actual_k), &temp.coeffRef(0));
- }
- }
-
- /** \brief Computes the product of a Householder sequence with a matrix.
- * \param[in] other %Matrix being multiplied.
- * \returns Expression object representing the product.
- *
- * This function computes \f$ HM \f$ where \f$ H \f$ is the Householder sequence represented by \p *this
- * and \f$ M \f$ is the matrix \p other.
- */
- template<typename OtherDerived>
- typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type operator*(const MatrixBase<OtherDerived>& other) const
- {
- typename internal::matrix_type_times_scalar_type<Scalar, OtherDerived>::Type
- res(other.template cast<typename internal::matrix_type_times_scalar_type<Scalar,OtherDerived>::ResultScalar>());
- applyThisOnTheLeft(res);
- return res;
- }
-
- template<typename _VectorsType, typename _CoeffsType, int _Side> friend struct internal::hseq_side_dependent_impl;
-
- /** \brief Sets the length of the Householder sequence.
- * \param [in] length New value for the length.
- *
- * By default, the length \f$ n \f$ of the Householder sequence \f$ H = H_0 H_1 \ldots H_{n-1} \f$ is set
- * to the number of columns of the matrix \p v passed to the constructor, or the number of rows if that
- * is smaller. After this function is called, the length equals \p length.
- *
- * \sa length()
- */
- HouseholderSequence& setLength(Index length)
- {
- m_length = length;
- return *this;
- }
-
- /** \brief Sets the shift of the Householder sequence.
- * \param [in] shift New value for the shift.
- *
- * By default, a %HouseholderSequence object represents \f$ H = H_0 H_1 \ldots H_{n-1} \f$ and the i-th
- * column of the matrix \p v passed to the constructor corresponds to the i-th Householder
- * reflection. After this function is called, the object represents \f$ H = H_{\mathrm{shift}}
- * H_{\mathrm{shift}+1} \ldots H_{n-1} \f$ and the i-th column of \p v corresponds to the (shift+i)-th
- * Householder reflection.
- *
- * \sa shift()
- */
- HouseholderSequence& setShift(Index shift)
- {
- m_shift = shift;
- return *this;
- }
-
- Index length() const { return m_length; } /**< \brief Returns the length of the Householder sequence. */
- Index shift() const { return m_shift; } /**< \brief Returns the shift of the Householder sequence. */
-
- /* Necessary for .adjoint() and .conjugate() */
- template <typename VectorsType2, typename CoeffsType2, int Side2> friend class HouseholderSequence;
-
- protected:
-
- /** \brief Sets the transpose flag.
- * \param [in] trans New value of the transpose flag.
- *
- * By default, the transpose flag is not set. If the transpose flag is set, then this object represents
- * \f$ H^T = H_{n-1}^T \ldots H_1^T H_0^T \f$ instead of \f$ H = H_0 H_1 \ldots H_{n-1} \f$.
- *
- * \sa trans()
- */
- HouseholderSequence& setTrans(bool trans)
- {
- m_trans = trans;
- return *this;
- }
-
- bool trans() const { return m_trans; } /**< \brief Returns the transpose flag. */
-
- typename VectorsType::Nested m_vectors;
- typename CoeffsType::Nested m_coeffs;
- bool m_trans;
- Index m_length;
- Index m_shift;
-};
-
-/** \brief Computes the product of a matrix with a Householder sequence.
- * \param[in] other %Matrix being multiplied.
- * \param[in] h %HouseholderSequence being multiplied.
- * \returns Expression object representing the product.
- *
- * This function computes \f$ MH \f$ where \f$ M \f$ is the matrix \p other and \f$ H \f$ is the
- * Householder sequence represented by \p h.
- */
-template<typename OtherDerived, typename VectorsType, typename CoeffsType, int Side>
-typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar,OtherDerived>::Type operator*(const MatrixBase<OtherDerived>& other, const HouseholderSequence<VectorsType,CoeffsType,Side>& h)
-{
- typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar,OtherDerived>::Type
- res(other.template cast<typename internal::matrix_type_times_scalar_type<typename VectorsType::Scalar,OtherDerived>::ResultScalar>());
- h.applyThisOnTheRight(res);
- return res;
-}
-
-/** \ingroup Householder_Module \householder_module
- * \brief Convenience function for constructing a Householder sequence.
- * \returns A HouseholderSequence constructed from the specified arguments.
- */
-template<typename VectorsType, typename CoeffsType>
-HouseholderSequence<VectorsType,CoeffsType> householderSequence(const VectorsType& v, const CoeffsType& h)
-{
- return HouseholderSequence<VectorsType,CoeffsType,OnTheLeft>(v, h);
-}
-
-/** \ingroup Householder_Module \householder_module
- * \brief Convenience function for constructing a Householder sequence.
- * \returns A HouseholderSequence constructed from the specified arguments.
- * \details This function differs from householderSequence() in that the template argument \p OnTheSide of
- * the constructed HouseholderSequence is set to OnTheRight, instead of the default OnTheLeft.
- */
-template<typename VectorsType, typename CoeffsType>
-HouseholderSequence<VectorsType,CoeffsType,OnTheRight> rightHouseholderSequence(const VectorsType& v, const CoeffsType& h)
-{
- return HouseholderSequence<VectorsType,CoeffsType,OnTheRight>(v, h);
-}
-
-#endif // EIGEN_HOUSEHOLDER_SEQUENCE_H
diff --git a/extern/Eigen3/Eigen/src/Jacobi/Jacobi.h b/extern/Eigen3/Eigen/src/Jacobi/Jacobi.h
deleted file mode 100644
index 98dea6800bc..00000000000
--- a/extern/Eigen3/Eigen/src/Jacobi/Jacobi.h
+++ /dev/null
@@ -1,430 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_JACOBI_H
-#define EIGEN_JACOBI_H
-
-/** \ingroup Jacobi_Module
- * \jacobi_module
- * \class JacobiRotation
- * \brief Rotation given by a cosine-sine pair.
- *
- * This class represents a Jacobi or Givens rotation.
- * This is a 2D rotation in the plane \c J of angle \f$ \theta \f$ defined by
- * its cosine \c c and sine \c s as follow:
- * \f$ J = \left ( \begin{array}{cc} c & \overline s \\ -s & \overline c \end{array} \right ) \f$
- *
- * You can apply the respective counter-clockwise rotation to a column vector \c v by
- * applying its adjoint on the left: \f$ v = J^* v \f$ that translates to the following Eigen code:
- * \code
- * v.applyOnTheLeft(J.adjoint());
- * \endcode
- *
- * \sa MatrixBase::applyOnTheLeft(), MatrixBase::applyOnTheRight()
- */
-template<typename Scalar> class JacobiRotation
-{
- public:
- typedef typename NumTraits<Scalar>::Real RealScalar;
-
- /** Default constructor without any initialization. */
- JacobiRotation() {}
-
- /** Construct a planar rotation from a cosine-sine pair (\a c, \c s). */
- JacobiRotation(const Scalar& c, const Scalar& s) : m_c(c), m_s(s) {}
-
- Scalar& c() { return m_c; }
- Scalar c() const { return m_c; }
- Scalar& s() { return m_s; }
- Scalar s() const { return m_s; }
-
- /** Concatenates two planar rotation */
- JacobiRotation operator*(const JacobiRotation& other)
- {
- return JacobiRotation(m_c * other.m_c - internal::conj(m_s) * other.m_s,
- internal::conj(m_c * internal::conj(other.m_s) + internal::conj(m_s) * internal::conj(other.m_c)));
- }
-
- /** Returns the transposed transformation */
- JacobiRotation transpose() const { return JacobiRotation(m_c, -internal::conj(m_s)); }
-
- /** Returns the adjoint transformation */
- JacobiRotation adjoint() const { return JacobiRotation(internal::conj(m_c), -m_s); }
-
- template<typename Derived>
- bool makeJacobi(const MatrixBase<Derived>&, typename Derived::Index p, typename Derived::Index q);
- bool makeJacobi(RealScalar x, Scalar y, RealScalar z);
-
- void makeGivens(const Scalar& p, const Scalar& q, Scalar* z=0);
-
- protected:
- void makeGivens(const Scalar& p, const Scalar& q, Scalar* z, internal::true_type);
- void makeGivens(const Scalar& p, const Scalar& q, Scalar* z, internal::false_type);
-
- Scalar m_c, m_s;
-};
-
-/** Makes \c *this as a Jacobi rotation \a J such that applying \a J on both the right and left sides of the selfadjoint 2x2 matrix
- * \f$ B = \left ( \begin{array}{cc} x & y \\ \overline y & z \end{array} \right )\f$ yields a diagonal matrix \f$ A = J^* B J \f$
- *
- * \sa MatrixBase::makeJacobi(const MatrixBase<Derived>&, Index, Index), MatrixBase::applyOnTheLeft(), MatrixBase::applyOnTheRight()
- */
-template<typename Scalar>
-bool JacobiRotation<Scalar>::makeJacobi(RealScalar x, Scalar y, RealScalar z)
-{
- typedef typename NumTraits<Scalar>::Real RealScalar;
- if(y == Scalar(0))
- {
- m_c = Scalar(1);
- m_s = Scalar(0);
- return false;
- }
- else
- {
- RealScalar tau = (x-z)/(RealScalar(2)*internal::abs(y));
- RealScalar w = internal::sqrt(internal::abs2(tau) + RealScalar(1));
- RealScalar t;
- if(tau>RealScalar(0))
- {
- t = RealScalar(1) / (tau + w);
- }
- else
- {
- t = RealScalar(1) / (tau - w);
- }
- RealScalar sign_t = t > RealScalar(0) ? RealScalar(1) : RealScalar(-1);
- RealScalar n = RealScalar(1) / internal::sqrt(internal::abs2(t)+RealScalar(1));
- m_s = - sign_t * (internal::conj(y) / internal::abs(y)) * internal::abs(t) * n;
- m_c = n;
- return true;
- }
-}
-
-/** Makes \c *this as a Jacobi rotation \c J such that applying \a J on both the right and left sides of the 2x2 selfadjoint matrix
- * \f$ B = \left ( \begin{array}{cc} \text{this}_{pp} & \text{this}_{pq} \\ (\text{this}_{pq})^* & \text{this}_{qq} \end{array} \right )\f$ yields
- * a diagonal matrix \f$ A = J^* B J \f$
- *
- * Example: \include Jacobi_makeJacobi.cpp
- * Output: \verbinclude Jacobi_makeJacobi.out
- *
- * \sa JacobiRotation::makeJacobi(RealScalar, Scalar, RealScalar), MatrixBase::applyOnTheLeft(), MatrixBase::applyOnTheRight()
- */
-template<typename Scalar>
-template<typename Derived>
-inline bool JacobiRotation<Scalar>::makeJacobi(const MatrixBase<Derived>& m, typename Derived::Index p, typename Derived::Index q)
-{
- return makeJacobi(internal::real(m.coeff(p,p)), m.coeff(p,q), internal::real(m.coeff(q,q)));
-}
-
-/** Makes \c *this as a Givens rotation \c G such that applying \f$ G^* \f$ to the left of the vector
- * \f$ V = \left ( \begin{array}{c} p \\ q \end{array} \right )\f$ yields:
- * \f$ G^* V = \left ( \begin{array}{c} r \\ 0 \end{array} \right )\f$.
- *
- * The value of \a z is returned if \a z is not null (the default is null).
- * Also note that G is built such that the cosine is always real.
- *
- * Example: \include Jacobi_makeGivens.cpp
- * Output: \verbinclude Jacobi_makeGivens.out
- *
- * This function implements the continuous Givens rotation generation algorithm
- * found in Anderson (2000), Discontinuous Plane Rotations and the Symmetric Eigenvalue Problem.
- * LAPACK Working Note 150, University of Tennessee, UT-CS-00-454, December 4, 2000.
- *
- * \sa MatrixBase::applyOnTheLeft(), MatrixBase::applyOnTheRight()
- */
-template<typename Scalar>
-void JacobiRotation<Scalar>::makeGivens(const Scalar& p, const Scalar& q, Scalar* z)
-{
- makeGivens(p, q, z, typename internal::conditional<NumTraits<Scalar>::IsComplex, internal::true_type, internal::false_type>::type());
-}
-
-
-// specialization for complexes
-template<typename Scalar>
-void JacobiRotation<Scalar>::makeGivens(const Scalar& p, const Scalar& q, Scalar* r, internal::true_type)
-{
- if(q==Scalar(0))
- {
- m_c = internal::real(p)<0 ? Scalar(-1) : Scalar(1);
- m_s = 0;
- if(r) *r = m_c * p;
- }
- else if(p==Scalar(0))
- {
- m_c = 0;
- m_s = -q/internal::abs(q);
- if(r) *r = internal::abs(q);
- }
- else
- {
- RealScalar p1 = internal::norm1(p);
- RealScalar q1 = internal::norm1(q);
- if(p1>=q1)
- {
- Scalar ps = p / p1;
- RealScalar p2 = internal::abs2(ps);
- Scalar qs = q / p1;
- RealScalar q2 = internal::abs2(qs);
-
- RealScalar u = internal::sqrt(RealScalar(1) + q2/p2);
- if(internal::real(p)<RealScalar(0))
- u = -u;
-
- m_c = Scalar(1)/u;
- m_s = -qs*internal::conj(ps)*(m_c/p2);
- if(r) *r = p * u;
- }
- else
- {
- Scalar ps = p / q1;
- RealScalar p2 = internal::abs2(ps);
- Scalar qs = q / q1;
- RealScalar q2 = internal::abs2(qs);
-
- RealScalar u = q1 * internal::sqrt(p2 + q2);
- if(internal::real(p)<RealScalar(0))
- u = -u;
-
- p1 = internal::abs(p);
- ps = p/p1;
- m_c = p1/u;
- m_s = -internal::conj(ps) * (q/u);
- if(r) *r = ps * u;
- }
- }
-}
-
-// specialization for reals
-template<typename Scalar>
-void JacobiRotation<Scalar>::makeGivens(const Scalar& p, const Scalar& q, Scalar* r, internal::false_type)
-{
-
- if(q==Scalar(0))
- {
- m_c = p<Scalar(0) ? Scalar(-1) : Scalar(1);
- m_s = Scalar(0);
- if(r) *r = internal::abs(p);
- }
- else if(p==Scalar(0))
- {
- m_c = Scalar(0);
- m_s = q<Scalar(0) ? Scalar(1) : Scalar(-1);
- if(r) *r = internal::abs(q);
- }
- else if(internal::abs(p) > internal::abs(q))
- {
- Scalar t = q/p;
- Scalar u = internal::sqrt(Scalar(1) + internal::abs2(t));
- if(p<Scalar(0))
- u = -u;
- m_c = Scalar(1)/u;
- m_s = -t * m_c;
- if(r) *r = p * u;
- }
- else
- {
- Scalar t = p/q;
- Scalar u = internal::sqrt(Scalar(1) + internal::abs2(t));
- if(q<Scalar(0))
- u = -u;
- m_s = -Scalar(1)/u;
- m_c = -t * m_s;
- if(r) *r = q * u;
- }
-
-}
-
-/****************************************************************************************
-* Implementation of MatrixBase methods
-****************************************************************************************/
-
-/** \jacobi_module
- * Applies the clock wise 2D rotation \a j to the set of 2D vectors of cordinates \a x and \a y:
- * \f$ \left ( \begin{array}{cc} x \\ y \end{array} \right ) = J \left ( \begin{array}{cc} x \\ y \end{array} \right ) \f$
- *
- * \sa MatrixBase::applyOnTheLeft(), MatrixBase::applyOnTheRight()
- */
-namespace internal {
-template<typename VectorX, typename VectorY, typename OtherScalar>
-void apply_rotation_in_the_plane(VectorX& _x, VectorY& _y, const JacobiRotation<OtherScalar>& j);
-}
-
-/** \jacobi_module
- * Applies the rotation in the plane \a j to the rows \a p and \a q of \c *this, i.e., it computes B = J * B,
- * with \f$ B = \left ( \begin{array}{cc} \text{*this.row}(p) \\ \text{*this.row}(q) \end{array} \right ) \f$.
- *
- * \sa class JacobiRotation, MatrixBase::applyOnTheRight(), internal::apply_rotation_in_the_plane()
- */
-template<typename Derived>
-template<typename OtherScalar>
-inline void MatrixBase<Derived>::applyOnTheLeft(Index p, Index q, const JacobiRotation<OtherScalar>& j)
-{
- RowXpr x(this->row(p));
- RowXpr y(this->row(q));
- internal::apply_rotation_in_the_plane(x, y, j);
-}
-
-/** \ingroup Jacobi_Module
- * Applies the rotation in the plane \a j to the columns \a p and \a q of \c *this, i.e., it computes B = B * J
- * with \f$ B = \left ( \begin{array}{cc} \text{*this.col}(p) & \text{*this.col}(q) \end{array} \right ) \f$.
- *
- * \sa class JacobiRotation, MatrixBase::applyOnTheLeft(), internal::apply_rotation_in_the_plane()
- */
-template<typename Derived>
-template<typename OtherScalar>
-inline void MatrixBase<Derived>::applyOnTheRight(Index p, Index q, const JacobiRotation<OtherScalar>& j)
-{
- ColXpr x(this->col(p));
- ColXpr y(this->col(q));
- internal::apply_rotation_in_the_plane(x, y, j.transpose());
-}
-
-namespace internal {
-template<typename VectorX, typename VectorY, typename OtherScalar>
-void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(VectorX& _x, VectorY& _y, const JacobiRotation<OtherScalar>& j)
-{
- typedef typename VectorX::Index Index;
- typedef typename VectorX::Scalar Scalar;
- enum { PacketSize = packet_traits<Scalar>::size };
- typedef typename packet_traits<Scalar>::type Packet;
- eigen_assert(_x.size() == _y.size());
- Index size = _x.size();
- Index incrx = _x.innerStride();
- Index incry = _y.innerStride();
-
- Scalar* EIGEN_RESTRICT x = &_x.coeffRef(0);
- Scalar* EIGEN_RESTRICT y = &_y.coeffRef(0);
-
- /*** dynamic-size vectorized paths ***/
-
- if(VectorX::SizeAtCompileTime == Dynamic &&
- (VectorX::Flags & VectorY::Flags & PacketAccessBit) &&
- ((incrx==1 && incry==1) || PacketSize == 1))
- {
- // both vectors are sequentially stored in memory => vectorization
- enum { Peeling = 2 };
-
- Index alignedStart = first_aligned(y, size);
- Index alignedEnd = alignedStart + ((size-alignedStart)/PacketSize)*PacketSize;
-
- const Packet pc = pset1<Packet>(j.c());
- const Packet ps = pset1<Packet>(j.s());
- conj_helper<Packet,Packet,NumTraits<Scalar>::IsComplex,false> pcj;
-
- for(Index i=0; i<alignedStart; ++i)
- {
- Scalar xi = x[i];
- Scalar yi = y[i];
- x[i] = j.c() * xi + conj(j.s()) * yi;
- y[i] = -j.s() * xi + conj(j.c()) * yi;
- }
-
- Scalar* EIGEN_RESTRICT px = x + alignedStart;
- Scalar* EIGEN_RESTRICT py = y + alignedStart;
-
- if(first_aligned(x, size)==alignedStart)
- {
- for(Index i=alignedStart; i<alignedEnd; i+=PacketSize)
- {
- Packet xi = pload<Packet>(px);
- Packet yi = pload<Packet>(py);
- pstore(px, padd(pmul(pc,xi),pcj.pmul(ps,yi)));
- pstore(py, psub(pcj.pmul(pc,yi),pmul(ps,xi)));
- px += PacketSize;
- py += PacketSize;
- }
- }
- else
- {
- Index peelingEnd = alignedStart + ((size-alignedStart)/(Peeling*PacketSize))*(Peeling*PacketSize);
- for(Index i=alignedStart; i<peelingEnd; i+=Peeling*PacketSize)
- {
- Packet xi = ploadu<Packet>(px);
- Packet xi1 = ploadu<Packet>(px+PacketSize);
- Packet yi = pload <Packet>(py);
- Packet yi1 = pload <Packet>(py+PacketSize);
- pstoreu(px, padd(pmul(pc,xi),pcj.pmul(ps,yi)));
- pstoreu(px+PacketSize, padd(pmul(pc,xi1),pcj.pmul(ps,yi1)));
- pstore (py, psub(pcj.pmul(pc,yi),pmul(ps,xi)));
- pstore (py+PacketSize, psub(pcj.pmul(pc,yi1),pmul(ps,xi1)));
- px += Peeling*PacketSize;
- py += Peeling*PacketSize;
- }
- if(alignedEnd!=peelingEnd)
- {
- Packet xi = ploadu<Packet>(x+peelingEnd);
- Packet yi = pload <Packet>(y+peelingEnd);
- pstoreu(x+peelingEnd, padd(pmul(pc,xi),pcj.pmul(ps,yi)));
- pstore (y+peelingEnd, psub(pcj.pmul(pc,yi),pmul(ps,xi)));
- }
- }
-
- for(Index i=alignedEnd; i<size; ++i)
- {
- Scalar xi = x[i];
- Scalar yi = y[i];
- x[i] = j.c() * xi + conj(j.s()) * yi;
- y[i] = -j.s() * xi + conj(j.c()) * yi;
- }
- }
-
- /*** fixed-size vectorized path ***/
- else if(VectorX::SizeAtCompileTime != Dynamic &&
- (VectorX::Flags & VectorY::Flags & PacketAccessBit) &&
- (VectorX::Flags & VectorY::Flags & AlignedBit))
- {
- const Packet pc = pset1<Packet>(j.c());
- const Packet ps = pset1<Packet>(j.s());
- conj_helper<Packet,Packet,NumTraits<Scalar>::IsComplex,false> pcj;
- Scalar* EIGEN_RESTRICT px = x;
- Scalar* EIGEN_RESTRICT py = y;
- for(Index i=0; i<size; i+=PacketSize)
- {
- Packet xi = pload<Packet>(px);
- Packet yi = pload<Packet>(py);
- pstore(px, padd(pmul(pc,xi),pcj.pmul(ps,yi)));
- pstore(py, psub(pcj.pmul(pc,yi),pmul(ps,xi)));
- px += PacketSize;
- py += PacketSize;
- }
- }
-
- /*** non-vectorized path ***/
- else
- {
- for(Index i=0; i<size; ++i)
- {
- Scalar xi = *x;
- Scalar yi = *y;
- *x = j.c() * xi + conj(j.s()) * yi;
- *y = -j.s() * xi + conj(j.c()) * yi;
- x += incrx;
- y += incry;
- }
- }
-}
-}
-
-#endif // EIGEN_JACOBI_H
diff --git a/extern/Eigen3/Eigen/src/LU/FullPivLU.h b/extern/Eigen3/Eigen/src/LU/FullPivLU.h
deleted file mode 100644
index 633fb23fdbe..00000000000
--- a/extern/Eigen3/Eigen/src/LU/FullPivLU.h
+++ /dev/null
@@ -1,754 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_LU_H
-#define EIGEN_LU_H
-
-/** \ingroup LU_Module
- *
- * \class FullPivLU
- *
- * \brief LU decomposition of a matrix with complete pivoting, and related features
- *
- * \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 decomposition provides the generic approach to solving systems of linear equations, computing
- * the rank, invertibility, inverse, kernel, and determinant.
- *
- * This LU decomposition is very stable and well tested with large matrices. However there are use cases where the SVD
- * decomposition is inherently more stable and/or flexible. For example, when computing the kernel of a matrix,
- * working with the SVD allows to select the smallest singular values of the matrix, something that
- * the LU decomposition doesn't see.
- *
- * The data of the LU decomposition can be directly accessed through the methods matrixLU(),
- * permutationP(), permutationQ().
- *
- * As an exemple, here is how the original matrix can be retrieved:
- * \include class_FullPivLU.cpp
- * Output: \verbinclude class_FullPivLU.out
- *
- * \sa MatrixBase::fullPivLu(), MatrixBase::determinant(), MatrixBase::inverse()
- */
-template<typename _MatrixType> class FullPivLU
-{
- public:
- typedef _MatrixType MatrixType;
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- Options = MatrixType::Options,
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
- };
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
- typedef typename internal::traits<MatrixType>::StorageKind StorageKind;
- typedef typename MatrixType::Index Index;
- typedef typename internal::plain_row_type<MatrixType, Index>::type IntRowVectorType;
- typedef typename internal::plain_col_type<MatrixType, Index>::type IntColVectorType;
- typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationQType;
- typedef PermutationMatrix<RowsAtCompileTime, MaxRowsAtCompileTime> PermutationPType;
-
- /**
- * \brief Default Constructor.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via LU::compute(const MatrixType&).
- */
- FullPivLU();
-
- /** \brief Default Constructor with memory preallocation
- *
- * Like the default constructor but with preallocation of the internal data
- * according to the specified problem \a size.
- * \sa FullPivLU()
- */
- FullPivLU(Index rows, Index cols);
-
- /** Constructor.
- *
- * \param matrix the matrix of which to compute the LU decomposition.
- * It is required to be nonzero.
- */
- FullPivLU(const MatrixType& matrix);
-
- /** Computes the LU decomposition of the given matrix.
- *
- * \param matrix the matrix of which to compute the LU decomposition.
- * It is required to be nonzero.
- *
- * \returns a reference to *this
- */
- FullPivLU& compute(const MatrixType& matrix);
-
- /** \returns the LU decomposition matrix: the upper-triangular part is U, the
- * unit-lower-triangular part is L (at least for square matrices; in the non-square
- * case, special care is needed, see the documentation of class FullPivLU).
- *
- * \sa matrixL(), matrixU()
- */
- inline const MatrixType& matrixLU() const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- return m_lu;
- }
-
- /** \returns the number of nonzero pivots in the LU decomposition.
- * Here nonzero is meant in the exact sense, not in a fuzzy sense.
- * So that notion isn't really intrinsically interesting, but it is
- * still useful when implementing algorithms.
- *
- * \sa rank()
- */
- inline Index nonzeroPivots() const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- return m_nonzero_pivots;
- }
-
- /** \returns the absolute value of the biggest pivot, i.e. the biggest
- * diagonal coefficient of U.
- */
- RealScalar maxPivot() const { return m_maxpivot; }
-
- /** \returns the permutation matrix P
- *
- * \sa permutationQ()
- */
- inline const PermutationPType& permutationP() const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- return m_p;
- }
-
- /** \returns the permutation matrix Q
- *
- * \sa permutationP()
- */
- inline const PermutationQType& permutationQ() const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- return m_q;
- }
-
- /** \returns the kernel of the matrix, also called its null-space. The columns of the returned matrix
- * will form a basis of the kernel.
- *
- * \note If the kernel has dimension zero, then the returned matrix is a column-vector filled with zeros.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- *
- * Example: \include FullPivLU_kernel.cpp
- * Output: \verbinclude FullPivLU_kernel.out
- *
- * \sa image()
- */
- inline const internal::kernel_retval<FullPivLU> kernel() const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- return internal::kernel_retval<FullPivLU>(*this);
- }
-
- /** \returns the image of the matrix, also called its column-space. The columns of the returned matrix
- * will form a basis of the kernel.
- *
- * \param originalMatrix the original matrix, of which *this is the LU decomposition.
- * The reason why it is needed to pass it here, is that this allows
- * a large optimization, as otherwise this method would need to reconstruct it
- * from the LU decomposition.
- *
- * \note If the image has dimension zero, then the returned matrix is a column-vector filled with zeros.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- *
- * Example: \include FullPivLU_image.cpp
- * Output: \verbinclude FullPivLU_image.out
- *
- * \sa kernel()
- */
- inline const internal::image_retval<FullPivLU>
- image(const MatrixType& originalMatrix) const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- return internal::image_retval<FullPivLU>(*this, originalMatrix);
- }
-
- /** \return a solution x to the equation Ax=b, where A is the matrix of which
- * *this is the LU decomposition.
- *
- * \param b the right-hand-side of the equation to solve. Can be a vector or a matrix,
- * the only requirement in order for the equation to make sense is that
- * b.rows()==A.rows(), where A is the matrix of which *this is the LU decomposition.
- *
- * \returns a solution.
- *
- * \note_about_checking_solutions
- *
- * \note_about_arbitrary_choice_of_solution
- * \note_about_using_kernel_to_study_multiple_solutions
- *
- * Example: \include FullPivLU_solve.cpp
- * Output: \verbinclude FullPivLU_solve.out
- *
- * \sa TriangularView::solve(), kernel(), inverse()
- */
- template<typename Rhs>
- inline const internal::solve_retval<FullPivLU, Rhs>
- solve(const MatrixBase<Rhs>& b) const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- return internal::solve_retval<FullPivLU, Rhs>(*this, b.derived());
- }
-
- /** \returns the determinant of the matrix of which
- * *this is the LU decomposition. It has only linear complexity
- * (that is, O(n) where n is the dimension of the square matrix)
- * as the LU decomposition has already been computed.
- *
- * \note This is only for square matrices.
- *
- * \note For fixed-size matrices of size up to 4, MatrixBase::determinant() offers
- * optimized paths.
- *
- * \warning a determinant can be very big or small, so for matrices
- * of large enough dimension, there is a risk of overflow/underflow.
- *
- * \sa MatrixBase::determinant()
- */
- typename internal::traits<MatrixType>::Scalar determinant() const;
-
- /** Allows to prescribe a threshold to be used by certain methods, such as rank(),
- * who need to determine when pivots are to be considered nonzero. This is not used for the
- * LU decomposition itself.
- *
- * When it needs to get the threshold value, Eigen calls threshold(). By default, this
- * uses a formula to automatically determine a reasonable threshold.
- * Once you have called the present method setThreshold(const RealScalar&),
- * your value is used instead.
- *
- * \param threshold The new value to use as the threshold.
- *
- * A pivot will be considered nonzero if its absolute value is strictly greater than
- * \f$ \vert pivot \vert \leqslant threshold \times \vert maxpivot \vert \f$
- * where maxpivot is the biggest pivot.
- *
- * If you want to come back to the default behavior, call setThreshold(Default_t)
- */
- FullPivLU& 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 lu.setThreshold(Eigen::Default); \endcode
- *
- * See the documentation of setThreshold(const RealScalar&).
- */
- FullPivLU& setThreshold(Default_t)
- {
- m_usePrescribedThreshold = false;
- }
-
- /** 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
- // this formula comes from experimenting (see "LU precision tuning" thread on the list)
- // and turns out to be identical to Higham's formula used already in LDLt.
- : NumTraits<Scalar>::epsilon() * m_lu.diagonalSize();
- }
-
- /** \returns the rank of the matrix of which *this is the LU decomposition.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline Index rank() const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- RealScalar premultiplied_threshold = internal::abs(m_maxpivot) * threshold();
- Index result = 0;
- for(Index i = 0; i < m_nonzero_pivots; ++i)
- result += (internal::abs(m_lu.coeff(i,i)) > premultiplied_threshold);
- return result;
- }
-
- /** \returns the dimension of the kernel of the matrix of which *this is the LU decomposition.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline Index dimensionOfKernel() const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- return cols() - rank();
- }
-
- /** \returns true if the matrix of which *this is the LU decomposition represents an injective
- * linear map, i.e. has trivial kernel; false otherwise.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline bool isInjective() const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- return rank() == cols();
- }
-
- /** \returns true if the matrix of which *this is the LU decomposition represents a surjective
- * linear map; false otherwise.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline bool isSurjective() const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- return rank() == rows();
- }
-
- /** \returns true if the matrix of which *this is the LU decomposition is invertible.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline bool isInvertible() const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- return isInjective() && (m_lu.rows() == m_lu.cols());
- }
-
- /** \returns the inverse of the matrix of which *this is the LU decomposition.
- *
- * \note If this matrix is not invertible, the returned matrix has undefined coefficients.
- * Use isInvertible() to first determine whether this matrix is invertible.
- *
- * \sa MatrixBase::inverse()
- */
- inline const internal::solve_retval<FullPivLU,typename MatrixType::IdentityReturnType> inverse() const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- eigen_assert(m_lu.rows() == m_lu.cols() && "You can't take the inverse of a non-square matrix!");
- return internal::solve_retval<FullPivLU,typename MatrixType::IdentityReturnType>
- (*this, MatrixType::Identity(m_lu.rows(), m_lu.cols()));
- }
-
- MatrixType reconstructedMatrix() const;
-
- inline Index rows() const { return m_lu.rows(); }
- inline Index cols() const { return m_lu.cols(); }
-
- protected:
- MatrixType m_lu;
- PermutationPType m_p;
- PermutationQType m_q;
- IntColVectorType m_rowsTranspositions;
- IntRowVectorType m_colsTranspositions;
- Index m_det_pq, m_nonzero_pivots;
- RealScalar m_maxpivot, m_prescribedThreshold;
- bool m_isInitialized, m_usePrescribedThreshold;
-};
-
-template<typename MatrixType>
-FullPivLU<MatrixType>::FullPivLU()
- : m_isInitialized(false), m_usePrescribedThreshold(false)
-{
-}
-
-template<typename MatrixType>
-FullPivLU<MatrixType>::FullPivLU(Index rows, Index cols)
- : m_lu(rows, cols),
- m_p(rows),
- m_q(cols),
- m_rowsTranspositions(rows),
- m_colsTranspositions(cols),
- m_isInitialized(false),
- m_usePrescribedThreshold(false)
-{
-}
-
-template<typename MatrixType>
-FullPivLU<MatrixType>::FullPivLU(const MatrixType& matrix)
- : m_lu(matrix.rows(), matrix.cols()),
- m_p(matrix.rows()),
- m_q(matrix.cols()),
- m_rowsTranspositions(matrix.rows()),
- m_colsTranspositions(matrix.cols()),
- m_isInitialized(false),
- m_usePrescribedThreshold(false)
-{
- compute(matrix);
-}
-
-template<typename MatrixType>
-FullPivLU<MatrixType>& FullPivLU<MatrixType>::compute(const MatrixType& matrix)
-{
- m_isInitialized = true;
- m_lu = matrix;
-
- const Index size = matrix.diagonalSize();
- const Index rows = matrix.rows();
- const Index cols = matrix.cols();
-
- // will store the transpositions, before we accumulate them at the end.
- // can't accumulate on-the-fly because that will be done in reverse order for the rows.
- m_rowsTranspositions.resize(matrix.rows());
- m_colsTranspositions.resize(matrix.cols());
- Index number_of_transpositions = 0; // number of NONTRIVIAL transpositions, i.e. m_rowsTranspositions[i]!=i
-
- m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case)
- m_maxpivot = RealScalar(0);
- RealScalar cutoff(0);
-
- for(Index k = 0; k < size; ++k)
- {
- // First, we need to find the pivot.
-
- // biggest coefficient in the remaining bottom-right corner (starting at row k, col k)
- Index row_of_biggest_in_corner, col_of_biggest_in_corner;
- RealScalar biggest_in_corner;
- biggest_in_corner = m_lu.bottomRightCorner(rows-k, cols-k)
- .cwiseAbs()
- .maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
- row_of_biggest_in_corner += k; // correct the values! since they were computed in the corner,
- col_of_biggest_in_corner += k; // need to add k to them.
-
- // when k==0, biggest_in_corner is the biggest coeff absolute value in the original matrix
- if(k == 0) cutoff = biggest_in_corner * NumTraits<Scalar>::epsilon();
-
- // if the pivot (hence the corner) is "zero", terminate to avoid generating nan/inf values.
- // Notice that using an exact comparison (biggest_in_corner==0) here, as Golub-van Loan do in
- // their pseudo-code, results in numerical instability! The cutoff here has been validated
- // by running the unit test 'lu' with many repetitions.
- if(biggest_in_corner < cutoff)
- {
- // before exiting, make sure to initialize the still uninitialized transpositions
- // in a sane state without destroying what we already have.
- m_nonzero_pivots = k;
- for(Index i = k; i < size; ++i)
- {
- m_rowsTranspositions.coeffRef(i) = i;
- m_colsTranspositions.coeffRef(i) = i;
- }
- break;
- }
-
- if(biggest_in_corner > m_maxpivot) m_maxpivot = biggest_in_corner;
-
- // Now that we've found the pivot, we need to apply the row/col swaps to
- // bring it to the location (k,k).
-
- m_rowsTranspositions.coeffRef(k) = row_of_biggest_in_corner;
- m_colsTranspositions.coeffRef(k) = col_of_biggest_in_corner;
- if(k != row_of_biggest_in_corner) {
- m_lu.row(k).swap(m_lu.row(row_of_biggest_in_corner));
- ++number_of_transpositions;
- }
- if(k != col_of_biggest_in_corner) {
- m_lu.col(k).swap(m_lu.col(col_of_biggest_in_corner));
- ++number_of_transpositions;
- }
-
- // Now that the pivot is at the right location, we update the remaining
- // bottom-right corner by Gaussian elimination.
-
- if(k<rows-1)
- m_lu.col(k).tail(rows-k-1) /= m_lu.coeff(k,k);
- if(k<size-1)
- m_lu.block(k+1,k+1,rows-k-1,cols-k-1).noalias() -= m_lu.col(k).tail(rows-k-1) * m_lu.row(k).tail(cols-k-1);
- }
-
- // the main loop is over, we still have to accumulate the transpositions to find the
- // permutations P and Q
-
- m_p.setIdentity(rows);
- for(Index k = size-1; k >= 0; --k)
- m_p.applyTranspositionOnTheRight(k, m_rowsTranspositions.coeff(k));
-
- m_q.setIdentity(cols);
- for(Index k = 0; k < size; ++k)
- m_q.applyTranspositionOnTheRight(k, m_colsTranspositions.coeff(k));
-
- m_det_pq = (number_of_transpositions%2) ? -1 : 1;
- return *this;
-}
-
-template<typename MatrixType>
-typename internal::traits<MatrixType>::Scalar FullPivLU<MatrixType>::determinant() const
-{
- eigen_assert(m_isInitialized && "LU is not initialized.");
- eigen_assert(m_lu.rows() == m_lu.cols() && "You can't take the determinant of a non-square matrix!");
- return Scalar(m_det_pq) * Scalar(m_lu.diagonal().prod());
-}
-
-/** \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. */
-template<typename MatrixType>
-MatrixType FullPivLU<MatrixType>::reconstructedMatrix() const
-{
- eigen_assert(m_isInitialized && "LU is not initialized.");
- const Index smalldim = (std::min)(m_lu.rows(), m_lu.cols());
- // LU
- MatrixType res(m_lu.rows(),m_lu.cols());
- // FIXME the .toDenseMatrix() should not be needed...
- res = m_lu.leftCols(smalldim)
- .template triangularView<UnitLower>().toDenseMatrix()
- * m_lu.topRows(smalldim)
- .template triangularView<Upper>().toDenseMatrix();
-
- // P^{-1}(LU)
- res = m_p.inverse() * res;
-
- // (P^{-1}LU)Q^{-1}
- res = res * m_q.inverse();
-
- return res;
-}
-
-/********* Implementation of kernel() **************************************************/
-
-namespace internal {
-template<typename _MatrixType>
-struct kernel_retval<FullPivLU<_MatrixType> >
- : kernel_retval_base<FullPivLU<_MatrixType> >
-{
- EIGEN_MAKE_KERNEL_HELPERS(FullPivLU<_MatrixType>)
-
- enum { MaxSmallDimAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(
- MatrixType::MaxColsAtCompileTime,
- MatrixType::MaxRowsAtCompileTime)
- };
-
- template<typename Dest> void evalTo(Dest& dst) const
- {
- const Index cols = dec().matrixLU().cols(), dimker = cols - rank();
- if(dimker == 0)
- {
- // The Kernel is just {0}, so it doesn't have a basis properly speaking, but let's
- // avoid crashing/asserting as that depends on floating point calculations. Let's
- // just return a single column vector filled with zeros.
- dst.setZero();
- return;
- }
-
- /* Let us use the following lemma:
- *
- * Lemma: If the matrix A has the LU decomposition PAQ = LU,
- * then Ker A = Q(Ker U).
- *
- * Proof: trivial: just keep in mind that P, Q, L are invertible.
- */
-
- /* Thus, all we need to do is to compute Ker U, and then apply Q.
- *
- * U is upper triangular, with eigenvalues sorted so that any zeros appear at the end.
- * Thus, the diagonal of U ends with exactly
- * dimKer zero's. Let us use that to construct dimKer linearly
- * independent vectors in Ker U.
- */
-
- Matrix<Index, Dynamic, 1, 0, MaxSmallDimAtCompileTime, 1> pivots(rank());
- RealScalar premultiplied_threshold = dec().maxPivot() * dec().threshold();
- Index p = 0;
- for(Index i = 0; i < dec().nonzeroPivots(); ++i)
- if(abs(dec().matrixLU().coeff(i,i)) > premultiplied_threshold)
- pivots.coeffRef(p++) = i;
- eigen_internal_assert(p == rank());
-
- // we construct a temporaty trapezoid matrix m, by taking the U matrix and
- // permuting the rows and cols to bring the nonnegligible pivots to the top of
- // the main diagonal. We need that to be able to apply our triangular solvers.
- // FIXME when we get triangularView-for-rectangular-matrices, this can be simplified
- Matrix<typename MatrixType::Scalar, Dynamic, Dynamic, MatrixType::Options,
- MaxSmallDimAtCompileTime, MatrixType::MaxColsAtCompileTime>
- m(dec().matrixLU().block(0, 0, rank(), cols));
- for(Index i = 0; i < rank(); ++i)
- {
- if(i) m.row(i).head(i).setZero();
- m.row(i).tail(cols-i) = dec().matrixLU().row(pivots.coeff(i)).tail(cols-i);
- }
- m.block(0, 0, rank(), rank());
- m.block(0, 0, rank(), rank()).template triangularView<StrictlyLower>().setZero();
- for(Index i = 0; i < rank(); ++i)
- m.col(i).swap(m.col(pivots.coeff(i)));
-
- // ok, we have our trapezoid matrix, we can apply the triangular solver.
- // notice that the math behind this suggests that we should apply this to the
- // negative of the RHS, but for performance we just put the negative sign elsewhere, see below.
- m.topLeftCorner(rank(), rank())
- .template triangularView<Upper>().solveInPlace(
- m.topRightCorner(rank(), dimker)
- );
-
- // now we must undo the column permutation that we had applied!
- for(Index i = rank()-1; i >= 0; --i)
- m.col(i).swap(m.col(pivots.coeff(i)));
-
- // see the negative sign in the next line, that's what we were talking about above.
- for(Index i = 0; i < rank(); ++i) dst.row(dec().permutationQ().indices().coeff(i)) = -m.row(i).tail(dimker);
- for(Index i = rank(); i < cols; ++i) dst.row(dec().permutationQ().indices().coeff(i)).setZero();
- for(Index k = 0; k < dimker; ++k) dst.coeffRef(dec().permutationQ().indices().coeff(rank()+k), k) = Scalar(1);
- }
-};
-
-/***** Implementation of image() *****************************************************/
-
-template<typename _MatrixType>
-struct image_retval<FullPivLU<_MatrixType> >
- : image_retval_base<FullPivLU<_MatrixType> >
-{
- EIGEN_MAKE_IMAGE_HELPERS(FullPivLU<_MatrixType>)
-
- enum { MaxSmallDimAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(
- MatrixType::MaxColsAtCompileTime,
- MatrixType::MaxRowsAtCompileTime)
- };
-
- template<typename Dest> void evalTo(Dest& dst) const
- {
- if(rank() == 0)
- {
- // The Image is just {0}, so it doesn't have a basis properly speaking, but let's
- // avoid crashing/asserting as that depends on floating point calculations. Let's
- // just return a single column vector filled with zeros.
- dst.setZero();
- return;
- }
-
- Matrix<Index, Dynamic, 1, 0, MaxSmallDimAtCompileTime, 1> pivots(rank());
- RealScalar premultiplied_threshold = dec().maxPivot() * dec().threshold();
- Index p = 0;
- for(Index i = 0; i < dec().nonzeroPivots(); ++i)
- if(abs(dec().matrixLU().coeff(i,i)) > premultiplied_threshold)
- pivots.coeffRef(p++) = i;
- eigen_internal_assert(p == rank());
-
- for(Index i = 0; i < rank(); ++i)
- dst.col(i) = originalMatrix().col(dec().permutationQ().indices().coeff(pivots.coeff(i)));
- }
-};
-
-/***** Implementation of solve() *****************************************************/
-
-template<typename _MatrixType, typename Rhs>
-struct solve_retval<FullPivLU<_MatrixType>, Rhs>
- : solve_retval_base<FullPivLU<_MatrixType>, Rhs>
-{
- EIGEN_MAKE_SOLVE_HELPERS(FullPivLU<_MatrixType>,Rhs)
-
- template<typename Dest> void evalTo(Dest& dst) const
- {
- /* The decomposition PAQ = LU can be rewritten as A = P^{-1} L U Q^{-1}.
- * So we proceed as follows:
- * Step 1: compute c = P * rhs.
- * Step 2: replace c by the solution x to Lx = c. Exists because L is invertible.
- * Step 3: replace c by the solution x to Ux = c. May or may not exist.
- * Step 4: result = Q * c;
- */
-
- const Index rows = dec().rows(), cols = dec().cols(),
- nonzero_pivots = dec().nonzeroPivots();
- eigen_assert(rhs().rows() == rows);
- const Index smalldim = (std::min)(rows, cols);
-
- if(nonzero_pivots == 0)
- {
- dst.setZero();
- return;
- }
-
- typename Rhs::PlainObject c(rhs().rows(), rhs().cols());
-
- // Step 1
- c = dec().permutationP() * rhs();
-
- // Step 2
- dec().matrixLU()
- .topLeftCorner(smalldim,smalldim)
- .template triangularView<UnitLower>()
- .solveInPlace(c.topRows(smalldim));
- if(rows>cols)
- {
- c.bottomRows(rows-cols)
- -= dec().matrixLU().bottomRows(rows-cols)
- * c.topRows(cols);
- }
-
- // Step 3
- dec().matrixLU()
- .topLeftCorner(nonzero_pivots, nonzero_pivots)
- .template triangularView<Upper>()
- .solveInPlace(c.topRows(nonzero_pivots));
-
- // Step 4
- for(Index i = 0; i < nonzero_pivots; ++i)
- dst.row(dec().permutationQ().indices().coeff(i)) = c.row(i);
- for(Index i = nonzero_pivots; i < dec().matrixLU().cols(); ++i)
- dst.row(dec().permutationQ().indices().coeff(i)).setZero();
- }
-};
-
-} // end namespace internal
-
-/******* MatrixBase methods *****************************************************************/
-
-/** \lu_module
- *
- * \return the full-pivoting LU decomposition of \c *this.
- *
- * \sa class FullPivLU
- */
-template<typename Derived>
-inline const FullPivLU<typename MatrixBase<Derived>::PlainObject>
-MatrixBase<Derived>::fullPivLu() const
-{
- return FullPivLU<PlainObject>(eval());
-}
-
-#endif // EIGEN_LU_H
diff --git a/extern/Eigen3/Eigen/src/LU/Inverse.h b/extern/Eigen3/Eigen/src/LU/Inverse.h
deleted file mode 100644
index 2d3e6d10529..00000000000
--- a/extern/Eigen3/Eigen/src/LU/Inverse.h
+++ /dev/null
@@ -1,407 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_INVERSE_H
-#define EIGEN_INVERSE_H
-
-namespace internal {
-
-/**********************************
-*** General case implementation ***
-**********************************/
-
-template<typename MatrixType, typename ResultType, int Size = MatrixType::RowsAtCompileTime>
-struct compute_inverse
-{
- static inline void run(const MatrixType& matrix, ResultType& result)
- {
- result = matrix.partialPivLu().inverse();
- }
-};
-
-template<typename MatrixType, typename ResultType, int Size = MatrixType::RowsAtCompileTime>
-struct compute_inverse_and_det_with_check { /* nothing! general case not supported. */ };
-
-/****************************
-*** Size 1 implementation ***
-****************************/
-
-template<typename MatrixType, typename ResultType>
-struct compute_inverse<MatrixType, ResultType, 1>
-{
- static inline void run(const MatrixType& matrix, ResultType& result)
- {
- typedef typename MatrixType::Scalar Scalar;
- result.coeffRef(0,0) = Scalar(1) / matrix.coeff(0,0);
- }
-};
-
-template<typename MatrixType, typename ResultType>
-struct compute_inverse_and_det_with_check<MatrixType, ResultType, 1>
-{
- static inline void run(
- const MatrixType& matrix,
- const typename MatrixType::RealScalar& absDeterminantThreshold,
- ResultType& result,
- typename ResultType::Scalar& determinant,
- bool& invertible
- )
- {
- determinant = matrix.coeff(0,0);
- invertible = abs(determinant) > absDeterminantThreshold;
- if(invertible) result.coeffRef(0,0) = typename ResultType::Scalar(1) / determinant;
- }
-};
-
-/****************************
-*** Size 2 implementation ***
-****************************/
-
-template<typename MatrixType, typename ResultType>
-inline void compute_inverse_size2_helper(
- const MatrixType& matrix, const typename ResultType::Scalar& invdet,
- ResultType& result)
-{
- result.coeffRef(0,0) = matrix.coeff(1,1) * invdet;
- result.coeffRef(1,0) = -matrix.coeff(1,0) * invdet;
- result.coeffRef(0,1) = -matrix.coeff(0,1) * invdet;
- result.coeffRef(1,1) = matrix.coeff(0,0) * invdet;
-}
-
-template<typename MatrixType, typename ResultType>
-struct compute_inverse<MatrixType, ResultType, 2>
-{
- static inline void run(const MatrixType& matrix, ResultType& result)
- {
- typedef typename ResultType::Scalar Scalar;
- const Scalar invdet = typename MatrixType::Scalar(1) / matrix.determinant();
- compute_inverse_size2_helper(matrix, invdet, result);
- }
-};
-
-template<typename MatrixType, typename ResultType>
-struct compute_inverse_and_det_with_check<MatrixType, ResultType, 2>
-{
- static inline void run(
- const MatrixType& matrix,
- const typename MatrixType::RealScalar& absDeterminantThreshold,
- ResultType& inverse,
- typename ResultType::Scalar& determinant,
- bool& invertible
- )
- {
- typedef typename ResultType::Scalar Scalar;
- determinant = matrix.determinant();
- invertible = abs(determinant) > absDeterminantThreshold;
- if(!invertible) return;
- const Scalar invdet = Scalar(1) / determinant;
- compute_inverse_size2_helper(matrix, invdet, inverse);
- }
-};
-
-/****************************
-*** Size 3 implementation ***
-****************************/
-
-template<typename MatrixType, int i, int j>
-inline typename MatrixType::Scalar cofactor_3x3(const MatrixType& m)
-{
- enum {
- i1 = (i+1) % 3,
- i2 = (i+2) % 3,
- j1 = (j+1) % 3,
- j2 = (j+2) % 3
- };
- return m.coeff(i1, j1) * m.coeff(i2, j2)
- - m.coeff(i1, j2) * m.coeff(i2, j1);
-}
-
-template<typename MatrixType, typename ResultType>
-inline void compute_inverse_size3_helper(
- const MatrixType& matrix,
- const typename ResultType::Scalar& invdet,
- const Matrix<typename ResultType::Scalar,3,1>& cofactors_col0,
- ResultType& result)
-{
- result.row(0) = cofactors_col0 * invdet;
- result.coeffRef(1,0) = cofactor_3x3<MatrixType,0,1>(matrix) * invdet;
- result.coeffRef(1,1) = cofactor_3x3<MatrixType,1,1>(matrix) * invdet;
- result.coeffRef(1,2) = cofactor_3x3<MatrixType,2,1>(matrix) * invdet;
- result.coeffRef(2,0) = cofactor_3x3<MatrixType,0,2>(matrix) * invdet;
- result.coeffRef(2,1) = cofactor_3x3<MatrixType,1,2>(matrix) * invdet;
- result.coeffRef(2,2) = cofactor_3x3<MatrixType,2,2>(matrix) * invdet;
-}
-
-template<typename MatrixType, typename ResultType>
-struct compute_inverse<MatrixType, ResultType, 3>
-{
- static inline void run(const MatrixType& matrix, ResultType& result)
- {
- typedef typename ResultType::Scalar Scalar;
- Matrix<typename MatrixType::Scalar,3,1> cofactors_col0;
- cofactors_col0.coeffRef(0) = cofactor_3x3<MatrixType,0,0>(matrix);
- cofactors_col0.coeffRef(1) = cofactor_3x3<MatrixType,1,0>(matrix);
- cofactors_col0.coeffRef(2) = cofactor_3x3<MatrixType,2,0>(matrix);
- const Scalar det = (cofactors_col0.cwiseProduct(matrix.col(0))).sum();
- const Scalar invdet = Scalar(1) / det;
- compute_inverse_size3_helper(matrix, invdet, cofactors_col0, result);
- }
-};
-
-template<typename MatrixType, typename ResultType>
-struct compute_inverse_and_det_with_check<MatrixType, ResultType, 3>
-{
- static inline void run(
- const MatrixType& matrix,
- const typename MatrixType::RealScalar& absDeterminantThreshold,
- ResultType& inverse,
- typename ResultType::Scalar& determinant,
- bool& invertible
- )
- {
- typedef typename ResultType::Scalar Scalar;
- Matrix<Scalar,3,1> cofactors_col0;
- cofactors_col0.coeffRef(0) = cofactor_3x3<MatrixType,0,0>(matrix);
- cofactors_col0.coeffRef(1) = cofactor_3x3<MatrixType,1,0>(matrix);
- cofactors_col0.coeffRef(2) = cofactor_3x3<MatrixType,2,0>(matrix);
- determinant = (cofactors_col0.cwiseProduct(matrix.col(0))).sum();
- invertible = abs(determinant) > absDeterminantThreshold;
- if(!invertible) return;
- const Scalar invdet = Scalar(1) / determinant;
- compute_inverse_size3_helper(matrix, invdet, cofactors_col0, inverse);
- }
-};
-
-/****************************
-*** Size 4 implementation ***
-****************************/
-
-template<typename Derived>
-inline const typename Derived::Scalar general_det3_helper
-(const MatrixBase<Derived>& matrix, int i1, int i2, int i3, int j1, int j2, int j3)
-{
- return matrix.coeff(i1,j1)
- * (matrix.coeff(i2,j2) * matrix.coeff(i3,j3) - matrix.coeff(i2,j3) * matrix.coeff(i3,j2));
-}
-
-template<typename MatrixType, int i, int j>
-inline typename MatrixType::Scalar cofactor_4x4(const MatrixType& matrix)
-{
- enum {
- i1 = (i+1) % 4,
- i2 = (i+2) % 4,
- i3 = (i+3) % 4,
- j1 = (j+1) % 4,
- j2 = (j+2) % 4,
- j3 = (j+3) % 4
- };
- return general_det3_helper(matrix, i1, i2, i3, j1, j2, j3)
- + general_det3_helper(matrix, i2, i3, i1, j1, j2, j3)
- + general_det3_helper(matrix, i3, i1, i2, j1, j2, j3);
-}
-
-template<int Arch, typename Scalar, typename MatrixType, typename ResultType>
-struct compute_inverse_size4
-{
- static void run(const MatrixType& matrix, ResultType& result)
- {
- result.coeffRef(0,0) = cofactor_4x4<MatrixType,0,0>(matrix);
- result.coeffRef(1,0) = -cofactor_4x4<MatrixType,0,1>(matrix);
- result.coeffRef(2,0) = cofactor_4x4<MatrixType,0,2>(matrix);
- result.coeffRef(3,0) = -cofactor_4x4<MatrixType,0,3>(matrix);
- result.coeffRef(0,2) = cofactor_4x4<MatrixType,2,0>(matrix);
- result.coeffRef(1,2) = -cofactor_4x4<MatrixType,2,1>(matrix);
- result.coeffRef(2,2) = cofactor_4x4<MatrixType,2,2>(matrix);
- result.coeffRef(3,2) = -cofactor_4x4<MatrixType,2,3>(matrix);
- result.coeffRef(0,1) = -cofactor_4x4<MatrixType,1,0>(matrix);
- result.coeffRef(1,1) = cofactor_4x4<MatrixType,1,1>(matrix);
- result.coeffRef(2,1) = -cofactor_4x4<MatrixType,1,2>(matrix);
- result.coeffRef(3,1) = cofactor_4x4<MatrixType,1,3>(matrix);
- result.coeffRef(0,3) = -cofactor_4x4<MatrixType,3,0>(matrix);
- result.coeffRef(1,3) = cofactor_4x4<MatrixType,3,1>(matrix);
- result.coeffRef(2,3) = -cofactor_4x4<MatrixType,3,2>(matrix);
- result.coeffRef(3,3) = cofactor_4x4<MatrixType,3,3>(matrix);
- result /= (matrix.col(0).cwiseProduct(result.row(0).transpose())).sum();
- }
-};
-
-template<typename MatrixType, typename ResultType>
-struct compute_inverse<MatrixType, ResultType, 4>
- : compute_inverse_size4<Architecture::Target, typename MatrixType::Scalar,
- MatrixType, ResultType>
-{
-};
-
-template<typename MatrixType, typename ResultType>
-struct compute_inverse_and_det_with_check<MatrixType, ResultType, 4>
-{
- static inline void run(
- const MatrixType& matrix,
- const typename MatrixType::RealScalar& absDeterminantThreshold,
- ResultType& inverse,
- typename ResultType::Scalar& determinant,
- bool& invertible
- )
- {
- determinant = matrix.determinant();
- invertible = abs(determinant) > absDeterminantThreshold;
- if(invertible) compute_inverse<MatrixType, ResultType>::run(matrix, inverse);
- }
-};
-
-/*************************
-*** MatrixBase methods ***
-*************************/
-
-template<typename MatrixType>
-struct traits<inverse_impl<MatrixType> >
-{
- typedef typename MatrixType::PlainObject ReturnType;
-};
-
-template<typename MatrixType>
-struct inverse_impl : public ReturnByValue<inverse_impl<MatrixType> >
-{
- typedef typename MatrixType::Index Index;
- typedef typename internal::eval<MatrixType>::type MatrixTypeNested;
- typedef typename remove_all<MatrixTypeNested>::type MatrixTypeNestedCleaned;
- const MatrixTypeNested m_matrix;
-
- inverse_impl(const MatrixType& matrix)
- : m_matrix(matrix)
- {}
-
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
-
- template<typename Dest> inline void evalTo(Dest& dst) const
- {
- const int Size = EIGEN_PLAIN_ENUM_MIN(MatrixType::ColsAtCompileTime,Dest::ColsAtCompileTime);
- EIGEN_ONLY_USED_FOR_DEBUG(Size);
- eigen_assert(( (Size<=1) || (Size>4) || (extract_data(m_matrix)!=extract_data(dst)))
- && "Aliasing problem detected in inverse(), you need to do inverse().eval() here.");
-
- compute_inverse<MatrixTypeNestedCleaned, Dest>::run(m_matrix, dst);
- }
-};
-
-} // end namespace internal
-
-/** \lu_module
- *
- * \returns the matrix inverse of this matrix.
- *
- * For small fixed sizes up to 4x4, this method uses cofactors.
- * In the general case, this method uses class PartialPivLU.
- *
- * \note This matrix must be invertible, otherwise the result is undefined. If you need an
- * invertibility check, do the following:
- * \li for fixed sizes up to 4x4, use computeInverseAndDetWithCheck().
- * \li for the general case, use class FullPivLU.
- *
- * Example: \include MatrixBase_inverse.cpp
- * Output: \verbinclude MatrixBase_inverse.out
- *
- * \sa computeInverseAndDetWithCheck()
- */
-template<typename Derived>
-inline const internal::inverse_impl<Derived> MatrixBase<Derived>::inverse() const
-{
- EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsInteger,THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES)
- eigen_assert(rows() == cols());
- return internal::inverse_impl<Derived>(derived());
-}
-
-/** \lu_module
- *
- * Computation of matrix inverse and determinant, with invertibility check.
- *
- * This is only for fixed-size square matrices of size up to 4x4.
- *
- * \param inverse Reference to the matrix in which to store the inverse.
- * \param determinant Reference to the variable in which to store the inverse.
- * \param invertible Reference to the bool variable in which to store whether the matrix is invertible.
- * \param absDeterminantThreshold Optional parameter controlling the invertibility check.
- * The matrix will be declared invertible if the absolute value of its
- * determinant is greater than this threshold.
- *
- * Example: \include MatrixBase_computeInverseAndDetWithCheck.cpp
- * Output: \verbinclude MatrixBase_computeInverseAndDetWithCheck.out
- *
- * \sa inverse(), computeInverseWithCheck()
- */
-template<typename Derived>
-template<typename ResultType>
-inline void MatrixBase<Derived>::computeInverseAndDetWithCheck(
- ResultType& inverse,
- typename ResultType::Scalar& determinant,
- bool& invertible,
- const RealScalar& absDeterminantThreshold
- ) const
-{
- // i'd love to put some static assertions there, but SFINAE means that they have no effect...
- eigen_assert(rows() == cols());
- // for 2x2, it's worth giving a chance to avoid evaluating.
- // for larger sizes, evaluating has negligible cost and limits code size.
- typedef typename internal::conditional<
- RowsAtCompileTime == 2,
- typename internal::remove_all<typename internal::nested<Derived, 2>::type>::type,
- PlainObject
- >::type MatrixType;
- internal::compute_inverse_and_det_with_check<MatrixType, ResultType>::run
- (derived(), absDeterminantThreshold, inverse, determinant, invertible);
-}
-
-/** \lu_module
- *
- * Computation of matrix inverse, with invertibility check.
- *
- * This is only for fixed-size square matrices of size up to 4x4.
- *
- * \param inverse Reference to the matrix in which to store the inverse.
- * \param invertible Reference to the bool variable in which to store whether the matrix is invertible.
- * \param absDeterminantThreshold Optional parameter controlling the invertibility check.
- * The matrix will be declared invertible if the absolute value of its
- * determinant is greater than this threshold.
- *
- * Example: \include MatrixBase_computeInverseWithCheck.cpp
- * Output: \verbinclude MatrixBase_computeInverseWithCheck.out
- *
- * \sa inverse(), computeInverseAndDetWithCheck()
- */
-template<typename Derived>
-template<typename ResultType>
-inline void MatrixBase<Derived>::computeInverseWithCheck(
- ResultType& inverse,
- bool& invertible,
- const RealScalar& absDeterminantThreshold
- ) const
-{
- RealScalar determinant;
- // i'd love to put some static assertions there, but SFINAE means that they have no effect...
- eigen_assert(rows() == cols());
- computeInverseAndDetWithCheck(inverse,determinant,invertible,absDeterminantThreshold);
-}
-
-#endif // EIGEN_INVERSE_H
diff --git a/extern/Eigen3/Eigen/src/LU/PartialPivLU.h b/extern/Eigen3/Eigen/src/LU/PartialPivLU.h
deleted file mode 100644
index 09394b01f5b..00000000000
--- a/extern/Eigen3/Eigen/src/LU/PartialPivLU.h
+++ /dev/null
@@ -1,509 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_PARTIALLU_H
-#define EIGEN_PARTIALLU_H
-
-/** \ingroup LU_Module
- *
- * \class PartialPivLU
- *
- * \brief LU decomposition of a matrix with partial pivoting, and related features
- *
- * \param MatrixType the type of the matrix of which we are computing the LU decomposition
- *
- * This class represents a LU decomposition of a \b square \b invertible matrix, with partial pivoting: the matrix A
- * is decomposed as A = PLU where L is unit-lower-triangular, U is upper-triangular, and P
- * is a permutation matrix.
- *
- * Typically, partial pivoting LU decomposition is only considered numerically stable for square invertible
- * matrices. Thus LAPACK's dgesv and dgesvx require the matrix to be square and invertible. The present class
- * does the same. It will assert that the matrix is square, but it won't (actually it can't) check that the
- * matrix is invertible: it is your task to check that you only use this decomposition on invertible matrices.
- *
- * The guaranteed safe alternative, working for all matrices, is the full pivoting LU decomposition, provided
- * by class FullPivLU.
- *
- * This is \b not a rank-revealing LU decomposition. Many features are intentionally absent from this class,
- * such as rank computation. If you need these features, use class FullPivLU.
- *
- * This LU decomposition is suitable to invert invertible matrices. It is what MatrixBase::inverse() uses
- * in the general case.
- * On the other hand, it is \b not suitable to determine whether a given matrix is invertible.
- *
- * The data of the LU decomposition can be directly accessed through the methods matrixLU(), permutationP().
- *
- * \sa MatrixBase::partialPivLu(), MatrixBase::determinant(), MatrixBase::inverse(), MatrixBase::computeInverse(), class FullPivLU
- */
-template<typename _MatrixType> class PartialPivLU
-{
- public:
-
- typedef _MatrixType MatrixType;
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- Options = MatrixType::Options,
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
- };
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
- typedef typename internal::traits<MatrixType>::StorageKind StorageKind;
- typedef typename MatrixType::Index Index;
- typedef PermutationMatrix<RowsAtCompileTime, MaxRowsAtCompileTime> PermutationType;
- typedef Transpositions<RowsAtCompileTime, MaxRowsAtCompileTime> TranspositionType;
-
-
- /**
- * \brief Default Constructor.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via PartialPivLU::compute(const MatrixType&).
- */
- PartialPivLU();
-
- /** \brief Default Constructor with memory preallocation
- *
- * Like the default constructor but with preallocation of the internal data
- * according to the specified problem \a size.
- * \sa PartialPivLU()
- */
- PartialPivLU(Index size);
-
- /** Constructor.
- *
- * \param matrix the matrix of which to compute the LU decomposition.
- *
- * \warning The matrix should have full rank (e.g. if it's square, it should be invertible).
- * If you need to deal with non-full rank, use class FullPivLU instead.
- */
- PartialPivLU(const MatrixType& matrix);
-
- PartialPivLU& compute(const MatrixType& matrix);
-
- /** \returns the LU decomposition matrix: the upper-triangular part is U, the
- * unit-lower-triangular part is L (at least for square matrices; in the non-square
- * case, special care is needed, see the documentation of class FullPivLU).
- *
- * \sa matrixL(), matrixU()
- */
- inline const MatrixType& matrixLU() const
- {
- eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
- return m_lu;
- }
-
- /** \returns the permutation matrix P.
- */
- inline const PermutationType& permutationP() const
- {
- eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
- return m_p;
- }
-
- /** This method returns the solution x to the equation Ax=b, where A is the matrix of which
- * *this is the LU decomposition.
- *
- * \param b the right-hand-side of the equation to solve. Can be a vector or a matrix,
- * the only requirement in order for the equation to make sense is that
- * b.rows()==A.rows(), where A is the matrix of which *this is the LU decomposition.
- *
- * \returns the solution.
- *
- * Example: \include PartialPivLU_solve.cpp
- * Output: \verbinclude PartialPivLU_solve.out
- *
- * Since this PartialPivLU class assumes anyway that the matrix A is invertible, the solution
- * theoretically exists and is unique regardless of b.
- *
- * \sa TriangularView::solve(), inverse(), computeInverse()
- */
- template<typename Rhs>
- inline const internal::solve_retval<PartialPivLU, Rhs>
- solve(const MatrixBase<Rhs>& b) const
- {
- eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
- return internal::solve_retval<PartialPivLU, Rhs>(*this, b.derived());
- }
-
- /** \returns the inverse of the matrix of which *this is the LU decomposition.
- *
- * \warning The matrix being decomposed here is assumed to be invertible. If you need to check for
- * invertibility, use class FullPivLU instead.
- *
- * \sa MatrixBase::inverse(), LU::inverse()
- */
- inline const internal::solve_retval<PartialPivLU,typename MatrixType::IdentityReturnType> inverse() const
- {
- eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
- return internal::solve_retval<PartialPivLU,typename MatrixType::IdentityReturnType>
- (*this, MatrixType::Identity(m_lu.rows(), m_lu.cols()));
- }
-
- /** \returns the determinant of the matrix of which
- * *this is the LU decomposition. It has only linear complexity
- * (that is, O(n) where n is the dimension of the square matrix)
- * as the LU decomposition has already been computed.
- *
- * \note For fixed-size matrices of size up to 4, MatrixBase::determinant() offers
- * optimized paths.
- *
- * \warning a determinant can be very big or small, so for matrices
- * of large enough dimension, there is a risk of overflow/underflow.
- *
- * \sa MatrixBase::determinant()
- */
- typename internal::traits<MatrixType>::Scalar determinant() const;
-
- MatrixType reconstructedMatrix() const;
-
- inline Index rows() const { return m_lu.rows(); }
- inline Index cols() const { return m_lu.cols(); }
-
- protected:
- MatrixType m_lu;
- PermutationType m_p;
- TranspositionType m_rowsTranspositions;
- Index m_det_p;
- bool m_isInitialized;
-};
-
-template<typename MatrixType>
-PartialPivLU<MatrixType>::PartialPivLU()
- : m_lu(),
- m_p(),
- m_rowsTranspositions(),
- m_det_p(0),
- m_isInitialized(false)
-{
-}
-
-template<typename MatrixType>
-PartialPivLU<MatrixType>::PartialPivLU(Index size)
- : m_lu(size, size),
- m_p(size),
- m_rowsTranspositions(size),
- m_det_p(0),
- m_isInitialized(false)
-{
-}
-
-template<typename MatrixType>
-PartialPivLU<MatrixType>::PartialPivLU(const MatrixType& matrix)
- : m_lu(matrix.rows(), matrix.rows()),
- m_p(matrix.rows()),
- m_rowsTranspositions(matrix.rows()),
- m_det_p(0),
- m_isInitialized(false)
-{
- compute(matrix);
-}
-
-namespace internal {
-
-/** \internal This is the blocked version of fullpivlu_unblocked() */
-template<typename Scalar, int StorageOrder, typename PivIndex>
-struct partial_lu_impl
-{
- // FIXME add a stride to Map, so that the following mapping becomes easier,
- // another option would be to create an expression being able to automatically
- // warp any Map, Matrix, and Block expressions as a unique type, but since that's exactly
- // a Map + stride, why not adding a stride to Map, and convenient ctors from a Matrix,
- // and Block.
- typedef Map<Matrix<Scalar, Dynamic, Dynamic, StorageOrder> > MapLU;
- typedef Block<MapLU, Dynamic, Dynamic> MatrixType;
- typedef Block<MatrixType,Dynamic,Dynamic> BlockType;
- typedef typename MatrixType::RealScalar RealScalar;
- typedef typename MatrixType::Index Index;
-
- /** \internal performs the LU decomposition in-place of the matrix \a lu
- * using an unblocked algorithm.
- *
- * In addition, this function returns the row transpositions in the
- * vector \a row_transpositions which must have a size equal to the number
- * of columns of the matrix \a lu, and an integer \a nb_transpositions
- * which returns the actual number of transpositions.
- *
- * \returns The index of the first pivot which is exactly zero if any, or a negative number otherwise.
- */
- static Index unblocked_lu(MatrixType& lu, PivIndex* row_transpositions, PivIndex& nb_transpositions)
- {
- const Index rows = lu.rows();
- const Index cols = lu.cols();
- const Index size = (std::min)(rows,cols);
- nb_transpositions = 0;
- int first_zero_pivot = -1;
- for(Index k = 0; k < size; ++k)
- {
- Index rrows = rows-k-1;
- Index rcols = cols-k-1;
-
- Index row_of_biggest_in_col;
- RealScalar biggest_in_corner
- = lu.col(k).tail(rows-k).cwiseAbs().maxCoeff(&row_of_biggest_in_col);
- row_of_biggest_in_col += k;
-
- row_transpositions[k] = row_of_biggest_in_col;
-
- if(biggest_in_corner != RealScalar(0))
- {
- if(k != row_of_biggest_in_col)
- {
- lu.row(k).swap(lu.row(row_of_biggest_in_col));
- ++nb_transpositions;
- }
-
- // FIXME shall we introduce a safe quotient expression in cas 1/lu.coeff(k,k)
- // overflow but not the actual quotient?
- lu.col(k).tail(rrows) /= lu.coeff(k,k);
- }
- else if(first_zero_pivot==-1)
- {
- // the pivot is exactly zero, we record the index of the first pivot which is exactly 0,
- // and continue the factorization such we still have A = PLU
- first_zero_pivot = k;
- }
-
- if(k<rows-1)
- lu.bottomRightCorner(rrows,rcols).noalias() -= lu.col(k).tail(rrows) * lu.row(k).tail(rcols);
- }
- return first_zero_pivot;
- }
-
- /** \internal performs the LU decomposition in-place of the matrix represented
- * by the variables \a rows, \a cols, \a lu_data, and \a lu_stride using a
- * recursive, blocked algorithm.
- *
- * In addition, this function returns the row transpositions in the
- * vector \a row_transpositions which must have a size equal to the number
- * of columns of the matrix \a lu, and an integer \a nb_transpositions
- * which returns the actual number of transpositions.
- *
- * \returns The index of the first pivot which is exactly zero if any, or a negative number otherwise.
- *
- * \note This very low level interface using pointers, etc. is to:
- * 1 - reduce the number of instanciations to the strict minimum
- * 2 - avoid infinite recursion of the instanciations with Block<Block<Block<...> > >
- */
- static Index blocked_lu(Index rows, Index cols, Scalar* lu_data, Index luStride, PivIndex* row_transpositions, PivIndex& nb_transpositions, Index maxBlockSize=256)
- {
- MapLU lu1(lu_data,StorageOrder==RowMajor?rows:luStride,StorageOrder==RowMajor?luStride:cols);
- MatrixType lu(lu1,0,0,rows,cols);
-
- const Index size = (std::min)(rows,cols);
-
- // if the matrix is too small, no blocking:
- if(size<=16)
- {
- return unblocked_lu(lu, row_transpositions, nb_transpositions);
- }
-
- // automatically adjust the number of subdivisions to the size
- // of the matrix so that there is enough sub blocks:
- Index blockSize;
- {
- blockSize = size/8;
- blockSize = (blockSize/16)*16;
- blockSize = (std::min)((std::max)(blockSize,Index(8)), maxBlockSize);
- }
-
- nb_transpositions = 0;
- int first_zero_pivot = -1;
- for(Index k = 0; k < size; k+=blockSize)
- {
- Index bs = (std::min)(size-k,blockSize); // actual size of the block
- Index trows = rows - k - bs; // trailing rows
- Index tsize = size - k - bs; // trailing size
-
- // partition the matrix:
- // A00 | A01 | A02
- // lu = A_0 | A_1 | A_2 = A10 | A11 | A12
- // A20 | A21 | A22
- BlockType A_0(lu,0,0,rows,k);
- BlockType A_2(lu,0,k+bs,rows,tsize);
- BlockType A11(lu,k,k,bs,bs);
- BlockType A12(lu,k,k+bs,bs,tsize);
- BlockType A21(lu,k+bs,k,trows,bs);
- BlockType A22(lu,k+bs,k+bs,trows,tsize);
-
- PivIndex nb_transpositions_in_panel;
- // recursively call the blocked LU algorithm on [A11^T A21^T]^T
- // with a very small blocking size:
- Index ret = blocked_lu(trows+bs, bs, &lu.coeffRef(k,k), luStride,
- row_transpositions+k, nb_transpositions_in_panel, 16);
- if(ret>=0 && first_zero_pivot==-1)
- first_zero_pivot = k+ret;
-
- nb_transpositions += nb_transpositions_in_panel;
- // update permutations and apply them to A_0
- for(Index i=k; i<k+bs; ++i)
- {
- Index piv = (row_transpositions[i] += k);
- A_0.row(i).swap(A_0.row(piv));
- }
-
- if(trows)
- {
- // apply permutations to A_2
- for(Index i=k;i<k+bs; ++i)
- A_2.row(i).swap(A_2.row(row_transpositions[i]));
-
- // A12 = A11^-1 A12
- A11.template triangularView<UnitLower>().solveInPlace(A12);
-
- A22.noalias() -= A21 * A12;
- }
- }
- return first_zero_pivot;
- }
-};
-
-/** \internal performs the LU decomposition with partial pivoting in-place.
- */
-template<typename MatrixType, typename TranspositionType>
-void partial_lu_inplace(MatrixType& lu, TranspositionType& row_transpositions, typename TranspositionType::Index& nb_transpositions)
-{
- eigen_assert(lu.cols() == row_transpositions.size());
- eigen_assert((&row_transpositions.coeffRef(1)-&row_transpositions.coeffRef(0)) == 1);
-
- partial_lu_impl
- <typename MatrixType::Scalar, MatrixType::Flags&RowMajorBit?RowMajor:ColMajor, typename TranspositionType::Index>
- ::blocked_lu(lu.rows(), lu.cols(), &lu.coeffRef(0,0), lu.outerStride(), &row_transpositions.coeffRef(0), nb_transpositions);
-}
-
-} // end namespace internal
-
-template<typename MatrixType>
-PartialPivLU<MatrixType>& PartialPivLU<MatrixType>::compute(const MatrixType& matrix)
-{
- m_lu = matrix;
-
- eigen_assert(matrix.rows() == matrix.cols() && "PartialPivLU is only for square (and moreover invertible) matrices");
- const Index size = matrix.rows();
-
- m_rowsTranspositions.resize(size);
-
- typename TranspositionType::Index nb_transpositions;
- internal::partial_lu_inplace(m_lu, m_rowsTranspositions, nb_transpositions);
- m_det_p = (nb_transpositions%2) ? -1 : 1;
-
- m_p = m_rowsTranspositions;
-
- m_isInitialized = true;
- return *this;
-}
-
-template<typename MatrixType>
-typename internal::traits<MatrixType>::Scalar PartialPivLU<MatrixType>::determinant() const
-{
- eigen_assert(m_isInitialized && "PartialPivLU is not initialized.");
- return Scalar(m_det_p) * m_lu.diagonal().prod();
-}
-
-/** \returns the matrix represented by the decomposition,
- * i.e., it returns the product: P^{-1} L U.
- * This function is provided for debug purpose. */
-template<typename MatrixType>
-MatrixType PartialPivLU<MatrixType>::reconstructedMatrix() const
-{
- eigen_assert(m_isInitialized && "LU is not initialized.");
- // LU
- MatrixType res = m_lu.template triangularView<UnitLower>().toDenseMatrix()
- * m_lu.template triangularView<Upper>();
-
- // P^{-1}(LU)
- res = m_p.inverse() * res;
-
- return res;
-}
-
-/***** Implementation of solve() *****************************************************/
-
-namespace internal {
-
-template<typename _MatrixType, typename Rhs>
-struct solve_retval<PartialPivLU<_MatrixType>, Rhs>
- : solve_retval_base<PartialPivLU<_MatrixType>, Rhs>
-{
- EIGEN_MAKE_SOLVE_HELPERS(PartialPivLU<_MatrixType>,Rhs)
-
- template<typename Dest> void evalTo(Dest& dst) const
- {
- /* The decomposition PA = LU can be rewritten as A = P^{-1} L U.
- * So we proceed as follows:
- * Step 1: compute c = Pb.
- * Step 2: replace c by the solution x to Lx = c.
- * Step 3: replace c by the solution x to Ux = c.
- */
-
- eigen_assert(rhs().rows() == dec().matrixLU().rows());
-
- // Step 1
- dst = dec().permutationP() * rhs();
-
- // Step 2
- dec().matrixLU().template triangularView<UnitLower>().solveInPlace(dst);
-
- // Step 3
- dec().matrixLU().template triangularView<Upper>().solveInPlace(dst);
- }
-};
-
-} // end namespace internal
-
-/******** MatrixBase methods *******/
-
-/** \lu_module
- *
- * \return the partial-pivoting LU decomposition of \c *this.
- *
- * \sa class PartialPivLU
- */
-template<typename Derived>
-inline const PartialPivLU<typename MatrixBase<Derived>::PlainObject>
-MatrixBase<Derived>::partialPivLu() const
-{
- return PartialPivLU<PlainObject>(eval());
-}
-
-#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS
-/** \lu_module
- *
- * Synonym of partialPivLu().
- *
- * \return the partial-pivoting LU decomposition of \c *this.
- *
- * \sa class PartialPivLU
- */
-template<typename Derived>
-inline const PartialPivLU<typename MatrixBase<Derived>::PlainObject>
-MatrixBase<Derived>::lu() const
-{
- return PartialPivLU<PlainObject>(eval());
-}
-#endif
-
-#endif // EIGEN_PARTIALLU_H
diff --git a/extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h b/extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h
deleted file mode 100644
index 176c349ce44..00000000000
--- a/extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h
+++ /dev/null
@@ -1,340 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2001 Intel Corporation
-// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-// The SSE code for the 4x4 float and double matrix inverse in this file
-// comes from the following Intel's library:
-// http://software.intel.com/en-us/articles/optimized-matrix-library-for-use-with-the-intel-pentiumr-4-processors-sse2-instructions/
-//
-// Here is the respective copyright and license statement:
-//
-// Copyright (c) 2001 Intel Corporation.
-//
-// Permition is granted to use, copy, distribute and prepare derivative works
-// of this library for any purpose and without fee, provided, that the above
-// copyright notice and this statement appear in all copies.
-// Intel makes no representations about the suitability of this software for
-// any purpose, and specifically disclaims all warranties.
-// See LEGAL.TXT for all the legal information.
-
-#ifndef EIGEN_INVERSE_SSE_H
-#define EIGEN_INVERSE_SSE_H
-
-namespace internal {
-
-template<typename MatrixType, typename ResultType>
-struct compute_inverse_size4<Architecture::SSE, float, MatrixType, ResultType>
-{
- enum {
- MatrixAlignment = bool(MatrixType::Flags&AlignedBit),
- ResultAlignment = bool(ResultType::Flags&AlignedBit),
- StorageOrdersMatch = (MatrixType::Flags&RowMajorBit) == (ResultType::Flags&RowMajorBit)
- };
-
- static void run(const MatrixType& matrix, ResultType& result)
- {
- EIGEN_ALIGN16 const int _Sign_PNNP[4] = { 0x00000000, 0x80000000, 0x80000000, 0x00000000 };
-
- // Load the full matrix into registers
- __m128 _L1 = matrix.template packet<MatrixAlignment>( 0);
- __m128 _L2 = matrix.template packet<MatrixAlignment>( 4);
- __m128 _L3 = matrix.template packet<MatrixAlignment>( 8);
- __m128 _L4 = matrix.template packet<MatrixAlignment>(12);
-
- // The inverse is calculated using "Divide and Conquer" technique. The
- // original matrix is divide into four 2x2 sub-matrices. Since each
- // register holds four matrix element, the smaller matrices are
- // represented as a registers. Hence we get a better locality of the
- // calculations.
-
- __m128 A, B, C, D; // the four sub-matrices
- if(!StorageOrdersMatch)
- {
- A = _mm_unpacklo_ps(_L1, _L2);
- B = _mm_unpacklo_ps(_L3, _L4);
- C = _mm_unpackhi_ps(_L1, _L2);
- D = _mm_unpackhi_ps(_L3, _L4);
- }
- else
- {
- A = _mm_movelh_ps(_L1, _L2);
- B = _mm_movehl_ps(_L2, _L1);
- C = _mm_movelh_ps(_L3, _L4);
- D = _mm_movehl_ps(_L4, _L3);
- }
-
- __m128 iA, iB, iC, iD, // partial inverse of the sub-matrices
- DC, AB;
- __m128 dA, dB, dC, dD; // determinant of the sub-matrices
- __m128 det, d, d1, d2;
- __m128 rd; // reciprocal of the determinant
-
- // AB = A# * B
- AB = _mm_mul_ps(_mm_shuffle_ps(A,A,0x0F), B);
- AB = _mm_sub_ps(AB,_mm_mul_ps(_mm_shuffle_ps(A,A,0xA5), _mm_shuffle_ps(B,B,0x4E)));
- // DC = D# * C
- DC = _mm_mul_ps(_mm_shuffle_ps(D,D,0x0F), C);
- DC = _mm_sub_ps(DC,_mm_mul_ps(_mm_shuffle_ps(D,D,0xA5), _mm_shuffle_ps(C,C,0x4E)));
-
- // dA = |A|
- dA = _mm_mul_ps(_mm_shuffle_ps(A, A, 0x5F),A);
- dA = _mm_sub_ss(dA, _mm_movehl_ps(dA,dA));
- // dB = |B|
- dB = _mm_mul_ps(_mm_shuffle_ps(B, B, 0x5F),B);
- dB = _mm_sub_ss(dB, _mm_movehl_ps(dB,dB));
-
- // dC = |C|
- dC = _mm_mul_ps(_mm_shuffle_ps(C, C, 0x5F),C);
- dC = _mm_sub_ss(dC, _mm_movehl_ps(dC,dC));
- // dD = |D|
- dD = _mm_mul_ps(_mm_shuffle_ps(D, D, 0x5F),D);
- dD = _mm_sub_ss(dD, _mm_movehl_ps(dD,dD));
-
- // d = trace(AB*DC) = trace(A#*B*D#*C)
- d = _mm_mul_ps(_mm_shuffle_ps(DC,DC,0xD8),AB);
-
- // iD = C*A#*B
- iD = _mm_mul_ps(_mm_shuffle_ps(C,C,0xA0), _mm_movelh_ps(AB,AB));
- iD = _mm_add_ps(iD,_mm_mul_ps(_mm_shuffle_ps(C,C,0xF5), _mm_movehl_ps(AB,AB)));
- // iA = B*D#*C
- iA = _mm_mul_ps(_mm_shuffle_ps(B,B,0xA0), _mm_movelh_ps(DC,DC));
- iA = _mm_add_ps(iA,_mm_mul_ps(_mm_shuffle_ps(B,B,0xF5), _mm_movehl_ps(DC,DC)));
-
- // d = trace(AB*DC) = trace(A#*B*D#*C) [continue]
- d = _mm_add_ps(d, _mm_movehl_ps(d, d));
- d = _mm_add_ss(d, _mm_shuffle_ps(d, d, 1));
- d1 = _mm_mul_ss(dA,dD);
- d2 = _mm_mul_ss(dB,dC);
-
- // iD = D*|A| - C*A#*B
- iD = _mm_sub_ps(_mm_mul_ps(D,_mm_shuffle_ps(dA,dA,0)), iD);
-
- // iA = A*|D| - B*D#*C;
- iA = _mm_sub_ps(_mm_mul_ps(A,_mm_shuffle_ps(dD,dD,0)), iA);
-
- // det = |A|*|D| + |B|*|C| - trace(A#*B*D#*C)
- det = _mm_sub_ss(_mm_add_ss(d1,d2),d);
- rd = _mm_div_ss(_mm_set_ss(1.0f), det);
-
-// #ifdef ZERO_SINGULAR
-// rd = _mm_and_ps(_mm_cmpneq_ss(det,_mm_setzero_ps()), rd);
-// #endif
-
- // iB = D * (A#B)# = D*B#*A
- iB = _mm_mul_ps(D, _mm_shuffle_ps(AB,AB,0x33));
- iB = _mm_sub_ps(iB, _mm_mul_ps(_mm_shuffle_ps(D,D,0xB1), _mm_shuffle_ps(AB,AB,0x66)));
- // iC = A * (D#C)# = A*C#*D
- iC = _mm_mul_ps(A, _mm_shuffle_ps(DC,DC,0x33));
- iC = _mm_sub_ps(iC, _mm_mul_ps(_mm_shuffle_ps(A,A,0xB1), _mm_shuffle_ps(DC,DC,0x66)));
-
- rd = _mm_shuffle_ps(rd,rd,0);
- rd = _mm_xor_ps(rd, _mm_load_ps((float*)_Sign_PNNP));
-
- // iB = C*|B| - D*B#*A
- iB = _mm_sub_ps(_mm_mul_ps(C,_mm_shuffle_ps(dB,dB,0)), iB);
-
- // iC = B*|C| - A*C#*D;
- iC = _mm_sub_ps(_mm_mul_ps(B,_mm_shuffle_ps(dC,dC,0)), iC);
-
- // iX = iX / det
- iA = _mm_mul_ps(rd,iA);
- iB = _mm_mul_ps(rd,iB);
- iC = _mm_mul_ps(rd,iC);
- iD = _mm_mul_ps(rd,iD);
-
- result.template writePacket<ResultAlignment>( 0, _mm_shuffle_ps(iA,iB,0x77));
- result.template writePacket<ResultAlignment>( 4, _mm_shuffle_ps(iA,iB,0x22));
- result.template writePacket<ResultAlignment>( 8, _mm_shuffle_ps(iC,iD,0x77));
- result.template writePacket<ResultAlignment>(12, _mm_shuffle_ps(iC,iD,0x22));
- }
-
-};
-
-template<typename MatrixType, typename ResultType>
-struct compute_inverse_size4<Architecture::SSE, double, MatrixType, ResultType>
-{
- enum {
- MatrixAlignment = bool(MatrixType::Flags&AlignedBit),
- ResultAlignment = bool(ResultType::Flags&AlignedBit),
- StorageOrdersMatch = (MatrixType::Flags&RowMajorBit) == (ResultType::Flags&RowMajorBit)
- };
- static void run(const MatrixType& matrix, ResultType& result)
- {
- const __m128d _Sign_NP = _mm_castsi128_pd(_mm_set_epi32(0x0,0x0,0x80000000,0x0));
- const __m128d _Sign_PN = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0));
-
- // The inverse is calculated using "Divide and Conquer" technique. The
- // original matrix is divide into four 2x2 sub-matrices. Since each
- // register of the matrix holds two element, the smaller matrices are
- // consisted of two registers. Hence we get a better locality of the
- // calculations.
-
- // the four sub-matrices
- __m128d A1, A2, B1, B2, C1, C2, D1, D2;
-
- if(StorageOrdersMatch)
- {
- A1 = matrix.template packet<MatrixAlignment>( 0); B1 = matrix.template packet<MatrixAlignment>( 2);
- A2 = matrix.template packet<MatrixAlignment>( 4); B2 = matrix.template packet<MatrixAlignment>( 6);
- C1 = matrix.template packet<MatrixAlignment>( 8); D1 = matrix.template packet<MatrixAlignment>(10);
- C2 = matrix.template packet<MatrixAlignment>(12); D2 = matrix.template packet<MatrixAlignment>(14);
- }
- else
- {
- __m128d tmp;
- A1 = matrix.template packet<MatrixAlignment>( 0); C1 = matrix.template packet<MatrixAlignment>( 2);
- A2 = matrix.template packet<MatrixAlignment>( 4); C2 = matrix.template packet<MatrixAlignment>( 6);
- tmp = A1;
- A1 = _mm_unpacklo_pd(A1,A2);
- A2 = _mm_unpackhi_pd(tmp,A2);
- tmp = C1;
- C1 = _mm_unpacklo_pd(C1,C2);
- C2 = _mm_unpackhi_pd(tmp,C2);
-
- B1 = matrix.template packet<MatrixAlignment>( 8); D1 = matrix.template packet<MatrixAlignment>(10);
- B2 = matrix.template packet<MatrixAlignment>(12); D2 = matrix.template packet<MatrixAlignment>(14);
- tmp = B1;
- B1 = _mm_unpacklo_pd(B1,B2);
- B2 = _mm_unpackhi_pd(tmp,B2);
- tmp = D1;
- D1 = _mm_unpacklo_pd(D1,D2);
- D2 = _mm_unpackhi_pd(tmp,D2);
- }
-
- __m128d iA1, iA2, iB1, iB2, iC1, iC2, iD1, iD2, // partial invese of the sub-matrices
- DC1, DC2, AB1, AB2;
- __m128d dA, dB, dC, dD; // determinant of the sub-matrices
- __m128d det, d1, d2, rd;
-
- // dA = |A|
- dA = _mm_shuffle_pd(A2, A2, 1);
- dA = _mm_mul_pd(A1, dA);
- dA = _mm_sub_sd(dA, _mm_shuffle_pd(dA,dA,3));
- // dB = |B|
- dB = _mm_shuffle_pd(B2, B2, 1);
- dB = _mm_mul_pd(B1, dB);
- dB = _mm_sub_sd(dB, _mm_shuffle_pd(dB,dB,3));
-
- // AB = A# * B
- AB1 = _mm_mul_pd(B1, _mm_shuffle_pd(A2,A2,3));
- AB2 = _mm_mul_pd(B2, _mm_shuffle_pd(A1,A1,0));
- AB1 = _mm_sub_pd(AB1, _mm_mul_pd(B2, _mm_shuffle_pd(A1,A1,3)));
- AB2 = _mm_sub_pd(AB2, _mm_mul_pd(B1, _mm_shuffle_pd(A2,A2,0)));
-
- // dC = |C|
- dC = _mm_shuffle_pd(C2, C2, 1);
- dC = _mm_mul_pd(C1, dC);
- dC = _mm_sub_sd(dC, _mm_shuffle_pd(dC,dC,3));
- // dD = |D|
- dD = _mm_shuffle_pd(D2, D2, 1);
- dD = _mm_mul_pd(D1, dD);
- dD = _mm_sub_sd(dD, _mm_shuffle_pd(dD,dD,3));
-
- // DC = D# * C
- DC1 = _mm_mul_pd(C1, _mm_shuffle_pd(D2,D2,3));
- DC2 = _mm_mul_pd(C2, _mm_shuffle_pd(D1,D1,0));
- DC1 = _mm_sub_pd(DC1, _mm_mul_pd(C2, _mm_shuffle_pd(D1,D1,3)));
- DC2 = _mm_sub_pd(DC2, _mm_mul_pd(C1, _mm_shuffle_pd(D2,D2,0)));
-
- // rd = trace(AB*DC) = trace(A#*B*D#*C)
- d1 = _mm_mul_pd(AB1, _mm_shuffle_pd(DC1, DC2, 0));
- d2 = _mm_mul_pd(AB2, _mm_shuffle_pd(DC1, DC2, 3));
- rd = _mm_add_pd(d1, d2);
- rd = _mm_add_sd(rd, _mm_shuffle_pd(rd, rd,3));
-
- // iD = C*A#*B
- iD1 = _mm_mul_pd(AB1, _mm_shuffle_pd(C1,C1,0));
- iD2 = _mm_mul_pd(AB1, _mm_shuffle_pd(C2,C2,0));
- iD1 = _mm_add_pd(iD1, _mm_mul_pd(AB2, _mm_shuffle_pd(C1,C1,3)));
- iD2 = _mm_add_pd(iD2, _mm_mul_pd(AB2, _mm_shuffle_pd(C2,C2,3)));
-
- // iA = B*D#*C
- iA1 = _mm_mul_pd(DC1, _mm_shuffle_pd(B1,B1,0));
- iA2 = _mm_mul_pd(DC1, _mm_shuffle_pd(B2,B2,0));
- iA1 = _mm_add_pd(iA1, _mm_mul_pd(DC2, _mm_shuffle_pd(B1,B1,3)));
- iA2 = _mm_add_pd(iA2, _mm_mul_pd(DC2, _mm_shuffle_pd(B2,B2,3)));
-
- // iD = D*|A| - C*A#*B
- dA = _mm_shuffle_pd(dA,dA,0);
- iD1 = _mm_sub_pd(_mm_mul_pd(D1, dA), iD1);
- iD2 = _mm_sub_pd(_mm_mul_pd(D2, dA), iD2);
-
- // iA = A*|D| - B*D#*C;
- dD = _mm_shuffle_pd(dD,dD,0);
- iA1 = _mm_sub_pd(_mm_mul_pd(A1, dD), iA1);
- iA2 = _mm_sub_pd(_mm_mul_pd(A2, dD), iA2);
-
- d1 = _mm_mul_sd(dA, dD);
- d2 = _mm_mul_sd(dB, dC);
-
- // iB = D * (A#B)# = D*B#*A
- iB1 = _mm_mul_pd(D1, _mm_shuffle_pd(AB2,AB1,1));
- iB2 = _mm_mul_pd(D2, _mm_shuffle_pd(AB2,AB1,1));
- iB1 = _mm_sub_pd(iB1, _mm_mul_pd(_mm_shuffle_pd(D1,D1,1), _mm_shuffle_pd(AB2,AB1,2)));
- iB2 = _mm_sub_pd(iB2, _mm_mul_pd(_mm_shuffle_pd(D2,D2,1), _mm_shuffle_pd(AB2,AB1,2)));
-
- // det = |A|*|D| + |B|*|C| - trace(A#*B*D#*C)
- det = _mm_add_sd(d1, d2);
- det = _mm_sub_sd(det, rd);
-
- // iC = A * (D#C)# = A*C#*D
- iC1 = _mm_mul_pd(A1, _mm_shuffle_pd(DC2,DC1,1));
- iC2 = _mm_mul_pd(A2, _mm_shuffle_pd(DC2,DC1,1));
- iC1 = _mm_sub_pd(iC1, _mm_mul_pd(_mm_shuffle_pd(A1,A1,1), _mm_shuffle_pd(DC2,DC1,2)));
- iC2 = _mm_sub_pd(iC2, _mm_mul_pd(_mm_shuffle_pd(A2,A2,1), _mm_shuffle_pd(DC2,DC1,2)));
-
- rd = _mm_div_sd(_mm_set_sd(1.0), det);
-// #ifdef ZERO_SINGULAR
-// rd = _mm_and_pd(_mm_cmpneq_sd(det,_mm_setzero_pd()), rd);
-// #endif
- rd = _mm_shuffle_pd(rd,rd,0);
-
- // iB = C*|B| - D*B#*A
- dB = _mm_shuffle_pd(dB,dB,0);
- iB1 = _mm_sub_pd(_mm_mul_pd(C1, dB), iB1);
- iB2 = _mm_sub_pd(_mm_mul_pd(C2, dB), iB2);
-
- d1 = _mm_xor_pd(rd, _Sign_PN);
- d2 = _mm_xor_pd(rd, _Sign_NP);
-
- // iC = B*|C| - A*C#*D;
- dC = _mm_shuffle_pd(dC,dC,0);
- iC1 = _mm_sub_pd(_mm_mul_pd(B1, dC), iC1);
- iC2 = _mm_sub_pd(_mm_mul_pd(B2, dC), iC2);
-
- result.template writePacket<ResultAlignment>( 0, _mm_mul_pd(_mm_shuffle_pd(iA2, iA1, 3), d1)); // iA# / det
- result.template writePacket<ResultAlignment>( 4, _mm_mul_pd(_mm_shuffle_pd(iA2, iA1, 0), d2));
- result.template writePacket<ResultAlignment>( 2, _mm_mul_pd(_mm_shuffle_pd(iB2, iB1, 3), d1)); // iB# / det
- result.template writePacket<ResultAlignment>( 6, _mm_mul_pd(_mm_shuffle_pd(iB2, iB1, 0), d2));
- result.template writePacket<ResultAlignment>( 8, _mm_mul_pd(_mm_shuffle_pd(iC2, iC1, 3), d1)); // iC# / det
- result.template writePacket<ResultAlignment>(12, _mm_mul_pd(_mm_shuffle_pd(iC2, iC1, 0), d2));
- result.template writePacket<ResultAlignment>(10, _mm_mul_pd(_mm_shuffle_pd(iD2, iD1, 3), d1)); // iD# / det
- result.template writePacket<ResultAlignment>(14, _mm_mul_pd(_mm_shuffle_pd(iD2, iD1, 0), d2));
- }
-};
-
-}
-
-#endif // EIGEN_INVERSE_SSE_H
diff --git a/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h b/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h
deleted file mode 100644
index f04c6038d6a..00000000000
--- a/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h
+++ /dev/null
@@ -1,532 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_COLPIVOTINGHOUSEHOLDERQR_H
-#define EIGEN_COLPIVOTINGHOUSEHOLDERQR_H
-
-/** \ingroup QR_Module
- *
- * \class ColPivHouseholderQR
- *
- * \brief Householder rank-revealing QR decomposition of a matrix with column-pivoting
- *
- * \param MatrixType the type of the matrix of which we are computing the QR decomposition
- *
- * This class performs a rank-revealing QR decomposition of a matrix \b A into matrices \b P, \b Q and \b R
- * such that
- * \f[
- * \mathbf{A} \, \mathbf{P} = \mathbf{Q} \, \mathbf{R}
- * \f]
- * by using Householder transformations. Here, \b P is a permutation matrix, \b Q a unitary matrix and \b R an
- * upper triangular matrix.
- *
- * This decomposition performs column pivoting in order to be rank-revealing and improve
- * numerical stability. It is slower than HouseholderQR, and faster than FullPivHouseholderQR.
- *
- * \sa MatrixBase::colPivHouseholderQr()
- */
-template<typename _MatrixType> class ColPivHouseholderQR
-{
- public:
-
- typedef _MatrixType MatrixType;
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- Options = MatrixType::Options,
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
- };
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
- typedef typename MatrixType::Index Index;
- typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, Options, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixQType;
- typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
- typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationType;
- typedef typename internal::plain_row_type<MatrixType, Index>::type IntRowVectorType;
- typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
- typedef typename internal::plain_row_type<MatrixType, RealScalar>::type RealRowVectorType;
- typedef typename HouseholderSequence<MatrixType,HCoeffsType>::ConjugateReturnType HouseholderSequenceType;
-
- /**
- * \brief Default Constructor.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via ColPivHouseholderQR::compute(const MatrixType&).
- */
- ColPivHouseholderQR()
- : m_qr(),
- m_hCoeffs(),
- m_colsPermutation(),
- m_colsTranspositions(),
- m_temp(),
- m_colSqNorms(),
- m_isInitialized(false) {}
-
- /** \brief Default Constructor with memory preallocation
- *
- * Like the default constructor but with preallocation of the internal data
- * according to the specified problem \a size.
- * \sa ColPivHouseholderQR()
- */
- ColPivHouseholderQR(Index rows, Index cols)
- : m_qr(rows, cols),
- m_hCoeffs((std::min)(rows,cols)),
- m_colsPermutation(cols),
- m_colsTranspositions(cols),
- m_temp(cols),
- m_colSqNorms(cols),
- m_isInitialized(false),
- m_usePrescribedThreshold(false) {}
-
- ColPivHouseholderQR(const MatrixType& matrix)
- : m_qr(matrix.rows(), matrix.cols()),
- m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
- m_colsPermutation(matrix.cols()),
- m_colsTranspositions(matrix.cols()),
- m_temp(matrix.cols()),
- m_colSqNorms(matrix.cols()),
- m_isInitialized(false),
- m_usePrescribedThreshold(false)
- {
- compute(matrix);
- }
-
- /** This method finds a solution x to the equation Ax=b, where A is the matrix of which
- * *this is the QR decomposition, if any exists.
- *
- * \param b the right-hand-side of the equation to solve.
- *
- * \returns a solution.
- *
- * \note The case where b is a matrix is not yet implemented. Also, this
- * code is space inefficient.
- *
- * \note_about_checking_solutions
- *
- * \note_about_arbitrary_choice_of_solution
- *
- * Example: \include ColPivHouseholderQR_solve.cpp
- * Output: \verbinclude ColPivHouseholderQR_solve.out
- */
- template<typename Rhs>
- inline const internal::solve_retval<ColPivHouseholderQR, Rhs>
- solve(const MatrixBase<Rhs>& b) const
- {
- eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- return internal::solve_retval<ColPivHouseholderQR, Rhs>(*this, b.derived());
- }
-
- HouseholderSequenceType householderQ(void) const;
-
- /** \returns a reference to the matrix where the Householder QR decomposition is stored
- */
- const MatrixType& matrixQR() const
- {
- eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- return m_qr;
- }
-
- ColPivHouseholderQR& compute(const MatrixType& matrix);
-
- const PermutationType& colsPermutation() const
- {
- eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- return m_colsPermutation;
- }
-
- /** \returns the absolute value of the determinant of the matrix of which
- * *this is the QR decomposition. It has only linear complexity
- * (that is, O(n) where n is the dimension of the square matrix)
- * as the QR decomposition has already been computed.
- *
- * \note This is only for square matrices.
- *
- * \warning a determinant can be very big or small, so for matrices
- * of large enough dimension, there is a risk of overflow/underflow.
- * One way to work around that is to use logAbsDeterminant() instead.
- *
- * \sa logAbsDeterminant(), MatrixBase::determinant()
- */
- typename MatrixType::RealScalar absDeterminant() const;
-
- /** \returns the natural log of the absolute value of the determinant of the matrix of which
- * *this is the QR decomposition. It has only linear complexity
- * (that is, O(n) where n is the dimension of the square matrix)
- * as the QR decomposition has already been computed.
- *
- * \note This is only for square matrices.
- *
- * \note This method is useful to work around the risk of overflow/underflow that's inherent
- * to determinant computation.
- *
- * \sa absDeterminant(), MatrixBase::determinant()
- */
- typename MatrixType::RealScalar logAbsDeterminant() const;
-
- /** \returns the rank of the matrix of which *this is the QR decomposition.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline Index rank() const
- {
- eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- RealScalar premultiplied_threshold = internal::abs(m_maxpivot) * threshold();
- Index result = 0;
- for(Index i = 0; i < m_nonzero_pivots; ++i)
- result += (internal::abs(m_qr.coeff(i,i)) > premultiplied_threshold);
- return result;
- }
-
- /** \returns the dimension of the kernel of the matrix of which *this is the QR decomposition.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline Index dimensionOfKernel() const
- {
- eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- return cols() - rank();
- }
-
- /** \returns true if the matrix of which *this is the QR decomposition represents an injective
- * linear map, i.e. has trivial kernel; false otherwise.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline bool isInjective() const
- {
- eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- return rank() == cols();
- }
-
- /** \returns true if the matrix of which *this is the QR decomposition represents a surjective
- * linear map; false otherwise.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline bool isSurjective() const
- {
- eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- return rank() == rows();
- }
-
- /** \returns true if the matrix of which *this is the QR decomposition is invertible.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline bool isInvertible() const
- {
- eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- return isInjective() && isSurjective();
- }
-
- /** \returns the inverse of the matrix of which *this is the QR decomposition.
- *
- * \note If this matrix is not invertible, the returned matrix has undefined coefficients.
- * Use isInvertible() to first determine whether this matrix is invertible.
- */
- inline const
- internal::solve_retval<ColPivHouseholderQR, typename MatrixType::IdentityReturnType>
- inverse() const
- {
- eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- return internal::solve_retval<ColPivHouseholderQR,typename MatrixType::IdentityReturnType>
- (*this, MatrixType::Identity(m_qr.rows(), m_qr.cols()));
- }
-
- inline Index rows() const { return m_qr.rows(); }
- inline Index cols() const { return m_qr.cols(); }
- const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
-
- /** Allows to prescribe a threshold to be used by certain methods, such as rank(),
- * who need to determine when pivots are to be considered nonzero. This is not used for the
- * QR decomposition itself.
- *
- * When it needs to get the threshold value, Eigen calls threshold(). By default, this
- * uses a formula to automatically determine a reasonable threshold.
- * Once you have called the present method setThreshold(const RealScalar&),
- * your value is used instead.
- *
- * \param threshold The new value to use as the threshold.
- *
- * A pivot will be considered nonzero if its absolute value is strictly greater than
- * \f$ \vert pivot \vert \leqslant threshold \times \vert maxpivot \vert \f$
- * where maxpivot is the biggest pivot.
- *
- * If you want to come back to the default behavior, call setThreshold(Default_t)
- */
- ColPivHouseholderQR& 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 qr.setThreshold(Eigen::Default); \endcode
- *
- * See the documentation of setThreshold(const RealScalar&).
- */
- ColPivHouseholderQR& 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
- // this formula comes from experimenting (see "LU precision tuning" thread on the list)
- // and turns out to be identical to Higham's formula used already in LDLt.
- : NumTraits<Scalar>::epsilon() * m_qr.diagonalSize();
- }
-
- /** \returns the number of nonzero pivots in the QR decomposition.
- * Here nonzero is meant in the exact sense, not in a fuzzy sense.
- * So that notion isn't really intrinsically interesting, but it is
- * still useful when implementing algorithms.
- *
- * \sa rank()
- */
- inline Index nonzeroPivots() const
- {
- eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- return m_nonzero_pivots;
- }
-
- /** \returns the absolute value of the biggest pivot, i.e. the biggest
- * diagonal coefficient of R.
- */
- RealScalar maxPivot() const { return m_maxpivot; }
-
- protected:
- MatrixType m_qr;
- HCoeffsType m_hCoeffs;
- PermutationType m_colsPermutation;
- IntRowVectorType m_colsTranspositions;
- RowVectorType m_temp;
- RealRowVectorType m_colSqNorms;
- bool m_isInitialized, m_usePrescribedThreshold;
- RealScalar m_prescribedThreshold, m_maxpivot;
- Index m_nonzero_pivots;
- Index m_det_pq;
-};
-
-template<typename MatrixType>
-typename MatrixType::RealScalar ColPivHouseholderQR<MatrixType>::absDeterminant() const
-{
- eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
- return internal::abs(m_qr.diagonal().prod());
-}
-
-template<typename MatrixType>
-typename MatrixType::RealScalar ColPivHouseholderQR<MatrixType>::logAbsDeterminant() const
-{
- eigen_assert(m_isInitialized && "ColPivHouseholderQR is not initialized.");
- eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
- return m_qr.diagonal().cwiseAbs().array().log().sum();
-}
-
-template<typename MatrixType>
-ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const MatrixType& matrix)
-{
- Index rows = matrix.rows();
- Index cols = matrix.cols();
- Index size = matrix.diagonalSize();
-
- m_qr = matrix;
- m_hCoeffs.resize(size);
-
- m_temp.resize(cols);
-
- m_colsTranspositions.resize(matrix.cols());
- Index number_of_transpositions = 0;
-
- m_colSqNorms.resize(cols);
- for(Index k = 0; k < cols; ++k)
- m_colSqNorms.coeffRef(k) = m_qr.col(k).squaredNorm();
-
- RealScalar threshold_helper = m_colSqNorms.maxCoeff() * internal::abs2(NumTraits<Scalar>::epsilon()) / RealScalar(rows);
-
- m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case)
- m_maxpivot = RealScalar(0);
-
- for(Index k = 0; k < size; ++k)
- {
- // first, we look up in our table m_colSqNorms which column has the biggest squared norm
- Index biggest_col_index;
- RealScalar biggest_col_sq_norm = m_colSqNorms.tail(cols-k).maxCoeff(&biggest_col_index);
- biggest_col_index += k;
-
- // since our table m_colSqNorms accumulates imprecision at every step, we must now recompute
- // the actual squared norm of the selected column.
- // Note that not doing so does result in solve() sometimes returning inf/nan values
- // when running the unit test with 1000 repetitions.
- biggest_col_sq_norm = m_qr.col(biggest_col_index).tail(rows-k).squaredNorm();
-
- // 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))
- {
- 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;
- if(k != biggest_col_index) {
- m_qr.col(k).swap(m_qr.col(biggest_col_index));
- std::swap(m_colSqNorms.coeffRef(k), m_colSqNorms.coeffRef(biggest_col_index));
- ++number_of_transpositions;
- }
-
- // generate the householder vector, store it below the diagonal
- RealScalar beta;
- m_qr.col(k).tail(rows-k).makeHouseholderInPlace(m_hCoeffs.coeffRef(k), beta);
-
- // apply the householder transformation to the diagonal coefficient
- m_qr.coeffRef(k,k) = beta;
-
- // remember the maximum absolute value of diagonal coefficients
- if(internal::abs(beta) > m_maxpivot) m_maxpivot = internal::abs(beta);
-
- // apply the householder transformation
- m_qr.bottomRightCorner(rows-k, cols-k-1)
- .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), m_hCoeffs.coeffRef(k), &m_temp.coeffRef(k+1));
-
- // update our table of squared norms of the columns
- m_colSqNorms.tail(cols-k-1) -= m_qr.row(k).tail(cols-k-1).cwiseAbs2();
- }
-
- m_colsPermutation.setIdentity(cols);
- for(Index k = 0; k < m_nonzero_pivots; ++k)
- m_colsPermutation.applyTranspositionOnTheRight(k, m_colsTranspositions.coeff(k));
-
- m_det_pq = (number_of_transpositions%2) ? -1 : 1;
- m_isInitialized = true;
-
- return *this;
-}
-
-namespace internal {
-
-template<typename _MatrixType, typename Rhs>
-struct solve_retval<ColPivHouseholderQR<_MatrixType>, Rhs>
- : solve_retval_base<ColPivHouseholderQR<_MatrixType>, Rhs>
-{
- EIGEN_MAKE_SOLVE_HELPERS(ColPivHouseholderQR<_MatrixType>,Rhs)
-
- template<typename Dest> void evalTo(Dest& dst) const
- {
- eigen_assert(rhs().rows() == dec().rows());
-
- const int cols = dec().cols(),
- nonzero_pivots = dec().nonzeroPivots();
-
- if(nonzero_pivots == 0)
- {
- dst.setZero();
- return;
- }
-
- typename Rhs::PlainObject c(rhs());
-
- // Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T
- c.applyOnTheLeft(householderSequence(dec().matrixQR(), dec().hCoeffs())
- .setLength(dec().nonzeroPivots())
- .transpose()
- );
-
- dec().matrixQR()
- .topLeftCorner(nonzero_pivots, nonzero_pivots)
- .template triangularView<Upper>()
- .solveInPlace(c.topRows(nonzero_pivots));
-
-
- typename Rhs::PlainObject d(c);
- d.topRows(nonzero_pivots)
- = dec().matrixQR()
- .topLeftCorner(nonzero_pivots, nonzero_pivots)
- .template triangularView<Upper>()
- * c.topRows(nonzero_pivots);
-
- for(Index i = 0; i < nonzero_pivots; ++i) dst.row(dec().colsPermutation().indices().coeff(i)) = c.row(i);
- for(Index i = nonzero_pivots; i < cols; ++i) dst.row(dec().colsPermutation().indices().coeff(i)).setZero();
- }
-};
-
-} // end namespace internal
-
-/** \returns the matrix Q as a sequence of householder transformations */
-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 the column-pivoting Householder QR decomposition of \c *this.
- *
- * \sa class ColPivHouseholderQR
- */
-template<typename Derived>
-const ColPivHouseholderQR<typename MatrixBase<Derived>::PlainObject>
-MatrixBase<Derived>::colPivHouseholderQr() const
-{
- return ColPivHouseholderQR<PlainObject>(eval());
-}
-
-
-#endif // EIGEN_COLPIVOTINGHOUSEHOLDERQR_H
diff --git a/extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h b/extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h
deleted file mode 100644
index dde3013be9d..00000000000
--- a/extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h
+++ /dev/null
@@ -1,546 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_FULLPIVOTINGHOUSEHOLDERQR_H
-#define EIGEN_FULLPIVOTINGHOUSEHOLDERQR_H
-
-/** \ingroup QR_Module
- *
- * \class FullPivHouseholderQR
- *
- * \brief Householder rank-revealing QR decomposition of a matrix with full pivoting
- *
- * \param MatrixType the type of the matrix of which we are computing the QR decomposition
- *
- * This class performs a rank-revealing QR decomposition of a matrix \b A into matrices \b P, \b Q and \b R
- * such that
- * \f[
- * \mathbf{A} \, \mathbf{P} = \mathbf{Q} \, \mathbf{R}
- * \f]
- * by using Householder transformations. Here, \b P is a permutation matrix, \b Q a unitary matrix and \b R an
- * upper triangular matrix.
- *
- * This decomposition performs a very prudent full pivoting in order to be rank-revealing and achieve optimal
- * numerical stability. The trade-off is that it is slower than HouseholderQR and ColPivHouseholderQR.
- *
- * \sa MatrixBase::fullPivHouseholderQr()
- */
-template<typename _MatrixType> class FullPivHouseholderQR
-{
- public:
-
- typedef _MatrixType MatrixType;
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- Options = MatrixType::Options,
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
- };
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
- typedef typename MatrixType::Index Index;
- typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, Options, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixQType;
- typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
- typedef Matrix<Index, 1, ColsAtCompileTime, RowMajor, 1, MaxColsAtCompileTime> IntRowVectorType;
- typedef PermutationMatrix<ColsAtCompileTime, MaxColsAtCompileTime> PermutationType;
- typedef typename internal::plain_col_type<MatrixType, Index>::type IntColVectorType;
- typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
- typedef typename internal::plain_col_type<MatrixType>::type ColVectorType;
-
- /** \brief Default Constructor.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via FullPivHouseholderQR::compute(const MatrixType&).
- */
- FullPivHouseholderQR()
- : m_qr(),
- m_hCoeffs(),
- m_rows_transpositions(),
- m_cols_transpositions(),
- m_cols_permutation(),
- m_temp(),
- m_isInitialized(false),
- m_usePrescribedThreshold(false) {}
-
- /** \brief Default Constructor with memory preallocation
- *
- * Like the default constructor but with preallocation of the internal data
- * according to the specified problem \a size.
- * \sa FullPivHouseholderQR()
- */
- FullPivHouseholderQR(Index rows, Index cols)
- : m_qr(rows, cols),
- m_hCoeffs((std::min)(rows,cols)),
- m_rows_transpositions(rows),
- m_cols_transpositions(cols),
- m_cols_permutation(cols),
- m_temp((std::min)(rows,cols)),
- m_isInitialized(false),
- m_usePrescribedThreshold(false) {}
-
- FullPivHouseholderQR(const MatrixType& matrix)
- : m_qr(matrix.rows(), matrix.cols()),
- m_hCoeffs((std::min)(matrix.rows(), matrix.cols())),
- m_rows_transpositions(matrix.rows()),
- m_cols_transpositions(matrix.cols()),
- m_cols_permutation(matrix.cols()),
- m_temp((std::min)(matrix.rows(), matrix.cols())),
- m_isInitialized(false),
- m_usePrescribedThreshold(false)
- {
- compute(matrix);
- }
-
- /** This method finds a solution x to the equation Ax=b, where A is the matrix of which
- * *this is the QR decomposition, if any exists.
- *
- * \param b the right-hand-side of the equation to solve.
- *
- * \returns a solution.
- *
- * \note The case where b is a matrix is not yet implemented. Also, this
- * code is space inefficient.
- *
- * \note_about_checking_solutions
- *
- * \note_about_arbitrary_choice_of_solution
- *
- * Example: \include FullPivHouseholderQR_solve.cpp
- * Output: \verbinclude FullPivHouseholderQR_solve.out
- */
- template<typename Rhs>
- inline const internal::solve_retval<FullPivHouseholderQR, Rhs>
- solve(const MatrixBase<Rhs>& b) const
- {
- eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- return internal::solve_retval<FullPivHouseholderQR, Rhs>(*this, b.derived());
- }
-
- MatrixQType matrixQ(void) const;
-
- /** \returns a reference to the matrix where the Householder QR decomposition is stored
- */
- const MatrixType& matrixQR() const
- {
- eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- return m_qr;
- }
-
- FullPivHouseholderQR& compute(const MatrixType& matrix);
-
- const PermutationType& colsPermutation() const
- {
- eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- return m_cols_permutation;
- }
-
- const IntColVectorType& rowsTranspositions() const
- {
- eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- return m_rows_transpositions;
- }
-
- /** \returns the absolute value of the determinant of the matrix of which
- * *this is the QR decomposition. It has only linear complexity
- * (that is, O(n) where n is the dimension of the square matrix)
- * as the QR decomposition has already been computed.
- *
- * \note This is only for square matrices.
- *
- * \warning a determinant can be very big or small, so for matrices
- * of large enough dimension, there is a risk of overflow/underflow.
- * One way to work around that is to use logAbsDeterminant() instead.
- *
- * \sa logAbsDeterminant(), MatrixBase::determinant()
- */
- typename MatrixType::RealScalar absDeterminant() const;
-
- /** \returns the natural log of the absolute value of the determinant of the matrix of which
- * *this is the QR decomposition. It has only linear complexity
- * (that is, O(n) where n is the dimension of the square matrix)
- * as the QR decomposition has already been computed.
- *
- * \note This is only for square matrices.
- *
- * \note This method is useful to work around the risk of overflow/underflow that's inherent
- * to determinant computation.
- *
- * \sa absDeterminant(), MatrixBase::determinant()
- */
- typename MatrixType::RealScalar logAbsDeterminant() const;
-
- /** \returns the rank of the matrix of which *this is the QR decomposition.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline Index rank() const
- {
- eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- RealScalar premultiplied_threshold = internal::abs(m_maxpivot) * threshold();
- Index result = 0;
- for(Index i = 0; i < m_nonzero_pivots; ++i)
- result += (internal::abs(m_qr.coeff(i,i)) > premultiplied_threshold);
- return result;
- }
-
- /** \returns the dimension of the kernel of the matrix of which *this is the QR decomposition.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline Index dimensionOfKernel() const
- {
- eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- return cols() - rank();
- }
-
- /** \returns true if the matrix of which *this is the QR decomposition represents an injective
- * linear map, i.e. has trivial kernel; false otherwise.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline bool isInjective() const
- {
- eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- return rank() == cols();
- }
-
- /** \returns true if the matrix of which *this is the QR decomposition represents a surjective
- * linear map; false otherwise.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline bool isSurjective() const
- {
- eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- return rank() == rows();
- }
-
- /** \returns true if the matrix of which *this is the QR decomposition is invertible.
- *
- * \note This method has to determine which pivots should be considered nonzero.
- * For that, it uses the threshold value that you can control by calling
- * setThreshold(const RealScalar&).
- */
- inline bool isInvertible() const
- {
- eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- return isInjective() && isSurjective();
- }
-
- /** \returns the inverse of the matrix of which *this is the QR decomposition.
- *
- * \note If this matrix is not invertible, the returned matrix has undefined coefficients.
- * Use isInvertible() to first determine whether this matrix is invertible.
- */ inline const
- internal::solve_retval<FullPivHouseholderQR, typename MatrixType::IdentityReturnType>
- inverse() const
- {
- eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- return internal::solve_retval<FullPivHouseholderQR,typename MatrixType::IdentityReturnType>
- (*this, MatrixType::Identity(m_qr.rows(), m_qr.cols()));
- }
-
- inline Index rows() const { return m_qr.rows(); }
- inline Index cols() const { return m_qr.cols(); }
- const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
-
- /** Allows to prescribe a threshold to be used by certain methods, such as rank(),
- * who need to determine when pivots are to be considered nonzero. This is not used for the
- * QR decomposition itself.
- *
- * When it needs to get the threshold value, Eigen calls threshold(). By default, this
- * uses a formula to automatically determine a reasonable threshold.
- * Once you have called the present method setThreshold(const RealScalar&),
- * your value is used instead.
- *
- * \param threshold The new value to use as the threshold.
- *
- * A pivot will be considered nonzero if its absolute value is strictly greater than
- * \f$ \vert pivot \vert \leqslant threshold \times \vert maxpivot \vert \f$
- * where maxpivot is the biggest pivot.
- *
- * If you want to come back to the default behavior, call setThreshold(Default_t)
- */
- FullPivHouseholderQR& 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 qr.setThreshold(Eigen::Default); \endcode
- *
- * See the documentation of setThreshold(const RealScalar&).
- */
- FullPivHouseholderQR& 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
- // this formula comes from experimenting (see "LU precision tuning" thread on the list)
- // and turns out to be identical to Higham's formula used already in LDLt.
- : NumTraits<Scalar>::epsilon() * m_qr.diagonalSize();
- }
-
- /** \returns the number of nonzero pivots in the QR decomposition.
- * Here nonzero is meant in the exact sense, not in a fuzzy sense.
- * So that notion isn't really intrinsically interesting, but it is
- * still useful when implementing algorithms.
- *
- * \sa rank()
- */
- inline Index nonzeroPivots() const
- {
- eigen_assert(m_isInitialized && "LU is not initialized.");
- return m_nonzero_pivots;
- }
-
- /** \returns the absolute value of the biggest pivot, i.e. the biggest
- * diagonal coefficient of U.
- */
- RealScalar maxPivot() const { return m_maxpivot; }
-
- protected:
- MatrixType m_qr;
- HCoeffsType m_hCoeffs;
- IntColVectorType m_rows_transpositions;
- IntRowVectorType m_cols_transpositions;
- PermutationType m_cols_permutation;
- RowVectorType m_temp;
- bool m_isInitialized, m_usePrescribedThreshold;
- RealScalar m_prescribedThreshold, m_maxpivot;
- Index m_nonzero_pivots;
- RealScalar m_precision;
- Index m_det_pq;
-};
-
-template<typename MatrixType>
-typename MatrixType::RealScalar FullPivHouseholderQR<MatrixType>::absDeterminant() const
-{
- eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
- return internal::abs(m_qr.diagonal().prod());
-}
-
-template<typename MatrixType>
-typename MatrixType::RealScalar FullPivHouseholderQR<MatrixType>::logAbsDeterminant() const
-{
- eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
- return m_qr.diagonal().cwiseAbs().array().log().sum();
-}
-
-template<typename MatrixType>
-FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(const MatrixType& matrix)
-{
- Index rows = matrix.rows();
- Index cols = matrix.cols();
- Index size = (std::min)(rows,cols);
-
- m_qr = matrix;
- m_hCoeffs.resize(size);
-
- m_temp.resize(cols);
-
- m_precision = NumTraits<Scalar>::epsilon() * size;
-
- m_rows_transpositions.resize(matrix.rows());
- m_cols_transpositions.resize(matrix.cols());
- Index number_of_transpositions = 0;
-
- RealScalar biggest(0);
-
- m_nonzero_pivots = size; // the generic case is that in which all pivots are nonzero (invertible case)
- m_maxpivot = RealScalar(0);
-
- for (Index k = 0; k < size; ++k)
- {
- Index row_of_biggest_in_corner, col_of_biggest_in_corner;
- RealScalar biggest_in_corner;
-
- biggest_in_corner = m_qr.bottomRightCorner(rows-k, cols-k)
- .cwiseAbs()
- .maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner);
- row_of_biggest_in_corner += k;
- col_of_biggest_in_corner += k;
- if(k==0) biggest = biggest_in_corner;
-
- // if the corner is negligible, then we have less than full rank, and we can finish early
- if(internal::isMuchSmallerThan(biggest_in_corner, biggest, m_precision))
- {
- m_nonzero_pivots = k;
- for(Index i = k; i < size; i++)
- {
- m_rows_transpositions.coeffRef(i) = i;
- m_cols_transpositions.coeffRef(i) = i;
- m_hCoeffs.coeffRef(i) = Scalar(0);
- }
- break;
- }
-
- m_rows_transpositions.coeffRef(k) = row_of_biggest_in_corner;
- m_cols_transpositions.coeffRef(k) = col_of_biggest_in_corner;
- if(k != row_of_biggest_in_corner) {
- m_qr.row(k).tail(cols-k).swap(m_qr.row(row_of_biggest_in_corner).tail(cols-k));
- ++number_of_transpositions;
- }
- if(k != col_of_biggest_in_corner) {
- m_qr.col(k).swap(m_qr.col(col_of_biggest_in_corner));
- ++number_of_transpositions;
- }
-
- RealScalar beta;
- m_qr.col(k).tail(rows-k).makeHouseholderInPlace(m_hCoeffs.coeffRef(k), beta);
- m_qr.coeffRef(k,k) = beta;
-
- // remember the maximum absolute value of diagonal coefficients
- if(internal::abs(beta) > m_maxpivot) m_maxpivot = internal::abs(beta);
-
- m_qr.bottomRightCorner(rows-k, cols-k-1)
- .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), m_hCoeffs.coeffRef(k), &m_temp.coeffRef(k+1));
- }
-
- m_cols_permutation.setIdentity(cols);
- for(Index k = 0; k < size; ++k)
- m_cols_permutation.applyTranspositionOnTheRight(k, m_cols_transpositions.coeff(k));
-
- m_det_pq = (number_of_transpositions%2) ? -1 : 1;
- m_isInitialized = true;
-
- return *this;
-}
-
-namespace internal {
-
-template<typename _MatrixType, typename Rhs>
-struct solve_retval<FullPivHouseholderQR<_MatrixType>, Rhs>
- : solve_retval_base<FullPivHouseholderQR<_MatrixType>, Rhs>
-{
- EIGEN_MAKE_SOLVE_HELPERS(FullPivHouseholderQR<_MatrixType>,Rhs)
-
- template<typename Dest> void evalTo(Dest& dst) const
- {
- const Index rows = dec().rows(), cols = dec().cols();
- eigen_assert(rhs().rows() == rows);
-
- // FIXME introduce nonzeroPivots() and use it here. and more generally,
- // make the same improvements in this dec as in FullPivLU.
- if(dec().rank()==0)
- {
- dst.setZero();
- return;
- }
-
- typename Rhs::PlainObject c(rhs());
-
- Matrix<Scalar,1,Rhs::ColsAtCompileTime> temp(rhs().cols());
- for (Index k = 0; k < dec().rank(); ++k)
- {
- Index remainingSize = rows-k;
- c.row(k).swap(c.row(dec().rowsTranspositions().coeff(k)));
- c.bottomRightCorner(remainingSize, rhs().cols())
- .applyHouseholderOnTheLeft(dec().matrixQR().col(k).tail(remainingSize-1),
- dec().hCoeffs().coeff(k), &temp.coeffRef(0));
- }
-
- if(!dec().isSurjective())
- {
- // is c is in the image of R ?
- RealScalar biggest_in_upper_part_of_c = c.topRows( dec().rank() ).cwiseAbs().maxCoeff();
- RealScalar biggest_in_lower_part_of_c = c.bottomRows(rows-dec().rank()).cwiseAbs().maxCoeff();
- // FIXME brain dead
- const RealScalar m_precision = NumTraits<Scalar>::epsilon() * (std::min)(rows,cols);
- // this internal:: prefix is needed by at least gcc 3.4 and ICC
- if(!internal::isMuchSmallerThan(biggest_in_lower_part_of_c, biggest_in_upper_part_of_c, m_precision))
- return;
- }
- dec().matrixQR()
- .topLeftCorner(dec().rank(), dec().rank())
- .template triangularView<Upper>()
- .solveInPlace(c.topRows(dec().rank()));
-
- for(Index i = 0; i < dec().rank(); ++i) dst.row(dec().colsPermutation().indices().coeff(i)) = c.row(i);
- for(Index i = dec().rank(); i < cols; ++i) dst.row(dec().colsPermutation().indices().coeff(i)).setZero();
- }
-};
-
-} // end namespace internal
-
-/** \returns the matrix Q */
-template<typename MatrixType>
-typename FullPivHouseholderQR<MatrixType>::MatrixQType FullPivHouseholderQR<MatrixType>::matrixQ() const
-{
- eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized.");
- // compute the product H'_0 H'_1 ... H'_n-1,
- // where H_k is the k-th Householder transformation I - h_k v_k v_k'
- // and v_k is the k-th Householder vector [1,m_qr(k+1,k), m_qr(k+2,k), ...]
- Index rows = m_qr.rows();
- Index cols = m_qr.cols();
- Index size = (std::min)(rows,cols);
- MatrixQType res = MatrixQType::Identity(rows, rows);
- Matrix<Scalar,1,MatrixType::RowsAtCompileTime> temp(rows);
- for (Index k = size-1; k >= 0; k--)
- {
- res.block(k, k, rows-k, rows-k)
- .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), internal::conj(m_hCoeffs.coeff(k)), &temp.coeffRef(k));
- res.row(k).swap(res.row(m_rows_transpositions.coeff(k)));
- }
- return res;
-}
-
-/** \return the full-pivoting Householder QR decomposition of \c *this.
- *
- * \sa class FullPivHouseholderQR
- */
-template<typename Derived>
-const FullPivHouseholderQR<typename MatrixBase<Derived>::PlainObject>
-MatrixBase<Derived>::fullPivHouseholderQr() const
-{
- return FullPivHouseholderQR<PlainObject>(eval());
-}
-
-#endif // EIGEN_FULLPIVOTINGHOUSEHOLDERQR_H
diff --git a/extern/Eigen3/Eigen/src/QR/HouseholderQR.h b/extern/Eigen3/Eigen/src/QR/HouseholderQR.h
deleted file mode 100644
index 9ee96de2680..00000000000
--- a/extern/Eigen3/Eigen/src/QR/HouseholderQR.h
+++ /dev/null
@@ -1,355 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-// Copyright (C) 2010 Vincent Lejeune
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_QR_H
-#define EIGEN_QR_H
-
-/** \ingroup QR_Module
- *
- *
- * \class HouseholderQR
- *
- * \brief Householder QR decomposition of a matrix
- *
- * \param MatrixType the type of the matrix of which we are computing the QR decomposition
- *
- * This class performs a QR decomposition of a matrix \b A into matrices \b Q and \b R
- * such that
- * \f[
- * \mathbf{A} = \mathbf{Q} \, \mathbf{R}
- * \f]
- * by using Householder transformations. Here, \b Q a unitary matrix and \b R an upper triangular matrix.
- * The result is stored in a compact way compatible with LAPACK.
- *
- * Note that no pivoting is performed. This is \b not a rank-revealing decomposition.
- * If you want that feature, use FullPivHouseholderQR or ColPivHouseholderQR instead.
- *
- * This Householder QR decomposition is faster, but less numerically stable and less feature-full than
- * FullPivHouseholderQR or ColPivHouseholderQR.
- *
- * \sa MatrixBase::householderQr()
- */
-template<typename _MatrixType> class HouseholderQR
-{
- public:
-
- typedef _MatrixType MatrixType;
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- Options = MatrixType::Options,
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
- };
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
- typedef typename MatrixType::Index Index;
- typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime, (MatrixType::Flags&RowMajorBit) ? RowMajor : ColMajor, MaxRowsAtCompileTime, MaxRowsAtCompileTime> MatrixQType;
- typedef typename internal::plain_diag_type<MatrixType>::type HCoeffsType;
- typedef typename internal::plain_row_type<MatrixType>::type RowVectorType;
- typedef typename HouseholderSequence<MatrixType,HCoeffsType>::ConjugateReturnType HouseholderSequenceType;
-
- /**
- * \brief Default Constructor.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via HouseholderQR::compute(const MatrixType&).
- */
- HouseholderQR() : m_qr(), m_hCoeffs(), m_temp(), m_isInitialized(false) {}
-
- /** \brief Default Constructor with memory preallocation
- *
- * Like the default constructor but with preallocation of the internal data
- * according to the specified problem \a size.
- * \sa HouseholderQR()
- */
- HouseholderQR(Index rows, Index cols)
- : m_qr(rows, cols),
- m_hCoeffs((std::min)(rows,cols)),
- m_temp(cols),
- m_isInitialized(false) {}
-
- HouseholderQR(const MatrixType& matrix)
- : m_qr(matrix.rows(), matrix.cols()),
- m_hCoeffs((std::min)(matrix.rows(),matrix.cols())),
- m_temp(matrix.cols()),
- m_isInitialized(false)
- {
- compute(matrix);
- }
-
- /** This method finds a solution x to the equation Ax=b, where A is the matrix of which
- * *this is the QR decomposition, if any exists.
- *
- * \param b the right-hand-side of the equation to solve.
- *
- * \returns a solution.
- *
- * \note The case where b is a matrix is not yet implemented. Also, this
- * code is space inefficient.
- *
- * \note_about_checking_solutions
- *
- * \note_about_arbitrary_choice_of_solution
- *
- * Example: \include HouseholderQR_solve.cpp
- * Output: \verbinclude HouseholderQR_solve.out
- */
- template<typename Rhs>
- inline const internal::solve_retval<HouseholderQR, Rhs>
- solve(const MatrixBase<Rhs>& b) const
- {
- eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
- return internal::solve_retval<HouseholderQR, Rhs>(*this, b.derived());
- }
-
- HouseholderSequenceType householderQ() const
- {
- eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
- return HouseholderSequenceType(m_qr, m_hCoeffs.conjugate());
- }
-
- /** \returns a reference to the matrix where the Householder QR decomposition is stored
- * in a LAPACK-compatible way.
- */
- const MatrixType& matrixQR() const
- {
- eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
- return m_qr;
- }
-
- HouseholderQR& compute(const MatrixType& matrix);
-
- /** \returns the absolute value of the determinant of the matrix of which
- * *this is the QR decomposition. It has only linear complexity
- * (that is, O(n) where n is the dimension of the square matrix)
- * as the QR decomposition has already been computed.
- *
- * \note This is only for square matrices.
- *
- * \warning a determinant can be very big or small, so for matrices
- * of large enough dimension, there is a risk of overflow/underflow.
- * One way to work around that is to use logAbsDeterminant() instead.
- *
- * \sa logAbsDeterminant(), MatrixBase::determinant()
- */
- typename MatrixType::RealScalar absDeterminant() const;
-
- /** \returns the natural log of the absolute value of the determinant of the matrix of which
- * *this is the QR decomposition. It has only linear complexity
- * (that is, O(n) where n is the dimension of the square matrix)
- * as the QR decomposition has already been computed.
- *
- * \note This is only for square matrices.
- *
- * \note This method is useful to work around the risk of overflow/underflow that's inherent
- * to determinant computation.
- *
- * \sa absDeterminant(), MatrixBase::determinant()
- */
- typename MatrixType::RealScalar logAbsDeterminant() const;
-
- inline Index rows() const { return m_qr.rows(); }
- inline Index cols() const { return m_qr.cols(); }
- const HCoeffsType& hCoeffs() const { return m_hCoeffs; }
-
- protected:
- MatrixType m_qr;
- HCoeffsType m_hCoeffs;
- RowVectorType m_temp;
- bool m_isInitialized;
-};
-
-template<typename MatrixType>
-typename MatrixType::RealScalar HouseholderQR<MatrixType>::absDeterminant() const
-{
- eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
- eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
- return internal::abs(m_qr.diagonal().prod());
-}
-
-template<typename MatrixType>
-typename MatrixType::RealScalar HouseholderQR<MatrixType>::logAbsDeterminant() const
-{
- eigen_assert(m_isInitialized && "HouseholderQR is not initialized.");
- eigen_assert(m_qr.rows() == m_qr.cols() && "You can't take the determinant of a non-square matrix!");
- return m_qr.diagonal().cwiseAbs().array().log().sum();
-}
-
-namespace internal {
-
-/** \internal */
-template<typename MatrixQR, typename HCoeffs>
-void householder_qr_inplace_unblocked(MatrixQR& mat, HCoeffs& hCoeffs, typename MatrixQR::Scalar* tempData = 0)
-{
- typedef typename MatrixQR::Index Index;
- typedef typename MatrixQR::Scalar Scalar;
- typedef typename MatrixQR::RealScalar RealScalar;
- Index rows = mat.rows();
- Index cols = mat.cols();
- Index size = (std::min)(rows,cols);
-
- eigen_assert(hCoeffs.size() == size);
-
- typedef Matrix<Scalar,MatrixQR::ColsAtCompileTime,1> TempType;
- TempType tempVector;
- if(tempData==0)
- {
- tempVector.resize(cols);
- tempData = tempVector.data();
- }
-
- for(Index k = 0; k < size; ++k)
- {
- Index remainingRows = rows - k;
- Index remainingCols = cols - k - 1;
-
- RealScalar beta;
- mat.col(k).tail(remainingRows).makeHouseholderInPlace(hCoeffs.coeffRef(k), beta);
- mat.coeffRef(k,k) = beta;
-
- // apply H to remaining part of m_qr from the left
- mat.bottomRightCorner(remainingRows, remainingCols)
- .applyHouseholderOnTheLeft(mat.col(k).tail(remainingRows-1), hCoeffs.coeffRef(k), tempData+k+1);
- }
-}
-
-/** \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)
-{
- typedef typename MatrixQR::Index Index;
- typedef typename MatrixQR::Scalar Scalar;
- typedef typename MatrixQR::RealScalar RealScalar;
- 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)
- {
- tempVector.resize(cols);
- tempData = tempVector.data();
- }
-
- Index blockSize = (std::min)(maxBlockSize,size);
-
- 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
-
- // 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>
- : solve_retval_base<HouseholderQR<_MatrixType>, Rhs>
-{
- EIGEN_MAKE_SOLVE_HELPERS(HouseholderQR<_MatrixType>,Rhs)
-
- template<typename Dest> void evalTo(Dest& dst) const
- {
- const Index rows = dec().rows(), cols = dec().cols();
- const Index rank = (std::min)(rows, cols);
- eigen_assert(rhs().rows() == rows);
-
- typename Rhs::PlainObject c(rhs());
-
- // Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T
- c.applyOnTheLeft(householderSequence(
- dec().matrixQR().leftCols(rank),
- dec().hCoeffs().head(rank)).transpose()
- );
-
- dec().matrixQR()
- .topLeftCorner(rank, rank)
- .template triangularView<Upper>()
- .solveInPlace(c.topRows(rank));
-
- dst.topRows(rank) = c.topRows(rank);
- dst.bottomRows(cols-rank).setZero();
- }
-};
-
-} // end namespace internal
-
-template<typename MatrixType>
-HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const MatrixType& matrix)
-{
- Index rows = matrix.rows();
- Index cols = matrix.cols();
- Index size = (std::min)(rows,cols);
-
- m_qr = matrix;
- m_hCoeffs.resize(size);
-
- m_temp.resize(cols);
-
- internal::householder_qr_inplace_blocked(m_qr, m_hCoeffs, 48, m_temp.data());
-
- m_isInitialized = true;
- return *this;
-}
-
-/** \return the Householder QR decomposition of \c *this.
- *
- * \sa class HouseholderQR
- */
-template<typename Derived>
-const HouseholderQR<typename MatrixBase<Derived>::PlainObject>
-MatrixBase<Derived>::householderQr() const
-{
- return HouseholderQR<PlainObject>(eval());
-}
-
-
-#endif // EIGEN_QR_H
diff --git a/extern/Eigen3/Eigen/src/SVD/JacobiSVD.h b/extern/Eigen3/Eigen/src/SVD/JacobiSVD.h
deleted file mode 100644
index 5f61399988c..00000000000
--- a/extern/Eigen3/Eigen/src/SVD/JacobiSVD.h
+++ /dev/null
@@ -1,716 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_JACOBISVD_H
-#define EIGEN_JACOBISVD_H
-
-namespace internal {
-// forward declaration (needed by ICC)
-// the empty body is required by MSVC
-template<typename MatrixType, int QRPreconditioner,
- bool IsComplex = NumTraits<typename MatrixType::Scalar>::IsComplex>
-struct svd_precondition_2x2_block_to_be_real {};
-
-/*** QR preconditioners (R-SVD)
- ***
- *** Their role is to reduce the problem of computing the SVD to the case of a square matrix.
- *** This approach, known as R-SVD, is an optimization for rectangular-enough matrices, and is a requirement for
- *** JacobiSVD which by itself is only able to work on square matrices.
- ***/
-
-enum { PreconditionIfMoreColsThanRows, PreconditionIfMoreRowsThanCols };
-
-template<typename MatrixType, int QRPreconditioner, int Case>
-struct qr_preconditioner_should_do_anything
-{
- enum { a = MatrixType::RowsAtCompileTime != Dynamic &&
- MatrixType::ColsAtCompileTime != Dynamic &&
- MatrixType::ColsAtCompileTime <= MatrixType::RowsAtCompileTime,
- b = MatrixType::RowsAtCompileTime != Dynamic &&
- MatrixType::ColsAtCompileTime != Dynamic &&
- MatrixType::RowsAtCompileTime <= MatrixType::ColsAtCompileTime,
- ret = !( (QRPreconditioner == NoQRPreconditioner) ||
- (Case == PreconditionIfMoreColsThanRows && bool(a)) ||
- (Case == PreconditionIfMoreRowsThanCols && bool(b)) )
- };
-};
-
-template<typename MatrixType, int QRPreconditioner, int Case,
- bool DoAnything = qr_preconditioner_should_do_anything<MatrixType, QRPreconditioner, Case>::ret
-> struct qr_preconditioner_impl {};
-
-template<typename MatrixType, int QRPreconditioner, int Case>
-struct qr_preconditioner_impl<MatrixType, QRPreconditioner, Case, false>
-{
- static bool run(JacobiSVD<MatrixType, QRPreconditioner>&, const MatrixType&)
- {
- return false;
- }
-};
-
-/*** preconditioner using FullPivHouseholderQR ***/
-
-template<typename MatrixType>
-struct qr_preconditioner_impl<MatrixType, FullPivHouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
-{
- static bool run(JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
- {
- if(matrix.rows() > matrix.cols())
- {
- FullPivHouseholderQR<MatrixType> qr(matrix);
- svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
- if(svd.m_computeFullU) svd.m_matrixU = qr.matrixQ();
- if(svd.computeV()) svd.m_matrixV = qr.colsPermutation();
- return true;
- }
- return false;
- }
-};
-
-template<typename MatrixType>
-struct qr_preconditioner_impl<MatrixType, FullPivHouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
-{
- static bool run(JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
- {
- if(matrix.cols() > matrix.rows())
- {
- typedef Matrix<typename MatrixType::Scalar, MatrixType::ColsAtCompileTime, MatrixType::RowsAtCompileTime,
- MatrixType::Options, MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime>
- TransposeTypeWithSameStorageOrder;
- FullPivHouseholderQR<TransposeTypeWithSameStorageOrder> qr(matrix.adjoint());
- svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
- if(svd.m_computeFullV) svd.m_matrixV = qr.matrixQ();
- if(svd.computeU()) svd.m_matrixU = qr.colsPermutation();
- return true;
- }
- else return false;
- }
-};
-
-/*** preconditioner using ColPivHouseholderQR ***/
-
-template<typename MatrixType>
-struct qr_preconditioner_impl<MatrixType, ColPivHouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
-{
- static bool run(JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
- {
- if(matrix.rows() > matrix.cols())
- {
- ColPivHouseholderQR<MatrixType> qr(matrix);
- svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
- if(svd.m_computeFullU) svd.m_matrixU = qr.householderQ();
- else if(svd.m_computeThinU) {
- svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
- qr.householderQ().applyThisOnTheLeft(svd.m_matrixU);
- }
- if(svd.computeV()) svd.m_matrixV = qr.colsPermutation();
- return true;
- }
- return false;
- }
-};
-
-template<typename MatrixType>
-struct qr_preconditioner_impl<MatrixType, ColPivHouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
-{
- static bool run(JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner>& svd, const MatrixType& matrix)
- {
- if(matrix.cols() > matrix.rows())
- {
- typedef Matrix<typename MatrixType::Scalar, MatrixType::ColsAtCompileTime, MatrixType::RowsAtCompileTime,
- MatrixType::Options, MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime>
- TransposeTypeWithSameStorageOrder;
- ColPivHouseholderQR<TransposeTypeWithSameStorageOrder> qr(matrix.adjoint());
- svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
- if(svd.m_computeFullV) svd.m_matrixV = qr.householderQ();
- else if(svd.m_computeThinV) {
- svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
- qr.householderQ().applyThisOnTheLeft(svd.m_matrixV);
- }
- if(svd.computeU()) svd.m_matrixU = qr.colsPermutation();
- return true;
- }
- else return false;
- }
-};
-
-/*** preconditioner using HouseholderQR ***/
-
-template<typename MatrixType>
-struct qr_preconditioner_impl<MatrixType, HouseholderQRPreconditioner, PreconditionIfMoreRowsThanCols, true>
-{
- static bool run(JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd, const MatrixType& matrix)
- {
- if(matrix.rows() > matrix.cols())
- {
- HouseholderQR<MatrixType> qr(matrix);
- svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView<Upper>();
- if(svd.m_computeFullU) svd.m_matrixU = qr.householderQ();
- else if(svd.m_computeThinU) {
- svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols());
- qr.householderQ().applyThisOnTheLeft(svd.m_matrixU);
- }
- if(svd.computeV()) svd.m_matrixV.setIdentity(matrix.cols(), matrix.cols());
- return true;
- }
- return false;
- }
-};
-
-template<typename MatrixType>
-struct qr_preconditioner_impl<MatrixType, HouseholderQRPreconditioner, PreconditionIfMoreColsThanRows, true>
-{
- static bool run(JacobiSVD<MatrixType, HouseholderQRPreconditioner>& svd, const MatrixType& matrix)
- {
- if(matrix.cols() > matrix.rows())
- {
- typedef Matrix<typename MatrixType::Scalar, MatrixType::ColsAtCompileTime, MatrixType::RowsAtCompileTime,
- MatrixType::Options, MatrixType::MaxColsAtCompileTime, MatrixType::MaxRowsAtCompileTime>
- TransposeTypeWithSameStorageOrder;
- HouseholderQR<TransposeTypeWithSameStorageOrder> qr(matrix.adjoint());
- svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView<Upper>().adjoint();
- if(svd.m_computeFullV) svd.m_matrixV = qr.householderQ();
- else if(svd.m_computeThinV) {
- svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows());
- qr.householderQ().applyThisOnTheLeft(svd.m_matrixV);
- }
- if(svd.computeU()) svd.m_matrixU.setIdentity(matrix.rows(), matrix.rows());
- return true;
- }
- else return false;
- }
-};
-
-/*** 2x2 SVD implementation
- ***
- *** JacobiSVD consists in performing a series of 2x2 SVD subproblems
- ***/
-
-template<typename MatrixType, int QRPreconditioner>
-struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, false>
-{
- typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
- typedef typename SVD::Index Index;
- static void run(typename SVD::WorkMatrixType&, SVD&, Index, Index) {}
-};
-
-template<typename MatrixType, int QRPreconditioner>
-struct svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner, true>
-{
- typedef JacobiSVD<MatrixType, QRPreconditioner> SVD;
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
- typedef typename SVD::Index Index;
- static void run(typename SVD::WorkMatrixType& work_matrix, SVD& svd, Index p, Index q)
- {
- Scalar z;
- JacobiRotation<Scalar> rot;
- RealScalar n = sqrt(abs2(work_matrix.coeff(p,p)) + 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);
- z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
- work_matrix.row(q) *= z;
- if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
- }
- else
- {
- rot.c() = conj(work_matrix.coeff(p,p)) / n;
- rot.s() = work_matrix.coeff(q,p) / n;
- work_matrix.applyOnTheLeft(p,q,rot);
- if(svd.computeU()) svd.m_matrixU.applyOnTheRight(p,q,rot.adjoint());
- if(work_matrix.coeff(p,q) != Scalar(0))
- {
- Scalar z = abs(work_matrix.coeff(p,q)) / work_matrix.coeff(p,q);
- work_matrix.col(q) *= z;
- if(svd.computeV()) svd.m_matrixV.col(q) *= z;
- }
- if(work_matrix.coeff(q,q) != Scalar(0))
- {
- z = abs(work_matrix.coeff(q,q)) / work_matrix.coeff(q,q);
- work_matrix.row(q) *= z;
- if(svd.computeU()) svd.m_matrixU.col(q) *= conj(z);
- }
- }
- }
-};
-
-template<typename MatrixType, typename RealScalar, typename Index>
-void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q,
- JacobiRotation<RealScalar> *j_left,
- JacobiRotation<RealScalar> *j_right)
-{
- Matrix<RealScalar,2,2> m;
- m << real(matrix.coeff(p,p)), real(matrix.coeff(p,q)),
- real(matrix.coeff(q,p)), real(matrix.coeff(q,q));
- JacobiRotation<RealScalar> rot1;
- RealScalar t = m.coeff(0,0) + m.coeff(1,1);
- RealScalar d = m.coeff(1,0) - m.coeff(0,1);
- if(t == RealScalar(0))
- {
- rot1.c() = RealScalar(0);
- rot1.s() = d > RealScalar(0) ? RealScalar(1) : RealScalar(-1);
- }
- else
- {
- RealScalar u = d / t;
- rot1.c() = RealScalar(1) / sqrt(RealScalar(1) + abs2(u));
- rot1.s() = rot1.c() * u;
- }
- m.applyOnTheLeft(0,1,rot1);
- j_right->makeJacobi(m,0,1);
- *j_left = rot1 * j_right->transpose();
-}
-
-} // end namespace internal
-
-/** \ingroup SVD_Module
- *
- *
- * \class JacobiSVD
- *
- * \brief Two-sided Jacobi SVD decomposition of a rectangular matrix
- *
- * \param MatrixType the type of the matrix of which we are computing the SVD decomposition
- * \param QRPreconditioner this optional parameter allows to specify the type of QR decomposition that will be used internally
- * for the R-SVD step for non-square matrices. See discussion of possible values below.
- *
- * SVD decomposition consists in decomposing any n-by-p matrix \a A as a product
- * \f[ A = U S V^* \f]
- * where \a U is a n-by-n unitary, \a V is a p-by-p unitary, and \a S is a n-by-p real positive matrix which is zero outside of its main diagonal;
- * the diagonal entries of S are known as the \em singular \em values of \a A and the columns of \a U and \a V are known as the left
- * and right \em singular \em vectors of \a A respectively.
- *
- * Singular values are always sorted in decreasing order.
- *
- * This JacobiSVD decomposition computes only the singular values by default. If you want \a U or \a V, you need to ask for them explicitly.
- *
- * You can ask for only \em thin \a U or \a V to be computed, meaning the following. In case of a rectangular n-by-p matrix, letting \a m be the
- * smaller value among \a n and \a p, there are only \a m singular vectors; the remaining columns of \a U and \a V do not correspond to actual
- * singular vectors. Asking for \em thin \a U or \a V means asking for only their \a m first columns to be formed. So \a U is then a n-by-m matrix,
- * and \a V is then a p-by-m matrix. Notice that thin \a U and \a V are all you need for (least squares) solving.
- *
- * Here's an example demonstrating basic usage:
- * \include JacobiSVD_basic.cpp
- * Output: \verbinclude JacobiSVD_basic.out
- *
- * This JacobiSVD class is a two-sided Jacobi R-SVD decomposition, ensuring optimal reliability and accuracy. The downside is that it's slower than
- * bidiagonalizing SVD algorithms for large square matrices; however its complexity is still \f$ O(n^2p) \f$ where \a n is the smaller dimension and
- * \a p is the greater dimension, meaning that it is still of the same order of complexity as the faster bidiagonalizing R-SVD algorithms.
- * In particular, like any R-SVD, it takes advantage of non-squareness in that its complexity is only linear in the greater dimension.
- *
- * If the input matrix has inf or nan coefficients, the result of the computation is undefined, but the computation is guaranteed to
- * terminate in finite (and reasonable) time.
- *
- * The possible values for QRPreconditioner are:
- * \li ColPivHouseholderQRPreconditioner is the default. In practice it's very safe. It uses column-pivoting QR.
- * \li FullPivHouseholderQRPreconditioner, is the safest and slowest. It uses full-pivoting QR.
- * Contrary to other QRs, it doesn't allow computing thin unitaries.
- * \li HouseholderQRPreconditioner is the fastest, and less safe and accurate than the pivoting variants. It uses non-pivoting QR.
- * This is very similar in safety and accuracy to the bidiagonalization process used by bidiagonalizing SVD algorithms (since bidiagonalization
- * is inherently non-pivoting). However the resulting SVD is still more reliable than bidiagonalizing SVDs because the Jacobi-based iterarive
- * process is more reliable than the optimized bidiagonal SVD iterations.
- * \li NoQRPreconditioner allows not to use a QR preconditioner at all. This is useful if you know that you will only be computing
- * JacobiSVD decompositions of square matrices. Non-square matrices require a QR preconditioner. Using this option will result in
- * faster compilation and smaller executable code. It won't significantly speed up computation, since JacobiSVD is always checking
- * if QR preconditioning is needed before applying it anyway.
- *
- * \sa MatrixBase::jacobiSvd()
- */
-template<typename _MatrixType, int QRPreconditioner> class JacobiSVD
-{
- public:
-
- typedef _MatrixType MatrixType;
- typedef typename MatrixType::Scalar Scalar;
- typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
- typedef typename MatrixType::Index Index;
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- DiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(RowsAtCompileTime,ColsAtCompileTime),
- MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
- MaxDiagSizeAtCompileTime = EIGEN_SIZE_MIN_PREFER_FIXED(MaxRowsAtCompileTime,MaxColsAtCompileTime),
- MatrixOptions = MatrixType::Options
- };
-
- typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime,
- MatrixOptions, MaxRowsAtCompileTime, MaxRowsAtCompileTime>
- MatrixUType;
- typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime,
- MatrixOptions, MaxColsAtCompileTime, MaxColsAtCompileTime>
- MatrixVType;
- typedef typename internal::plain_diag_type<MatrixType, RealScalar>::type SingularValuesType;
- typedef typename internal::plain_row_type<MatrixType>::type RowType;
- typedef typename internal::plain_col_type<MatrixType>::type ColType;
- typedef Matrix<Scalar, DiagSizeAtCompileTime, DiagSizeAtCompileTime,
- MatrixOptions, MaxDiagSizeAtCompileTime, MaxDiagSizeAtCompileTime>
- WorkMatrixType;
-
- /** \brief Default Constructor.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via JacobiSVD::compute(const MatrixType&).
- */
- JacobiSVD()
- : m_isInitialized(false),
- m_isAllocated(false),
- m_computationOptions(0),
- m_rows(-1), m_cols(-1)
- {}
-
-
- /** \brief Default Constructor with memory preallocation
- *
- * Like the default constructor but with preallocation of the internal data
- * according to the specified problem size.
- * \sa JacobiSVD()
- */
- JacobiSVD(Index rows, Index cols, unsigned int computationOptions = 0)
- : m_isInitialized(false),
- m_isAllocated(false),
- m_computationOptions(0),
- m_rows(-1), m_cols(-1)
- {
- allocate(rows, cols, computationOptions);
- }
-
- /** \brief Constructor performing the decomposition of given matrix.
- *
- * \param matrix the matrix to decompose
- * \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
- * By default, none is computed. This is a bit-field, the possible bits are #ComputeFullU, #ComputeThinU,
- * #ComputeFullV, #ComputeThinV.
- *
- * Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
- * available with the (non-default) FullPivHouseholderQR preconditioner.
- */
- JacobiSVD(const MatrixType& matrix, unsigned int computationOptions = 0)
- : m_isInitialized(false),
- m_isAllocated(false),
- m_computationOptions(0),
- m_rows(-1), m_cols(-1)
- {
- compute(matrix, computationOptions);
- }
-
- /** \brief Method performing the decomposition of given matrix using custom options.
- *
- * \param matrix the matrix to decompose
- * \param computationOptions optional parameter allowing to specify if you want full or thin U or V unitaries to be computed.
- * By default, none is computed. This is a bit-field, the possible bits are #ComputeFullU, #ComputeThinU,
- * #ComputeFullV, #ComputeThinV.
- *
- * Thin unitaries are only available if your matrix type has a Dynamic number of columns (for example MatrixXf). They also are not
- * available with the (non-default) FullPivHouseholderQR preconditioner.
- */
- JacobiSVD& compute(const MatrixType& matrix, unsigned int computationOptions);
-
- /** \brief Method performing the decomposition of given matrix using current options.
- *
- * \param matrix the matrix to decompose
- *
- * This method uses the current \a computationOptions, as already passed to the constructor or to compute(const MatrixType&, unsigned int).
- */
- JacobiSVD& compute(const MatrixType& matrix)
- {
- return compute(matrix, m_computationOptions);
- }
-
- /** \returns the \a U matrix.
- *
- * For the SVD decomposition of a n-by-p matrix, letting \a m be the minimum of \a n and \a p,
- * the U matrix is n-by-n if you asked for #ComputeFullU, and is n-by-m if you asked for #ComputeThinU.
- *
- * The \a m first columns of \a U are the left singular vectors of the matrix being decomposed.
- *
- * This method asserts that you asked for \a U to be computed.
- */
- const MatrixUType& matrixU() const
- {
- eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
- eigen_assert(computeU() && "This JacobiSVD decomposition didn't compute U. Did you ask for it?");
- return m_matrixU;
- }
-
- /** \returns the \a V matrix.
- *
- * For the SVD decomposition of a n-by-p matrix, letting \a m be the minimum of \a n and \a p,
- * the V matrix is p-by-p if you asked for #ComputeFullV, and is p-by-m if you asked for ComputeThinV.
- *
- * The \a m first columns of \a V are the right singular vectors of the matrix being decomposed.
- *
- * This method asserts that you asked for \a V to be computed.
- */
- const MatrixVType& matrixV() const
- {
- eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
- eigen_assert(computeV() && "This JacobiSVD decomposition didn't compute V. Did you ask for it?");
- return m_matrixV;
- }
-
- /** \returns the vector of singular values.
- *
- * For the SVD decomposition of a n-by-p matrix, letting \a m be the minimum of \a n and \a p, the
- * returned vector has size \a m. Singular values are always sorted in decreasing order.
- */
- const SingularValuesType& singularValues() const
- {
- eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
- return m_singularValues;
- }
-
- /** \returns true if \a U (full or thin) is asked for in this SVD decomposition */
- inline bool computeU() const { return m_computeFullU || m_computeThinU; }
- /** \returns true if \a V (full or thin) is asked for in this SVD decomposition */
- inline bool computeV() const { return m_computeFullV || m_computeThinV; }
-
- /** \returns a (least squares) solution of \f$ A x = b \f$ using the current SVD decomposition of A.
- *
- * \param b the right-hand-side of the equation to solve.
- *
- * \note Solving requires both U and V to be computed. Thin U and V are enough, there is no need for full U or V.
- *
- * \note SVD solving is implicitly least-squares. Thus, this method serves both purposes of exact solving and least-squares solving.
- * In other words, the returned solution is guaranteed to minimize the Euclidean norm \f$ \Vert A x - b \Vert \f$.
- */
- template<typename Rhs>
- inline const internal::solve_retval<JacobiSVD, Rhs>
- solve(const MatrixBase<Rhs>& b) const
- {
- eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
- eigen_assert(computeU() && computeV() && "JacobiSVD::solve() requires both unitaries U and V to be computed (thin unitaries suffice).");
- return internal::solve_retval<JacobiSVD, Rhs>(*this, b.derived());
- }
-
- /** \returns the number of singular values that are not exactly 0 */
- Index nonzeroSingularValues() const
- {
- eigen_assert(m_isInitialized && "JacobiSVD is not initialized.");
- return m_nonzeroSingularValues;
- }
-
- inline Index rows() const { return m_rows; }
- inline Index cols() const { return m_cols; }
-
- private:
- void allocate(Index rows, Index cols, unsigned int computationOptions);
-
- protected:
- MatrixUType m_matrixU;
- MatrixVType m_matrixV;
- SingularValuesType m_singularValues;
- WorkMatrixType m_workMatrix;
- bool m_isInitialized, m_isAllocated;
- bool m_computeFullU, m_computeThinU;
- bool m_computeFullV, m_computeThinV;
- unsigned int m_computationOptions;
- Index m_nonzeroSingularValues, m_rows, m_cols, m_diagSize;
-
- template<typename __MatrixType, int _QRPreconditioner, bool _IsComplex>
- friend struct internal::svd_precondition_2x2_block_to_be_real;
- template<typename __MatrixType, int _QRPreconditioner, int _Case, bool _DoAnything>
- friend struct internal::qr_preconditioner_impl;
-};
-
-template<typename MatrixType, int QRPreconditioner>
-void JacobiSVD<MatrixType, QRPreconditioner>::allocate(Index rows, Index cols, unsigned int computationOptions)
-{
- eigen_assert(rows >= 0 && cols >= 0);
-
- if (m_isAllocated &&
- rows == m_rows &&
- cols == m_cols &&
- computationOptions == m_computationOptions)
- {
- return;
- }
-
- m_rows = rows;
- m_cols = cols;
- m_isInitialized = false;
- m_isAllocated = true;
- m_computationOptions = computationOptions;
- m_computeFullU = (computationOptions & ComputeFullU) != 0;
- m_computeThinU = (computationOptions & ComputeThinU) != 0;
- m_computeFullV = (computationOptions & ComputeFullV) != 0;
- m_computeThinV = (computationOptions & ComputeThinV) != 0;
- eigen_assert(!(m_computeFullU && m_computeThinU) && "JacobiSVD: you can't ask for both full and thin U");
- eigen_assert(!(m_computeFullV && m_computeThinV) && "JacobiSVD: you can't ask for both full and thin V");
- eigen_assert(EIGEN_IMPLIES(m_computeThinU || m_computeThinV, MatrixType::ColsAtCompileTime==Dynamic) &&
- "JacobiSVD: thin U and V are only available when your matrix has a dynamic number of columns.");
- if (QRPreconditioner == FullPivHouseholderQRPreconditioner)
- {
- eigen_assert(!(m_computeThinU || m_computeThinV) &&
- "JacobiSVD: can't compute thin U or thin V with the FullPivHouseholderQR preconditioner. "
- "Use the ColPivHouseholderQR preconditioner instead.");
- }
- m_diagSize = (std::min)(m_rows, m_cols);
- m_singularValues.resize(m_diagSize);
- m_matrixU.resize(m_rows, m_computeFullU ? m_rows
- : m_computeThinU ? m_diagSize
- : 0);
- m_matrixV.resize(m_cols, m_computeFullV ? m_cols
- : m_computeThinV ? m_diagSize
- : 0);
- m_workMatrix.resize(m_diagSize, m_diagSize);
-}
-
-template<typename MatrixType, int QRPreconditioner>
-JacobiSVD<MatrixType, QRPreconditioner>&
-JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType& matrix, unsigned int computationOptions)
-{
- allocate(matrix.rows(), matrix.cols(), computationOptions);
-
- // currently we stop when we reach precision 2*epsilon as the last bit of precision can require an unreasonable number of iterations,
- // only worsening the precision of U and V as we accumulate more rotations
- const RealScalar precision = RealScalar(2) * NumTraits<Scalar>::epsilon();
-
- /*** step 1. The R-SVD step: we use a QR decomposition to reduce to the case of a square matrix */
-
- if(!internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreColsThanRows>::run(*this, matrix)
- && !internal::qr_preconditioner_impl<MatrixType, QRPreconditioner, internal::PreconditionIfMoreRowsThanCols>::run(*this, matrix))
- {
- m_workMatrix = matrix.block(0,0,m_diagSize,m_diagSize);
- 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);
- if(m_computeThinV) m_matrixV.setIdentity(m_cols, m_diagSize);
- }
-
- /*** step 2. The main Jacobi SVD iteration. ***/
-
- bool finished = false;
- while(!finished)
- {
- finished = true;
-
- // do a sweep: for all index pairs (p,q), perform SVD of the corresponding 2x2 sub-matrix
-
- for(Index p = 1; p < m_diagSize; ++p)
- {
- for(Index q = 0; q < p; ++q)
- {
- // if this 2x2 sub-matrix is not diagonal already...
- // notice that this comparison will evaluate to false if any NaN is involved, ensuring that NaN's don't
- // keep us iterating forever.
- using std::max;
- if((max)(internal::abs(m_workMatrix.coeff(p,q)),internal::abs(m_workMatrix.coeff(q,p)))
- > (max)(internal::abs(m_workMatrix.coeff(p,p)),internal::abs(m_workMatrix.coeff(q,q)))*precision)
- {
- finished = false;
-
- // perform SVD decomposition of 2x2 sub-matrix corresponding to indices p,q to make it diagonal
- internal::svd_precondition_2x2_block_to_be_real<MatrixType, QRPreconditioner>::run(m_workMatrix, *this, p, q);
- JacobiRotation<RealScalar> j_left, j_right;
- internal::real_2x2_jacobi_svd(m_workMatrix, p, q, &j_left, &j_right);
-
- // accumulate resulting Jacobi rotations
- m_workMatrix.applyOnTheLeft(p,q,j_left);
- if(computeU()) m_matrixU.applyOnTheRight(p,q,j_left.transpose());
-
- m_workMatrix.applyOnTheRight(p,q,j_right);
- if(computeV()) m_matrixV.applyOnTheRight(p,q,j_right);
- }
- }
- }
- }
-
- /*** step 3. The work matrix is now diagonal, so ensure it's positive so its diagonal entries are the singular values ***/
-
- for(Index i = 0; i < m_diagSize; ++i)
- {
- RealScalar a = internal::abs(m_workMatrix.coeff(i,i));
- m_singularValues.coeffRef(i) = a;
- if(computeU() && (a!=RealScalar(0))) m_matrixU.col(i) *= m_workMatrix.coeff(i,i)/a;
- }
-
- /*** step 4. Sort singular values in descending order and compute the number of nonzero singular values ***/
-
- m_nonzeroSingularValues = m_diagSize;
- for(Index i = 0; i < m_diagSize; i++)
- {
- Index pos;
- RealScalar maxRemainingSingularValue = m_singularValues.tail(m_diagSize-i).maxCoeff(&pos);
- if(maxRemainingSingularValue == RealScalar(0))
- {
- m_nonzeroSingularValues = i;
- break;
- }
- if(pos)
- {
- pos += i;
- std::swap(m_singularValues.coeffRef(i), m_singularValues.coeffRef(pos));
- if(computeU()) m_matrixU.col(pos).swap(m_matrixU.col(i));
- if(computeV()) m_matrixV.col(pos).swap(m_matrixV.col(i));
- }
- }
-
- m_isInitialized = true;
- return *this;
-}
-
-namespace internal {
-template<typename _MatrixType, int QRPreconditioner, typename Rhs>
-struct solve_retval<JacobiSVD<_MatrixType, QRPreconditioner>, Rhs>
- : solve_retval_base<JacobiSVD<_MatrixType, QRPreconditioner>, Rhs>
-{
- typedef JacobiSVD<_MatrixType, QRPreconditioner> JacobiSVDType;
- EIGEN_MAKE_SOLVE_HELPERS(JacobiSVDType,Rhs)
-
- template<typename Dest> void evalTo(Dest& dst) const
- {
- eigen_assert(rhs().rows() == dec().rows());
-
- // A = U S V^*
- // So A^{-1} = V S^{-1} U^*
-
- Index diagSize = (std::min)(dec().rows(), dec().cols());
- typename JacobiSVDType::SingularValuesType invertedSingVals(diagSize);
-
- Index nonzeroSingVals = dec().nonzeroSingularValues();
- invertedSingVals.head(nonzeroSingVals) = dec().singularValues().head(nonzeroSingVals).array().inverse();
- invertedSingVals.tail(diagSize - nonzeroSingVals).setZero();
-
- dst = dec().matrixV().leftCols(diagSize)
- * invertedSingVals.asDiagonal()
- * dec().matrixU().leftCols(diagSize).adjoint()
- * rhs();
- }
-};
-} // end namespace internal
-
-template<typename Derived>
-JacobiSVD<typename MatrixBase<Derived>::PlainObject>
-MatrixBase<Derived>::jacobiSvd(unsigned int computationOptions) const
-{
- return JacobiSVD<PlainObject>(*this, computationOptions);
-}
-
-
-
-#endif // EIGEN_JACOBISVD_H
diff --git a/extern/Eigen3/Eigen/src/SVD/UpperBidiagonalization.h b/extern/Eigen3/Eigen/src/SVD/UpperBidiagonalization.h
deleted file mode 100644
index 2de197da953..00000000000
--- a/extern/Eigen3/Eigen/src/SVD/UpperBidiagonalization.h
+++ /dev/null
@@ -1,159 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_BIDIAGONALIZATION_H
-#define EIGEN_BIDIAGONALIZATION_H
-
-namespace internal {
-// UpperBidiagonalization will probably be replaced by a Bidiagonalization class, don't want to make it stable API.
-// At the same time, it's useful to keep for now as it's about the only thing that is testing the BandMatrix class.
-
-template<typename _MatrixType> class UpperBidiagonalization
-{
- public:
-
- typedef _MatrixType MatrixType;
- enum {
- RowsAtCompileTime = MatrixType::RowsAtCompileTime,
- ColsAtCompileTime = MatrixType::ColsAtCompileTime,
- ColsAtCompileTimeMinusOne = internal::decrement_size<ColsAtCompileTime>::ret
- };
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::RealScalar RealScalar;
- typedef typename MatrixType::Index Index;
- typedef Matrix<Scalar, 1, ColsAtCompileTime> RowVectorType;
- typedef Matrix<Scalar, RowsAtCompileTime, 1> ColVectorType;
- typedef BandMatrix<RealScalar, ColsAtCompileTime, ColsAtCompileTime, 1, 0> BidiagonalType;
- typedef Matrix<Scalar, ColsAtCompileTime, 1> DiagVectorType;
- typedef Matrix<Scalar, ColsAtCompileTimeMinusOne, 1> SuperDiagVectorType;
- typedef HouseholderSequence<
- const MatrixType,
- CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, const Diagonal<const MatrixType,0> >
- > HouseholderUSequenceType;
- typedef HouseholderSequence<
- const MatrixType,
- Diagonal<const MatrixType,1>,
- OnTheRight
- > HouseholderVSequenceType;
-
- /**
- * \brief Default Constructor.
- *
- * The default constructor is useful in cases in which the user intends to
- * perform decompositions via Bidiagonalization::compute(const MatrixType&).
- */
- UpperBidiagonalization() : m_householder(), m_bidiagonal(), m_isInitialized(false) {}
-
- UpperBidiagonalization(const MatrixType& matrix)
- : m_householder(matrix.rows(), matrix.cols()),
- m_bidiagonal(matrix.cols(), matrix.cols()),
- m_isInitialized(false)
- {
- compute(matrix);
- }
-
- UpperBidiagonalization& compute(const MatrixType& matrix);
-
- const MatrixType& householder() const { return m_householder; }
- const BidiagonalType& bidiagonal() const { return m_bidiagonal; }
-
- const HouseholderUSequenceType householderU() const
- {
- eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized.");
- return HouseholderUSequenceType(m_householder, m_householder.diagonal().conjugate());
- }
-
- const HouseholderVSequenceType householderV() // const here gives nasty errors and i'm lazy
- {
- eigen_assert(m_isInitialized && "UpperBidiagonalization is not initialized.");
- return HouseholderVSequenceType(m_householder, m_householder.const_derived().template diagonal<1>())
- .setLength(m_householder.cols()-1)
- .setShift(1);
- }
-
- protected:
- MatrixType m_householder;
- BidiagonalType m_bidiagonal;
- bool m_isInitialized;
-};
-
-template<typename _MatrixType>
-UpperBidiagonalization<_MatrixType>& UpperBidiagonalization<_MatrixType>::compute(const _MatrixType& matrix)
-{
- Index rows = matrix.rows();
- Index cols = matrix.cols();
-
- eigen_assert(rows >= cols && "UpperBidiagonalization is only for matrices satisfying rows>=cols.");
-
- m_householder = matrix;
-
- ColVectorType temp(rows);
-
- for (Index k = 0; /* breaks at k==cols-1 below */ ; ++k)
- {
- Index remainingRows = rows - k;
- Index remainingCols = cols - k - 1;
-
- // construct left householder transform in-place in m_householder
- m_householder.col(k).tail(remainingRows)
- .makeHouseholderInPlace(m_householder.coeffRef(k,k),
- m_bidiagonal.template diagonal<0>().coeffRef(k));
- // apply householder transform to remaining part of m_householder on the left
- m_householder.bottomRightCorner(remainingRows, remainingCols)
- .applyHouseholderOnTheLeft(m_householder.col(k).tail(remainingRows-1),
- m_householder.coeff(k,k),
- temp.data());
-
- if(k == cols-1) break;
-
- // construct right householder transform in-place in m_householder
- m_householder.row(k).tail(remainingCols)
- .makeHouseholderInPlace(m_householder.coeffRef(k,k+1),
- m_bidiagonal.template diagonal<1>().coeffRef(k));
- // apply householder transform to remaining part of m_householder on the left
- m_householder.bottomRightCorner(remainingRows-1, remainingCols)
- .applyHouseholderOnTheRight(m_householder.row(k).tail(remainingCols-1).transpose(),
- m_householder.coeff(k,k+1),
- temp.data());
- }
- m_isInitialized = true;
- return *this;
-}
-
-#if 0
-/** \return the Householder QR decomposition of \c *this.
- *
- * \sa class Bidiagonalization
- */
-template<typename Derived>
-const UpperBidiagonalization<typename MatrixBase<Derived>::PlainObject>
-MatrixBase<Derived>::bidiagonalization() const
-{
- return UpperBidiagonalization<PlainObject>(eval());
-}
-#endif
-
-} // end namespace internal
-
-#endif // EIGEN_BIDIAGONALIZATION_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseCwiseBinaryOp.h b/extern/Eigen3/Eigen/src/Sparse/SparseCwiseBinaryOp.h
deleted file mode 100644
index cde5bbc0300..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/SparseCwiseBinaryOp.h
+++ /dev/null
@@ -1,375 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSE_CWISE_BINARY_OP_H
-#define EIGEN_SPARSE_CWISE_BINARY_OP_H
-
-// Here we have to handle 3 cases:
-// 1 - sparse op dense
-// 2 - dense op sparse
-// 3 - sparse op sparse
-// We also need to implement a 4th iterator for:
-// 4 - dense op dense
-// Finally, we also need to distinguish between the product and other operations :
-// configuration returned mode
-// 1 - sparse op dense product sparse
-// generic dense
-// 2 - dense op sparse product sparse
-// generic dense
-// 3 - sparse op sparse product sparse
-// generic sparse
-// 4 - dense op dense product dense
-// generic dense
-
-namespace internal {
-
-template<> struct promote_storage_type<Dense,Sparse>
-{ typedef Sparse ret; };
-
-template<> struct promote_storage_type<Sparse,Dense>
-{ typedef Sparse ret; };
-
-template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived,
- typename _LhsStorageMode = typename traits<Lhs>::StorageKind,
- typename _RhsStorageMode = typename traits<Rhs>::StorageKind>
-class sparse_cwise_binary_op_inner_iterator_selector;
-
-} // end namespace internal
-
-template<typename BinaryOp, typename Lhs, typename Rhs>
-class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Sparse>
- : public SparseMatrixBase<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
-{
- public:
- class InnerIterator;
- typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> Derived;
- EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
-};
-
-template<typename BinaryOp, typename Lhs, typename Rhs>
-class CwiseBinaryOpImpl<BinaryOp,Lhs,Rhs,Sparse>::InnerIterator
- : public internal::sparse_cwise_binary_op_inner_iterator_selector<BinaryOp,Lhs,Rhs,typename CwiseBinaryOpImpl<BinaryOp,Lhs,Rhs,Sparse>::InnerIterator>
-{
- public:
- typedef typename Lhs::Index Index;
- typedef internal::sparse_cwise_binary_op_inner_iterator_selector<
- BinaryOp,Lhs,Rhs, InnerIterator> Base;
-
- EIGEN_STRONG_INLINE InnerIterator(const CwiseBinaryOpImpl& binOp, Index outer)
- : Base(binOp.derived(),outer)
- {}
-};
-
-/***************************************************************************
-* Implementation of inner-iterators
-***************************************************************************/
-
-// template<typename T> struct internal::func_is_conjunction { enum { ret = false }; };
-// template<typename T> struct internal::func_is_conjunction<internal::scalar_product_op<T> > { enum { ret = true }; };
-
-// TODO generalize the internal::scalar_product_op specialization to all conjunctions if any !
-
-namespace internal {
-
-// sparse - sparse (generic)
-template<typename BinaryOp, typename Lhs, typename Rhs, typename Derived>
-class sparse_cwise_binary_op_inner_iterator_selector<BinaryOp, Lhs, Rhs, Derived, Sparse, Sparse>
-{
- typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> CwiseBinaryXpr;
- typedef typename traits<CwiseBinaryXpr>::Scalar Scalar;
- typedef typename traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
- typedef typename traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
- typedef typename _LhsNested::InnerIterator LhsIterator;
- typedef typename _RhsNested::InnerIterator RhsIterator;
- typedef typename Lhs::Index Index;
-
- public:
-
- EIGEN_STRONG_INLINE sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, Index outer)
- : m_lhsIter(xpr.lhs(),outer), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor())
- {
- this->operator++();
- }
-
- EIGEN_STRONG_INLINE Derived& operator++()
- {
- if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index()))
- {
- m_id = m_lhsIter.index();
- m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
- ++m_lhsIter;
- ++m_rhsIter;
- }
- else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index())))
- {
- m_id = m_lhsIter.index();
- m_value = m_functor(m_lhsIter.value(), Scalar(0));
- ++m_lhsIter;
- }
- else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index())))
- {
- m_id = m_rhsIter.index();
- m_value = m_functor(Scalar(0), m_rhsIter.value());
- ++m_rhsIter;
- }
- else
- {
- m_value = 0; // this is to avoid a compilation warning
- m_id = -1;
- }
- return *static_cast<Derived*>(this);
- }
-
- EIGEN_STRONG_INLINE Scalar value() const { return m_value; }
-
- EIGEN_STRONG_INLINE Index index() const { return m_id; }
- EIGEN_STRONG_INLINE Index row() const { return Lhs::IsRowMajor ? m_lhsIter.row() : index(); }
- EIGEN_STRONG_INLINE Index col() const { return Lhs::IsRowMajor ? index() : m_lhsIter.col(); }
-
- EIGEN_STRONG_INLINE operator bool() const { return m_id>=0; }
-
- protected:
- LhsIterator m_lhsIter;
- RhsIterator m_rhsIter;
- const BinaryOp& m_functor;
- Scalar m_value;
- Index m_id;
-};
-
-// sparse - sparse (product)
-template<typename T, typename Lhs, typename Rhs, typename Derived>
-class sparse_cwise_binary_op_inner_iterator_selector<scalar_product_op<T>, Lhs, Rhs, Derived, Sparse, Sparse>
-{
- typedef scalar_product_op<T> BinaryFunc;
- typedef CwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
- typedef typename CwiseBinaryXpr::Scalar Scalar;
- typedef typename traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
- typedef typename _LhsNested::InnerIterator LhsIterator;
- typedef typename traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
- typedef typename _RhsNested::InnerIterator RhsIterator;
- typedef typename Lhs::Index Index;
- public:
-
- EIGEN_STRONG_INLINE sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, Index outer)
- : m_lhsIter(xpr.lhs(),outer), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor())
- {
- while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
- {
- if (m_lhsIter.index() < m_rhsIter.index())
- ++m_lhsIter;
- else
- ++m_rhsIter;
- }
- }
-
- EIGEN_STRONG_INLINE Derived& operator++()
- {
- ++m_lhsIter;
- ++m_rhsIter;
- while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index()))
- {
- if (m_lhsIter.index() < m_rhsIter.index())
- ++m_lhsIter;
- else
- ++m_rhsIter;
- }
- return *static_cast<Derived*>(this);
- }
-
- EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }
-
- EIGEN_STRONG_INLINE Index index() const { return m_lhsIter.index(); }
- EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
- EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }
-
- EIGEN_STRONG_INLINE operator bool() const { return (m_lhsIter && m_rhsIter); }
-
- protected:
- LhsIterator m_lhsIter;
- RhsIterator m_rhsIter;
- const BinaryFunc& m_functor;
-};
-
-// sparse - dense (product)
-template<typename T, typename Lhs, typename Rhs, typename Derived>
-class sparse_cwise_binary_op_inner_iterator_selector<scalar_product_op<T>, Lhs, Rhs, Derived, Sparse, Dense>
-{
- typedef scalar_product_op<T> BinaryFunc;
- typedef CwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
- typedef typename CwiseBinaryXpr::Scalar Scalar;
- typedef typename traits<CwiseBinaryXpr>::_LhsNested _LhsNested;
- typedef typename traits<CwiseBinaryXpr>::RhsNested RhsNested;
- typedef typename _LhsNested::InnerIterator LhsIterator;
- typedef typename Lhs::Index Index;
- enum { IsRowMajor = (int(Lhs::Flags)&RowMajorBit)==RowMajorBit };
- public:
-
- EIGEN_STRONG_INLINE sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, Index outer)
- : m_rhs(xpr.rhs()), m_lhsIter(xpr.lhs(),outer), m_functor(xpr.functor()), m_outer(outer)
- {}
-
- EIGEN_STRONG_INLINE Derived& operator++()
- {
- ++m_lhsIter;
- return *static_cast<Derived*>(this);
- }
-
- EIGEN_STRONG_INLINE Scalar value() const
- { return m_functor(m_lhsIter.value(),
- m_rhs.coeff(IsRowMajor?m_outer:m_lhsIter.index(),IsRowMajor?m_lhsIter.index():m_outer)); }
-
- EIGEN_STRONG_INLINE Index index() const { return m_lhsIter.index(); }
- EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
- EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }
-
- EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; }
-
- protected:
- const RhsNested m_rhs;
- LhsIterator m_lhsIter;
- const BinaryFunc m_functor;
- const Index m_outer;
-};
-
-// sparse - dense (product)
-template<typename T, typename Lhs, typename Rhs, typename Derived>
-class sparse_cwise_binary_op_inner_iterator_selector<scalar_product_op<T>, Lhs, Rhs, Derived, Dense, Sparse>
-{
- typedef scalar_product_op<T> BinaryFunc;
- typedef CwiseBinaryOp<BinaryFunc, Lhs, Rhs> CwiseBinaryXpr;
- typedef typename CwiseBinaryXpr::Scalar Scalar;
- typedef typename traits<CwiseBinaryXpr>::_RhsNested _RhsNested;
- typedef typename _RhsNested::InnerIterator RhsIterator;
- typedef typename Lhs::Index Index;
-
- enum { IsRowMajor = (int(Rhs::Flags)&RowMajorBit)==RowMajorBit };
- public:
-
- EIGEN_STRONG_INLINE sparse_cwise_binary_op_inner_iterator_selector(const CwiseBinaryXpr& xpr, Index outer)
- : m_xpr(xpr), m_rhsIter(xpr.rhs(),outer), m_functor(xpr.functor()), m_outer(outer)
- {}
-
- EIGEN_STRONG_INLINE Derived& operator++()
- {
- ++m_rhsIter;
- return *static_cast<Derived*>(this);
- }
-
- EIGEN_STRONG_INLINE Scalar value() const
- { return m_functor(m_xpr.lhs().coeff(IsRowMajor?m_outer:m_rhsIter.index(),IsRowMajor?m_rhsIter.index():m_outer), m_rhsIter.value()); }
-
- EIGEN_STRONG_INLINE Index index() const { return m_rhsIter.index(); }
- EIGEN_STRONG_INLINE Index row() const { return m_rhsIter.row(); }
- EIGEN_STRONG_INLINE Index col() const { return m_rhsIter.col(); }
-
- EIGEN_STRONG_INLINE operator bool() const { return m_rhsIter; }
-
- protected:
- const CwiseBinaryXpr& m_xpr;
- RhsIterator m_rhsIter;
- const BinaryFunc& m_functor;
- const Index m_outer;
-};
-
-} // end namespace internal
-
-/***************************************************************************
-* Implementation of SparseMatrixBase and SparseCwise functions/operators
-***************************************************************************/
-
-// template<typename Derived>
-// template<typename OtherDerived>
-// EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_difference_op<typename internal::traits<Derived>::Scalar>,
-// Derived, OtherDerived>
-// SparseMatrixBase<Derived>::operator-(const SparseMatrixBase<OtherDerived> &other) const
-// {
-// return CwiseBinaryOp<internal::scalar_difference_op<Scalar>,
-// Derived, OtherDerived>(derived(), other.derived());
-// }
-
-template<typename Derived>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE Derived &
-SparseMatrixBase<Derived>::operator-=(const SparseMatrixBase<OtherDerived> &other)
-{
- return *this = derived() - other.derived();
-}
-
-// template<typename Derived>
-// template<typename OtherDerived>
-// EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_sum_op<typename internal::traits<Derived>::Scalar>, Derived, OtherDerived>
-// SparseMatrixBase<Derived>::operator+(const SparseMatrixBase<OtherDerived> &other) const
-// {
-// return CwiseBinaryOp<internal::scalar_sum_op<Scalar>, Derived, OtherDerived>(derived(), other.derived());
-// }
-
-template<typename Derived>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE Derived &
-SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& other)
-{
- return *this = derived() + other.derived();
-}
-
-// template<typename ExpressionType>
-// template<typename OtherDerived>
-// EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
-// SparseCwise<ExpressionType>::operator*(const SparseMatrixBase<OtherDerived> &other) const
-// {
-// return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(_expression(), other.derived());
-// }
-
-template<typename Derived>
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE
-SparseMatrixBase<Derived>::cwiseProduct(const MatrixBase<OtherDerived> &other) const
-{
- return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(derived(), other.derived());
-}
-
-// template<typename ExpressionType>
-// template<typename OtherDerived>
-// EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)
-// SparseCwise<ExpressionType>::operator/(const SparseMatrixBase<OtherDerived> &other) const
-// {
-// return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)(_expression(), other.derived());
-// }
-//
-// template<typename ExpressionType>
-// template<typename OtherDerived>
-// EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)
-// SparseCwise<ExpressionType>::operator/(const MatrixBase<OtherDerived> &other) const
-// {
-// return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)(_expression(), other.derived());
-// }
-
-// template<typename ExpressionType>
-// template<typename OtherDerived>
-// inline ExpressionType& SparseCwise<ExpressionType>::operator*=(const SparseMatrixBase<OtherDerived> &other)
-// {
-// return m_matrix.const_cast_derived() = _expression() * other.derived();
-// }
-
-
-#endif // EIGEN_SPARSE_CWISE_BINARY_OP_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseCwiseUnaryOp.h b/extern/Eigen3/Eigen/src/Sparse/SparseCwiseUnaryOp.h
deleted file mode 100644
index aa068835fbb..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/SparseCwiseUnaryOp.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSE_CWISE_UNARY_OP_H
-#define EIGEN_SPARSE_CWISE_UNARY_OP_H
-
-// template<typename UnaryOp, typename MatrixType>
-// struct internal::traits<SparseCwiseUnaryOp<UnaryOp, MatrixType> > : internal::traits<MatrixType>
-// {
-// typedef typename internal::result_of<
-// UnaryOp(typename MatrixType::Scalar)
-// >::type Scalar;
-// typedef typename MatrixType::Nested MatrixTypeNested;
-// typedef typename internal::remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
-// enum {
-// CoeffReadCost = _MatrixTypeNested::CoeffReadCost + internal::functor_traits<UnaryOp>::Cost
-// };
-// };
-
-template<typename UnaryOp, typename MatrixType>
-class CwiseUnaryOpImpl<UnaryOp,MatrixType,Sparse>
- : public SparseMatrixBase<CwiseUnaryOp<UnaryOp, MatrixType> >
-{
- public:
-
- class InnerIterator;
-// typedef typename internal::remove_reference<LhsNested>::type _LhsNested;
-
- typedef CwiseUnaryOp<UnaryOp, MatrixType> Derived;
- EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
-};
-
-template<typename UnaryOp, typename MatrixType>
-class CwiseUnaryOpImpl<UnaryOp,MatrixType,Sparse>::InnerIterator
-{
- typedef typename CwiseUnaryOpImpl::Scalar Scalar;
- typedef typename internal::traits<Derived>::_XprTypeNested _MatrixTypeNested;
- typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
- typedef typename MatrixType::Index Index;
- public:
-
- EIGEN_STRONG_INLINE InnerIterator(const CwiseUnaryOpImpl& unaryOp, Index outer)
- : m_iter(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor())
- {}
-
- EIGEN_STRONG_INLINE InnerIterator& operator++()
- { ++m_iter; return *this; }
-
- EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_iter.value()); }
-
- EIGEN_STRONG_INLINE Index index() const { return m_iter.index(); }
- EIGEN_STRONG_INLINE Index row() const { return m_iter.row(); }
- EIGEN_STRONG_INLINE Index col() const { return m_iter.col(); }
-
- EIGEN_STRONG_INLINE operator bool() const { return m_iter; }
-
- protected:
- MatrixTypeIterator m_iter;
- const UnaryOp m_functor;
-};
-
-template<typename ViewOp, typename MatrixType>
-class CwiseUnaryViewImpl<ViewOp,MatrixType,Sparse>
- : public SparseMatrixBase<CwiseUnaryView<ViewOp, MatrixType> >
-{
- public:
-
- class InnerIterator;
-// typedef typename internal::remove_reference<LhsNested>::type _LhsNested;
-
- typedef CwiseUnaryView<ViewOp, MatrixType> Derived;
- EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
-};
-
-template<typename ViewOp, typename MatrixType>
-class CwiseUnaryViewImpl<ViewOp,MatrixType,Sparse>::InnerIterator
-{
- typedef typename CwiseUnaryViewImpl::Scalar Scalar;
- typedef typename internal::traits<Derived>::_MatrixTypeNested _MatrixTypeNested;
- typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator;
- typedef typename MatrixType::Index Index;
- public:
-
- EIGEN_STRONG_INLINE InnerIterator(const CwiseUnaryViewImpl& unaryView, Index outer)
- : m_iter(unaryView.derived().nestedExpression(),outer), m_functor(unaryView.derived().functor())
- {}
-
- EIGEN_STRONG_INLINE InnerIterator& operator++()
- { ++m_iter; return *this; }
-
- EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_iter.value()); }
- EIGEN_STRONG_INLINE Scalar& valueRef() { return m_functor(m_iter.valueRef()); }
-
- EIGEN_STRONG_INLINE Index index() const { return m_iter.index(); }
- EIGEN_STRONG_INLINE Index row() const { return m_iter.row(); }
- EIGEN_STRONG_INLINE Index col() const { return m_iter.col(); }
-
- EIGEN_STRONG_INLINE operator bool() const { return m_iter; }
-
- protected:
- MatrixTypeIterator m_iter;
- const ViewOp m_functor;
-};
-
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived&
-SparseMatrixBase<Derived>::operator*=(const Scalar& other)
-{
- for (Index j=0; j<outerSize(); ++j)
- for (typename Derived::InnerIterator i(derived(),j); i; ++i)
- i.valueRef() *= other;
- return derived();
-}
-
-template<typename Derived>
-EIGEN_STRONG_INLINE Derived&
-SparseMatrixBase<Derived>::operator/=(const Scalar& other)
-{
- for (Index j=0; j<outerSize(); ++j)
- for (typename Derived::InnerIterator i(derived(),j); i; ++i)
- i.valueRef() /= other;
- return derived();
-}
-
-#endif // EIGEN_SPARSE_CWISE_UNARY_OP_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseDenseProduct.h b/extern/Eigen3/Eigen/src/Sparse/SparseDenseProduct.h
deleted file mode 100644
index 0f77aa5be99..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/SparseDenseProduct.h
+++ /dev/null
@@ -1,231 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSEDENSEPRODUCT_H
-#define EIGEN_SPARSEDENSEPRODUCT_H
-
-template<typename Lhs, typename Rhs, int InnerSize> struct SparseDenseProductReturnType
-{
- typedef SparseTimeDenseProduct<Lhs,Rhs> Type;
-};
-
-template<typename Lhs, typename Rhs> struct SparseDenseProductReturnType<Lhs,Rhs,1>
-{
- typedef SparseDenseOuterProduct<Lhs,Rhs,false> Type;
-};
-
-template<typename Lhs, typename Rhs, int InnerSize> struct DenseSparseProductReturnType
-{
- typedef DenseTimeSparseProduct<Lhs,Rhs> Type;
-};
-
-template<typename Lhs, typename Rhs> struct DenseSparseProductReturnType<Lhs,Rhs,1>
-{
- typedef SparseDenseOuterProduct<Rhs,Lhs,true> Type;
-};
-
-namespace internal {
-
-template<typename Lhs, typename Rhs, bool Tr>
-struct traits<SparseDenseOuterProduct<Lhs,Rhs,Tr> >
-{
- typedef Sparse StorageKind;
- typedef typename scalar_product_traits<typename traits<Lhs>::Scalar,
- typename traits<Rhs>::Scalar>::ReturnType Scalar;
- typedef typename Lhs::Index Index;
- typedef typename Lhs::Nested LhsNested;
- typedef typename Rhs::Nested RhsNested;
- typedef typename remove_all<LhsNested>::type _LhsNested;
- typedef typename remove_all<RhsNested>::type _RhsNested;
-
- enum {
- LhsCoeffReadCost = traits<_LhsNested>::CoeffReadCost,
- RhsCoeffReadCost = traits<_RhsNested>::CoeffReadCost,
-
- RowsAtCompileTime = Tr ? int(traits<Rhs>::RowsAtCompileTime) : int(traits<Lhs>::RowsAtCompileTime),
- ColsAtCompileTime = Tr ? int(traits<Lhs>::ColsAtCompileTime) : int(traits<Rhs>::ColsAtCompileTime),
- MaxRowsAtCompileTime = Tr ? int(traits<Rhs>::MaxRowsAtCompileTime) : int(traits<Lhs>::MaxRowsAtCompileTime),
- MaxColsAtCompileTime = Tr ? int(traits<Lhs>::MaxColsAtCompileTime) : int(traits<Rhs>::MaxColsAtCompileTime),
-
- Flags = Tr ? RowMajorBit : 0,
-
- CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + NumTraits<Scalar>::MulCost
- };
-};
-
-} // end namespace internal
-
-template<typename Lhs, typename Rhs, bool Tr>
-class SparseDenseOuterProduct
- : public SparseMatrixBase<SparseDenseOuterProduct<Lhs,Rhs,Tr> >
-{
- public:
-
- typedef SparseMatrixBase<SparseDenseOuterProduct> Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(SparseDenseOuterProduct)
- typedef internal::traits<SparseDenseOuterProduct> Traits;
-
- private:
-
- typedef typename Traits::LhsNested LhsNested;
- typedef typename Traits::RhsNested RhsNested;
- typedef typename Traits::_LhsNested _LhsNested;
- typedef typename Traits::_RhsNested _RhsNested;
-
- public:
-
- class InnerIterator;
-
- EIGEN_STRONG_INLINE SparseDenseOuterProduct(const Lhs& lhs, const Rhs& rhs)
- : m_lhs(lhs), m_rhs(rhs)
- {
- EIGEN_STATIC_ASSERT(!Tr,YOU_MADE_A_PROGRAMMING_MISTAKE);
- }
-
- EIGEN_STRONG_INLINE SparseDenseOuterProduct(const Rhs& rhs, const Lhs& lhs)
- : m_lhs(lhs), m_rhs(rhs)
- {
- EIGEN_STATIC_ASSERT(Tr,YOU_MADE_A_PROGRAMMING_MISTAKE);
- }
-
- EIGEN_STRONG_INLINE Index rows() const { return Tr ? m_rhs.rows() : m_lhs.rows(); }
- EIGEN_STRONG_INLINE Index cols() const { return Tr ? m_lhs.cols() : m_rhs.cols(); }
-
- EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
- EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
-
- protected:
- LhsNested m_lhs;
- RhsNested m_rhs;
-};
-
-template<typename Lhs, typename Rhs, bool Transpose>
-class SparseDenseOuterProduct<Lhs,Rhs,Transpose>::InnerIterator : public _LhsNested::InnerIterator
-{
- typedef typename _LhsNested::InnerIterator Base;
- public:
- EIGEN_STRONG_INLINE InnerIterator(const SparseDenseOuterProduct& prod, Index outer)
- : Base(prod.lhs(), 0), m_outer(outer), m_factor(prod.rhs().coeff(outer))
- {
- }
-
- 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 Scalar value() const { return Base::value() * m_factor; }
-
- protected:
- int m_outer;
- Scalar m_factor;
-};
-
-namespace internal {
-template<typename Lhs, typename Rhs>
-struct traits<SparseTimeDenseProduct<Lhs,Rhs> >
- : traits<ProductBase<SparseTimeDenseProduct<Lhs,Rhs>, Lhs, Rhs> >
-{
- typedef Dense StorageKind;
- typedef MatrixXpr XprKind;
-};
-} // end namespace internal
-
-template<typename Lhs, typename Rhs>
-class SparseTimeDenseProduct
- : public ProductBase<SparseTimeDenseProduct<Lhs,Rhs>, Lhs, Rhs>
-{
- public:
- EIGEN_PRODUCT_PUBLIC_INTERFACE(SparseTimeDenseProduct)
-
- SparseTimeDenseProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
- {}
-
- template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
- {
- typedef typename internal::remove_all<Lhs>::type _Lhs;
- typedef typename internal::remove_all<Rhs>::type _Rhs;
- typedef typename _Lhs::InnerIterator LhsInnerIterator;
- enum { LhsIsRowMajor = (_Lhs::Flags&RowMajorBit)==RowMajorBit };
- for(Index j=0; j<m_lhs.outerSize(); ++j)
- {
- typename Rhs::Scalar rhs_j = alpha * m_rhs.coeff(LhsIsRowMajor ? 0 : j,0);
- typename Dest::RowXpr dest_j(dest.row(LhsIsRowMajor ? j : 0));
- for(LhsInnerIterator it(m_lhs,j); it ;++it)
- {
- if(LhsIsRowMajor) dest_j += (alpha*it.value()) * m_rhs.row(it.index());
- else if(Rhs::ColsAtCompileTime==1) dest.coeffRef(it.index()) += it.value() * rhs_j;
- else dest.row(it.index()) += (alpha*it.value()) * m_rhs.row(j);
- }
- }
- }
-
- private:
- SparseTimeDenseProduct& operator=(const SparseTimeDenseProduct&);
-};
-
-
-// dense = dense * sparse
-namespace internal {
-template<typename Lhs, typename Rhs>
-struct traits<DenseTimeSparseProduct<Lhs,Rhs> >
- : traits<ProductBase<DenseTimeSparseProduct<Lhs,Rhs>, Lhs, Rhs> >
-{
- typedef Dense StorageKind;
-};
-} // end namespace internal
-
-template<typename Lhs, typename Rhs>
-class DenseTimeSparseProduct
- : public ProductBase<DenseTimeSparseProduct<Lhs,Rhs>, Lhs, Rhs>
-{
- public:
- EIGEN_PRODUCT_PUBLIC_INTERFACE(DenseTimeSparseProduct)
-
- DenseTimeSparseProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
- {}
-
- template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
- {
- typedef typename internal::remove_all<Rhs>::type _Rhs;
- typedef typename _Rhs::InnerIterator RhsInnerIterator;
- enum { RhsIsRowMajor = (_Rhs::Flags&RowMajorBit)==RowMajorBit };
- for(Index j=0; j<m_rhs.outerSize(); ++j)
- for(RhsInnerIterator i(m_rhs,j); i; ++i)
- dest.col(RhsIsRowMajor ? i.index() : j) += (alpha*i.value()) * m_lhs.col(RhsIsRowMajor ? j : i.index());
- }
-
- private:
- 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());
-}
-
-#endif // EIGEN_SPARSEDENSEPRODUCT_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseDiagonalProduct.h b/extern/Eigen3/Eigen/src/Sparse/SparseDiagonalProduct.h
deleted file mode 100644
index fb9a29c051b..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/SparseDiagonalProduct.h
+++ /dev/null
@@ -1,195 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSE_DIAGONAL_PRODUCT_H
-#define EIGEN_SPARSE_DIAGONAL_PRODUCT_H
-
-// The product of a diagonal matrix with a sparse matrix can be easily
-// implemented using expression template.
-// We have two consider very different cases:
-// 1 - diag * row-major sparse
-// => each inner vector <=> scalar * sparse vector product
-// => so we can reuse CwiseUnaryOp::InnerIterator
-// 2 - diag * col-major sparse
-// => each inner vector <=> densevector * sparse vector cwise product
-// => again, we can reuse specialization of CwiseBinaryOp::InnerIterator
-// for that particular case
-// The two other cases are symmetric.
-
-namespace internal {
-
-template<typename Lhs, typename Rhs>
-struct traits<SparseDiagonalProduct<Lhs, Rhs> >
-{
- typedef typename remove_all<Lhs>::type _Lhs;
- typedef typename remove_all<Rhs>::type _Rhs;
- typedef typename _Lhs::Scalar Scalar;
- typedef typename promote_index_type<typename traits<Lhs>::Index,
- typename traits<Rhs>::Index>::type Index;
- typedef Sparse StorageKind;
- typedef MatrixXpr XprKind;
- enum {
- RowsAtCompileTime = _Lhs::RowsAtCompileTime,
- ColsAtCompileTime = _Rhs::ColsAtCompileTime,
-
- MaxRowsAtCompileTime = _Lhs::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = _Rhs::MaxColsAtCompileTime,
-
- SparseFlags = is_diagonal<_Lhs>::ret ? int(_Rhs::Flags) : int(_Lhs::Flags),
- Flags = (SparseFlags&RowMajorBit),
- CoeffReadCost = Dynamic
- };
-};
-
-enum {SDP_IsDiagonal, SDP_IsSparseRowMajor, SDP_IsSparseColMajor};
-template<typename Lhs, typename Rhs, typename SparseDiagonalProductType, int RhsMode, int LhsMode>
-class sparse_diagonal_product_inner_iterator_selector;
-
-} // end namespace internal
-
-template<typename Lhs, typename Rhs>
-class SparseDiagonalProduct
- : public SparseMatrixBase<SparseDiagonalProduct<Lhs,Rhs> >,
- internal::no_assignment_operator
-{
- typedef typename Lhs::Nested LhsNested;
- typedef typename Rhs::Nested RhsNested;
-
- typedef typename internal::remove_all<LhsNested>::type _LhsNested;
- typedef typename internal::remove_all<RhsNested>::type _RhsNested;
-
- enum {
- LhsMode = internal::is_diagonal<_LhsNested>::ret ? internal::SDP_IsDiagonal
- : (_LhsNested::Flags&RowMajorBit) ? internal::SDP_IsSparseRowMajor : internal::SDP_IsSparseColMajor,
- RhsMode = internal::is_diagonal<_RhsNested>::ret ? internal::SDP_IsDiagonal
- : (_RhsNested::Flags&RowMajorBit) ? internal::SDP_IsSparseRowMajor : internal::SDP_IsSparseColMajor
- };
-
- public:
-
- EIGEN_SPARSE_PUBLIC_INTERFACE(SparseDiagonalProduct)
-
- typedef internal::sparse_diagonal_product_inner_iterator_selector
- <_LhsNested,_RhsNested,SparseDiagonalProduct,LhsMode,RhsMode> InnerIterator;
-
- EIGEN_STRONG_INLINE SparseDiagonalProduct(const Lhs& lhs, const Rhs& rhs)
- : m_lhs(lhs), m_rhs(rhs)
- {
- eigen_assert(lhs.cols() == rhs.rows() && "invalid sparse matrix * diagonal matrix product");
- }
-
- EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); }
- EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); }
-
- EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
- EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
-
- protected:
- LhsNested m_lhs;
- RhsNested m_rhs;
-};
-
-namespace internal {
-
-template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
-class sparse_diagonal_product_inner_iterator_selector
-<Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseRowMajor>
- : public CwiseUnaryOp<scalar_multiple_op<typename Lhs::Scalar>,const Rhs>::InnerIterator
-{
- typedef typename CwiseUnaryOp<scalar_multiple_op<typename Lhs::Scalar>,const Rhs>::InnerIterator Base;
- typedef typename Lhs::Index Index;
- public:
- inline sparse_diagonal_product_inner_iterator_selector(
- const SparseDiagonalProductType& expr, Index outer)
- : Base(expr.rhs()*(expr.lhs().diagonal().coeff(outer)), outer)
- {}
-};
-
-template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
-class sparse_diagonal_product_inner_iterator_selector
-<Lhs,Rhs,SparseDiagonalProductType,SDP_IsDiagonal,SDP_IsSparseColMajor>
- : public CwiseBinaryOp<
- scalar_product_op<typename Lhs::Scalar>,
- SparseInnerVectorSet<Rhs,1>,
- typename Lhs::DiagonalVectorType>::InnerIterator
-{
- typedef typename CwiseBinaryOp<
- scalar_product_op<typename Lhs::Scalar>,
- SparseInnerVectorSet<Rhs,1>,
- typename Lhs::DiagonalVectorType>::InnerIterator Base;
- typedef typename Lhs::Index Index;
- public:
- inline sparse_diagonal_product_inner_iterator_selector(
- const SparseDiagonalProductType& expr, Index outer)
- : Base(expr.rhs().innerVector(outer) .cwiseProduct(expr.lhs().diagonal()), 0)
- {}
-};
-
-template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
-class sparse_diagonal_product_inner_iterator_selector
-<Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseColMajor,SDP_IsDiagonal>
- : public CwiseUnaryOp<scalar_multiple_op<typename Rhs::Scalar>,const Lhs>::InnerIterator
-{
- typedef typename CwiseUnaryOp<scalar_multiple_op<typename Rhs::Scalar>,const Lhs>::InnerIterator Base;
- typedef typename Lhs::Index Index;
- public:
- inline sparse_diagonal_product_inner_iterator_selector(
- const SparseDiagonalProductType& expr, Index outer)
- : Base(expr.lhs()*expr.rhs().diagonal().coeff(outer), outer)
- {}
-};
-
-template<typename Lhs, typename Rhs, typename SparseDiagonalProductType>
-class sparse_diagonal_product_inner_iterator_selector
-<Lhs,Rhs,SparseDiagonalProductType,SDP_IsSparseRowMajor,SDP_IsDiagonal>
- : public CwiseBinaryOp<
- scalar_product_op<typename Rhs::Scalar>,
- SparseInnerVectorSet<Lhs,1>,
- Transpose<const typename Rhs::DiagonalVectorType> >::InnerIterator
-{
- typedef typename CwiseBinaryOp<
- scalar_product_op<typename Rhs::Scalar>,
- SparseInnerVectorSet<Lhs,1>,
- Transpose<const typename Rhs::DiagonalVectorType> >::InnerIterator Base;
- typedef typename Lhs::Index Index;
- public:
- inline sparse_diagonal_product_inner_iterator_selector(
- const SparseDiagonalProductType& expr, Index outer)
- : Base(expr.lhs().innerVector(outer) .cwiseProduct(expr.rhs().diagonal().transpose()), 0)
- {}
-};
-
-} // end namespace internal
-
-// SparseMatrixBase functions
-
-template<typename Derived>
-template<typename OtherDerived>
-const SparseDiagonalProduct<Derived,OtherDerived>
-SparseMatrixBase<Derived>::operator*(const DiagonalBase<OtherDerived> &other) const
-{
- return SparseDiagonalProduct<Derived,OtherDerived>(this->derived(), other.derived());
-}
-
-#endif // EIGEN_SPARSE_DIAGONAL_PRODUCT_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseMatrix.h b/extern/Eigen3/Eigen/src/Sparse/SparseMatrix.h
deleted file mode 100644
index 0e175ec6e71..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/SparseMatrix.h
+++ /dev/null
@@ -1,651 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSEMATRIX_H
-#define EIGEN_SPARSEMATRIX_H
-
-/** \ingroup Sparse_Module
- *
- * \class SparseMatrix
- *
- * \brief The main sparse matrix class
- *
- * This class implements a sparse matrix using the very common compressed row/column storage
- * scheme.
- *
- * \tparam _Scalar the scalar type, i.e. the type of the coefficients
- * \tparam _Options Union of bit flags controlling the storage scheme. Currently the only possibility
- * is RowMajor. The default is 0 which means column-major.
- * \tparam _Index the type of the indices. Default is \c int.
- *
- * See http://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme.
- *
- * 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_SPARSEMATRIX_PLUGIN.
- */
-
-namespace internal {
-template<typename _Scalar, int _Options, typename _Index>
-struct traits<SparseMatrix<_Scalar, _Options, _Index> >
-{
- typedef _Scalar Scalar;
- typedef _Index Index;
- typedef Sparse StorageKind;
- typedef MatrixXpr XprKind;
- enum {
- RowsAtCompileTime = Dynamic,
- ColsAtCompileTime = Dynamic,
- MaxRowsAtCompileTime = Dynamic,
- MaxColsAtCompileTime = Dynamic,
- Flags = _Options | NestByRefBit | LvalueBit,
- CoeffReadCost = NumTraits<Scalar>::ReadCost,
- SupportedAccessPatterns = InnerRandomAccessPattern
- };
-};
-
-} // end namespace internal
-
-template<typename _Scalar, int _Options, typename _Index>
-class SparseMatrix
- : public SparseMatrixBase<SparseMatrix<_Scalar, _Options, _Index> >
-{
- public:
- EIGEN_SPARSE_PUBLIC_INTERFACE(SparseMatrix)
-// using Base::operator=;
- EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, +=)
- EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, -=)
- // FIXME: why are these operator already alvailable ???
- // EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(SparseMatrix, *=)
- // EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(SparseMatrix, /=)
-
- typedef MappedSparseMatrix<Scalar,Flags> Map;
- using Base::IsRowMajor;
- typedef CompressedStorage<Scalar,Index> Storage;
- enum {
- Options = _Options
- };
-
- protected:
-
- typedef SparseMatrix<Scalar,(Flags&~RowMajorBit)|(IsRowMajor?RowMajorBit:0)> TransposedSparseMatrix;
-
- Index m_outerSize;
- Index m_innerSize;
- Index* m_outerIndex;
- CompressedStorage<Scalar,Index> m_data;
-
- public:
-
- inline Index rows() const { return IsRowMajor ? m_outerSize : m_innerSize; }
- inline Index cols() const { return IsRowMajor ? m_innerSize : m_outerSize; }
-
- inline Index innerSize() const { return m_innerSize; }
- inline Index outerSize() const { return m_outerSize; }
- inline Index innerNonZeros(Index j) const { return m_outerIndex[j+1]-m_outerIndex[j]; }
-
- inline const Scalar* _valuePtr() const { return &m_data.value(0); }
- inline Scalar* _valuePtr() { return &m_data.value(0); }
-
- inline const Index* _innerIndexPtr() const { return &m_data.index(0); }
- inline Index* _innerIndexPtr() { return &m_data.index(0); }
-
- inline const Index* _outerIndexPtr() const { return m_outerIndex; }
- inline Index* _outerIndexPtr() { return m_outerIndex; }
-
- inline Storage& data() { return m_data; }
- inline const Storage& data() const { return m_data; }
-
- inline Scalar coeff(Index row, Index col) const
- {
- const Index outer = IsRowMajor ? row : col;
- const Index inner = IsRowMajor ? col : row;
- return m_data.atInRange(m_outerIndex[outer], m_outerIndex[outer+1], inner);
- }
-
- inline Scalar& coeffRef(Index row, Index col)
- {
- const Index outer = IsRowMajor ? row : col;
- const Index inner = IsRowMajor ? col : row;
-
- Index start = m_outerIndex[outer];
- Index end = m_outerIndex[outer+1];
- eigen_assert(end>=start && "you probably called coeffRef on a non finalized matrix");
- eigen_assert(end>start && "coeffRef cannot be called on a zero coefficient");
- const Index p = m_data.searchLowerIndex(start,end-1,inner);
- eigen_assert((p<end) && (m_data.index(p)==inner) && "coeffRef cannot be called on a zero coefficient");
- return m_data.value(p);
- }
-
- public:
-
- class InnerIterator;
-
- /** Removes all non zeros */
- inline void setZero()
- {
- m_data.clear();
- memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(Index));
- }
-
- /** \returns the number of non zero coefficients */
- inline Index nonZeros() const { return static_cast<Index>(m_data.size()); }
-
- /** Preallocates \a reserveSize non zeros */
- inline void reserve(Index reserveSize)
- {
- m_data.reserve(reserveSize);
- }
-
- //--- low level purely coherent filling ---
-
- /** \returns a reference to the non zero coefficient at position \a row, \a col assuming that:
- * - the nonzero does not already exist
- * - the new coefficient is the last one according to the storage order
- *
- * Before filling a given inner vector you must call the statVec(Index) function.
- *
- * After an insertion session, you should call the finalize() function.
- *
- * \sa insert, insertBackByOuterInner, startVec */
- inline Scalar& insertBack(Index row, Index col)
- {
- return insertBackByOuterInner(IsRowMajor?row:col, IsRowMajor?col:row);
- }
-
- /** \sa insertBack, startVec */
- inline Scalar& insertBackByOuterInner(Index outer, Index inner)
- {
- eigen_assert(size_t(m_outerIndex[outer+1]) == m_data.size() && "Invalid ordered insertion (invalid outer index)");
- eigen_assert( (m_outerIndex[outer+1]-m_outerIndex[outer]==0 || m_data.index(m_data.size()-1)<inner) && "Invalid ordered insertion (invalid inner index)");
- Index p = m_outerIndex[outer+1];
- ++m_outerIndex[outer+1];
- m_data.append(0, inner);
- return m_data.value(p);
- }
-
- /** \warning use it only if you know what you are doing */
- inline Scalar& insertBackByOuterInnerUnordered(Index outer, Index inner)
- {
- Index p = m_outerIndex[outer+1];
- ++m_outerIndex[outer+1];
- m_data.append(0, inner);
- return m_data.value(p);
- }
-
- /** \sa insertBack, insertBackByOuterInner */
- inline void startVec(Index outer)
- {
- eigen_assert(m_outerIndex[outer]==int(m_data.size()) && "You must call startVec for each inner vector sequentially");
- eigen_assert(m_outerIndex[outer+1]==0 && "You must call startVec for each inner vector sequentially");
- m_outerIndex[outer+1] = m_outerIndex[outer];
- }
-
- //---
-
- /** \returns a reference to a novel non zero coefficient with coordinates \a row x \a col.
- * The non zero coefficient must \b not already exist.
- *
- * \warning This function can be extremely slow if the non zero coefficients
- * are not inserted in a coherent order.
- *
- * After an insertion session, you should call the finalize() function.
- */
- EIGEN_DONT_INLINE Scalar& insert(Index row, Index col)
- {
- const Index outer = IsRowMajor ? row : col;
- const Index inner = IsRowMajor ? col : row;
-
- Index previousOuter = outer;
- if (m_outerIndex[outer+1]==0)
- {
- // we start a new inner vector
- while (previousOuter>=0 && m_outerIndex[previousOuter]==0)
- {
- m_outerIndex[previousOuter] = static_cast<Index>(m_data.size());
- --previousOuter;
- }
- m_outerIndex[outer+1] = m_outerIndex[outer];
- }
-
- // here we have to handle the tricky case where the outerIndex array
- // starts with: [ 0 0 0 0 0 1 ...] and we are inserting in, e.g.,
- // the 2nd inner vector...
- bool isLastVec = (!(previousOuter==-1 && m_data.size()!=0))
- && (size_t(m_outerIndex[outer+1]) == m_data.size());
-
- size_t startId = m_outerIndex[outer];
- // FIXME let's make sure sizeof(long int) == sizeof(size_t)
- size_t p = m_outerIndex[outer+1];
- ++m_outerIndex[outer+1];
-
- float reallocRatio = 1;
- if (m_data.allocatedSize()<=m_data.size())
- {
- // if there is no preallocated memory, let's reserve a minimum of 32 elements
- if (m_data.size()==0)
- {
- m_data.reserve(32);
- }
- else
- {
- // 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());
- // 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);
- }
- }
- m_data.resize(m_data.size()+1,reallocRatio);
-
- if (!isLastVec)
- {
- if (previousOuter==-1)
- {
- // oops wrong guess.
- // let's correct the outer offsets
- for (Index k=0; k<=(outer+1); ++k)
- m_outerIndex[k] = 0;
- Index k=outer+1;
- while(m_outerIndex[k]==0)
- m_outerIndex[k++] = 1;
- while (k<=m_outerSize && m_outerIndex[k]!=0)
- m_outerIndex[k++]++;
- p = 0;
- --k;
- k = m_outerIndex[k]-1;
- while (k>0)
- {
- m_data.index(k) = m_data.index(k-1);
- m_data.value(k) = m_data.value(k-1);
- k--;
- }
- }
- else
- {
- // we are not inserting into the last inner vec
- // update outer indices:
- Index j = outer+2;
- while (j<=m_outerSize && m_outerIndex[j]!=0)
- m_outerIndex[j++]++;
- --j;
- // shift data of last vecs:
- Index k = m_outerIndex[j]-1;
- while (k>=Index(p))
- {
- m_data.index(k) = m_data.index(k-1);
- m_data.value(k) = m_data.value(k-1);
- k--;
- }
- }
- }
-
- while ( (p > startId) && (m_data.index(p-1) > inner) )
- {
- m_data.index(p) = m_data.index(p-1);
- m_data.value(p) = m_data.value(p-1);
- --p;
- }
-
- m_data.index(p) = inner;
- return (m_data.value(p) = 0);
- }
-
-
-
-
- /** Must be called after inserting a set of non zero entries.
- */
- inline void finalize()
- {
- Index size = static_cast<Index>(m_data.size());
- Index i = m_outerSize;
- // find the last filled column
- while (i>=0 && m_outerIndex[i]==0)
- --i;
- ++i;
- while (i<=m_outerSize)
- {
- m_outerIndex[i] = size;
- ++i;
- }
- }
-
- /** Suppress all nonzeros which are smaller than \a reference under the tolerence \a epsilon */
- void prune(Scalar reference, RealScalar epsilon = NumTraits<RealScalar>::dummy_precision())
- {
- prune(default_prunning_func(reference,epsilon));
- }
-
- /** Suppress all nonzeros which do not satisfy the predicate \a keep.
- * The functor type \a KeepFunc must implement the following function:
- * \code
- * bool operator() (const Index& row, const Index& col, const Scalar& value) const;
- * \endcode
- * \sa prune(Scalar,RealScalar)
- */
- template<typename KeepFunc>
- void prune(const KeepFunc& keep = KeepFunc())
- {
- Index k = 0;
- for(Index j=0; j<m_outerSize; ++j)
- {
- Index previousStart = m_outerIndex[j];
- m_outerIndex[j] = k;
- Index end = m_outerIndex[j+1];
- for(Index i=previousStart; i<end; ++i)
- {
- if(keep(IsRowMajor?j:m_data.index(i), IsRowMajor?m_data.index(i):j, m_data.value(i)))
- {
- m_data.value(k) = m_data.value(i);
- m_data.index(k) = m_data.index(i);
- ++k;
- }
- }
- }
- m_outerIndex[m_outerSize] = k;
- m_data.resize(k,0);
- }
-
- /** Resizes the matrix to a \a rows x \a cols matrix and initializes it to zero
- * \sa resizeNonZeros(Index), reserve(), setZero()
- */
- void resize(Index rows, Index cols)
- {
- const Index outerSize = IsRowMajor ? rows : cols;
- m_innerSize = IsRowMajor ? cols : rows;
- m_data.clear();
- if (m_outerSize != outerSize || m_outerSize==0)
- {
- delete[] m_outerIndex;
- m_outerIndex = new Index [outerSize+1];
- m_outerSize = outerSize;
- }
- memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(Index));
- }
-
- /** Low level API
- * Resize the nonzero vector to \a size */
- void resizeNonZeros(Index size)
- {
- m_data.resize(size);
- }
-
- /** Default constructor yielding an empty \c 0 \c x \c 0 matrix */
- inline SparseMatrix()
- : m_outerSize(-1), m_innerSize(0), m_outerIndex(0)
- {
- resize(0, 0);
- }
-
- /** Constructs a \a rows \c x \a cols empty matrix */
- inline SparseMatrix(Index rows, Index cols)
- : m_outerSize(0), m_innerSize(0), m_outerIndex(0)
- {
- resize(rows, cols);
- }
-
- /** Constructs a sparse matrix from the sparse expression \a other */
- template<typename OtherDerived>
- inline SparseMatrix(const SparseMatrixBase<OtherDerived>& other)
- : m_outerSize(0), m_innerSize(0), m_outerIndex(0)
- {
- *this = other.derived();
- }
-
- /** Copy constructor */
- inline SparseMatrix(const SparseMatrix& other)
- : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0)
- {
- *this = other.derived();
- }
-
- /** Swap the content of two sparse matrices of same type (optimization) */
- inline void swap(SparseMatrix& other)
- {
- //EIGEN_DBG_SPARSE(std::cout << "SparseMatrix:: swap\n");
- std::swap(m_outerIndex, other.m_outerIndex);
- std::swap(m_innerSize, other.m_innerSize);
- std::swap(m_outerSize, other.m_outerSize);
- m_data.swap(other.m_data);
- }
-
- inline SparseMatrix& operator=(const SparseMatrix& other)
- {
-// std::cout << "SparseMatrix& operator=(const SparseMatrix& other)\n";
- if (other.isRValue())
- {
- swap(other.const_cast_derived());
- }
- else
- {
- resize(other.rows(), other.cols());
- memcpy(m_outerIndex, other.m_outerIndex, (m_outerSize+1)*sizeof(Index));
- m_data = other.m_data;
- }
- return *this;
- }
-
- #ifndef EIGEN_PARSED_BY_DOXYGEN
- template<typename Lhs, typename Rhs>
- inline SparseMatrix& operator=(const SparseSparseProduct<Lhs,Rhs>& product)
- { return Base::operator=(product); }
-
- template<typename OtherDerived>
- inline SparseMatrix& operator=(const ReturnByValue<OtherDerived>& other)
- { return Base::operator=(other); }
-
- template<typename OtherDerived>
- inline SparseMatrix& operator=(const EigenBase<OtherDerived>& other)
- { return Base::operator=(other); }
- #endif
-
- template<typename OtherDerived>
- EIGEN_DONT_INLINE SparseMatrix& operator=(const SparseMatrixBase<OtherDerived>& other)
- {
- const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
- if (needToTranspose)
- {
- // two passes algorithm:
- // 1 - compute the number of coeffs per dest inner vector
- // 2 - do the actual copy/eval
- // Since each coeff of the rhs has to be evaluated twice, let's evaluate it if needed
- typedef typename internal::nested<OtherDerived,2>::type OtherCopy;
- typedef typename internal::remove_all<OtherCopy>::type _OtherCopy;
- OtherCopy otherCopy(other.derived());
-
- resize(other.rows(), other.cols());
- Eigen::Map<Matrix<Index, Dynamic, 1> > (m_outerIndex,outerSize()).setZero();
- // pass 1
- // FIXME the above copy could be merged with that pass
- for (Index j=0; j<otherCopy.outerSize(); ++j)
- for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
- ++m_outerIndex[it.index()];
-
- // prefix sum
- Index count = 0;
- VectorXi positions(outerSize());
- for (Index j=0; j<outerSize(); ++j)
- {
- Index tmp = m_outerIndex[j];
- m_outerIndex[j] = count;
- positions[j] = count;
- count += tmp;
- }
- m_outerIndex[outerSize()] = count;
- // alloc
- m_data.resize(count);
- // pass 2
- for (Index j=0; j<otherCopy.outerSize(); ++j)
- {
- for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
- {
- Index pos = positions[it.index()]++;
- m_data.index(pos) = j;
- m_data.value(pos) = it.value();
- }
- }
- return *this;
- }
- else
- {
- // there is no special optimization
- return SparseMatrixBase<SparseMatrix>::operator=(other.derived());
- }
- }
-
- friend std::ostream & operator << (std::ostream & s, const SparseMatrix& m)
- {
- EIGEN_DBG_SPARSE(
- s << "Nonzero entries:\n";
- for (Index i=0; i<m.nonZeros(); ++i)
- {
- s << "(" << m.m_data.value(i) << "," << m.m_data.index(i) << ") ";
- }
- s << std::endl;
- s << std::endl;
- s << "Column pointers:\n";
- for (Index i=0; i<m.outerSize(); ++i)
- {
- s << m.m_outerIndex[i] << " ";
- }
- s << " $" << std::endl;
- s << std::endl;
- );
- s << static_cast<const SparseMatrixBase<SparseMatrix>&>(m);
- return s;
- }
-
- /** Destructor */
- inline ~SparseMatrix()
- {
- delete[] m_outerIndex;
- }
-
- /** Overloaded for performance */
- Scalar sum() const;
-
- public:
-
- /** \deprecated use setZero() and reserve()
- * Initializes the filling process of \c *this.
- * \param reserveSize approximate number of nonzeros
- * Note that the matrix \c *this is zero-ed.
- */
- EIGEN_DEPRECATED void startFill(Index reserveSize = 1000)
- {
- setZero();
- m_data.reserve(reserveSize);
- }
-
- /** \deprecated use insert()
- * Like fill() but with random inner coordinates.
- */
- EIGEN_DEPRECATED Scalar& fillrand(Index row, Index col)
- {
- return insert(row,col);
- }
-
- /** \deprecated use insert()
- */
- EIGEN_DEPRECATED Scalar& fill(Index row, Index col)
- {
- const Index outer = IsRowMajor ? row : col;
- const Index inner = IsRowMajor ? col : row;
-
- if (m_outerIndex[outer+1]==0)
- {
- // we start a new inner vector
- Index i = outer;
- while (i>=0 && m_outerIndex[i]==0)
- {
- m_outerIndex[i] = m_data.size();
- --i;
- }
- m_outerIndex[outer+1] = m_outerIndex[outer];
- }
- else
- {
- eigen_assert(m_data.index(m_data.size()-1)<inner && "wrong sorted insertion");
- }
-// std::cerr << size_t(m_outerIndex[outer+1]) << " == " << m_data.size() << "\n";
- assert(size_t(m_outerIndex[outer+1]) == m_data.size());
- Index p = m_outerIndex[outer+1];
- ++m_outerIndex[outer+1];
-
- m_data.append(0, inner);
- return m_data.value(p);
- }
-
- /** \deprecated use finalize */
- EIGEN_DEPRECATED void endFill() { finalize(); }
-
-# ifdef EIGEN_SPARSEMATRIX_PLUGIN
-# include EIGEN_SPARSEMATRIX_PLUGIN
-# endif
-
-private:
- struct default_prunning_func {
- default_prunning_func(Scalar ref, RealScalar eps) : reference(ref), epsilon(eps) {}
- inline bool operator() (const Index&, const Index&, const Scalar& value) const
- {
- return !internal::isMuchSmallerThan(value, reference, epsilon);
- }
- Scalar reference;
- RealScalar epsilon;
- };
-};
-
-template<typename Scalar, int _Options, typename _Index>
-class SparseMatrix<Scalar,_Options,_Index>::InnerIterator
-{
- public:
- InnerIterator(const SparseMatrix& mat, Index outer)
- : m_values(mat._valuePtr()), m_indices(mat._innerIndexPtr()), m_outer(outer), m_id(mat.m_outerIndex[outer]), m_end(mat.m_outerIndex[outer+1])
- {}
-
- inline InnerIterator& operator++() { m_id++; return *this; }
-
- inline const Scalar& value() const { return m_values[m_id]; }
- inline Scalar& valueRef() { return const_cast<Scalar&>(m_values[m_id]); }
-
- inline Index index() const { return m_indices[m_id]; }
- inline Index outer() const { return m_outer; }
- inline Index row() const { return IsRowMajor ? m_outer : index(); }
- inline Index col() const { return IsRowMajor ? index() : m_outer; }
-
- inline operator bool() const { return (m_id < m_end); }
-
- protected:
- const Scalar* m_values;
- const Index* m_indices;
- const Index m_outer;
- Index m_id;
- const Index m_end;
-};
-
-#endif // EIGEN_SPARSEMATRIX_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseProduct.h b/extern/Eigen3/Eigen/src/Sparse/SparseProduct.h
deleted file mode 100644
index 1c1f54706ac..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/SparseProduct.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSEPRODUCT_H
-#define EIGEN_SPARSEPRODUCT_H
-
-template<typename Lhs, typename Rhs>
-struct SparseSparseProductReturnType
-{
- typedef typename internal::traits<Lhs>::Scalar Scalar;
- enum {
- LhsRowMajor = internal::traits<Lhs>::Flags & RowMajorBit,
- RhsRowMajor = internal::traits<Rhs>::Flags & RowMajorBit,
- TransposeRhs = (!LhsRowMajor) && RhsRowMajor,
- TransposeLhs = LhsRowMajor && (!RhsRowMajor)
- };
-
- typedef typename internal::conditional<TransposeLhs,
- SparseMatrix<Scalar,0>,
- const typename internal::nested<Lhs,Rhs::RowsAtCompileTime>::type>::type LhsNested;
-
- typedef typename internal::conditional<TransposeRhs,
- SparseMatrix<Scalar,0>,
- const typename internal::nested<Rhs,Lhs::RowsAtCompileTime>::type>::type RhsNested;
-
- typedef SparseSparseProduct<LhsNested, RhsNested> Type;
-};
-
-namespace internal {
-template<typename LhsNested, typename RhsNested>
-struct traits<SparseSparseProduct<LhsNested, RhsNested> >
-{
- typedef MatrixXpr XprKind;
- // clean the nested types:
- typedef typename remove_all<LhsNested>::type _LhsNested;
- typedef typename remove_all<RhsNested>::type _RhsNested;
- typedef typename _LhsNested::Scalar Scalar;
- typedef typename promote_index_type<typename traits<_LhsNested>::Index,
- typename traits<_RhsNested>::Index>::type Index;
-
- enum {
- LhsCoeffReadCost = _LhsNested::CoeffReadCost,
- RhsCoeffReadCost = _RhsNested::CoeffReadCost,
- LhsFlags = _LhsNested::Flags,
- RhsFlags = _RhsNested::Flags,
-
- RowsAtCompileTime = _LhsNested::RowsAtCompileTime,
- ColsAtCompileTime = _RhsNested::ColsAtCompileTime,
- MaxRowsAtCompileTime = _LhsNested::MaxRowsAtCompileTime,
- MaxColsAtCompileTime = _RhsNested::MaxColsAtCompileTime,
-
- InnerSize = EIGEN_SIZE_MIN_PREFER_FIXED(_LhsNested::ColsAtCompileTime, _RhsNested::RowsAtCompileTime),
-
- EvalToRowMajor = (RhsFlags & LhsFlags & RowMajorBit),
-
- RemovedBits = ~(EvalToRowMajor ? 0 : RowMajorBit),
-
- Flags = (int(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
- | EvalBeforeAssigningBit
- | EvalBeforeNestingBit,
-
- CoeffReadCost = Dynamic
- };
-
- typedef Sparse StorageKind;
-};
-
-} // end namespace internal
-
-template<typename LhsNested, typename RhsNested>
-class SparseSparseProduct : internal::no_assignment_operator,
- public SparseMatrixBase<SparseSparseProduct<LhsNested, RhsNested> >
-{
- public:
-
- typedef SparseMatrixBase<SparseSparseProduct> Base;
- EIGEN_DENSE_PUBLIC_INTERFACE(SparseSparseProduct)
-
- private:
-
- typedef typename internal::traits<SparseSparseProduct>::_LhsNested _LhsNested;
- typedef typename internal::traits<SparseSparseProduct>::_RhsNested _RhsNested;
-
- public:
-
- template<typename Lhs, typename Rhs>
- EIGEN_STRONG_INLINE SparseSparseProduct(const Lhs& lhs, const Rhs& rhs)
- : m_lhs(lhs), m_rhs(rhs)
- {
- eigen_assert(lhs.cols() == rhs.rows());
-
- enum {
- ProductIsValid = _LhsNested::ColsAtCompileTime==Dynamic
- || _RhsNested::RowsAtCompileTime==Dynamic
- || int(_LhsNested::ColsAtCompileTime)==int(_RhsNested::RowsAtCompileTime),
- AreVectors = _LhsNested::IsVectorAtCompileTime && _RhsNested::IsVectorAtCompileTime,
- SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(_LhsNested,_RhsNested)
- };
- // note to the lost user:
- // * for a dot product use: v1.dot(v2)
- // * for a coeff-wise product use: v1.cwise()*v2
- EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes),
- INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS)
- EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors),
- INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION)
- EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
- }
-
- EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); }
- EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); }
-
- EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; }
- EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; }
-
- protected:
- LhsNested m_lhs;
- RhsNested m_rhs;
-};
-
-#endif // EIGEN_SPARSEPRODUCT_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseRedux.h b/extern/Eigen3/Eigen/src/Sparse/SparseRedux.h
deleted file mode 100644
index afc49de7aad..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/SparseRedux.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSEREDUX_H
-#define EIGEN_SPARSEREDUX_H
-
-template<typename Derived>
-typename internal::traits<Derived>::Scalar
-SparseMatrixBase<Derived>::sum() const
-{
- eigen_assert(rows()>0 && cols()>0 && "you are using a non initialized matrix");
- Scalar res = 0;
- for (Index j=0; j<outerSize(); ++j)
- for (typename Derived::InnerIterator iter(derived(),j); iter; ++iter)
- res += iter.value();
- return res;
-}
-
-template<typename _Scalar, int _Options, typename _Index>
-typename internal::traits<SparseMatrix<_Scalar,_Options,_Index> >::Scalar
-SparseMatrix<_Scalar,_Options,_Index>::sum() const
-{
- eigen_assert(rows()>0 && cols()>0 && "you are using a non initialized matrix");
- return Matrix<Scalar,1,Dynamic>::Map(&m_data.value(0), m_data.size()).sum();
-}
-
-template<typename _Scalar, int _Options, typename _Index>
-typename internal::traits<SparseVector<_Scalar,_Options, _Index> >::Scalar
-SparseVector<_Scalar,_Options,_Index>::sum() const
-{
- eigen_assert(rows()>0 && cols()>0 && "you are using a non initialized matrix");
- return Matrix<Scalar,1,Dynamic>::Map(&m_data.value(0), m_data.size()).sum();
-}
-
-#endif // EIGEN_SPARSEREDUX_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseSelfAdjointView.h b/extern/Eigen3/Eigen/src/Sparse/SparseSelfAdjointView.h
deleted file mode 100644
index d82044c789c..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/SparseSelfAdjointView.h
+++ /dev/null
@@ -1,454 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSE_SELFADJOINTVIEW_H
-#define EIGEN_SPARSE_SELFADJOINTVIEW_H
-
-/** \class SparseSelfAdjointView
- *
- *
- * \brief Pseudo expression to manipulate a triangular sparse matrix as a selfadjoint matrix.
- *
- * \param MatrixType the type of the dense matrix storing the coefficients
- * \param UpLo can be either \c #Lower or \c #Upper
- *
- * This class is an expression of a sefladjoint matrix from a triangular part of a matrix
- * with given dense storage of the coefficients. It is the return type of MatrixBase::selfadjointView()
- * and most of the time this is the only way that it is used.
- *
- * \sa SparseMatrixBase::selfadjointView()
- */
-template<typename Lhs, typename Rhs, int UpLo>
-class SparseSelfAdjointTimeDenseProduct;
-
-template<typename Lhs, typename Rhs, int UpLo>
-class DenseTimeSparseSelfAdjointProduct;
-
-template<typename MatrixType,int UpLo>
-class SparseSymmetricPermutationProduct;
-
-namespace internal {
-
-template<typename MatrixType, unsigned int UpLo>
-struct traits<SparseSelfAdjointView<MatrixType,UpLo> > : traits<MatrixType> {
-};
-
-template<int SrcUpLo,int DstUpLo,typename MatrixType,int DestOrder>
-void permute_symm_to_symm(const MatrixType& mat, SparseMatrix<typename MatrixType::Scalar,DestOrder,typename MatrixType::Index>& _dest, const typename MatrixType::Index* perm = 0);
-
-template<int UpLo,typename MatrixType,int DestOrder>
-void permute_symm_to_fullsymm(const MatrixType& mat, SparseMatrix<typename MatrixType::Scalar,DestOrder,typename MatrixType::Index>& _dest, const typename MatrixType::Index* perm = 0);
-
-}
-
-template<typename MatrixType, unsigned int UpLo> class SparseSelfAdjointView
- : public EigenBase<SparseSelfAdjointView<MatrixType,UpLo> >
-{
- public:
-
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::Index Index;
- typedef Matrix<Index,Dynamic,1> VectorI;
- typedef typename MatrixType::Nested MatrixTypeNested;
- typedef typename internal::remove_all<MatrixTypeNested>::type _MatrixTypeNested;
-
- inline SparseSelfAdjointView(const MatrixType& matrix) : m_matrix(matrix)
- {
- eigen_assert(rows()==cols() && "SelfAdjointView is only for squared matrices");
- }
-
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
-
- /** \internal \returns a reference to the nested matrix */
- const _MatrixTypeNested& matrix() const { return m_matrix; }
- _MatrixTypeNested& matrix() { return m_matrix.const_cast_derived(); }
-
- /** Efficient sparse self-adjoint matrix times dense vector/matrix product */
- template<typename OtherDerived>
- SparseSelfAdjointTimeDenseProduct<MatrixType,OtherDerived,UpLo>
- operator*(const MatrixBase<OtherDerived>& rhs) const
- {
- return SparseSelfAdjointTimeDenseProduct<MatrixType,OtherDerived,UpLo>(m_matrix, rhs.derived());
- }
-
- /** Efficient dense vector/matrix times sparse self-adjoint matrix product */
- template<typename OtherDerived> friend
- DenseTimeSparseSelfAdjointProduct<OtherDerived,MatrixType,UpLo>
- operator*(const MatrixBase<OtherDerived>& lhs, const SparseSelfAdjointView& rhs)
- {
- return DenseTimeSparseSelfAdjointProduct<OtherDerived,_MatrixTypeNested,UpLo>(lhs.derived(), rhs.m_matrix);
- }
-
- /** Perform a symmetric rank K update of the selfadjoint matrix \c *this:
- * \f$ this = this + \alpha ( u u^* ) \f$ where \a u is a vector or matrix.
- *
- * \returns a reference to \c *this
- *
- * Note that it is faster to set alpha=0 than initializing the matrix to zero
- * and then keep the default value alpha=1.
- *
- * To perform \f$ this = this + \alpha ( u^* u ) \f$ you can simply
- * call this function with u.adjoint().
- */
- template<typename DerivedU>
- SparseSelfAdjointView& rankUpdate(const SparseMatrixBase<DerivedU>& u, Scalar alpha = Scalar(1));
-
- /** \internal triggered by sparse_matrix = SparseSelfadjointView; */
- template<typename DestScalar> void evalTo(SparseMatrix<DestScalar>& _dest) const
- {
- internal::permute_symm_to_fullsymm<UpLo>(m_matrix, _dest);
- }
-
- template<typename DestScalar> void evalTo(DynamicSparseMatrix<DestScalar>& _dest) const
- {
- // TODO directly evaluate into _dest;
- SparseMatrix<DestScalar> tmp(_dest.rows(),_dest.cols());
- internal::permute_symm_to_fullsymm<UpLo>(m_matrix, tmp);
- _dest = tmp;
- }
-
- /** \returns an expression of P^-1 H P */
- SparseSymmetricPermutationProduct<_MatrixTypeNested,UpLo> twistedBy(const PermutationMatrix<Dynamic>& perm) const
- {
- return SparseSymmetricPermutationProduct<_MatrixTypeNested,UpLo>(m_matrix, perm);
- }
-
- template<typename SrcMatrixType,int SrcUpLo>
- SparseSelfAdjointView& operator=(const SparseSymmetricPermutationProduct<SrcMatrixType,SrcUpLo>& permutedMatrix)
- {
- permutedMatrix.evalTo(*this);
- return *this;
- }
-
-
- // const SparseLLT<PlainObject, UpLo> llt() const;
- // const SparseLDLT<PlainObject, UpLo> ldlt() const;
-
- protected:
-
- const typename MatrixType::Nested m_matrix;
- mutable VectorI m_countPerRow;
- mutable VectorI m_countPerCol;
-};
-
-/***************************************************************************
-* Implementation of SparseMatrixBase methods
-***************************************************************************/
-
-template<typename Derived>
-template<unsigned int UpLo>
-const SparseSelfAdjointView<Derived, UpLo> SparseMatrixBase<Derived>::selfadjointView() const
-{
- return derived();
-}
-
-template<typename Derived>
-template<unsigned int UpLo>
-SparseSelfAdjointView<Derived, UpLo> SparseMatrixBase<Derived>::selfadjointView()
-{
- return derived();
-}
-
-/***************************************************************************
-* Implementation of SparseSelfAdjointView methods
-***************************************************************************/
-
-template<typename MatrixType, unsigned int UpLo>
-template<typename DerivedU>
-SparseSelfAdjointView<MatrixType,UpLo>&
-SparseSelfAdjointView<MatrixType,UpLo>::rankUpdate(const SparseMatrixBase<DerivedU>& u, Scalar alpha)
-{
- SparseMatrix<Scalar,MatrixType::Flags&RowMajorBit?RowMajor:ColMajor> tmp = u * u.adjoint();
- if(alpha==Scalar(0))
- m_matrix.const_cast_derived() = tmp.template triangularView<UpLo>();
- else
- m_matrix.const_cast_derived() += alpha * tmp.template triangularView<UpLo>();
-
- return *this;
-}
-
-/***************************************************************************
-* Implementation of sparse self-adjoint time dense matrix
-***************************************************************************/
-
-namespace internal {
-template<typename Lhs, typename Rhs, int UpLo>
-struct traits<SparseSelfAdjointTimeDenseProduct<Lhs,Rhs,UpLo> >
- : traits<ProductBase<SparseSelfAdjointTimeDenseProduct<Lhs,Rhs,UpLo>, Lhs, Rhs> >
-{
- typedef Dense StorageKind;
-};
-}
-
-template<typename Lhs, typename Rhs, int UpLo>
-class SparseSelfAdjointTimeDenseProduct
- : public ProductBase<SparseSelfAdjointTimeDenseProduct<Lhs,Rhs,UpLo>, Lhs, Rhs>
-{
- public:
- EIGEN_PRODUCT_PUBLIC_INTERFACE(SparseSelfAdjointTimeDenseProduct)
-
- SparseSelfAdjointTimeDenseProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
- {}
-
- template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const
- {
- // TODO use alpha
- eigen_assert(alpha==Scalar(1) && "alpha != 1 is not implemented yet, sorry");
- typedef typename internal::remove_all<Lhs>::type _Lhs;
- typedef typename internal::remove_all<Rhs>::type _Rhs;
- typedef typename _Lhs::InnerIterator LhsInnerIterator;
- enum {
- LhsIsRowMajor = (_Lhs::Flags&RowMajorBit)==RowMajorBit,
- ProcessFirstHalf =
- ((UpLo&(Upper|Lower))==(Upper|Lower))
- || ( (UpLo&Upper) && !LhsIsRowMajor)
- || ( (UpLo&Lower) && LhsIsRowMajor),
- ProcessSecondHalf = !ProcessFirstHalf
- };
- for (Index j=0; j<m_lhs.outerSize(); ++j)
- {
- LhsInnerIterator i(m_lhs,j);
- if (ProcessSecondHalf && i && (i.index()==j))
- {
- dest.row(j) += i.value() * m_rhs.row(j);
- ++i;
- }
- Block<Dest,1,Dest::ColsAtCompileTime> dest_j(dest.row(LhsIsRowMajor ? j : 0));
- for(; (ProcessFirstHalf ? i && i.index() < j : i) ; ++i)
- {
- Index a = LhsIsRowMajor ? j : i.index();
- Index b = LhsIsRowMajor ? i.index() : j;
- typename Lhs::Scalar v = i.value();
- dest.row(a) += (v) * m_rhs.row(b);
- dest.row(b) += internal::conj(v) * m_rhs.row(a);
- }
- if (ProcessFirstHalf && i && (i.index()==j))
- dest.row(j) += i.value() * m_rhs.row(j);
- }
- }
-
- private:
- SparseSelfAdjointTimeDenseProduct& operator=(const SparseSelfAdjointTimeDenseProduct&);
-};
-
-namespace internal {
-template<typename Lhs, typename Rhs, int UpLo>
-struct traits<DenseTimeSparseSelfAdjointProduct<Lhs,Rhs,UpLo> >
- : traits<ProductBase<DenseTimeSparseSelfAdjointProduct<Lhs,Rhs,UpLo>, Lhs, Rhs> >
-{};
-}
-
-template<typename Lhs, typename Rhs, int UpLo>
-class DenseTimeSparseSelfAdjointProduct
- : public ProductBase<DenseTimeSparseSelfAdjointProduct<Lhs,Rhs,UpLo>, Lhs, Rhs>
-{
- public:
- EIGEN_PRODUCT_PUBLIC_INTERFACE(DenseTimeSparseSelfAdjointProduct)
-
- DenseTimeSparseSelfAdjointProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs)
- {}
-
- template<typename Dest> void scaleAndAddTo(Dest& /*dest*/, Scalar /*alpha*/) const
- {
- // TODO
- }
-
- private:
- DenseTimeSparseSelfAdjointProduct& operator=(const DenseTimeSparseSelfAdjointProduct&);
-};
-
-/***************************************************************************
-* Implementation of symmetric copies and permutations
-***************************************************************************/
-namespace internal {
-
-template<typename MatrixType, int UpLo>
-struct traits<SparseSymmetricPermutationProduct<MatrixType,UpLo> > : traits<MatrixType> {
-};
-
-template<int UpLo,typename MatrixType,int DestOrder>
-void permute_symm_to_fullsymm(const MatrixType& mat, SparseMatrix<typename MatrixType::Scalar,DestOrder,typename MatrixType::Index>& _dest, const typename MatrixType::Index* perm)
-{
- typedef typename MatrixType::Index Index;
- typedef typename MatrixType::Scalar Scalar;
- typedef SparseMatrix<Scalar,DestOrder,Index> Dest;
- typedef Matrix<Index,Dynamic,1> VectorI;
-
- Dest& dest(_dest.derived());
- enum {
- StorageOrderMatch = int(Dest::IsRowMajor) == int(MatrixType::IsRowMajor)
- };
- eigen_assert(perm==0);
- Index size = mat.rows();
- VectorI count;
- count.resize(size);
- count.setZero();
- dest.resize(size,size);
- for(Index j = 0; j<size; ++j)
- {
- Index jp = perm ? perm[j] : j;
- for(typename MatrixType::InnerIterator it(mat,j); it; ++it)
- {
- Index i = it.index();
- Index ip = perm ? perm[i] : i;
- if(i==j)
- count[ip]++;
- else if((UpLo==Lower && i>j) || (UpLo==Upper && i<j))
- {
- count[ip]++;
- count[jp]++;
- }
- }
- }
- Index nnz = count.sum();
-
- // reserve space
- dest.reserve(nnz);
- dest._outerIndexPtr()[0] = 0;
- for(Index j=0; j<size; ++j)
- dest._outerIndexPtr()[j+1] = dest._outerIndexPtr()[j] + count[j];
- for(Index j=0; j<size; ++j)
- count[j] = dest._outerIndexPtr()[j];
-
- // copy data
- for(Index j = 0; j<size; ++j)
- {
- Index jp = perm ? perm[j] : j;
- for(typename MatrixType::InnerIterator it(mat,j); it; ++it)
- {
- Index i = it.index();
- Index ip = perm ? perm[i] : i;
- if(i==j)
- {
- int k = count[ip]++;
- dest._innerIndexPtr()[k] = ip;
- dest._valuePtr()[k] = it.value();
- }
- else if((UpLo==Lower && i>j) || (UpLo==Upper && i<j))
- {
- int k = count[jp]++;
- dest._innerIndexPtr()[k] = ip;
- dest._valuePtr()[k] = it.value();
- k = count[ip]++;
- dest._innerIndexPtr()[k] = jp;
- dest._valuePtr()[k] = internal::conj(it.value());
- }
- }
- }
-}
-
-template<int SrcUpLo,int DstUpLo,typename MatrixType,int DestOrder>
-void permute_symm_to_symm(const MatrixType& mat, SparseMatrix<typename MatrixType::Scalar,DestOrder,typename MatrixType::Index>& _dest, const typename MatrixType::Index* perm)
-{
- typedef typename MatrixType::Index Index;
- typedef typename MatrixType::Scalar Scalar;
- typedef SparseMatrix<Scalar,DestOrder,Index> Dest;
- Dest& dest(_dest.derived());
- typedef Matrix<Index,Dynamic,1> VectorI;
- //internal::conj_if<SrcUpLo!=DstUpLo> cj;
-
- Index size = mat.rows();
- VectorI count(size);
- count.setZero();
- dest.resize(size,size);
- for(Index j = 0; j<size; ++j)
- {
- Index jp = perm ? perm[j] : j;
- for(typename MatrixType::InnerIterator it(mat,j); it; ++it)
- {
- Index i = it.index();
- if((SrcUpLo==Lower && i<j) || (SrcUpLo==Upper && i>j))
- continue;
-
- Index ip = perm ? perm[i] : i;
- count[DstUpLo==Lower ? (std::min)(ip,jp) : (std::max)(ip,jp)]++;
- }
- }
- dest._outerIndexPtr()[0] = 0;
- for(Index j=0; j<size; ++j)
- dest._outerIndexPtr()[j+1] = dest._outerIndexPtr()[j] + count[j];
- dest.resizeNonZeros(dest._outerIndexPtr()[size]);
- for(Index j=0; j<size; ++j)
- count[j] = dest._outerIndexPtr()[j];
-
- for(Index j = 0; j<size; ++j)
- {
- Index jp = perm ? perm[j] : j;
- for(typename MatrixType::InnerIterator it(mat,j); it; ++it)
- {
- Index i = it.index();
- if((SrcUpLo==Lower && i<j) || (SrcUpLo==Upper && i>j))
- continue;
-
- Index ip = perm? perm[i] : i;
- Index k = count[DstUpLo==Lower ? (std::min)(ip,jp) : (std::max)(ip,jp)]++;
- dest._innerIndexPtr()[k] = DstUpLo==Lower ? (std::max)(ip,jp) : (std::min)(ip,jp);
-
- if((DstUpLo==Lower && ip<jp) || (DstUpLo==Upper && ip>jp))
- dest._valuePtr()[k] = conj(it.value());
- else
- dest._valuePtr()[k] = it.value();
- }
- }
-}
-
-}
-
-template<typename MatrixType,int UpLo>
-class SparseSymmetricPermutationProduct
- : public EigenBase<SparseSymmetricPermutationProduct<MatrixType,UpLo> >
-{
- typedef PermutationMatrix<Dynamic> Perm;
- public:
- typedef typename MatrixType::Scalar Scalar;
- typedef typename MatrixType::Index Index;
- typedef Matrix<Index,Dynamic,1> VectorI;
- typedef typename MatrixType::Nested MatrixTypeNested;
- typedef typename internal::remove_all<MatrixTypeNested>::type _MatrixTypeNested;
-
- SparseSymmetricPermutationProduct(const MatrixType& mat, const Perm& perm)
- : m_matrix(mat), m_perm(perm)
- {}
-
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
-
- template<typename DestScalar> void evalTo(SparseMatrix<DestScalar>& _dest) const
- {
- internal::permute_symm_to_fullsymm<UpLo>(m_matrix,_dest,m_perm.indices().data());
- }
-
- template<typename DestType,unsigned int DestUpLo> void evalTo(SparseSelfAdjointView<DestType,DestUpLo>& dest) const
- {
- internal::permute_symm_to_symm<UpLo,DestUpLo>(m_matrix,dest.matrix(),m_perm.indices().data());
- }
-
- protected:
- const MatrixTypeNested m_matrix;
- const Perm& m_perm;
-
-};
-
-#endif // EIGEN_SPARSE_SELFADJOINTVIEW_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseSparseProduct.h b/extern/Eigen3/Eigen/src/Sparse/SparseSparseProduct.h
deleted file mode 100644
index 19abcd1f8e4..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/SparseSparseProduct.h
+++ /dev/null
@@ -1,401 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSESPARSEPRODUCT_H
-#define EIGEN_SPARSESPARSEPRODUCT_H
-
-namespace internal {
-
-template<typename Lhs, typename Rhs, typename ResultType>
-static void sparse_product_impl2(const Lhs& lhs, const Rhs& rhs, ResultType& res)
-{
- typedef typename remove_all<Lhs>::type::Scalar Scalar;
- typedef typename remove_all<Lhs>::type::Index Index;
-
- // make sure to call innerSize/outerSize since we fake the storage order.
- Index rows = lhs.innerSize();
- Index cols = rhs.outerSize();
- eigen_assert(lhs.outerSize() == rhs.innerSize());
-
- std::vector<bool> mask(rows,false);
- Matrix<Scalar,Dynamic,1> values(rows);
- Matrix<Index,Dynamic,1> indices(rows);
-
- // estimate the number of non zero entries
- float ratioLhs = float(lhs.nonZeros())/(float(lhs.rows())*float(lhs.cols()));
- float avgNnzPerRhsColumn = float(rhs.nonZeros())/float(cols);
- float ratioRes = (std::min)(ratioLhs * avgNnzPerRhsColumn, 1.f);
-
-// int t200 = rows/(log2(200)*1.39);
-// int t = (rows*100)/139;
-
- res.resize(rows, cols);
- res.reserve(Index(ratioRes*rows*cols));
- // we compute each column of the result, one after the other
- for (Index j=0; j<cols; ++j)
- {
-
- res.startVec(j);
- Index nnz = 0;
- for (typename Rhs::InnerIterator rhsIt(rhs, j); rhsIt; ++rhsIt)
- {
- Scalar y = rhsIt.value();
- Index k = rhsIt.index();
- for (typename Lhs::InnerIterator lhsIt(lhs, k); lhsIt; ++lhsIt)
- {
- Index i = lhsIt.index();
- Scalar x = lhsIt.value();
- if(!mask[i])
- {
- mask[i] = true;
-// values[i] = x * y;
-// indices[nnz] = i;
- ++nnz;
- }
- else
- values[i] += x * y;
- }
- }
- // FIXME reserve nnz non zeros
- // FIXME implement fast sort algorithms for very small nnz
- // if the result is sparse enough => use a quick sort
- // otherwise => loop through the entire vector
- // In order to avoid to perform an expensive log2 when the
- // result is clearly very sparse we use a linear bound up to 200.
-// if((nnz<200 && nnz<t200) || nnz * log2(nnz) < t)
-// {
-// if(nnz>1) std::sort(indices.data(),indices.data()+nnz);
-// for(int k=0; k<nnz; ++k)
-// {
-// int i = indices[k];
-// res.insertBackNoCheck(j,i) = values[i];
-// mask[i] = false;
-// }
-// }
-// else
-// {
-// // dense path
-// for(int i=0; i<rows; ++i)
-// {
-// if(mask[i])
-// {
-// mask[i] = false;
-// res.insertBackNoCheck(j,i) = values[i];
-// }
-// }
-// }
-
- }
- res.finalize();
-}
-
-// perform a pseudo in-place sparse * sparse product assuming all matrices are col major
-template<typename Lhs, typename Rhs, typename ResultType>
-static void sparse_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res)
-{
-// return sparse_product_impl2(lhs,rhs,res);
-
- typedef typename remove_all<Lhs>::type::Scalar Scalar;
- typedef typename remove_all<Lhs>::type::Index Index;
-
- // make sure to call innerSize/outerSize since we fake the storage order.
- Index rows = lhs.innerSize();
- Index cols = rhs.outerSize();
- //int size = lhs.outerSize();
- eigen_assert(lhs.outerSize() == rhs.innerSize());
-
- // allocate a temporary buffer
- AmbiVector<Scalar,Index> tempVector(rows);
-
- // estimate the number of non zero entries
- float ratioLhs = float(lhs.nonZeros())/(float(lhs.rows())*float(lhs.cols()));
- float avgNnzPerRhsColumn = float(rhs.nonZeros())/float(cols);
- float ratioRes = (std::min)(ratioLhs * avgNnzPerRhsColumn, 1.f);
-
- // mimics a resizeByInnerOuter:
- if(ResultType::IsRowMajor)
- res.resize(cols, rows);
- else
- res.resize(rows, cols);
-
- res.reserve(Index(ratioRes*rows*cols));
- for (Index j=0; j<cols; ++j)
- {
- // let's do a more accurate determination of the nnz ratio for the current column j of res
- //float ratioColRes = (std::min)(ratioLhs * rhs.innerNonZeros(j), 1.f);
- // FIXME find a nice way to get the number of nonzeros of a sub matrix (here an inner vector)
- float ratioColRes = ratioRes;
- tempVector.init(ratioColRes);
- tempVector.setZero();
- for (typename Rhs::InnerIterator rhsIt(rhs, j); rhsIt; ++rhsIt)
- {
- // FIXME should be written like this: tmp += rhsIt.value() * lhs.col(rhsIt.index())
- tempVector.restart();
- Scalar x = rhsIt.value();
- for (typename Lhs::InnerIterator lhsIt(lhs, rhsIt.index()); lhsIt; ++lhsIt)
- {
- tempVector.coeffRef(lhsIt.index()) += lhsIt.value() * x;
- }
- }
- res.startVec(j);
- for (typename AmbiVector<Scalar,Index>::Iterator it(tempVector); it; ++it)
- res.insertBackByOuterInner(j,it.index()) = it.value();
- }
- res.finalize();
-}
-
-template<typename Lhs, typename Rhs, typename ResultType,
- int LhsStorageOrder = traits<Lhs>::Flags&RowMajorBit,
- int RhsStorageOrder = traits<Rhs>::Flags&RowMajorBit,
- int ResStorageOrder = traits<ResultType>::Flags&RowMajorBit>
-struct sparse_product_selector;
-
-template<typename Lhs, typename Rhs, typename ResultType>
-struct sparse_product_selector<Lhs,Rhs,ResultType,ColMajor,ColMajor,ColMajor>
-{
- typedef typename traits<typename remove_all<Lhs>::type>::Scalar Scalar;
-
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
- {
-// std::cerr << __LINE__ << "\n";
- typename remove_all<ResultType>::type _res(res.rows(), res.cols());
- sparse_product_impl<Lhs,Rhs,ResultType>(lhs, rhs, _res);
- res.swap(_res);
- }
-};
-
-template<typename Lhs, typename Rhs, typename ResultType>
-struct sparse_product_selector<Lhs,Rhs,ResultType,ColMajor,ColMajor,RowMajor>
-{
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
- {
-// std::cerr << __LINE__ << "\n";
- // we need a col-major matrix to hold the result
- typedef SparseMatrix<typename ResultType::Scalar> SparseTemporaryType;
- SparseTemporaryType _res(res.rows(), res.cols());
- sparse_product_impl<Lhs,Rhs,SparseTemporaryType>(lhs, rhs, _res);
- res = _res;
- }
-};
-
-template<typename Lhs, typename Rhs, typename ResultType>
-struct sparse_product_selector<Lhs,Rhs,ResultType,RowMajor,RowMajor,RowMajor>
-{
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
- {
-// std::cerr << __LINE__ << "\n";
- // let's transpose the product to get a column x column product
- typename remove_all<ResultType>::type _res(res.rows(), res.cols());
- sparse_product_impl<Rhs,Lhs,ResultType>(rhs, lhs, _res);
- res.swap(_res);
- }
-};
-
-template<typename Lhs, typename Rhs, typename ResultType>
-struct sparse_product_selector<Lhs,Rhs,ResultType,RowMajor,RowMajor,ColMajor>
-{
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
- {
-// std::cerr << "here...\n";
- typedef SparseMatrix<typename ResultType::Scalar,ColMajor> ColMajorMatrix;
- ColMajorMatrix colLhs(lhs);
- ColMajorMatrix colRhs(rhs);
-// std::cerr << "more...\n";
- sparse_product_impl<ColMajorMatrix,ColMajorMatrix,ResultType>(colLhs, colRhs, res);
-// std::cerr << "OK.\n";
-
- // let's transpose the product to get a column x column product
-
-// typedef SparseMatrix<typename ResultType::Scalar> SparseTemporaryType;
-// SparseTemporaryType _res(res.cols(), res.rows());
-// sparse_product_impl<Rhs,Lhs,SparseTemporaryType>(rhs, lhs, _res);
-// res = _res.transpose();
- }
-};
-
-// NOTE the 2 others cases (col row *) must never occur since they are caught
-// by ProductReturnType which transforms it to (col col *) by evaluating rhs.
-
-} // end namespace internal
-
-// sparse = sparse * sparse
-template<typename Derived>
-template<typename Lhs, typename Rhs>
-inline Derived& SparseMatrixBase<Derived>::operator=(const SparseSparseProduct<Lhs,Rhs>& product)
-{
-// std::cerr << "there..." << typeid(Lhs).name() << " " << typeid(Lhs).name() << " " << (Derived::Flags&&RowMajorBit) << "\n";
- internal::sparse_product_selector<
- typename internal::remove_all<Lhs>::type,
- typename internal::remove_all<Rhs>::type,
- Derived>::run(product.lhs(),product.rhs(),derived());
- return derived();
-}
-
-namespace internal {
-
-template<typename Lhs, typename Rhs, typename ResultType,
- int LhsStorageOrder = traits<Lhs>::Flags&RowMajorBit,
- int RhsStorageOrder = traits<Rhs>::Flags&RowMajorBit,
- int ResStorageOrder = traits<ResultType>::Flags&RowMajorBit>
-struct sparse_product_selector2;
-
-template<typename Lhs, typename Rhs, typename ResultType>
-struct sparse_product_selector2<Lhs,Rhs,ResultType,ColMajor,ColMajor,ColMajor>
-{
- typedef typename traits<typename remove_all<Lhs>::type>::Scalar Scalar;
-
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
- {
- sparse_product_impl2<Lhs,Rhs,ResultType>(lhs, rhs, res);
- }
-};
-
-template<typename Lhs, typename Rhs, typename ResultType>
-struct sparse_product_selector2<Lhs,Rhs,ResultType,RowMajor,ColMajor,ColMajor>
-{
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
- {
- // prevent warnings until the code is fixed
- EIGEN_UNUSED_VARIABLE(lhs);
- EIGEN_UNUSED_VARIABLE(rhs);
- EIGEN_UNUSED_VARIABLE(res);
-
-// typedef SparseMatrix<typename ResultType::Scalar,RowMajor> RowMajorMatrix;
-// RowMajorMatrix rhsRow = rhs;
-// RowMajorMatrix resRow(res.rows(), res.cols());
-// sparse_product_impl2<RowMajorMatrix,Lhs,RowMajorMatrix>(rhsRow, lhs, resRow);
-// res = resRow;
- }
-};
-
-template<typename Lhs, typename Rhs, typename ResultType>
-struct sparse_product_selector2<Lhs,Rhs,ResultType,ColMajor,RowMajor,ColMajor>
-{
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
- {
- typedef SparseMatrix<typename ResultType::Scalar,RowMajor> RowMajorMatrix;
- RowMajorMatrix lhsRow = lhs;
- RowMajorMatrix resRow(res.rows(), res.cols());
- sparse_product_impl2<Rhs,RowMajorMatrix,RowMajorMatrix>(rhs, lhsRow, resRow);
- res = resRow;
- }
-};
-
-template<typename Lhs, typename Rhs, typename ResultType>
-struct sparse_product_selector2<Lhs,Rhs,ResultType,RowMajor,RowMajor,ColMajor>
-{
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
- {
- typedef SparseMatrix<typename ResultType::Scalar,RowMajor> RowMajorMatrix;
- RowMajorMatrix resRow(res.rows(), res.cols());
- sparse_product_impl2<Rhs,Lhs,RowMajorMatrix>(rhs, lhs, resRow);
- res = resRow;
- }
-};
-
-
-template<typename Lhs, typename Rhs, typename ResultType>
-struct sparse_product_selector2<Lhs,Rhs,ResultType,ColMajor,ColMajor,RowMajor>
-{
- typedef typename traits<typename remove_all<Lhs>::type>::Scalar Scalar;
-
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
- {
- typedef SparseMatrix<typename ResultType::Scalar,ColMajor> ColMajorMatrix;
- ColMajorMatrix resCol(res.rows(), res.cols());
- sparse_product_impl2<Lhs,Rhs,ColMajorMatrix>(lhs, rhs, resCol);
- res = resCol;
- }
-};
-
-template<typename Lhs, typename Rhs, typename ResultType>
-struct sparse_product_selector2<Lhs,Rhs,ResultType,RowMajor,ColMajor,RowMajor>
-{
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
- {
- typedef SparseMatrix<typename ResultType::Scalar,ColMajor> ColMajorMatrix;
- ColMajorMatrix lhsCol = lhs;
- ColMajorMatrix resCol(res.rows(), res.cols());
- sparse_product_impl2<ColMajorMatrix,Rhs,ColMajorMatrix>(lhsCol, rhs, resCol);
- res = resCol;
- }
-};
-
-template<typename Lhs, typename Rhs, typename ResultType>
-struct sparse_product_selector2<Lhs,Rhs,ResultType,ColMajor,RowMajor,RowMajor>
-{
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
- {
- typedef SparseMatrix<typename ResultType::Scalar,ColMajor> ColMajorMatrix;
- ColMajorMatrix rhsCol = rhs;
- ColMajorMatrix resCol(res.rows(), res.cols());
- sparse_product_impl2<Lhs,ColMajorMatrix,ColMajorMatrix>(lhs, rhsCol, resCol);
- res = resCol;
- }
-};
-
-template<typename Lhs, typename Rhs, typename ResultType>
-struct sparse_product_selector2<Lhs,Rhs,ResultType,RowMajor,RowMajor,RowMajor>
-{
- static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res)
- {
- typedef SparseMatrix<typename ResultType::Scalar,ColMajor> ColMajorMatrix;
-// ColMajorMatrix lhsTr(lhs);
-// ColMajorMatrix rhsTr(rhs);
-// ColMajorMatrix aux(res.rows(), res.cols());
-// sparse_product_impl2<Rhs,Lhs,ColMajorMatrix>(rhs, lhs, aux);
-// // ColMajorMatrix aux2 = aux.transpose();
-// res = aux;
- typedef SparseMatrix<typename ResultType::Scalar,ColMajor> ColMajorMatrix;
- ColMajorMatrix lhsCol(lhs);
- ColMajorMatrix rhsCol(rhs);
- ColMajorMatrix resCol(res.rows(), res.cols());
- sparse_product_impl2<ColMajorMatrix,ColMajorMatrix,ColMajorMatrix>(lhsCol, rhsCol, resCol);
- res = resCol;
- }
-};
-
-} // end namespace internal
-
-template<typename Derived>
-template<typename Lhs, typename Rhs>
-inline void SparseMatrixBase<Derived>::_experimentalNewProduct(const Lhs& lhs, const Rhs& rhs)
-{
- //derived().resize(lhs.rows(), rhs.cols());
- internal::sparse_product_selector2<
- typename internal::remove_all<Lhs>::type,
- typename internal::remove_all<Rhs>::type,
- Derived>::run(lhs,rhs,derived());
-}
-
-// sparse * sparse
-template<typename Derived>
-template<typename OtherDerived>
-inline const typename SparseSparseProductReturnType<Derived,OtherDerived>::Type
-SparseMatrixBase<Derived>::operator*(const SparseMatrixBase<OtherDerived> &other) const
-{
- return typename SparseSparseProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived());
-}
-
-#endif // EIGEN_SPARSESPARSEPRODUCT_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseTranspose.h b/extern/Eigen3/Eigen/src/Sparse/SparseTranspose.h
deleted file mode 100644
index 2aea2fa32c7..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/SparseTranspose.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSETRANSPOSE_H
-#define EIGEN_SPARSETRANSPOSE_H
-
-template<typename MatrixType> class TransposeImpl<MatrixType,Sparse>
- : public SparseMatrixBase<Transpose<MatrixType> >
-{
- typedef typename internal::remove_all<typename MatrixType::Nested>::type _MatrixTypeNested;
- public:
-
- EIGEN_SPARSE_PUBLIC_INTERFACE(Transpose<MatrixType>)
-
- class InnerIterator;
- class ReverseInnerIterator;
-
- inline Index nonZeros() const { return derived().nestedExpression().nonZeros(); }
-};
-
-template<typename MatrixType> class TransposeImpl<MatrixType,Sparse>::InnerIterator
- : public _MatrixTypeNested::InnerIterator
-{
- typedef typename _MatrixTypeNested::InnerIterator Base;
- public:
-
- EIGEN_STRONG_INLINE InnerIterator(const TransposeImpl& trans, Index outer)
- : Base(trans.derived().nestedExpression(), outer)
- {}
- inline Index row() const { return Base::col(); }
- inline Index col() const { return Base::row(); }
-};
-
-template<typename MatrixType> class TransposeImpl<MatrixType,Sparse>::ReverseInnerIterator
- : public _MatrixTypeNested::ReverseInnerIterator
-{
- typedef typename _MatrixTypeNested::ReverseInnerIterator Base;
- public:
-
- EIGEN_STRONG_INLINE ReverseInnerIterator(const TransposeImpl& xpr, Index outer)
- : Base(xpr.derived().nestedExpression(), outer)
- {}
- inline Index row() const { return Base::col(); }
- inline Index col() const { return Base::row(); }
-};
-
-#endif // EIGEN_SPARSETRANSPOSE_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseTriangularView.h b/extern/Eigen3/Eigen/src/Sparse/SparseTriangularView.h
deleted file mode 100644
index 319eaf06638..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/SparseTriangularView.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSE_TRIANGULARVIEW_H
-#define EIGEN_SPARSE_TRIANGULARVIEW_H
-
-namespace internal {
-
-template<typename MatrixType, int Mode>
-struct traits<SparseTriangularView<MatrixType,Mode> >
-: public traits<MatrixType>
-{};
-
-} // namespace internal
-
-template<typename MatrixType, int Mode> class SparseTriangularView
- : public SparseMatrixBase<SparseTriangularView<MatrixType,Mode> >
-{
- enum { SkipFirst = (Mode==Lower && !(MatrixType::Flags&RowMajorBit))
- || (Mode==Upper && (MatrixType::Flags&RowMajorBit)) };
- public:
-
- EIGEN_SPARSE_PUBLIC_INTERFACE(SparseTriangularView)
-
- class InnerIterator;
-
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
-
- typedef typename internal::conditional<internal::must_nest_by_value<MatrixType>::ret,
- MatrixType, const MatrixType&>::type MatrixTypeNested;
-
- inline SparseTriangularView(const MatrixType& matrix) : m_matrix(matrix) {}
-
- /** \internal */
- inline const MatrixType& nestedExpression() const { return m_matrix; }
-
- template<typename OtherDerived>
- typename internal::plain_matrix_type_column_major<OtherDerived>::type
- solve(const MatrixBase<OtherDerived>& other) const;
-
- template<typename OtherDerived> void solveInPlace(MatrixBase<OtherDerived>& other) const;
- template<typename OtherDerived> void solveInPlace(SparseMatrixBase<OtherDerived>& other) const;
-
- protected:
- MatrixTypeNested m_matrix;
-};
-
-template<typename MatrixType, int Mode>
-class SparseTriangularView<MatrixType,Mode>::InnerIterator : public MatrixType::InnerIterator
-{
- typedef typename MatrixType::InnerIterator Base;
- public:
-
- EIGEN_STRONG_INLINE InnerIterator(const SparseTriangularView& view, Index outer)
- : Base(view.nestedExpression(), outer)
- {
- if(SkipFirst)
- while((*this) && this->index()<outer)
- ++(*this);
- }
- inline Index row() const { return Base::row(); }
- inline Index col() const { return Base::col(); }
-
- EIGEN_STRONG_INLINE operator bool() const
- {
- return SkipFirst ? Base::operator bool() : (Base::operator bool() && this->index() <= this->outer());
- }
-};
-
-template<typename Derived>
-template<int Mode>
-inline const SparseTriangularView<Derived, Mode>
-SparseMatrixBase<Derived>::triangularView() const
-{
- return derived();
-}
-
-#endif // EIGEN_SPARSE_TRIANGULARVIEW_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseUtil.h b/extern/Eigen3/Eigen/src/Sparse/SparseUtil.h
deleted file mode 100644
index db9ae98e7a0..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/SparseUtil.h
+++ /dev/null
@@ -1,130 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSEUTIL_H
-#define EIGEN_SPARSEUTIL_H
-
-#ifdef NDEBUG
-#define EIGEN_DBG_SPARSE(X)
-#else
-#define EIGEN_DBG_SPARSE(X) X
-#endif
-
-#define EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(Derived, Op) \
-template<typename OtherDerived> \
-EIGEN_STRONG_INLINE Derived& operator Op(const Eigen::SparseMatrixBase<OtherDerived>& other) \
-{ \
- return Base::operator Op(other.derived()); \
-} \
-EIGEN_STRONG_INLINE Derived& operator Op(const Derived& other) \
-{ \
- return Base::operator Op(other); \
-}
-
-#define EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, Op) \
-template<typename Other> \
-EIGEN_STRONG_INLINE Derived& operator Op(const Other& scalar) \
-{ \
- return Base::operator Op(scalar); \
-}
-
-#define EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATORS(Derived) \
-EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(Derived, =) \
-EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(Derived, +=) \
-EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(Derived, -=) \
-EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, *=) \
-EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, /=)
-
-#define _EIGEN_SPARSE_PUBLIC_INTERFACE(Derived, BaseClass) \
- typedef BaseClass Base; \
- typedef typename Eigen::internal::traits<Derived>::Scalar Scalar; \
- typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; \
- typedef typename Eigen::internal::nested<Derived>::type Nested; \
- typedef typename Eigen::internal::traits<Derived>::StorageKind StorageKind; \
- typedef typename Eigen::internal::traits<Derived>::Index Index; \
- enum { RowsAtCompileTime = Eigen::internal::traits<Derived>::RowsAtCompileTime, \
- ColsAtCompileTime = Eigen::internal::traits<Derived>::ColsAtCompileTime, \
- Flags = Eigen::internal::traits<Derived>::Flags, \
- CoeffReadCost = Eigen::internal::traits<Derived>::CoeffReadCost, \
- SizeAtCompileTime = Base::SizeAtCompileTime, \
- IsVectorAtCompileTime = Base::IsVectorAtCompileTime }; \
- using Base::derived; \
- using Base::const_cast_derived;
-
-#define EIGEN_SPARSE_PUBLIC_INTERFACE(Derived) \
- _EIGEN_SPARSE_PUBLIC_INTERFACE(Derived, Eigen::SparseMatrixBase<Derived>)
-
-const int CoherentAccessPattern = 0x1;
-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;
-template<typename _Scalar, int _Flags = 0, typename _Index = int> class MappedSparseMatrix;
-
-template<typename MatrixType, int Size> class SparseInnerVectorSet;
-template<typename MatrixType, int Mode> class SparseTriangularView;
-template<typename MatrixType, unsigned int UpLo> class SparseSelfAdjointView;
-template<typename Lhs, typename Rhs> class SparseDiagonalProduct;
-template<typename MatrixType> class SparseView;
-
-template<typename Lhs, typename Rhs> class SparseSparseProduct;
-template<typename Lhs, typename Rhs> class SparseTimeDenseProduct;
-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;
-
-namespace internal {
-
-template<typename T> struct eval<T,Sparse>
-{
- typedef typename traits<T>::Scalar _Scalar;
- enum {
- _Flags = traits<T>::Flags
- };
-
- public:
- typedef SparseMatrix<_Scalar, _Flags> type;
-};
-
-template<typename T> struct plain_matrix_type<T,Sparse>
-{
- typedef typename traits<T>::Scalar _Scalar;
- enum {
- _Flags = traits<T>::Flags
- };
-
- public:
- typedef SparseMatrix<_Scalar, _Flags> type;
-};
-
-} // end namespace internal
-
-#endif // EIGEN_SPARSEUTIL_H
diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseView.h b/extern/Eigen3/Eigen/src/Sparse/SparseView.h
deleted file mode 100644
index 24306561098..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/SparseView.h
+++ /dev/null
@@ -1,109 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2010 Daniel Lowengrub <lowdanie@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSEVIEW_H
-#define EIGEN_SPARSEVIEW_H
-
-namespace internal {
-
-template<typename MatrixType>
-struct traits<SparseView<MatrixType> > : traits<MatrixType>
-{
- typedef int Index;
- typedef Sparse StorageKind;
- enum {
- Flags = int(traits<MatrixType>::Flags) & (RowMajorBit)
- };
-};
-
-} // end namespace internal
-
-template<typename MatrixType>
-class SparseView : public SparseMatrixBase<SparseView<MatrixType> >
-{
- typedef typename MatrixType::Nested MatrixTypeNested;
- typedef typename internal::remove_all<MatrixTypeNested>::type _MatrixTypeNested;
-public:
- EIGEN_SPARSE_PUBLIC_INTERFACE(SparseView)
-
- SparseView(const MatrixType& mat, const Scalar& m_reference = Scalar(0),
- typename NumTraits<Scalar>::Real m_epsilon = NumTraits<Scalar>::dummy_precision()) :
- m_matrix(mat), m_reference(m_reference), m_epsilon(m_epsilon) {}
-
- class InnerIterator;
-
- inline Index rows() const { return m_matrix.rows(); }
- inline Index cols() const { return m_matrix.cols(); }
-
- inline Index innerSize() const { return m_matrix.innerSize(); }
- inline Index outerSize() const { return m_matrix.outerSize(); }
-
-protected:
- const MatrixTypeNested m_matrix;
- Scalar m_reference;
- typename NumTraits<Scalar>::Real m_epsilon;
-};
-
-template<typename MatrixType>
-class SparseView<MatrixType>::InnerIterator : public _MatrixTypeNested::InnerIterator
-{
-public:
- typedef typename _MatrixTypeNested::InnerIterator IterBase;
- InnerIterator(const SparseView& view, Index outer) :
- IterBase(view.m_matrix, outer), m_view(view)
- {
- incrementToNonZero();
- }
-
- EIGEN_STRONG_INLINE InnerIterator& operator++()
- {
- IterBase::operator++();
- incrementToNonZero();
- return *this;
- }
-
- using IterBase::value;
-
-protected:
- const SparseView& m_view;
-
-private:
- void incrementToNonZero()
- {
- while(internal::isMuchSmallerThan(value(), m_view.m_reference, m_view.m_epsilon) && (bool(*this)))
- {
- IterBase::operator++();
- }
- }
-};
-
-template<typename Derived>
-const SparseView<Derived> MatrixBase<Derived>::sparseView(const Scalar& m_reference,
- typename NumTraits<Scalar>::Real m_epsilon) const
-{
- return SparseView<Derived>(derived(), m_reference, m_epsilon);
-}
-
-#endif
diff --git a/extern/Eigen3/Eigen/src/Sparse/TriangularSolver.h b/extern/Eigen3/Eigen/src/Sparse/TriangularSolver.h
deleted file mode 100644
index 73468e0446c..00000000000
--- a/extern/Eigen3/Eigen/src/Sparse/TriangularSolver.h
+++ /dev/null
@@ -1,339 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_SPARSETRIANGULARSOLVER_H
-#define EIGEN_SPARSETRIANGULARSOLVER_H
-
-namespace internal {
-
-template<typename Lhs, typename Rhs, int Mode,
- int UpLo = (Mode & Lower)
- ? Lower
- : (Mode & Upper)
- ? Upper
- : -1,
- int StorageOrder = int(traits<Lhs>::Flags) & RowMajorBit>
-struct sparse_solve_triangular_selector;
-
-// forward substitution, row-major
-template<typename Lhs, typename Rhs, int Mode>
-struct sparse_solve_triangular_selector<Lhs,Rhs,Mode,Lower,RowMajor>
-{
- typedef typename Rhs::Scalar Scalar;
- static void run(const Lhs& lhs, Rhs& other)
- {
- for(int col=0 ; col<other.cols() ; ++col)
- {
- for(int i=0; i<lhs.rows(); ++i)
- {
- Scalar tmp = other.coeff(i,col);
- Scalar lastVal = 0;
- int lastIndex = 0;
- for(typename Lhs::InnerIterator it(lhs, i); it; ++it)
- {
- lastVal = it.value();
- lastIndex = it.index();
- if(lastIndex==i)
- break;
- tmp -= lastVal * other.coeff(lastIndex,col);
- }
- if (Mode & UnitDiag)
- other.coeffRef(i,col) = tmp;
- else
- {
- eigen_assert(lastIndex==i);
- other.coeffRef(i,col) = tmp/lastVal;
- }
- }
- }
- }
-};
-
-// backward substitution, row-major
-template<typename Lhs, typename Rhs, int Mode>
-struct sparse_solve_triangular_selector<Lhs,Rhs,Mode,Upper,RowMajor>
-{
- typedef typename Rhs::Scalar Scalar;
- static void run(const Lhs& lhs, Rhs& other)
- {
- for(int col=0 ; col<other.cols() ; ++col)
- {
- for(int i=lhs.rows()-1 ; i>=0 ; --i)
- {
- Scalar tmp = other.coeff(i,col);
- typename Lhs::InnerIterator it(lhs, i);
- if (it && it.index() == i)
- ++it;
- for(; it; ++it)
- {
- tmp -= it.value() * other.coeff(it.index(),col);
- }
-
- if (Mode & UnitDiag)
- other.coeffRef(i,col) = tmp;
- else
- {
- typename Lhs::InnerIterator it(lhs, i);
- eigen_assert(it && it.index() == i);
- other.coeffRef(i,col) = tmp/it.value();
- }
- }
- }
- }
-};
-
-// forward substitution, col-major
-template<typename Lhs, typename Rhs, int Mode>
-struct sparse_solve_triangular_selector<Lhs,Rhs,Mode,Lower,ColMajor>
-{
- typedef typename Rhs::Scalar Scalar;
- static void run(const Lhs& lhs, Rhs& other)
- {
- for(int col=0 ; col<other.cols() ; ++col)
- {
- for(int i=0; i<lhs.cols(); ++i)
- {
- Scalar& tmp = other.coeffRef(i,col);
- if (tmp!=Scalar(0)) // optimization when other is actually sparse
- {
- typename Lhs::InnerIterator it(lhs, i);
- if(!(Mode & UnitDiag))
- {
- eigen_assert(it.index()==i);
- tmp /= it.value();
- }
- if (it && it.index()==i)
- ++it;
- for(; it; ++it)
- other.coeffRef(it.index(), col) -= tmp * it.value();
- }
- }
- }
- }
-};
-
-// backward substitution, col-major
-template<typename Lhs, typename Rhs, int Mode>
-struct sparse_solve_triangular_selector<Lhs,Rhs,Mode,Upper,ColMajor>
-{
- typedef typename Rhs::Scalar Scalar;
- static void run(const Lhs& lhs, Rhs& other)
- {
- for(int col=0 ; col<other.cols() ; ++col)
- {
- for(int i=lhs.cols()-1; i>=0; --i)
- {
- Scalar& tmp = other.coeffRef(i,col);
- if (tmp!=Scalar(0)) // optimization when other is actually sparse
- {
- if(!(Mode & UnitDiag))
- {
- // FIXME lhs.coeff(i,i) might not be always efficient while it must simply be the
- // last element of the column !
- other.coeffRef(i,col) /= lhs.innerVector(i).lastCoeff();
- }
- typename Lhs::InnerIterator it(lhs, i);
- for(; it && it.index()<i; ++it)
- other.coeffRef(it.index(), col) -= tmp * it.value();
- }
- }
- }
- }
-};
-
-} // end namespace internal
-
-template<typename ExpressionType,int Mode>
-template<typename OtherDerived>
-void SparseTriangularView<ExpressionType,Mode>::solveInPlace(MatrixBase<OtherDerived>& other) const
-{
- eigen_assert(m_matrix.cols() == m_matrix.rows());
- eigen_assert(m_matrix.cols() == other.rows());
- eigen_assert(!(Mode & ZeroDiag));
- eigen_assert(Mode & (Upper|Lower));
-
- enum { copy = internal::traits<OtherDerived>::Flags & RowMajorBit };
-
- typedef typename internal::conditional<copy,
- typename internal::plain_matrix_type_column_major<OtherDerived>::type, OtherDerived&>::type OtherCopy;
- OtherCopy otherCopy(other.derived());
-
- internal::sparse_solve_triangular_selector<ExpressionType, typename internal::remove_reference<OtherCopy>::type, Mode>::run(m_matrix, otherCopy);
-
- if (copy)
- other = otherCopy;
-}
-
-template<typename ExpressionType,int Mode>
-template<typename OtherDerived>
-typename internal::plain_matrix_type_column_major<OtherDerived>::type
-SparseTriangularView<ExpressionType,Mode>::solve(const MatrixBase<OtherDerived>& other) const
-{
- typename internal::plain_matrix_type_column_major<OtherDerived>::type res(other);
- solveInPlace(res);
- return res;
-}
-
-// pure sparse path
-
-namespace internal {
-
-template<typename Lhs, typename Rhs, int Mode,
- int UpLo = (Mode & Lower)
- ? Lower
- : (Mode & Upper)
- ? Upper
- : -1,
- int StorageOrder = int(Lhs::Flags) & (RowMajorBit)>
-struct sparse_solve_triangular_sparse_selector;
-
-// forward substitution, col-major
-template<typename Lhs, typename Rhs, int Mode, int UpLo>
-struct sparse_solve_triangular_sparse_selector<Lhs,Rhs,Mode,UpLo,ColMajor>
-{
- typedef typename Rhs::Scalar Scalar;
- typedef typename promote_index_type<typename traits<Lhs>::Index,
- typename traits<Rhs>::Index>::type Index;
- static void run(const Lhs& lhs, Rhs& other)
- {
- const bool IsLower = (UpLo==Lower);
- AmbiVector<Scalar,Index> tempVector(other.rows()*2);
- tempVector.setBounds(0,other.rows());
-
- Rhs res(other.rows(), other.cols());
- res.reserve(other.nonZeros());
-
- for(int col=0 ; col<other.cols() ; ++col)
- {
- // FIXME estimate number of non zeros
- tempVector.init(.99/*float(other.col(col).nonZeros())/float(other.rows())*/);
- tempVector.setZero();
- tempVector.restart();
- for (typename Rhs::InnerIterator rhsIt(other, col); rhsIt; ++rhsIt)
- {
- tempVector.coeffRef(rhsIt.index()) = rhsIt.value();
- }
-
- for(int i=IsLower?0:lhs.cols()-1;
- IsLower?i<lhs.cols():i>=0;
- i+=IsLower?1:-1)
- {
- tempVector.restart();
- Scalar& ci = tempVector.coeffRef(i);
- if (ci!=Scalar(0))
- {
- // find
- typename Lhs::InnerIterator it(lhs, i);
- if(!(Mode & UnitDiag))
- {
- if (IsLower)
- {
- eigen_assert(it.index()==i);
- ci /= it.value();
- }
- else
- ci /= lhs.coeff(i,i);
- }
- tempVector.restart();
- if (IsLower)
- {
- if (it.index()==i)
- ++it;
- for(; it; ++it)
- tempVector.coeffRef(it.index()) -= ci * it.value();
- }
- else
- {
- for(; it && it.index()<i; ++it)
- tempVector.coeffRef(it.index()) -= ci * it.value();
- }
- }
- }
-
-
- int count = 0;
- // FIXME compute a reference value to filter zeros
- for (typename AmbiVector<Scalar,Index>::Iterator it(tempVector/*,1e-12*/); it; ++it)
- {
- ++ count;
-// std::cerr << "fill " << it.index() << ", " << col << "\n";
-// std::cout << it.value() << " ";
- // FIXME use insertBack
- res.insert(it.index(), col) = it.value();
- }
-// std::cout << "tempVector.nonZeros() == " << int(count) << " / " << (other.rows()) << "\n";
- }
- res.finalize();
- other = res.markAsRValue();
- }
-};
-
-} // end namespace internal
-
-template<typename ExpressionType,int Mode>
-template<typename OtherDerived>
-void SparseTriangularView<ExpressionType,Mode>::solveInPlace(SparseMatrixBase<OtherDerived>& other) const
-{
- eigen_assert(m_matrix.cols() == m_matrix.rows());
- eigen_assert(m_matrix.cols() == other.rows());
- eigen_assert(!(Mode & ZeroDiag));
- eigen_assert(Mode & (Upper|Lower));
-
-// enum { copy = internal::traits<OtherDerived>::Flags & RowMajorBit };
-
-// typedef typename internal::conditional<copy,
-// typename internal::plain_matrix_type_column_major<OtherDerived>::type, OtherDerived&>::type OtherCopy;
-// OtherCopy otherCopy(other.derived());
-
- internal::sparse_solve_triangular_sparse_selector<ExpressionType, OtherDerived, Mode>::run(m_matrix, other.derived());
-
-// if (copy)
-// other = otherCopy;
-}
-
-#ifdef EIGEN2_SUPPORT
-
-// deprecated stuff:
-
-/** \deprecated */
-template<typename Derived>
-template<typename OtherDerived>
-void SparseMatrixBase<Derived>::solveTriangularInPlace(MatrixBase<OtherDerived>& other) const
-{
- this->template triangular<Flags&(Upper|Lower)>().solveInPlace(other);
-}
-
-/** \deprecated */
-template<typename Derived>
-template<typename OtherDerived>
-typename internal::plain_matrix_type_column_major<OtherDerived>::type
-SparseMatrixBase<Derived>::solveTriangular(const MatrixBase<OtherDerived>& other) const
-{
- typename internal::plain_matrix_type_column_major<OtherDerived>::type res(other);
- derived().solveTriangularInPlace(res);
- return res;
-}
-#endif // EIGEN2_SUPPORT
-
-#endif // EIGEN_SPARSETRIANGULARSOLVER_H
diff --git a/extern/Eigen3/Eigen/src/StlSupport/StdDeque.h b/extern/Eigen3/Eigen/src/StlSupport/StdDeque.h
deleted file mode 100644
index 6f12c106dbc..00000000000
--- a/extern/Eigen3/Eigen/src/StlSupport/StdDeque.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_STDDEQUE_H
-#define EIGEN_STDDEQUE_H
-
-#include "Eigen/src/StlSupport/details.h"
-
-// Define the explicit instantiation (e.g. necessary for the Intel compiler)
-#if defined(__INTEL_COMPILER) || defined(__GNUC__)
- #define EIGEN_EXPLICIT_STL_DEQUE_INSTANTIATION(...) template class std::deque<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> >;
-#else
- #define EIGEN_EXPLICIT_STL_DEQUE_INSTANTIATION(...)
-#endif
-
-/**
- * This section contains a convenience MACRO which allows an easy specialization of
- * std::deque such that for data types with alignment issues the correct allocator
- * is used automatically.
- */
-#define EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(...) \
-EIGEN_EXPLICIT_STL_DEQUE_INSTANTIATION(__VA_ARGS__) \
-namespace std \
-{ \
- template<typename _Ay> \
- class deque<__VA_ARGS__, _Ay> \
- : public deque<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > \
- { \
- typedef deque<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > deque_base; \
- public: \
- typedef __VA_ARGS__ value_type; \
- typedef typename deque_base::allocator_type allocator_type; \
- typedef typename deque_base::size_type size_type; \
- typedef typename deque_base::iterator iterator; \
- explicit deque(const allocator_type& a = allocator_type()) : deque_base(a) {} \
- template<typename InputIterator> \
- deque(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) : deque_base(first, last, a) {} \
- deque(const deque& c) : deque_base(c) {} \
- explicit deque(size_type num, const value_type& val = value_type()) : deque_base(num, val) {} \
- deque(iterator start, iterator end) : deque_base(start, end) {} \
- deque& operator=(const deque& x) { \
- deque_base::operator=(x); \
- return *this; \
- } \
- }; \
-}
-
-// check whether we really need the std::deque specialization
-#if !(defined(_GLIBCXX_DEQUE) && (!EIGEN_GNUC_AT_LEAST(4,1))) /* Note that before gcc-4.1 we already have: std::deque::resize(size_type,const T&). */
-
-namespace std {
-
-#define EIGEN_STD_DEQUE_SPECIALIZATION_BODY \
- public: \
- typedef T value_type; \
- typedef typename deque_base::allocator_type allocator_type; \
- typedef typename deque_base::size_type size_type; \
- typedef typename deque_base::iterator iterator; \
- typedef typename deque_base::const_iterator const_iterator; \
- explicit deque(const allocator_type& a = allocator_type()) : deque_base(a) {} \
- template<typename InputIterator> \
- deque(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) \
- : deque_base(first, last, a) {} \
- deque(const deque& c) : deque_base(c) {} \
- explicit deque(size_type num, const value_type& val = value_type()) : deque_base(num, val) {} \
- deque(iterator start, iterator end) : deque_base(start, end) {} \
- deque& operator=(const deque& x) { \
- deque_base::operator=(x); \
- return *this; \
- }
-
- template<typename T>
- class deque<T,EIGEN_ALIGNED_ALLOCATOR<T> >
- : public deque<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T),
- Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T)> >
-{
- typedef deque<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T),
- Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T)> > deque_base;
- EIGEN_STD_DEQUE_SPECIALIZATION_BODY
-
- void resize(size_type new_size)
- { resize(new_size, T()); }
-
-#if defined(_DEQUE_)
- // workaround MSVC std::deque implementation
- void resize(size_type new_size, const value_type& x)
- {
- if (deque_base::size() < new_size)
- deque_base::_Insert_n(deque_base::end(), new_size - deque_base::size(), x);
- else if (new_size < deque_base::size())
- deque_base::erase(deque_base::begin() + new_size, deque_base::end());
- }
- void push_back(const value_type& x)
- { deque_base::push_back(x); }
- void push_front(const value_type& x)
- { deque_base::push_front(x); }
- using deque_base::insert;
- iterator insert(const_iterator position, const value_type& x)
- { return deque_base::insert(position,x); }
- void insert(const_iterator position, size_type new_size, const value_type& x)
- { deque_base::insert(position, new_size, x); }
-#elif defined(_GLIBCXX_DEQUE) && EIGEN_GNUC_AT_LEAST(4,2)
- // workaround GCC std::deque implementation
- void resize(size_type new_size, const value_type& x)
- {
- if (new_size < deque_base::size())
- deque_base::_M_erase_at_end(this->_M_impl._M_start + new_size);
- else
- deque_base::insert(deque_base::end(), new_size - deque_base::size(), x);
- }
-#else
- // either GCC 4.1 or non-GCC
- // default implementation which should always work.
- void resize(size_type new_size, const value_type& x)
- {
- if (new_size < deque_base::size())
- deque_base::erase(deque_base::begin() + new_size, deque_base::end());
- else if (new_size > deque_base::size())
- deque_base::insert(deque_base::end(), new_size - deque_base::size(), x);
- }
-#endif
- };
-}
-
-#endif // check whether specialization is actually required
-
-#endif // EIGEN_STDDEQUE_H
diff --git a/extern/Eigen3/Eigen/src/StlSupport/StdList.h b/extern/Eigen3/Eigen/src/StlSupport/StdList.h
deleted file mode 100644
index d329a0b2dc5..00000000000
--- a/extern/Eigen3/Eigen/src/StlSupport/StdList.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_STDLIST_H
-#define EIGEN_STDLIST_H
-
-#include "Eigen/src/StlSupport/details.h"
-
-// Define the explicit instantiation (e.g. necessary for the Intel compiler)
-#if defined(__INTEL_COMPILER) || defined(__GNUC__)
- #define EIGEN_EXPLICIT_STL_LIST_INSTANTIATION(...) template class std::list<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> >;
-#else
- #define EIGEN_EXPLICIT_STL_LIST_INSTANTIATION(...)
-#endif
-
-/**
- * This section contains a convenience MACRO which allows an easy specialization of
- * std::list such that for data types with alignment issues the correct allocator
- * is used automatically.
- */
-#define EIGEN_DEFINE_STL_LIST_SPECIALIZATION(...) \
-EIGEN_EXPLICIT_STL_LIST_INSTANTIATION(__VA_ARGS__) \
-namespace std \
-{ \
- template<typename _Ay> \
- class list<__VA_ARGS__, _Ay> \
- : public list<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > \
- { \
- typedef list<__VA_ARGS__, EIGEN_ALIGNED_ALLOCATOR<__VA_ARGS__> > list_base; \
- public: \
- typedef __VA_ARGS__ value_type; \
- typedef typename list_base::allocator_type allocator_type; \
- typedef typename list_base::size_type size_type; \
- typedef typename list_base::iterator iterator; \
- explicit list(const allocator_type& a = allocator_type()) : list_base(a) {} \
- template<typename InputIterator> \
- list(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) : list_base(first, last, a) {} \
- list(const list& c) : list_base(c) {} \
- explicit list(size_type num, const value_type& val = value_type()) : list_base(num, val) {} \
- list(iterator start, iterator end) : list_base(start, end) {} \
- list& operator=(const list& x) { \
- list_base::operator=(x); \
- return *this; \
- } \
- }; \
-}
-
-// check whether we really need the std::vector specialization
-#if !(defined(_GLIBCXX_VECTOR) && (!EIGEN_GNUC_AT_LEAST(4,1))) /* Note that before gcc-4.1 we already have: std::list::resize(size_type,const T&). */
-
-namespace std
-{
-
-#define EIGEN_STD_LIST_SPECIALIZATION_BODY \
- public: \
- typedef T value_type; \
- typedef typename list_base::allocator_type allocator_type; \
- typedef typename list_base::size_type size_type; \
- typedef typename list_base::iterator iterator; \
- typedef typename list_base::const_iterator const_iterator; \
- explicit list(const allocator_type& a = allocator_type()) : list_base(a) {} \
- template<typename InputIterator> \
- list(InputIterator first, InputIterator last, const allocator_type& a = allocator_type()) \
- : list_base(first, last, a) {} \
- list(const list& c) : list_base(c) {} \
- explicit list(size_type num, const value_type& val = value_type()) : list_base(num, val) {} \
- list(iterator start, iterator end) : list_base(start, end) {} \
- list& operator=(const list& x) { \
- list_base::operator=(x); \
- return *this; \
- }
-
- template<typename T>
- class list<T,EIGEN_ALIGNED_ALLOCATOR<T> >
- : public list<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T),
- Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T)> >
- {
- typedef list<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T),
- Eigen::aligned_allocator_indirection<EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T)> > list_base;
- EIGEN_STD_LIST_SPECIALIZATION_BODY
-
- void resize(size_type new_size)
- { resize(new_size, T()); }
-
- void resize(size_type new_size, const value_type& x)
- {
- if (list_base::size() < new_size)
- list_base::insert(list_base::end(), new_size - list_base::size(), x);
- else
- while (new_size < list_base::size()) list_base::pop_back();
- }
-
-#if defined(_LIST_)
- // workaround MSVC std::list implementation
- void push_back(const value_type& x)
- { list_base::push_back(x); }
- using list_base::insert;
- iterator insert(const_iterator position, const value_type& x)
- { return list_base::insert(position,x); }
- void insert(const_iterator position, size_type new_size, const value_type& x)
- { list_base::insert(position, new_size, x); }
-#endif
- };
-}
-
-#endif // check whether specialization is actually required
-
-#endif // EIGEN_STDLIST_H
diff --git a/extern/Eigen3/Eigen/src/StlSupport/details.h b/extern/Eigen3/Eigen/src/StlSupport/details.h
deleted file mode 100644
index 397c8ef8581..00000000000
--- a/extern/Eigen3/Eigen/src/StlSupport/details.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2009 Hauke Heibel <hauke.heibel@googlemail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_STL_DETAILS_H
-#define EIGEN_STL_DETAILS_H
-
-#ifndef EIGEN_ALIGNED_ALLOCATOR
- #define EIGEN_ALIGNED_ALLOCATOR Eigen::aligned_allocator
-#endif
-
-namespace Eigen {
-
- // This one is needed to prevent reimplementing the whole std::vector.
- template <class T>
- class aligned_allocator_indirection : public EIGEN_ALIGNED_ALLOCATOR<T>
- {
- public:
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef T value_type;
-
- template<class U>
- struct rebind
- {
- typedef aligned_allocator_indirection<U> other;
- };
-
- aligned_allocator_indirection() {}
- aligned_allocator_indirection(const aligned_allocator_indirection& ) : EIGEN_ALIGNED_ALLOCATOR<T>() {}
- aligned_allocator_indirection(const EIGEN_ALIGNED_ALLOCATOR<T>& ) {}
- template<class U>
- aligned_allocator_indirection(const aligned_allocator_indirection<U>& ) {}
- template<class U>
- aligned_allocator_indirection(const EIGEN_ALIGNED_ALLOCATOR<U>& ) {}
- ~aligned_allocator_indirection() {}
- };
-
-#ifdef _MSC_VER
-
- // sometimes, MSVC detects, at compile time, that the argument x
- // in std::vector::resize(size_t s,T x) won't be aligned and generate an error
- // even if this function is never called. Whence this little wrapper.
-#define EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T) \
- typename Eigen::internal::conditional< \
- Eigen::internal::is_arithmetic<T>::value, \
- T, \
- Eigen::internal::workaround_msvc_stl_support<T> \
- >::type
-
- namespace internal {
- template<typename T> struct workaround_msvc_stl_support : public T
- {
- inline workaround_msvc_stl_support() : T() {}
- inline workaround_msvc_stl_support(const T& other) : T(other) {}
- inline operator T& () { return *static_cast<T*>(this); }
- inline operator const T& () const { return *static_cast<const T*>(this); }
- template<typename OtherT>
- inline T& operator=(const OtherT& other)
- { T::operator=(other); return *this; }
- inline workaround_msvc_stl_support& operator=(const workaround_msvc_stl_support& other)
- { T::operator=(other); return *this; }
- };
- }
-
-#else
-
-#define EIGEN_WORKAROUND_MSVC_STL_SUPPORT(T) T
-
-#endif
-
-}
-
-#endif // EIGEN_STL_DETAILS_H
diff --git a/extern/Eigen3/Eigen/src/misc/Image.h b/extern/Eigen3/Eigen/src/misc/Image.h
deleted file mode 100644
index 19b3e08cbfd..00000000000
--- a/extern/Eigen3/Eigen/src/misc/Image.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_MISC_IMAGE_H
-#define EIGEN_MISC_IMAGE_H
-
-namespace internal {
-
-/** \class image_retval_base
- *
- */
-template<typename DecompositionType>
-struct traits<image_retval_base<DecompositionType> >
-{
- typedef typename DecompositionType::MatrixType MatrixType;
- typedef Matrix<
- typename MatrixType::Scalar,
- MatrixType::RowsAtCompileTime, // the image is a subspace of the destination space, whose
- // dimension is the number of rows of the original matrix
- Dynamic, // we don't know at compile time the dimension of the image (the rank)
- MatrixType::Options,
- MatrixType::MaxRowsAtCompileTime, // the image matrix will consist of columns from the original matrix,
- MatrixType::MaxColsAtCompileTime // so it has the same number of rows and at most as many columns.
- > ReturnType;
-};
-
-template<typename _DecompositionType> struct image_retval_base
- : public ReturnByValue<image_retval_base<_DecompositionType> >
-{
- typedef _DecompositionType DecompositionType;
- typedef typename DecompositionType::MatrixType MatrixType;
- typedef ReturnByValue<image_retval_base> Base;
- typedef typename Base::Index Index;
-
- image_retval_base(const DecompositionType& dec, const MatrixType& originalMatrix)
- : m_dec(dec), m_rank(dec.rank()),
- m_cols(m_rank == 0 ? 1 : m_rank),
- m_originalMatrix(originalMatrix)
- {}
-
- inline Index rows() const { return m_dec.rows(); }
- inline Index cols() const { return m_cols; }
- inline Index rank() const { return m_rank; }
- inline const DecompositionType& dec() const { return m_dec; }
- inline const MatrixType& originalMatrix() const { return m_originalMatrix; }
-
- template<typename Dest> inline void evalTo(Dest& dst) const
- {
- static_cast<const image_retval<DecompositionType>*>(this)->evalTo(dst);
- }
-
- protected:
- const DecompositionType& m_dec;
- Index m_rank, m_cols;
- const MatrixType& m_originalMatrix;
-};
-
-} // end namespace internal
-
-#define EIGEN_MAKE_IMAGE_HELPERS(DecompositionType) \
- typedef typename DecompositionType::MatrixType MatrixType; \
- typedef typename MatrixType::Scalar Scalar; \
- typedef typename MatrixType::RealScalar RealScalar; \
- typedef typename MatrixType::Index Index; \
- typedef Eigen::internal::image_retval_base<DecompositionType> Base; \
- using Base::dec; \
- using Base::originalMatrix; \
- using Base::rank; \
- using Base::rows; \
- using Base::cols; \
- image_retval(const DecompositionType& dec, const MatrixType& originalMatrix) \
- : Base(dec, originalMatrix) {}
-
-#endif // EIGEN_MISC_IMAGE_H
diff --git a/extern/Eigen3/Eigen/src/misc/Kernel.h b/extern/Eigen3/Eigen/src/misc/Kernel.h
deleted file mode 100644
index 0115970e8eb..00000000000
--- a/extern/Eigen3/Eigen/src/misc/Kernel.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_MISC_KERNEL_H
-#define EIGEN_MISC_KERNEL_H
-
-namespace internal {
-
-/** \class kernel_retval_base
- *
- */
-template<typename DecompositionType>
-struct traits<kernel_retval_base<DecompositionType> >
-{
- typedef typename DecompositionType::MatrixType MatrixType;
- typedef Matrix<
- typename MatrixType::Scalar,
- MatrixType::ColsAtCompileTime, // the number of rows in the "kernel matrix"
- // is the number of cols of the original matrix
- // so that the product "matrix * kernel = zero" makes sense
- Dynamic, // we don't know at compile-time the dimension of the kernel
- MatrixType::Options,
- MatrixType::MaxColsAtCompileTime, // see explanation for 2nd template parameter
- MatrixType::MaxColsAtCompileTime // the kernel is a subspace of the domain space,
- // whose dimension is the number of columns of the original matrix
- > ReturnType;
-};
-
-template<typename _DecompositionType> struct kernel_retval_base
- : public ReturnByValue<kernel_retval_base<_DecompositionType> >
-{
- typedef _DecompositionType DecompositionType;
- typedef ReturnByValue<kernel_retval_base> Base;
- typedef typename Base::Index Index;
-
- kernel_retval_base(const DecompositionType& dec)
- : m_dec(dec),
- m_rank(dec.rank()),
- m_cols(m_rank==dec.cols() ? 1 : dec.cols() - m_rank)
- {}
-
- inline Index rows() const { return m_dec.cols(); }
- inline Index cols() const { return m_cols; }
- inline Index rank() const { return m_rank; }
- inline const DecompositionType& dec() const { return m_dec; }
-
- template<typename Dest> inline void evalTo(Dest& dst) const
- {
- static_cast<const kernel_retval<DecompositionType>*>(this)->evalTo(dst);
- }
-
- protected:
- const DecompositionType& m_dec;
- Index m_rank, m_cols;
-};
-
-} // end namespace internal
-
-#define EIGEN_MAKE_KERNEL_HELPERS(DecompositionType) \
- typedef typename DecompositionType::MatrixType MatrixType; \
- typedef typename MatrixType::Scalar Scalar; \
- typedef typename MatrixType::RealScalar RealScalar; \
- typedef typename MatrixType::Index Index; \
- typedef Eigen::internal::kernel_retval_base<DecompositionType> Base; \
- using Base::dec; \
- using Base::rank; \
- using Base::rows; \
- using Base::cols; \
- kernel_retval(const DecompositionType& dec) : Base(dec) {}
-
-#endif // EIGEN_MISC_KERNEL_H
diff --git a/extern/Eigen3/Eigen/src/misc/Solve.h b/extern/Eigen3/Eigen/src/misc/Solve.h
deleted file mode 100644
index b7cbcadb392..00000000000
--- a/extern/Eigen3/Eigen/src/misc/Solve.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_MISC_SOLVE_H
-#define EIGEN_MISC_SOLVE_H
-
-namespace internal {
-
-/** \class solve_retval_base
- *
- */
-template<typename DecompositionType, typename Rhs>
-struct traits<solve_retval_base<DecompositionType, Rhs> >
-{
- typedef typename DecompositionType::MatrixType MatrixType;
- typedef Matrix<typename Rhs::Scalar,
- MatrixType::ColsAtCompileTime,
- Rhs::ColsAtCompileTime,
- Rhs::PlainObject::Options,
- MatrixType::MaxColsAtCompileTime,
- Rhs::MaxColsAtCompileTime> ReturnType;
-};
-
-template<typename _DecompositionType, typename Rhs> struct solve_retval_base
- : public ReturnByValue<solve_retval_base<_DecompositionType, Rhs> >
-{
- typedef typename remove_all<typename Rhs::Nested>::type RhsNestedCleaned;
- typedef _DecompositionType DecompositionType;
- typedef ReturnByValue<solve_retval_base> Base;
- typedef typename Base::Index Index;
-
- solve_retval_base(const DecompositionType& dec, const Rhs& rhs)
- : m_dec(dec), m_rhs(rhs)
- {}
-
- inline Index rows() const { return m_dec.cols(); }
- inline Index cols() const { return m_rhs.cols(); }
- inline const DecompositionType& dec() const { return m_dec; }
- inline const RhsNestedCleaned& rhs() const { return m_rhs; }
-
- template<typename Dest> inline void evalTo(Dest& dst) const
- {
- static_cast<const solve_retval<DecompositionType,Rhs>*>(this)->evalTo(dst);
- }
-
- protected:
- const DecompositionType& m_dec;
- const typename Rhs::Nested m_rhs;
-};
-
-} // end namespace internal
-
-#define EIGEN_MAKE_SOLVE_HELPERS(DecompositionType,Rhs) \
- typedef typename DecompositionType::MatrixType MatrixType; \
- typedef typename MatrixType::Scalar Scalar; \
- typedef typename MatrixType::RealScalar RealScalar; \
- typedef typename MatrixType::Index Index; \
- typedef Eigen::internal::solve_retval_base<DecompositionType,Rhs> Base; \
- using Base::dec; \
- using Base::rhs; \
- using Base::rows; \
- using Base::cols; \
- solve_retval(const DecompositionType& dec, const Rhs& rhs) \
- : Base(dec, rhs) {}
-
-#endif // EIGEN_MISC_SOLVE_H
diff --git a/extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h b/extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h
deleted file mode 100644
index 7d509e78f3a..00000000000
--- a/extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/** \returns an expression of the coefficient wise product of \c *this and \a other
- *
- * \sa MatrixBase::cwiseProduct
- */
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE const EIGEN_CWISE_PRODUCT_RETURN_TYPE(Derived,OtherDerived)
-operator*(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
-{
- return EIGEN_CWISE_PRODUCT_RETURN_TYPE(Derived,OtherDerived)(derived(), other.derived());
-}
-
-/** \returns an expression of the coefficient wise quotient of \c *this and \a other
- *
- * \sa MatrixBase::cwiseQuotient
- */
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_quotient_op<Scalar>, const Derived, const OtherDerived>
-operator/(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
-{
- return CwiseBinaryOp<internal::scalar_quotient_op<Scalar>, const Derived, const OtherDerived>(derived(), other.derived());
-}
-
-/** \returns an expression of the coefficient-wise min of \c *this and \a other
- *
- * Example: \include Cwise_min.cpp
- * Output: \verbinclude Cwise_min.out
- *
- * \sa max()
- */
-EIGEN_MAKE_CWISE_BINARY_OP(min,internal::scalar_min_op)
-
-/** \returns an expression of the coefficient-wise max of \c *this and \a other
- *
- * Example: \include Cwise_max.cpp
- * Output: \verbinclude Cwise_max.out
- *
- * \sa min()
- */
-EIGEN_MAKE_CWISE_BINARY_OP(max,internal::scalar_max_op)
-
-/** \returns an expression of the coefficient-wise \< operator of *this and \a other
- *
- * Example: \include Cwise_less.cpp
- * Output: \verbinclude Cwise_less.out
- *
- * \sa all(), any(), operator>(), operator<=()
- */
-EIGEN_MAKE_CWISE_BINARY_OP(operator<,std::less)
-
-/** \returns an expression of the coefficient-wise \<= operator of *this and \a other
- *
- * Example: \include Cwise_less_equal.cpp
- * Output: \verbinclude Cwise_less_equal.out
- *
- * \sa all(), any(), operator>=(), operator<()
- */
-EIGEN_MAKE_CWISE_BINARY_OP(operator<=,std::less_equal)
-
-/** \returns an expression of the coefficient-wise \> operator of *this and \a other
- *
- * Example: \include Cwise_greater.cpp
- * Output: \verbinclude Cwise_greater.out
- *
- * \sa all(), any(), operator>=(), operator<()
- */
-EIGEN_MAKE_CWISE_BINARY_OP(operator>,std::greater)
-
-/** \returns an expression of the coefficient-wise \>= operator of *this and \a other
- *
- * Example: \include Cwise_greater_equal.cpp
- * Output: \verbinclude Cwise_greater_equal.out
- *
- * \sa all(), any(), operator>(), operator<=()
- */
-EIGEN_MAKE_CWISE_BINARY_OP(operator>=,std::greater_equal)
-
-/** \returns an expression of the coefficient-wise == operator of *this and \a other
- *
- * \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().
- *
- * Example: \include Cwise_equal_equal.cpp
- * Output: \verbinclude Cwise_equal_equal.out
- *
- * \sa all(), any(), isApprox(), isMuchSmallerThan()
- */
-EIGEN_MAKE_CWISE_BINARY_OP(operator==,std::equal_to)
-
-/** \returns an expression of the coefficient-wise != operator of *this and \a other
- *
- * \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().
- *
- * Example: \include Cwise_not_equal.cpp
- * Output: \verbinclude Cwise_not_equal.out
- *
- * \sa all(), any(), isApprox(), isMuchSmallerThan()
- */
-EIGEN_MAKE_CWISE_BINARY_OP(operator!=,std::not_equal_to)
-
-// scalar addition
-
-/** \returns an expression of \c *this with each coeff incremented by the constant \a scalar
- *
- * Example: \include Cwise_plus.cpp
- * Output: \verbinclude Cwise_plus.out
- *
- * \sa operator+=(), operator-()
- */
-inline const CwiseUnaryOp<internal::scalar_add_op<Scalar>, const Derived>
-operator+(const Scalar& scalar) const
-{
- return CwiseUnaryOp<internal::scalar_add_op<Scalar>, const Derived>(derived(), internal::scalar_add_op<Scalar>(scalar));
-}
-
-friend inline const CwiseUnaryOp<internal::scalar_add_op<Scalar>, const Derived>
-operator+(const Scalar& scalar,const EIGEN_CURRENT_STORAGE_BASE_CLASS<Derived>& other)
-{
- return other + scalar;
-}
-
-/** \returns an expression of \c *this with each coeff decremented by the constant \a scalar
- *
- * Example: \include Cwise_minus.cpp
- * Output: \verbinclude Cwise_minus.out
- *
- * \sa operator+(), operator-=()
- */
-inline const CwiseUnaryOp<internal::scalar_add_op<Scalar>, const Derived>
-operator-(const Scalar& scalar) const
-{
- return *this + (-scalar);
-}
-
-friend inline const CwiseUnaryOp<internal::scalar_add_op<Scalar>, const CwiseUnaryOp<internal::scalar_opposite_op<Scalar>, const Derived> >
-operator-(const Scalar& scalar,const EIGEN_CURRENT_STORAGE_BASE_CLASS<Derived>& other)
-{
- return (-other) + scalar;
-}
diff --git a/extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h b/extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h
deleted file mode 100644
index 0dffaf4135c..00000000000
--- a/extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h
+++ /dev/null
@@ -1,202 +0,0 @@
-
-
-/** \returns an expression of the coefficient-wise absolute value of \c *this
- *
- * Example: \include Cwise_abs.cpp
- * Output: \verbinclude Cwise_abs.out
- *
- * \sa abs2()
- */
-EIGEN_STRONG_INLINE const CwiseUnaryOp<internal::scalar_abs_op<Scalar>, const Derived>
-abs() const
-{
- return derived();
-}
-
-/** \returns an expression of the coefficient-wise squared absolute value of \c *this
- *
- * Example: \include Cwise_abs2.cpp
- * Output: \verbinclude Cwise_abs2.out
- *
- * \sa abs(), square()
- */
-EIGEN_STRONG_INLINE const CwiseUnaryOp<internal::scalar_abs2_op<Scalar>, const Derived>
-abs2() const
-{
- return derived();
-}
-
-/** \returns an expression of the coefficient-wise exponential of *this.
- *
- * Example: \include Cwise_exp.cpp
- * Output: \verbinclude Cwise_exp.out
- *
- * \sa pow(), log(), sin(), cos()
- */
-inline const CwiseUnaryOp<internal::scalar_exp_op<Scalar>, const Derived>
-exp() const
-{
- return derived();
-}
-
-/** \returns an expression of the coefficient-wise logarithm of *this.
- *
- * Example: \include Cwise_log.cpp
- * Output: \verbinclude Cwise_log.out
- *
- * \sa exp()
- */
-inline const CwiseUnaryOp<internal::scalar_log_op<Scalar>, const Derived>
-log() const
-{
- return derived();
-}
-
-/** \returns an expression of the coefficient-wise square root of *this.
- *
- * Example: \include Cwise_sqrt.cpp
- * Output: \verbinclude Cwise_sqrt.out
- *
- * \sa pow(), square()
- */
-inline const CwiseUnaryOp<internal::scalar_sqrt_op<Scalar>, const Derived>
-sqrt() const
-{
- return derived();
-}
-
-/** \returns an expression of the coefficient-wise cosine of *this.
- *
- * Example: \include Cwise_cos.cpp
- * Output: \verbinclude Cwise_cos.out
- *
- * \sa sin(), acos()
- */
-inline const CwiseUnaryOp<internal::scalar_cos_op<Scalar>, const Derived>
-cos() const
-{
- return derived();
-}
-
-
-/** \returns an expression of the coefficient-wise sine of *this.
- *
- * Example: \include Cwise_sin.cpp
- * Output: \verbinclude Cwise_sin.out
- *
- * \sa cos(), asin()
- */
-inline const CwiseUnaryOp<internal::scalar_sin_op<Scalar>, const Derived>
-sin() const
-{
- return derived();
-}
-
-/** \returns an expression of the coefficient-wise arc cosine of *this.
- *
- * Example: \include Cwise_acos.cpp
- * Output: \verbinclude Cwise_acos.out
- *
- * \sa cos(), asin()
- */
-inline const CwiseUnaryOp<internal::scalar_acos_op<Scalar>, const Derived>
-acos() const
-{
- return derived();
-}
-
-/** \returns an expression of the coefficient-wise arc sine of *this.
- *
- * Example: \include Cwise_asin.cpp
- * Output: \verbinclude Cwise_asin.out
- *
- * \sa sin(), acos()
- */
-inline const CwiseUnaryOp<internal::scalar_asin_op<Scalar>, const Derived>
-asin() const
-{
- return derived();
-}
-
-/** \returns an expression of the coefficient-wise tan of *this.
- *
- * Example: \include Cwise_tan.cpp
- * Output: \verbinclude Cwise_tan.out
- *
- * \sa cos(), sin()
- */
-inline const CwiseUnaryOp<internal::scalar_tan_op<Scalar>, Derived>
-tan() const
-{
- return derived();
-}
-
-
-/** \returns an expression of the coefficient-wise power of *this to the given exponent.
- *
- * Example: \include Cwise_pow.cpp
- * Output: \verbinclude Cwise_pow.out
- *
- * \sa exp(), log()
- */
-inline const CwiseUnaryOp<internal::scalar_pow_op<Scalar>, const Derived>
-pow(const Scalar& exponent) const
-{
- return CwiseUnaryOp<internal::scalar_pow_op<Scalar>, const Derived>
- (derived(), internal::scalar_pow_op<Scalar>(exponent));
-}
-
-
-/** \returns an expression of the coefficient-wise inverse of *this.
- *
- * Example: \include Cwise_inverse.cpp
- * Output: \verbinclude Cwise_inverse.out
- *
- * \sa operator/(), operator*()
- */
-inline const CwiseUnaryOp<internal::scalar_inverse_op<Scalar>, const Derived>
-inverse() const
-{
- return derived();
-}
-
-/** \returns an expression of the coefficient-wise square of *this.
- *
- * Example: \include Cwise_square.cpp
- * Output: \verbinclude Cwise_square.out
- *
- * \sa operator/(), operator*(), abs2()
- */
-inline const CwiseUnaryOp<internal::scalar_square_op<Scalar>, const Derived>
-square() const
-{
- return derived();
-}
-
-/** \returns an expression of the coefficient-wise cube of *this.
- *
- * Example: \include Cwise_cube.cpp
- * Output: \verbinclude Cwise_cube.out
- *
- * \sa square(), pow()
- */
-inline const CwiseUnaryOp<internal::scalar_cube_op<Scalar>, const Derived>
-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/BlockMethods.h b/extern/Eigen3/Eigen/src/plugins/BlockMethods.h
deleted file mode 100644
index 4eba933388a..00000000000
--- a/extern/Eigen3/Eigen/src/plugins/BlockMethods.h
+++ /dev/null
@@ -1,595 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-#ifndef EIGEN_BLOCKMETHODS_H
-#define EIGEN_BLOCKMETHODS_H
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
-
-/** \internal expression type of a column */
-typedef Block<Derived, internal::traits<Derived>::RowsAtCompileTime, 1, !IsRowMajor> ColXpr;
-typedef const Block<const Derived, internal::traits<Derived>::RowsAtCompileTime, 1, !IsRowMajor> ConstColXpr;
-/** \internal expression type of a row */
-typedef Block<Derived, 1, internal::traits<Derived>::ColsAtCompileTime, IsRowMajor> RowXpr;
-typedef const Block<const Derived, 1, internal::traits<Derived>::ColsAtCompileTime, IsRowMajor> ConstRowXpr;
-/** \internal expression type of a block of whole columns */
-typedef Block<Derived, internal::traits<Derived>::RowsAtCompileTime, Dynamic, !IsRowMajor> ColsBlockXpr;
-typedef const Block<const Derived, internal::traits<Derived>::RowsAtCompileTime, Dynamic, !IsRowMajor> ConstColsBlockXpr;
-/** \internal expression type of a block of whole rows */
-typedef Block<Derived, Dynamic, internal::traits<Derived>::ColsAtCompileTime, IsRowMajor> RowsBlockXpr;
-typedef const Block<const Derived, Dynamic, internal::traits<Derived>::ColsAtCompileTime, IsRowMajor> ConstRowsBlockXpr;
-/** \internal expression type of a block of whole columns */
-template<int N> struct NColsBlockXpr { typedef Block<Derived, internal::traits<Derived>::RowsAtCompileTime, N, !IsRowMajor> Type; };
-template<int N> struct ConstNColsBlockXpr { typedef const Block<const Derived, internal::traits<Derived>::RowsAtCompileTime, N, !IsRowMajor> Type; };
-/** \internal expression type of a block of whole rows */
-template<int N> struct NRowsBlockXpr { typedef Block<Derived, N, internal::traits<Derived>::ColsAtCompileTime, IsRowMajor> Type; };
-template<int N> struct ConstNRowsBlockXpr { typedef const Block<const Derived, N, internal::traits<Derived>::ColsAtCompileTime, IsRowMajor> Type; };
-
-
-#endif // not EIGEN_PARSED_BY_DOXYGEN
-
-/** \returns a dynamic-size expression of a block in *this.
- *
- * \param startRow the first row in the block
- * \param startCol the first column in the block
- * \param blockRows the number of rows in the block
- * \param blockCols the number of columns in the block
- *
- * Example: \include MatrixBase_block_int_int_int_int.cpp
- * Output: \verbinclude MatrixBase_block_int_int_int_int.out
- *
- * \note Even though the returned expression has dynamic size, in the case
- * when it is applied to a fixed-size matrix, it inherits a fixed maximal size,
- * which means that evaluating it does not cause a dynamic memory allocation.
- *
- * \sa class Block, block(Index,Index)
- */
-inline Block<Derived> block(Index startRow, Index startCol, Index blockRows, Index blockCols)
-{
- return Block<Derived>(derived(), startRow, startCol, blockRows, blockCols);
-}
-
-/** This is the const version of block(Index,Index,Index,Index). */
-inline const Block<const Derived> block(Index startRow, Index startCol, Index blockRows, Index blockCols) const
-{
- return Block<const Derived>(derived(), startRow, startCol, blockRows, blockCols);
-}
-
-
-
-
-/** \returns a dynamic-size expression of a top-right corner of *this.
- *
- * \param cRows the number of rows in the corner
- * \param cCols the number of columns in the corner
- *
- * Example: \include MatrixBase_topRightCorner_int_int.cpp
- * Output: \verbinclude MatrixBase_topRightCorner_int_int.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-inline Block<Derived> topRightCorner(Index cRows, Index cCols)
-{
- return Block<Derived>(derived(), 0, cols() - cCols, cRows, cCols);
-}
-
-/** This is the const version of topRightCorner(Index, Index).*/
-inline const Block<const Derived> topRightCorner(Index cRows, Index cCols) const
-{
- return Block<const Derived>(derived(), 0, cols() - cCols, cRows, cCols);
-}
-
-/** \returns an expression of a fixed-size top-right corner of *this.
- *
- * The template parameters CRows and CCols are the number of rows and columns in the corner.
- *
- * Example: \include MatrixBase_template_int_int_topRightCorner.cpp
- * Output: \verbinclude MatrixBase_template_int_int_topRightCorner.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-template<int CRows, int CCols>
-inline Block<Derived, CRows, CCols> topRightCorner()
-{
- return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols);
-}
-
-/** This is the const version of topRightCorner<int, int>().*/
-template<int CRows, int CCols>
-inline const Block<const Derived, CRows, CCols> topRightCorner() const
-{
- return Block<const Derived, CRows, CCols>(derived(), 0, cols() - CCols);
-}
-
-
-
-
-/** \returns a dynamic-size expression of a top-left corner of *this.
- *
- * \param cRows the number of rows in the corner
- * \param cCols the number of columns in the corner
- *
- * Example: \include MatrixBase_topLeftCorner_int_int.cpp
- * Output: \verbinclude MatrixBase_topLeftCorner_int_int.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-inline Block<Derived> topLeftCorner(Index cRows, Index cCols)
-{
- return Block<Derived>(derived(), 0, 0, cRows, cCols);
-}
-
-/** This is the const version of topLeftCorner(Index, Index).*/
-inline const Block<const Derived> topLeftCorner(Index cRows, Index cCols) const
-{
- return Block<const Derived>(derived(), 0, 0, cRows, cCols);
-}
-
-/** \returns an expression of a fixed-size top-left corner of *this.
- *
- * The template parameters CRows and CCols are the number of rows and columns in the corner.
- *
- * Example: \include MatrixBase_template_int_int_topLeftCorner.cpp
- * Output: \verbinclude MatrixBase_template_int_int_topLeftCorner.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-template<int CRows, int CCols>
-inline Block<Derived, CRows, CCols> topLeftCorner()
-{
- return Block<Derived, CRows, CCols>(derived(), 0, 0);
-}
-
-/** This is the const version of topLeftCorner<int, int>().*/
-template<int CRows, int CCols>
-inline const Block<const Derived, CRows, CCols> topLeftCorner() const
-{
- return Block<const Derived, CRows, CCols>(derived(), 0, 0);
-}
-
-
-
-/** \returns a dynamic-size expression of a bottom-right corner of *this.
- *
- * \param cRows the number of rows in the corner
- * \param cCols the number of columns in the corner
- *
- * Example: \include MatrixBase_bottomRightCorner_int_int.cpp
- * Output: \verbinclude MatrixBase_bottomRightCorner_int_int.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-inline Block<Derived> bottomRightCorner(Index cRows, Index cCols)
-{
- return Block<Derived>(derived(), rows() - cRows, cols() - cCols, cRows, cCols);
-}
-
-/** This is the const version of bottomRightCorner(Index, Index).*/
-inline const Block<const Derived> bottomRightCorner(Index cRows, Index cCols) const
-{
- return Block<const Derived>(derived(), rows() - cRows, cols() - cCols, cRows, cCols);
-}
-
-/** \returns an expression of a fixed-size bottom-right corner of *this.
- *
- * The template parameters CRows and CCols are the number of rows and columns in the corner.
- *
- * Example: \include MatrixBase_template_int_int_bottomRightCorner.cpp
- * Output: \verbinclude MatrixBase_template_int_int_bottomRightCorner.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-template<int CRows, int CCols>
-inline Block<Derived, CRows, CCols> bottomRightCorner()
-{
- return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols);
-}
-
-/** This is the const version of bottomRightCorner<int, int>().*/
-template<int CRows, int CCols>
-inline const Block<const Derived, CRows, CCols> bottomRightCorner() const
-{
- return Block<const Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols);
-}
-
-
-
-/** \returns a dynamic-size expression of a bottom-left corner of *this.
- *
- * \param cRows the number of rows in the corner
- * \param cCols the number of columns in the corner
- *
- * Example: \include MatrixBase_bottomLeftCorner_int_int.cpp
- * Output: \verbinclude MatrixBase_bottomLeftCorner_int_int.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-inline Block<Derived> bottomLeftCorner(Index cRows, Index cCols)
-{
- return Block<Derived>(derived(), rows() - cRows, 0, cRows, cCols);
-}
-
-/** This is the const version of bottomLeftCorner(Index, Index).*/
-inline const Block<const Derived> bottomLeftCorner(Index cRows, Index cCols) const
-{
- return Block<const Derived>(derived(), rows() - cRows, 0, cRows, cCols);
-}
-
-/** \returns an expression of a fixed-size bottom-left corner of *this.
- *
- * The template parameters CRows and CCols are the number of rows and columns in the corner.
- *
- * Example: \include MatrixBase_template_int_int_bottomLeftCorner.cpp
- * Output: \verbinclude MatrixBase_template_int_int_bottomLeftCorner.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-template<int CRows, int CCols>
-inline Block<Derived, CRows, CCols> bottomLeftCorner()
-{
- return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0);
-}
-
-/** This is the const version of bottomLeftCorner<int, int>().*/
-template<int CRows, int CCols>
-inline const Block<const Derived, CRows, CCols> bottomLeftCorner() const
-{
- return Block<const Derived, CRows, CCols>(derived(), rows() - CRows, 0);
-}
-
-
-
-/** \returns a block consisting of the top rows of *this.
- *
- * \param n the number of rows in the block
- *
- * Example: \include MatrixBase_topRows_int.cpp
- * Output: \verbinclude MatrixBase_topRows_int.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-inline RowsBlockXpr topRows(Index n)
-{
- return RowsBlockXpr(derived(), 0, 0, n, cols());
-}
-
-/** This is the const version of topRows(Index).*/
-inline ConstRowsBlockXpr topRows(Index n) const
-{
- return ConstRowsBlockXpr(derived(), 0, 0, n, cols());
-}
-
-/** \returns a block consisting of the top rows of *this.
- *
- * \tparam N the number of rows in the block
- *
- * Example: \include MatrixBase_template_int_topRows.cpp
- * Output: \verbinclude MatrixBase_template_int_topRows.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-template<int N>
-inline typename NRowsBlockXpr<N>::Type topRows()
-{
- return typename NRowsBlockXpr<N>::Type(derived(), 0, 0, N, cols());
-}
-
-/** This is the const version of topRows<int>().*/
-template<int N>
-inline typename ConstNRowsBlockXpr<N>::Type topRows() const
-{
- return typename ConstNRowsBlockXpr<N>::Type(derived(), 0, 0, N, cols());
-}
-
-
-
-/** \returns a block consisting of the bottom rows of *this.
- *
- * \param n the number of rows in the block
- *
- * Example: \include MatrixBase_bottomRows_int.cpp
- * Output: \verbinclude MatrixBase_bottomRows_int.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-inline RowsBlockXpr bottomRows(Index n)
-{
- return RowsBlockXpr(derived(), rows() - n, 0, n, cols());
-}
-
-/** This is the const version of bottomRows(Index).*/
-inline ConstRowsBlockXpr bottomRows(Index n) const
-{
- return ConstRowsBlockXpr(derived(), rows() - n, 0, n, cols());
-}
-
-/** \returns a block consisting of the bottom rows of *this.
- *
- * \tparam N the number of rows in the block
- *
- * Example: \include MatrixBase_template_int_bottomRows.cpp
- * Output: \verbinclude MatrixBase_template_int_bottomRows.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-template<int N>
-inline typename NRowsBlockXpr<N>::Type bottomRows()
-{
- return typename NRowsBlockXpr<N>::Type(derived(), rows() - N, 0, N, cols());
-}
-
-/** This is the const version of bottomRows<int>().*/
-template<int N>
-inline typename ConstNRowsBlockXpr<N>::Type bottomRows() const
-{
- return typename ConstNRowsBlockXpr<N>::Type(derived(), rows() - N, 0, N, cols());
-}
-
-
-
-/** \returns a block consisting of a range of rows of *this.
- *
- * \param startRow the index of the first row in the block
- * \param numRows the number of rows in the block
- *
- * Example: \include DenseBase_middleRows_int.cpp
- * Output: \verbinclude DenseBase_middleRows_int.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-inline RowsBlockXpr middleRows(Index startRow, Index numRows)
-{
- return RowsBlockXpr(derived(), startRow, 0, numRows, cols());
-}
-
-/** This is the const version of middleRows(Index,Index).*/
-inline ConstRowsBlockXpr middleRows(Index startRow, Index numRows) const
-{
- return ConstRowsBlockXpr(derived(), startRow, 0, numRows, cols());
-}
-
-/** \returns a block consisting of a range of rows of *this.
- *
- * \tparam N the number of rows in the block
- * \param startRow the index of the first row in the block
- *
- * Example: \include DenseBase_template_int_middleRows.cpp
- * Output: \verbinclude DenseBase_template_int_middleRows.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-template<int N>
-inline typename NRowsBlockXpr<N>::Type middleRows(Index startRow)
-{
- return typename NRowsBlockXpr<N>::Type(derived(), startRow, 0, N, cols());
-}
-
-/** This is the const version of middleRows<int>().*/
-template<int N>
-inline typename ConstNRowsBlockXpr<N>::Type middleRows(Index startRow) const
-{
- return typename ConstNRowsBlockXpr<N>::Type(derived(), startRow, 0, N, cols());
-}
-
-
-
-/** \returns a block consisting of the left columns of *this.
- *
- * \param n the number of columns in the block
- *
- * Example: \include MatrixBase_leftCols_int.cpp
- * Output: \verbinclude MatrixBase_leftCols_int.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-inline ColsBlockXpr leftCols(Index n)
-{
- return ColsBlockXpr(derived(), 0, 0, rows(), n);
-}
-
-/** This is the const version of leftCols(Index).*/
-inline ConstColsBlockXpr leftCols(Index n) const
-{
- return ConstColsBlockXpr(derived(), 0, 0, rows(), n);
-}
-
-/** \returns a block consisting of the left columns of *this.
- *
- * \tparam N the number of columns in the block
- *
- * Example: \include MatrixBase_template_int_leftCols.cpp
- * Output: \verbinclude MatrixBase_template_int_leftCols.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-template<int N>
-inline typename NColsBlockXpr<N>::Type leftCols()
-{
- return typename NColsBlockXpr<N>::Type(derived(), 0, 0, rows(), N);
-}
-
-/** This is the const version of leftCols<int>().*/
-template<int N>
-inline typename ConstNColsBlockXpr<N>::Type leftCols() const
-{
- return typename ConstNColsBlockXpr<N>::Type(derived(), 0, 0, rows(), N);
-}
-
-
-
-/** \returns a block consisting of the right columns of *this.
- *
- * \param n the number of columns in the block
- *
- * Example: \include MatrixBase_rightCols_int.cpp
- * Output: \verbinclude MatrixBase_rightCols_int.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-inline ColsBlockXpr rightCols(Index n)
-{
- return ColsBlockXpr(derived(), 0, cols() - n, rows(), n);
-}
-
-/** This is the const version of rightCols(Index).*/
-inline ConstColsBlockXpr rightCols(Index n) const
-{
- return ConstColsBlockXpr(derived(), 0, cols() - n, rows(), n);
-}
-
-/** \returns a block consisting of the right columns of *this.
- *
- * \tparam N the number of columns in the block
- *
- * Example: \include MatrixBase_template_int_rightCols.cpp
- * Output: \verbinclude MatrixBase_template_int_rightCols.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-template<int N>
-inline typename NColsBlockXpr<N>::Type rightCols()
-{
- return typename NColsBlockXpr<N>::Type(derived(), 0, cols() - N, rows(), N);
-}
-
-/** This is the const version of rightCols<int>().*/
-template<int N>
-inline typename ConstNColsBlockXpr<N>::Type rightCols() const
-{
- return typename ConstNColsBlockXpr<N>::Type(derived(), 0, cols() - N, rows(), N);
-}
-
-
-
-/** \returns a block consisting of a range of columns of *this.
- *
- * \param startCol the index of the first column in the block
- * \param numCols the number of columns in the block
- *
- * Example: \include DenseBase_middleCols_int.cpp
- * Output: \verbinclude DenseBase_middleCols_int.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-inline ColsBlockXpr middleCols(Index startCol, Index numCols)
-{
- return ColsBlockXpr(derived(), 0, startCol, rows(), numCols);
-}
-
-/** This is the const version of middleCols(Index,Index).*/
-inline ConstColsBlockXpr middleCols(Index startCol, Index numCols) const
-{
- return ConstColsBlockXpr(derived(), 0, startCol, rows(), numCols);
-}
-
-/** \returns a block consisting of a range of columns of *this.
- *
- * \tparam N the number of columns in the block
- * \param startCol the index of the first column in the block
- *
- * Example: \include DenseBase_template_int_middleCols.cpp
- * Output: \verbinclude DenseBase_template_int_middleCols.out
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-template<int N>
-inline typename NColsBlockXpr<N>::Type middleCols(Index startCol)
-{
- return typename NColsBlockXpr<N>::Type(derived(), 0, startCol, rows(), N);
-}
-
-/** This is the const version of middleCols<int>().*/
-template<int N>
-inline typename ConstNColsBlockXpr<N>::Type middleCols(Index startCol) const
-{
- return typename ConstNColsBlockXpr<N>::Type(derived(), 0, startCol, rows(), N);
-}
-
-
-
-/** \returns a fixed-size expression of a block in *this.
- *
- * The template parameters \a BlockRows and \a BlockCols are the number of
- * rows and columns in the block.
- *
- * \param startRow the first row in the block
- * \param startCol the first column in the block
- *
- * Example: \include MatrixBase_block_int_int.cpp
- * Output: \verbinclude MatrixBase_block_int_int.out
- *
- * \note since block is a templated member, the keyword template has to be used
- * if the matrix type is also a template parameter: \code m.template block<3,3>(1,1); \endcode
- *
- * \sa class Block, block(Index,Index,Index,Index)
- */
-template<int BlockRows, int BlockCols>
-inline Block<Derived, BlockRows, BlockCols> block(Index startRow, Index startCol)
-{
- return Block<Derived, BlockRows, BlockCols>(derived(), startRow, startCol);
-}
-
-/** This is the const version of block<>(Index, Index). */
-template<int BlockRows, int BlockCols>
-inline const Block<const Derived, BlockRows, BlockCols> block(Index startRow, Index startCol) const
-{
- return Block<const Derived, BlockRows, BlockCols>(derived(), startRow, startCol);
-}
-
-/** \returns an expression of the \a i-th column of *this. Note that the numbering starts at 0.
- *
- * Example: \include MatrixBase_col.cpp
- * Output: \verbinclude MatrixBase_col.out
- *
- * \sa row(), class Block */
-inline ColXpr col(Index i)
-{
- return ColXpr(derived(), i);
-}
-
-/** This is the const version of col(). */
-inline ConstColXpr col(Index i) const
-{
- return ConstColXpr(derived(), i);
-}
-
-/** \returns an expression of the \a i-th row of *this. Note that the numbering starts at 0.
- *
- * Example: \include MatrixBase_row.cpp
- * Output: \verbinclude MatrixBase_row.out
- *
- * \sa col(), class Block */
-inline RowXpr row(Index i)
-{
- return RowXpr(derived(), i);
-}
-
-/** This is the const version of row(). */
-inline ConstRowXpr row(Index i) const
-{
- return ConstRowXpr(derived(), i);
-}
-
-#endif // EIGEN_BLOCKMETHODS_H
diff --git a/extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h b/extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h
deleted file mode 100644
index 8f7765e72bd..00000000000
--- a/extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-// This file is a base class plugin containing common coefficient wise functions.
-
-/** \returns an expression of the difference of \c *this and \a other
- *
- * \note If you want to substract a given scalar from all coefficients, see Cwise::operator-().
- *
- * \sa class CwiseBinaryOp, operator-=()
- */
-EIGEN_MAKE_CWISE_BINARY_OP(operator-,internal::scalar_difference_op)
-
-/** \returns an expression of the sum of \c *this and \a other
- *
- * \note If you want to add a given scalar to all coefficients, see Cwise::operator+().
- *
- * \sa class CwiseBinaryOp, operator+=()
- */
-EIGEN_MAKE_CWISE_BINARY_OP(operator+,internal::scalar_sum_op)
-
-/** \returns an expression of a custom coefficient-wise operator \a func of *this and \a other
- *
- * The template parameter \a CustomBinaryOp is the type of the functor
- * of the custom operator (see class CwiseBinaryOp for an example)
- *
- * Here is an example illustrating the use of custom functors:
- * \include class_CwiseBinaryOp.cpp
- * Output: \verbinclude class_CwiseBinaryOp.out
- *
- * \sa class CwiseBinaryOp, operator+(), operator-(), cwiseProduct()
- */
-template<typename CustomBinaryOp, typename OtherDerived>
-EIGEN_STRONG_INLINE const CwiseBinaryOp<CustomBinaryOp, const Derived, const OtherDerived>
-binaryExpr(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other, const CustomBinaryOp& func = CustomBinaryOp()) const
-{
- return CwiseBinaryOp<CustomBinaryOp, const Derived, const OtherDerived>(derived(), other.derived(), func);
-}
-
diff --git a/extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h b/extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h
deleted file mode 100644
index 941d5153c59..00000000000
--- a/extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h
+++ /dev/null
@@ -1,187 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-// This file is a base class plugin containing common coefficient wise functions.
-
-#ifndef EIGEN_PARSED_BY_DOXYGEN
-
-/** \internal Represents a scalar multiple of an expression */
-typedef CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const Derived> ScalarMultipleReturnType;
-/** \internal Represents a quotient of an expression by a scalar*/
-typedef CwiseUnaryOp<internal::scalar_quotient1_op<Scalar>, const Derived> ScalarQuotient1ReturnType;
-/** \internal the return type of conjugate() */
-typedef typename internal::conditional<NumTraits<Scalar>::IsComplex,
- const CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, const Derived>,
- const Derived&
- >::type ConjugateReturnType;
-/** \internal the return type of real() const */
-typedef typename internal::conditional<NumTraits<Scalar>::IsComplex,
- const CwiseUnaryOp<internal::scalar_real_op<Scalar>, const Derived>,
- const Derived&
- >::type RealReturnType;
-/** \internal the return type of real() */
-typedef typename internal::conditional<NumTraits<Scalar>::IsComplex,
- CwiseUnaryView<internal::scalar_real_ref_op<Scalar>, Derived>,
- Derived&
- >::type NonConstRealReturnType;
-/** \internal the return type of imag() const */
-typedef CwiseUnaryOp<internal::scalar_imag_op<Scalar>, const Derived> ImagReturnType;
-/** \internal the return type of imag() */
-typedef CwiseUnaryView<internal::scalar_imag_ref_op<Scalar>, Derived> NonConstImagReturnType;
-
-#endif // not EIGEN_PARSED_BY_DOXYGEN
-
-/** \returns an expression of the opposite of \c *this
- */
-inline const CwiseUnaryOp<internal::scalar_opposite_op<typename internal::traits<Derived>::Scalar>, const Derived>
-operator-() const { return derived(); }
-
-
-/** \returns an expression of \c *this scaled by the scalar factor \a scalar */
-inline const ScalarMultipleReturnType
-operator*(const Scalar& scalar) const
-{
- return CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const Derived>
- (derived(), internal::scalar_multiple_op<Scalar>(scalar));
-}
-
-#ifdef EIGEN_PARSED_BY_DOXYGEN
-const ScalarMultipleReturnType operator*(const RealScalar& scalar) const;
-#endif
-
-/** \returns an expression of \c *this divided by the scalar value \a scalar */
-inline const CwiseUnaryOp<internal::scalar_quotient1_op<typename internal::traits<Derived>::Scalar>, const Derived>
-operator/(const Scalar& scalar) const
-{
- return CwiseUnaryOp<internal::scalar_quotient1_op<Scalar>, const Derived>
- (derived(), internal::scalar_quotient1_op<Scalar>(scalar));
-}
-
-/** Overloaded for efficient real matrix times complex scalar value */
-inline const CwiseUnaryOp<internal::scalar_multiple2_op<Scalar,std::complex<Scalar> >, const Derived>
-operator*(const std::complex<Scalar>& scalar) const
-{
- return CwiseUnaryOp<internal::scalar_multiple2_op<Scalar,std::complex<Scalar> >, const Derived>
- (*static_cast<const Derived*>(this), internal::scalar_multiple2_op<Scalar,std::complex<Scalar> >(scalar));
-}
-
-inline friend const ScalarMultipleReturnType
-operator*(const Scalar& scalar, const StorageBaseType& matrix)
-{ return matrix*scalar; }
-
-inline friend const CwiseUnaryOp<internal::scalar_multiple2_op<Scalar,std::complex<Scalar> >, const Derived>
-operator*(const std::complex<Scalar>& scalar, const StorageBaseType& matrix)
-{ return matrix*scalar; }
-
-/** \returns an expression of *this with the \a Scalar type casted to
- * \a NewScalar.
- *
- * The template parameter \a NewScalar is the type we are casting the scalars to.
- *
- * \sa class CwiseUnaryOp
- */
-template<typename NewType>
-typename internal::cast_return_type<Derived,const CwiseUnaryOp<internal::scalar_cast_op<typename internal::traits<Derived>::Scalar, NewType>, const Derived> >::type
-cast() const
-{
- return derived();
-}
-
-/** \returns an expression of the complex conjugate of \c *this.
- *
- * \sa adjoint() */
-inline ConjugateReturnType
-conjugate() const
-{
- return ConjugateReturnType(derived());
-}
-
-/** \returns a read-only expression of the real part of \c *this.
- *
- * \sa imag() */
-inline RealReturnType
-real() const { return derived(); }
-
-/** \returns an read-only expression of the imaginary part of \c *this.
- *
- * \sa real() */
-inline const ImagReturnType
-imag() const { return derived(); }
-
-/** \brief Apply a unary operator coefficient-wise
- * \param[in] func Functor implementing the unary operator
- * \tparam CustomUnaryOp Type of \a func
- * \returns An expression of a custom coefficient-wise unary operator \a func of *this
- *
- * The function \c ptr_fun() from the C++ standard library can be used to make functors out of normal functions.
- *
- * Example:
- * \include class_CwiseUnaryOp_ptrfun.cpp
- * Output: \verbinclude class_CwiseUnaryOp_ptrfun.out
- *
- * Genuine functors allow for more possibilities, for instance it may contain a state.
- *
- * Example:
- * \include class_CwiseUnaryOp.cpp
- * Output: \verbinclude class_CwiseUnaryOp.out
- *
- * \sa class CwiseUnaryOp, class CwiseBinaryOp
- */
-template<typename CustomUnaryOp>
-inline const CwiseUnaryOp<CustomUnaryOp, const Derived>
-unaryExpr(const CustomUnaryOp& func = CustomUnaryOp()) const
-{
- return CwiseUnaryOp<CustomUnaryOp, const Derived>(derived(), func);
-}
-
-/** \returns an expression of a custom coefficient-wise unary operator \a func of *this
- *
- * The template parameter \a CustomUnaryOp is the type of the functor
- * of the custom unary operator.
- *
- * Example:
- * \include class_CwiseUnaryOp.cpp
- * Output: \verbinclude class_CwiseUnaryOp.out
- *
- * \sa class CwiseUnaryOp, class CwiseBinaryOp
- */
-template<typename CustomViewOp>
-inline const CwiseUnaryView<CustomViewOp, const Derived>
-unaryViewExpr(const CustomViewOp& func = CustomViewOp()) const
-{
- return CwiseUnaryView<CustomViewOp, const Derived>(derived(), func);
-}
-
-/** \returns a non const expression of the real part of \c *this.
- *
- * \sa imag() */
-inline NonConstRealReturnType
-real() { return derived(); }
-
-/** \returns a non const expression of the imaginary part of \c *this.
- *
- * \sa real() */
-inline NonConstImagReturnType
-imag() { return derived(); }
diff --git a/extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h b/extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h
deleted file mode 100644
index 35183f91f80..00000000000
--- a/extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-// This file is a base class plugin containing matrix specifics coefficient wise functions.
-
-/** \returns an expression of the Schur product (coefficient wise product) of *this and \a other
- *
- * Example: \include MatrixBase_cwiseProduct.cpp
- * Output: \verbinclude MatrixBase_cwiseProduct.out
- *
- * \sa class CwiseBinaryOp, cwiseAbs2
- */
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE const EIGEN_CWISE_PRODUCT_RETURN_TYPE(Derived,OtherDerived)
-cwiseProduct(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
-{
- return EIGEN_CWISE_PRODUCT_RETURN_TYPE(Derived,OtherDerived)(derived(), other.derived());
-}
-
-/** \returns an expression of the coefficient-wise == operator of *this and \a other
- *
- * \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().
- *
- * Example: \include MatrixBase_cwiseEqual.cpp
- * Output: \verbinclude MatrixBase_cwiseEqual.out
- *
- * \sa cwiseNotEqual(), isApprox(), isMuchSmallerThan()
- */
-template<typename OtherDerived>
-inline const CwiseBinaryOp<std::equal_to<Scalar>, const Derived, const OtherDerived>
-cwiseEqual(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
-{
- return CwiseBinaryOp<std::equal_to<Scalar>, const Derived, const OtherDerived>(derived(), other.derived());
-}
-
-/** \returns an expression of the coefficient-wise != operator of *this and \a other
- *
- * \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().
- *
- * Example: \include MatrixBase_cwiseNotEqual.cpp
- * Output: \verbinclude MatrixBase_cwiseNotEqual.out
- *
- * \sa cwiseEqual(), isApprox(), isMuchSmallerThan()
- */
-template<typename OtherDerived>
-inline const CwiseBinaryOp<std::not_equal_to<Scalar>, const Derived, const OtherDerived>
-cwiseNotEqual(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
-{
- return CwiseBinaryOp<std::not_equal_to<Scalar>, const Derived, const OtherDerived>(derived(), other.derived());
-}
-
-/** \returns an expression of the coefficient-wise min of *this and \a other
- *
- * Example: \include MatrixBase_cwiseMin.cpp
- * Output: \verbinclude MatrixBase_cwiseMin.out
- *
- * \sa class CwiseBinaryOp, max()
- */
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_min_op<Scalar>, const Derived, const OtherDerived>
-cwiseMin(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
-{
- return CwiseBinaryOp<internal::scalar_min_op<Scalar>, const Derived, const OtherDerived>(derived(), other.derived());
-}
-
-/** \returns an expression of the coefficient-wise max of *this and \a other
- *
- * Example: \include MatrixBase_cwiseMax.cpp
- * Output: \verbinclude MatrixBase_cwiseMax.out
- *
- * \sa class CwiseBinaryOp, min()
- */
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_max_op<Scalar>, const Derived, const OtherDerived>
-cwiseMax(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
-{
- return CwiseBinaryOp<internal::scalar_max_op<Scalar>, const Derived, const OtherDerived>(derived(), other.derived());
-}
-
-/** \returns an expression of the coefficient-wise quotient of *this and \a other
- *
- * Example: \include MatrixBase_cwiseQuotient.cpp
- * Output: \verbinclude MatrixBase_cwiseQuotient.out
- *
- * \sa class CwiseBinaryOp, cwiseProduct(), cwiseInverse()
- */
-template<typename OtherDerived>
-EIGEN_STRONG_INLINE const CwiseBinaryOp<internal::scalar_quotient_op<Scalar>, const Derived, const OtherDerived>
-cwiseQuotient(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
-{
- return CwiseBinaryOp<internal::scalar_quotient_op<Scalar>, const Derived, const OtherDerived>(derived(), other.derived());
-}
diff --git a/extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h b/extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h
deleted file mode 100644
index a3d9a0e1465..00000000000
--- a/extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
-// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
-//
-// Eigen 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 3 of the License, or (at your option) any later version.
-//
-// Alternatively, 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.
-//
-// Eigen 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 or the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License and a copy of the GNU General Public License along with
-// Eigen. If not, see <http://www.gnu.org/licenses/>.
-
-// This file is a base class plugin containing matrix specifics coefficient wise functions.
-
-/** \returns an expression of the coefficient-wise absolute value of \c *this
- *
- * Example: \include MatrixBase_cwiseAbs.cpp
- * Output: \verbinclude MatrixBase_cwiseAbs.out
- *
- * \sa cwiseAbs2()
- */
-EIGEN_STRONG_INLINE const CwiseUnaryOp<internal::scalar_abs_op<Scalar>, const Derived>
-cwiseAbs() const { return derived(); }
-
-/** \returns an expression of the coefficient-wise squared absolute value of \c *this
- *
- * Example: \include MatrixBase_cwiseAbs2.cpp
- * Output: \verbinclude MatrixBase_cwiseAbs2.out
- *
- * \sa cwiseAbs()
- */
-EIGEN_STRONG_INLINE const CwiseUnaryOp<internal::scalar_abs2_op<Scalar>, const Derived>
-cwiseAbs2() const { return derived(); }
-
-/** \returns an expression of the coefficient-wise square root of *this.
- *
- * Example: \include MatrixBase_cwiseSqrt.cpp
- * Output: \verbinclude MatrixBase_cwiseSqrt.out
- *
- * \sa cwisePow(), cwiseSquare()
- */
-inline const CwiseUnaryOp<internal::scalar_sqrt_op<Scalar>, const Derived>
-cwiseSqrt() const { return derived(); }
-
-/** \returns an expression of the coefficient-wise inverse of *this.
- *
- * Example: \include MatrixBase_cwiseInverse.cpp
- * Output: \verbinclude MatrixBase_cwiseInverse.out
- *
- * \sa cwiseProduct()
- */
-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/SConscript b/extern/SConscript
index f363d75d068..6bb060adeda 100644
--- a/extern/SConscript
+++ b/extern/SConscript
@@ -3,7 +3,6 @@
Import('env')
SConscript(['glew/SConscript'])
-SConscript(['colamd/SConscript'])
if env['WITH_BF_GAMEENGINE']:
SConscript(['recastnavigation/SConscript'])
diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h
index 6ba6c5ad30d..165626d530f 100644
--- a/extern/bullet2/src/LinearMath/btScalar.h
+++ b/extern/bullet2/src/LinearMath/btScalar.h
@@ -29,7 +29,7 @@ subject to the following restrictions:
#include <cfloat>
#include <float.h>
-/* SVN $Revision: 35500 $ on $Date: 2011-03-12 21:34:17 +0100 (Sat, 12 Mar 2011) $ from http://bullet.googlecode.com*/
+/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
#define BT_BULLET_VERSION 278
inline int btGetVersion()
diff --git a/extern/colamd/CMakeLists.txt b/extern/colamd/CMakeLists.txt
deleted file mode 100644
index 5b565518e4f..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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/glew/CMakeLists.txt b/extern/glew/CMakeLists.txt
index 9704c137f8b..87f8bb6e940 100644
--- a/extern/glew/CMakeLists.txt
+++ b/extern/glew/CMakeLists.txt
@@ -1,3 +1,4 @@
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/extern/lzma/CMakeLists.txt b/extern/lzma/CMakeLists.txt
index 89993d61491..bfb52591e08 100644
--- a/extern/lzma/CMakeLists.txt
+++ b/extern/lzma/CMakeLists.txt
@@ -1,3 +1,4 @@
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/extern/lzo/CMakeLists.txt b/extern/lzo/CMakeLists.txt
index 75b3605f75b..11eb18520b6 100644
--- a/extern/lzo/CMakeLists.txt
+++ b/extern/lzo/CMakeLists.txt
@@ -1,3 +1,4 @@
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/extern/recastnavigation/recast-capi.cpp b/extern/recastnavigation/recast-capi.cpp
index 9aeb0d65cb0..42a9a4b82c8 100644
--- a/extern/recastnavigation/recast-capi.cpp
+++ b/extern/recastnavigation/recast-capi.cpp
@@ -1,4 +1,5 @@
/*
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/extern/recastnavigation/recast-capi.h b/extern/recastnavigation/recast-capi.h
index 52a8e215ea1..e8831bcdc58 100644
--- a/extern/recastnavigation/recast-capi.h
+++ b/extern/recastnavigation/recast-capi.h
@@ -1,4 +1,5 @@
/*
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt
index 0c4df1ce392..e321673b07d 100644
--- a/intern/audaspace/CMakeLists.txt
+++ b/intern/audaspace/CMakeLists.txt
@@ -1,3 +1,4 @@
+# $Id$
# ***** BEGIN LGPL LICENSE BLOCK *****
#
# Copyright 2009 Jrg Hermann Mller
diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h
index dfdad22e176..41c113a413d 100644
--- a/intern/ffmpeg/ffmpeg_compat.h
+++ b/intern/ffmpeg/ffmpeg_compat.h
@@ -150,8 +150,7 @@ int64_t av_get_pts_from_frame(AVFormatContext *avctx, AVFrame * picture)
if (pts == AV_NOPTS_VALUE) {
pts = 0;
}
-
- (void)avctx;
+
return pts;
}
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index f926c07a8e5..a46a0079f6b 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -252,7 +252,7 @@ public:
* @return Indication of success.
*/
virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window,
- const bool stereoVisual, const GHOST_TUns16 numOfAASamples=0) = 0;
+ const bool stereoVisual) = 0;
/**
* Ends full screen mode.
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index 839e014aff6..afc54d3c6a0 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -136,7 +136,7 @@ bool GHOST_System::validWindow(GHOST_IWindow* window)
GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window,
- const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
+ const bool stereoVisual)
{
GHOST_TSuccess success = GHOST_kFailure;
GHOST_ASSERT(m_windowManager, "GHOST_System::beginFullScreen(): invalid window manager")
@@ -148,7 +148,7 @@ GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting
success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, setting);
if (success == GHOST_kSuccess) {
//GHOST_PRINT("GHOST_System::beginFullScreen(): creating full-screen window\n");
- success = createFullScreenWindow((GHOST_Window**)window, stereoVisual, numOfAASamples);
+ success = createFullScreenWindow((GHOST_Window**)window, stereoVisual);
if (success == GHOST_kSuccess) {
m_windowManager->beginFullScreen(*window, stereoVisual);
}
@@ -330,7 +330,7 @@ GHOST_TSuccess GHOST_System::exit()
}
-GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window** window, const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
+GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window** window, const bool stereoVisual)
{
GHOST_TSuccess success;
GHOST_ASSERT(m_displayManager, "GHOST_System::createFullScreenWindow(): invalid display manager")
@@ -344,8 +344,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window** window, const
0, 0, settings.xPixels, settings.yPixels,
GHOST_kWindowStateFullScreen,
GHOST_kDrawingContextTypeOpenGL,
- stereoVisual,
- numOfAASamples);
+ stereoVisual);
success = *window == 0 ? GHOST_kFailure : GHOST_kSuccess;
}
return success;
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index c958d54f2d0..573ac7dc43d 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -141,7 +141,7 @@ public:
* @return Indication of success.
*/
virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window,
- const bool stereoVisual, const GHOST_TUns16 numOfAASamples=0);
+ const bool stereoVisual);
/**
* Ends full screen mode.
@@ -305,7 +305,7 @@ protected:
* @return Indication of success.
*/
virtual GHOST_TSuccess createFullScreenWindow(GHOST_Window** window,
- const bool stereoVisual, const GHOST_TUns16 numOfAASamples=0);
+ const bool stereoVisual);
/** The display manager (platform dependant). */
GHOST_DisplayManager* m_displayManager;
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index d9eab56cfdc..ffc858d2fc5 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -1685,10 +1685,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
}
}
- /* arrow keys should not have utf8 */
- if ((keyCode > 266) && (keyCode < 271))
- utf8_buf[0] = '\0';
-
if ((keyCode == GHOST_kKeyQ) && (m_modifierMask & NSCommandKeyMask))
break; //Cmd-Q is directly handled by Cocoa
diff --git a/intern/itasc/Armature.cpp b/intern/itasc/Armature.cpp
index 916b0bc7bf3..517876d9560 100644
--- a/intern/itasc/Armature.cpp
+++ b/intern/itasc/Armature.cpp
@@ -1,7 +1,6 @@
/** \file itasc/Armature.cpp
* \ingroup itasc
*/
-/*
* Armature.cpp
*
* Created on: Feb 3, 2009
diff --git a/intern/itasc/Armature.hpp b/intern/itasc/Armature.hpp
index 0f4abeab4f0..e41b2577c4b 100644
--- a/intern/itasc/Armature.hpp
+++ b/intern/itasc/Armature.hpp
@@ -1,4 +1,3 @@
-/*
* Armature.hpp
*
* Created on: Feb 3, 2009
diff --git a/intern/itasc/CMakeLists.txt b/intern/itasc/CMakeLists.txt
index 3d24a0cb8c6..0277460220f 100644
--- a/intern/itasc/CMakeLists.txt
+++ b/intern/itasc/CMakeLists.txt
@@ -24,7 +24,7 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../../extern/Eigen3
+ ../../extern/Eigen2
)
set(INC_SYS
@@ -46,8 +46,6 @@ set(SRC
WSDLSSolver.cpp
WorldObject.cpp
eigen_types.cpp
- ublas_types.hpp
-
kdl/chain.cpp
kdl/chainfksolverpos_recursive.cpp
kdl/chainjnttojacsolver.cpp
@@ -115,211 +113,116 @@ set(SRC
kdl/utilities/traits.h
kdl/utilities/utility.h
kdl/utilities/utility_io.h
-
- kdl/frameacc.inl
- kdl/frames.inl
- kdl/framevel.inl
+ ublas_types.hpp
# until we have another user...
- ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h
- ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h
- ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h
- ../../extern/Eigen3/Eigen/src/plugins/BlockMethods.h
- ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h
- ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h
- ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h
- ../../extern/Eigen3/Eigen/src/misc/Kernel.h
- ../../extern/Eigen3/Eigen/src/misc/Image.h
- ../../extern/Eigen3/Eigen/src/misc/Solve.h
- ../../extern/Eigen3/Eigen/src/QR/HouseholderQR.h
- ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h
- ../../extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h
- ../../extern/Eigen3/Eigen/src/StlSupport/details.h
- ../../extern/Eigen3/Eigen/src/StlSupport/StdList.h
- ../../extern/Eigen3/Eigen/src/StlSupport/StdDeque.h
- ../../extern/Eigen3/Eigen/src/StlSupport/StdVector.h
- ../../extern/Eigen3/Eigen/src/SVD/UpperBidiagonalization.h
- ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/EigenvaluesCommon.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h
- ../../extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h
- ../../extern/Eigen3/Eigen/src/Jacobi/Jacobi.h
- ../../extern/Eigen3/Eigen/src/Householder/Householder.h
- ../../extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h
- ../../extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h
- ../../extern/Eigen3/Eigen/src/Geometry/RotationBase.h
- ../../extern/Eigen3/Eigen/src/Geometry/Rotation2D.h
- ../../extern/Eigen3/Eigen/src/Geometry/Homogeneous.h
- ../../extern/Eigen3/Eigen/src/Geometry/Hyperplane.h
- ../../extern/Eigen3/Eigen/src/Geometry/EulerAngles.h
- ../../extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h
- ../../extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h
- ../../extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h
- ../../extern/Eigen3/Eigen/src/Geometry/AngleAxis.h
- ../../extern/Eigen3/Eigen/src/Geometry/Umeyama.h
- ../../extern/Eigen3/Eigen/src/Geometry/Scaling.h
- ../../extern/Eigen3/Eigen/src/Geometry/Translation.h
- ../../extern/Eigen3/Eigen/src/Geometry/AlignedBox.h
- ../../extern/Eigen3/Eigen/src/Geometry/Transform.h
- ../../extern/Eigen3/Eigen/src/Geometry/Quaternion.h
- ../../extern/Eigen3/Eigen/src/LU/PartialPivLU.h
- ../../extern/Eigen3/Eigen/src/LU/Determinant.h
- ../../extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h
- ../../extern/Eigen3/Eigen/src/LU/FullPivLU.h
- ../../extern/Eigen3/Eigen/src/LU/Inverse.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseMatrixBase.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseSelfAdjointView.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseVector.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseDiagonalProduct.h
- ../../extern/Eigen3/Eigen/src/Sparse/TriangularSolver.h
- ../../extern/Eigen3/Eigen/src/Sparse/AmbiVector.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseDenseProduct.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseBlock.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseTriangularView.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseCwiseBinaryOp.h
- ../../extern/Eigen3/Eigen/src/Sparse/CoreIterators.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseMatrix.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseAssign.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseSparseProduct.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseDot.h
- ../../extern/Eigen3/Eigen/src/Sparse/DynamicSparseMatrix.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseRedux.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseFuzzy.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseCwiseUnaryOp.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseView.h
- ../../extern/Eigen3/Eigen/src/Sparse/MappedSparseMatrix.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseUtil.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseTranspose.h
- ../../extern/Eigen3/Eigen/src/Sparse/SparseProduct.h
- ../../extern/Eigen3/Eigen/src/Sparse/CompressedStorage.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/QR.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Memory.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/SVD.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Meta.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Macros.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/LU.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Block.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AngleAxis.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/All.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/Minor.h
- ../../extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h
- ../../extern/Eigen3/Eigen/src/Core/SelfAdjointView.h
- ../../extern/Eigen3/Eigen/src/Core/MatrixBase.h
- ../../extern/Eigen3/Eigen/src/Core/Swap.h
- ../../extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h
- ../../extern/Eigen3/Eigen/src/Core/DenseBase.h
- ../../extern/Eigen3/Eigen/src/Core/GlobalFunctions.h
- ../../extern/Eigen3/Eigen/src/Core/ProductBase.h
- ../../extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h
- ../../extern/Eigen3/Eigen/src/Core/Stride.h
- ../../extern/Eigen3/Eigen/src/Core/Matrix.h
- ../../extern/Eigen3/Eigen/src/Core/Visitor.h
- ../../extern/Eigen3/Eigen/src/Core/Array.h
- ../../extern/Eigen3/Eigen/src/Core/ReturnByValue.h
- ../../extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h
- ../../extern/Eigen3/Eigen/src/Core/EigenBase.h
- ../../extern/Eigen3/Eigen/src/Core/Random.h
- ../../extern/Eigen3/Eigen/src/Core/Redux.h
- ../../extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h
- ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h
- ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h
- ../../extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h
- ../../extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h
- ../../extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h
- ../../extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h
- ../../extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h
- ../../extern/Eigen3/Eigen/src/Core/BooleanRedux.h
- ../../extern/Eigen3/Eigen/src/Core/util/ReenableStupidWarnings.h
- ../../extern/Eigen3/Eigen/src/Core/util/BlasUtil.h
- ../../extern/Eigen3/Eigen/src/Core/util/Memory.h
- ../../extern/Eigen3/Eigen/src/Core/util/Meta.h
- ../../extern/Eigen3/Eigen/src/Core/util/Constants.h
- ../../extern/Eigen3/Eigen/src/Core/util/Macros.h
- ../../extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h
- ../../extern/Eigen3/Eigen/src/Core/util/StaticAssert.h
- ../../extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h
- ../../extern/Eigen3/Eigen/src/Core/util/XprHelper.h
- ../../extern/Eigen3/Eigen/src/Core/VectorBlock.h
- ../../extern/Eigen3/Eigen/src/Core/Transpositions.h
- ../../extern/Eigen3/Eigen/src/Core/Select.h
- ../../extern/Eigen3/Eigen/src/Core/BandMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h
- ../../extern/Eigen3/Eigen/src/Core/Dot.h
- ../../extern/Eigen3/Eigen/src/Core/GenericPacketMath.h
- ../../extern/Eigen3/Eigen/src/Core/Product.h
- ../../extern/Eigen3/Eigen/src/Core/Transpose.h
- ../../extern/Eigen3/Eigen/src/Core/Block.h
- ../../extern/Eigen3/Eigen/src/Core/ArrayWrapper.h
- ../../extern/Eigen3/Eigen/src/Core/MapBase.h
- ../../extern/Eigen3/Eigen/src/Core/NoAlias.h
- ../../extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h
- ../../extern/Eigen3/Eigen/src/Core/PlainObjectBase.h
- ../../extern/Eigen3/Eigen/src/Core/IO.h
- ../../extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h
- ../../extern/Eigen3/Eigen/src/Core/Reverse.h
- ../../extern/Eigen3/Eigen/src/Core/Fuzzy.h
- ../../extern/Eigen3/Eigen/src/Core/DenseStorage.h
- ../../extern/Eigen3/Eigen/src/Core/StableNorm.h
- ../../extern/Eigen3/Eigen/src/Core/NumTraits.h
- ../../extern/Eigen3/Eigen/src/Core/Map.h
- ../../extern/Eigen3/Eigen/src/Core/Functors.h
- ../../extern/Eigen3/Eigen/src/Core/PermutationMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/ArrayBase.h
- ../../extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h
- ../../extern/Eigen3/Eigen/src/Core/SolveTriangular.h
- ../../extern/Eigen3/Eigen/src/Core/NestByValue.h
- ../../extern/Eigen3/Eigen/src/Core/DiagonalProduct.h
- ../../extern/Eigen3/Eigen/src/Core/CommaInitializer.h
- ../../extern/Eigen3/Eigen/src/Core/MathFunctions.h
- ../../extern/Eigen3/Eigen/src/Core/Diagonal.h
- ../../extern/Eigen3/Eigen/src/Core/Replicate.h
- ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h
- ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h
- ../../extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h
- ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h
- ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h
- ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h
- ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/products/Parallelizer.h
- ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h
- ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h
- ../../extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h
- ../../extern/Eigen3/Eigen/src/Core/TriangularMatrix.h
- ../../extern/Eigen3/Eigen/src/Core/VectorwiseOp.h
- ../../extern/Eigen3/Eigen/src/Core/Assign.h
- ../../extern/Eigen3/Eigen/src/Core/Flagged.h
- ../../extern/Eigen3/Eigen/src/Cholesky/LDLT.h
- ../../extern/Eigen3/Eigen/src/Cholesky/LLT.h
+ ../../extern/Eigen2/Eigen/src/Array/BooleanRedux.h
+ ../../extern/Eigen2/Eigen/src/Array/CwiseOperators.h
+ ../../extern/Eigen2/Eigen/src/Array/Functors.h
+ ../../extern/Eigen2/Eigen/src/Array/Norms.h
+ ../../extern/Eigen2/Eigen/src/Array/PartialRedux.h
+ ../../extern/Eigen2/Eigen/src/Array/Random.h
+ ../../extern/Eigen2/Eigen/src/Array/Select.h
+ ../../extern/Eigen2/Eigen/src/Cholesky/LDLT.h
+ ../../extern/Eigen2/Eigen/src/Cholesky/LLT.h
+ ../../extern/Eigen2/Eigen/src/Core/Assign.h
+ ../../extern/Eigen2/Eigen/src/Core/Block.h
+ ../../extern/Eigen2/Eigen/src/Core/CacheFriendlyProduct.h
+ ../../extern/Eigen2/Eigen/src/Core/Coeffs.h
+ ../../extern/Eigen2/Eigen/src/Core/CommaInitializer.h
+ ../../extern/Eigen2/Eigen/src/Core/Cwise.h
+ ../../extern/Eigen2/Eigen/src/Core/CwiseBinaryOp.h
+ ../../extern/Eigen2/Eigen/src/Core/CwiseNullaryOp.h
+ ../../extern/Eigen2/Eigen/src/Core/CwiseUnaryOp.h
+ ../../extern/Eigen2/Eigen/src/Core/DiagonalCoeffs.h
+ ../../extern/Eigen2/Eigen/src/Core/DiagonalMatrix.h
+ ../../extern/Eigen2/Eigen/src/Core/DiagonalProduct.h
+ ../../extern/Eigen2/Eigen/src/Core/Dot.h
+ ../../extern/Eigen2/Eigen/src/Core/Flagged.h
+ ../../extern/Eigen2/Eigen/src/Core/Functors.h
+ ../../extern/Eigen2/Eigen/src/Core/Fuzzy.h
+ ../../extern/Eigen2/Eigen/src/Core/GenericPacketMath.h
+ ../../extern/Eigen2/Eigen/src/Core/IO.h
+ ../../extern/Eigen2/Eigen/src/Core/Map.h
+ ../../extern/Eigen2/Eigen/src/Core/MapBase.h
+ ../../extern/Eigen2/Eigen/src/Core/MathFunctions.h
+ ../../extern/Eigen2/Eigen/src/Core/Matrix.h
+ ../../extern/Eigen2/Eigen/src/Core/MatrixBase.h
+ ../../extern/Eigen2/Eigen/src/Core/MatrixStorage.h
+ ../../extern/Eigen2/Eigen/src/Core/Minor.h
+ ../../extern/Eigen2/Eigen/src/Core/NestByValue.h
+ ../../extern/Eigen2/Eigen/src/Core/NumTraits.h
+ ../../extern/Eigen2/Eigen/src/Core/Part.h
+ ../../extern/Eigen2/Eigen/src/Core/Product.h
+ ../../extern/Eigen2/Eigen/src/Core/Redux.h
+ ../../extern/Eigen2/Eigen/src/Core/SolveTriangular.h
+ ../../extern/Eigen2/Eigen/src/Core/Sum.h
+ ../../extern/Eigen2/Eigen/src/Core/Swap.h
+ ../../extern/Eigen2/Eigen/src/Core/Transpose.h
+ ../../extern/Eigen2/Eigen/src/Core/Visitor.h
+ ../../extern/Eigen2/Eigen/src/Core/arch/AltiVec/PacketMath.h
+ ../../extern/Eigen2/Eigen/src/Core/arch/SSE/PacketMath.h
+ ../../extern/Eigen2/Eigen/src/Core/util/Constants.h
+ ../../extern/Eigen2/Eigen/src/Core/util/DisableMSVCWarnings.h
+ ../../extern/Eigen2/Eigen/src/Core/util/EnableMSVCWarnings.h
+ ../../extern/Eigen2/Eigen/src/Core/util/ForwardDeclarations.h
+ ../../extern/Eigen2/Eigen/src/Core/util/Macros.h
+ ../../extern/Eigen2/Eigen/src/Core/util/Memory.h
+ ../../extern/Eigen2/Eigen/src/Core/util/Meta.h
+ ../../extern/Eigen2/Eigen/src/Core/util/StaticAssert.h
+ ../../extern/Eigen2/Eigen/src/Core/util/XprHelper.h
+ ../../extern/Eigen2/Eigen/src/Geometry/AlignedBox.h
+ ../../extern/Eigen2/Eigen/src/Geometry/AngleAxis.h
+ ../../extern/Eigen2/Eigen/src/Geometry/EulerAngles.h
+ ../../extern/Eigen2/Eigen/src/Geometry/Hyperplane.h
+ ../../extern/Eigen2/Eigen/src/Geometry/OrthoMethods.h
+ ../../extern/Eigen2/Eigen/src/Geometry/ParametrizedLine.h
+ ../../extern/Eigen2/Eigen/src/Geometry/Quaternion.h
+ ../../extern/Eigen2/Eigen/src/Geometry/Rotation2D.h
+ ../../extern/Eigen2/Eigen/src/Geometry/RotationBase.h
+ ../../extern/Eigen2/Eigen/src/Geometry/Scaling.h
+ ../../extern/Eigen2/Eigen/src/Geometry/Transform.h
+ ../../extern/Eigen2/Eigen/src/Geometry/Translation.h
+ ../../extern/Eigen2/Eigen/src/LU/Determinant.h
+ ../../extern/Eigen2/Eigen/src/LU/Inverse.h
+ ../../extern/Eigen2/Eigen/src/LU/LU.h
+ ../../extern/Eigen2/Eigen/src/LeastSquares/LeastSquares.h
+ ../../extern/Eigen2/Eigen/src/QR/EigenSolver.h
+ ../../extern/Eigen2/Eigen/src/QR/HessenbergDecomposition.h
+ ../../extern/Eigen2/Eigen/src/QR/QR.h
+ ../../extern/Eigen2/Eigen/src/QR/SelfAdjointEigenSolver.h
+ ../../extern/Eigen2/Eigen/src/QR/Tridiagonalization.h
+ ../../extern/Eigen2/Eigen/src/SVD/SVD.h
+ ../../extern/Eigen2/Eigen/src/Sparse/AmbiVector.h
+ ../../extern/Eigen2/Eigen/src/Sparse/CholmodSupport.h
+ ../../extern/Eigen2/Eigen/src/Sparse/CompressedStorage.h
+ ../../extern/Eigen2/Eigen/src/Sparse/CoreIterators.h
+ ../../extern/Eigen2/Eigen/src/Sparse/DynamicSparseMatrix.h
+ ../../extern/Eigen2/Eigen/src/Sparse/MappedSparseMatrix.h
+ ../../extern/Eigen2/Eigen/src/Sparse/RandomSetter.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseAssign.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseBlock.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseCwise.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseCwiseBinaryOp.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseCwiseUnaryOp.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseDiagonalProduct.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseDot.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseFlagged.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseFuzzy.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseLDLT.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseLLT.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseLU.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseMatrix.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseMatrixBase.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseProduct.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseRedux.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseTranspose.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseUtil.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SparseVector.h
+ ../../extern/Eigen2/Eigen/src/Sparse/SuperLUSupport.h
+ ../../extern/Eigen2/Eigen/src/Sparse/TaucsSupport.h
+ ../../extern/Eigen2/Eigen/src/Sparse/TriangularSolver.h
+ ../../extern/Eigen2/Eigen/src/Sparse/UmfPackSupport.h
)
-if(WIN32)
- add_definitions(-DEIGEN_DONT_ALIGN_STATICALLY)
-endif()
-
blender_add_lib(bf_intern_itasc "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/itasc/Cache.cpp b/intern/itasc/Cache.cpp
index 6a698005d63..fe749f00053 100644
--- a/intern/itasc/Cache.cpp
+++ b/intern/itasc/Cache.cpp
@@ -1,7 +1,6 @@
/** \file itasc/Cache.cpp
* \ingroup itasc
*/
-/*
* Cache.cpp
*
* Created on: Feb 24, 2009
diff --git a/intern/itasc/Cache.hpp b/intern/itasc/Cache.hpp
index a533d75b53a..ee39130032f 100644
--- a/intern/itasc/Cache.hpp
+++ b/intern/itasc/Cache.hpp
@@ -1,4 +1,3 @@
-/*
* Cache.hpp
*
* Created on: Feb 24, 2009
diff --git a/intern/itasc/ConstraintSet.cpp b/intern/itasc/ConstraintSet.cpp
index e21cd36e4c8..45dc695707c 100644
--- a/intern/itasc/ConstraintSet.cpp
+++ b/intern/itasc/ConstraintSet.cpp
@@ -1,7 +1,6 @@
/** \file itasc/ConstraintSet.cpp
* \ingroup itasc
*/
-/*
* ConstraintSet.cpp
*
* Created on: Jan 5, 2009
@@ -80,7 +79,7 @@ void ConstraintSet::modelUpdate(Frame& _external_pose,const Timestamp& timestamp
double ConstraintSet::getMaxTimestep(double& timestep)
{
- e_scalar maxChidot = m_chidot.array().abs().maxCoeff();
+ e_scalar maxChidot = m_chidot.cwise().abs().maxCoeff();
if (timestep*maxChidot > m_maxDeltaChi) {
timestep = m_maxDeltaChi/maxChidot;
}
@@ -162,9 +161,9 @@ bool ConstraintSet::closeLoop(){
}else
m_B.row(i) = m_U.col(i)/m_S(i);
- m_Jf_inv.noalias()=m_V*m_B;
+ m_Jf_inv=(m_V*m_B).lazy();
- m_chi.noalias()+=m_Jf_inv*m_tdelta;
+ m_chi+=(m_Jf_inv*m_tdelta).lazy();
updateJacobian();
// m_externalPose-m_internalPose in end effector frame
// this is just to compare the pose, a different formula would work too
diff --git a/intern/itasc/ConstraintSet.hpp b/intern/itasc/ConstraintSet.hpp
index bf29190a050..030cc7debf6 100644
--- a/intern/itasc/ConstraintSet.hpp
+++ b/intern/itasc/ConstraintSet.hpp
@@ -1,4 +1,3 @@
-/*
* ConstraintSet.hpp
*
* Created on: Jan 5, 2009
diff --git a/intern/itasc/ControlledObject.cpp b/intern/itasc/ControlledObject.cpp
index 4055aad7768..4e14ada4a1d 100644
--- a/intern/itasc/ControlledObject.cpp
+++ b/intern/itasc/ControlledObject.cpp
@@ -1,7 +1,6 @@
/** \file itasc/ControlledObject.cpp
* \ingroup itasc
*/
-/*
* ControlledObject.cpp
*
* Created on: Jan 5, 2009
@@ -54,7 +53,7 @@ const e_matrix& ControlledObject::getJq(unsigned int ee) const
double ControlledObject::getMaxTimestep(double& timestep)
{
- e_scalar maxQdot = m_qdot.array().abs().maxCoeff();
+ e_scalar maxQdot = m_qdot.cwise().abs().maxCoeff();
if (timestep*maxQdot > m_maxDeltaQ) {
timestep = m_maxDeltaQ/maxQdot;
}
diff --git a/intern/itasc/ControlledObject.hpp b/intern/itasc/ControlledObject.hpp
index 4530bf9823b..5ad5a60bafd 100644
--- a/intern/itasc/ControlledObject.hpp
+++ b/intern/itasc/ControlledObject.hpp
@@ -1,4 +1,3 @@
-/*
* ControlledObject.hpp
*
* Created on: Jan 5, 2009
diff --git a/intern/itasc/CopyPose.cpp b/intern/itasc/CopyPose.cpp
index a9d4c2f0a2a..eb47ab58e9a 100644
--- a/intern/itasc/CopyPose.cpp
+++ b/intern/itasc/CopyPose.cpp
@@ -1,7 +1,6 @@
/** \file itasc/CopyPose.cpp
* \ingroup itasc
*/
-/*
* CopyPose.cpp
*
* Created on: Mar 17, 2009
@@ -473,7 +472,7 @@ double CopyPose::getMaxTimestep(double& timestep)
// CopyPose should not have any limit on linear velocity:
// in case the target is out of reach, this can be very high.
// We will simply limit on rotation
- e_scalar maxChidot = m_chidot.block(3,0,3,1).array().abs().maxCoeff();
+ e_scalar maxChidot = m_chidot.block(3,0,3,1).cwise().abs().maxCoeff();
if (timestep*maxChidot > m_maxDeltaChi) {
timestep = m_maxDeltaChi/maxChidot;
}
diff --git a/intern/itasc/CopyPose.hpp b/intern/itasc/CopyPose.hpp
index fd8a5451310..e2a4eb18cf4 100644
--- a/intern/itasc/CopyPose.hpp
+++ b/intern/itasc/CopyPose.hpp
@@ -1,4 +1,3 @@
-/*
* CopyPose.h
*
* Created on: Mar 17, 2009
diff --git a/intern/itasc/Distance.cpp b/intern/itasc/Distance.cpp
index 7cf04367a4e..68c66633ac8 100644
--- a/intern/itasc/Distance.cpp
+++ b/intern/itasc/Distance.cpp
@@ -1,7 +1,6 @@
/** \file itasc/Distance.cpp
* \ingroup itasc
*/
-/*
* Distance.cpp
*
* Created on: Jan 30, 2009
diff --git a/intern/itasc/Distance.hpp b/intern/itasc/Distance.hpp
index 5c56dd871ef..bc06c4f9d16 100644
--- a/intern/itasc/Distance.hpp
+++ b/intern/itasc/Distance.hpp
@@ -1,4 +1,3 @@
-/*
* Distance.hpp
*
* Created on: Jan 30, 2009
diff --git a/intern/itasc/FixedObject.cpp b/intern/itasc/FixedObject.cpp
index 9dc4d69878a..26d69b357b2 100644
--- a/intern/itasc/FixedObject.cpp
+++ b/intern/itasc/FixedObject.cpp
@@ -1,7 +1,6 @@
/** \file itasc/FixedObject.cpp
* \ingroup itasc
*/
-/*
* FixedObject.cpp
*
* Created on: Feb 10, 2009
diff --git a/intern/itasc/FixedObject.hpp b/intern/itasc/FixedObject.hpp
index b4279d9adcb..10e68ff9457 100644
--- a/intern/itasc/FixedObject.hpp
+++ b/intern/itasc/FixedObject.hpp
@@ -1,4 +1,3 @@
-/*
* FixedObject.h
*
* Created on: Feb 10, 2009
diff --git a/intern/itasc/MovingFrame.cpp b/intern/itasc/MovingFrame.cpp
index 3b0ee7842ca..2e72c366153 100644
--- a/intern/itasc/MovingFrame.cpp
+++ b/intern/itasc/MovingFrame.cpp
@@ -1,7 +1,6 @@
/** \file itasc/MovingFrame.cpp
* \ingroup itasc
*/
-/*
* MovingFrame.cpp
*
* Created on: Feb 10, 2009
diff --git a/intern/itasc/MovingFrame.hpp b/intern/itasc/MovingFrame.hpp
index 21cb344980a..a398cac2727 100644
--- a/intern/itasc/MovingFrame.hpp
+++ b/intern/itasc/MovingFrame.hpp
@@ -1,4 +1,3 @@
-/*
* MovingFrame.h
*
* Created on: Feb 10, 2009
diff --git a/intern/itasc/Object.hpp b/intern/itasc/Object.hpp
index 5aa4346fc4b..c51caa0bf05 100644
--- a/intern/itasc/Object.hpp
+++ b/intern/itasc/Object.hpp
@@ -1,4 +1,3 @@
-/*
* Object.hpp
*
* Created on: Jan 5, 2009
diff --git a/intern/itasc/SConscript b/intern/itasc/SConscript
index 69dddf40228..5fa4246d711 100644
--- a/intern/itasc/SConscript
+++ b/intern/itasc/SConscript
@@ -5,12 +5,7 @@ sources = env.Glob('*.cpp')
sources += env.Glob('kdl/*.cpp')
sources += env.Glob('kdl/utilities/*.cpp')
-incs = '. ../../extern/Eigen3'
+incs = '. ../../extern/Eigen2'
-defs = []
-
-if env['PLATFORM'] == 'win32':
- defs.append('EIGEN_DONT_ALIGN_STATICALLY')
-
-env.BlenderLib ('bf_intern_itasc', sources, Split(incs), defs, libtype=['intern','player'], priority=[20,100] )
+env.BlenderLib ('bf_intern_itasc', sources, Split(incs), [], libtype=['intern','player'], priority=[20,100] )
diff --git a/intern/itasc/Scene.cpp b/intern/itasc/Scene.cpp
index 16f8551bfc7..861874c80e0 100644
--- a/intern/itasc/Scene.cpp
+++ b/intern/itasc/Scene.cpp
@@ -1,7 +1,6 @@
/** \file itasc/Scene.cpp
* \ingroup itasc
*/
-/*
* Scene.cpp
*
* Created on: Jan 5, 2009
@@ -356,7 +355,7 @@ bool Scene::update(double timestamp, double timestep, unsigned int numsubstep, b
m_Uf.col(i).setConstant(0.0);
else
m_Uf.col(i)*=(1/m_Sf(i));
- project(m_Jf_inv,cs->featurerange,cs->featurerange).noalias()=m_Vf*m_Uf.transpose();
+ project(m_Jf_inv,cs->featurerange,cs->featurerange)=(m_Vf*m_Uf.transpose()).lazy();
//Get the robotjacobian associated with this constraintset
//Each jacobian is expressed in robot base frame => convert to world reference
@@ -410,11 +409,11 @@ bool Scene::update(double timestamp, double timestep, unsigned int numsubstep, b
}
//Calculate A
- m_Atemp.noalias()=m_Cf*m_Jf_inv;
- m_A.noalias() = m_Cq-(m_Atemp*m_Jq);
+ m_Atemp=(m_Cf*m_Jf_inv).lazy();
+ m_A = m_Cq-(m_Atemp*m_Jq).lazy();
if (m_nuTotal > 0) {
- m_B.noalias()=m_Atemp*m_Ju;
- m_ydot.noalias() += m_B*m_xdot;
+ m_B=(m_Atemp*m_Ju).lazy();
+ m_ydot += (m_B*m_xdot).lazy();
}
//Call the solver with A, Wq, Wy, ydot to solver qdot:
@@ -435,13 +434,13 @@ bool Scene::update(double timestamp, double timestep, unsigned int numsubstep, b
//Calculate the twist of the world reference frame due to the robots (Jq*qdot+Ju*chiudot):
e_vector6 external_vel = e_zero_vector(6);
if (ob1->jointrange.count > 0)
- external_vel.noalias() += (project(m_Jq,cs->featurerange,ob1->jointrange)*project(m_qdot,ob1->jointrange));
+ external_vel += (project(m_Jq,cs->featurerange,ob1->jointrange)*project(m_qdot,ob1->jointrange)).lazy();
if (ob2->jointrange.count > 0)
- external_vel.noalias() += (project(m_Jq,cs->featurerange,ob2->jointrange)*project(m_qdot,ob2->jointrange));
+ external_vel += (project(m_Jq,cs->featurerange,ob2->jointrange)*project(m_qdot,ob2->jointrange)).lazy();
if (ob1->coordinaterange.count > 0)
- external_vel.noalias() += (project(m_Ju,cs->featurerange,ob1->coordinaterange)*project(m_xdot,ob1->coordinaterange));
+ external_vel += (project(m_Ju,cs->featurerange,ob1->coordinaterange)*project(m_xdot,ob1->coordinaterange)).lazy();
if (ob2->coordinaterange.count > 0)
- external_vel.noalias() += (project(m_Ju,cs->featurerange,ob2->coordinaterange)*project(m_xdot,ob2->coordinaterange));
+ external_vel += (project(m_Ju,cs->featurerange,ob2->coordinaterange)*project(m_xdot,ob2->coordinaterange)).lazy();
//the twist caused by the constraint must be opposite because of the closed loop
//estimate the velocity of the joints using the inverse jacobian
e_vector6 estimated_chidot = project(m_Jf_inv,cs->featurerange,cs->featurerange)*(-external_vel);
diff --git a/intern/itasc/Scene.hpp b/intern/itasc/Scene.hpp
index 5ed031b543e..78f95e2967f 100644
--- a/intern/itasc/Scene.hpp
+++ b/intern/itasc/Scene.hpp
@@ -1,4 +1,3 @@
-/*
* Scene.hpp
*
* Created on: Jan 5, 2009
diff --git a/intern/itasc/Solver.hpp b/intern/itasc/Solver.hpp
index 809c03d9bce..c8c5c05448e 100644
--- a/intern/itasc/Solver.hpp
+++ b/intern/itasc/Solver.hpp
@@ -1,4 +1,3 @@
-/*
* Solver.hpp
*
* Created on: Jan 8, 2009
diff --git a/intern/itasc/UncontrolledObject.cpp b/intern/itasc/UncontrolledObject.cpp
index a5f2362aa94..bf9f949380d 100644
--- a/intern/itasc/UncontrolledObject.cpp
+++ b/intern/itasc/UncontrolledObject.cpp
@@ -1,7 +1,6 @@
/** \file itasc/UncontrolledObject.cpp
* \ingroup itasc
*/
-/*
* UncontrolledObject.cpp
*
* Created on: Jan 5, 2009
diff --git a/intern/itasc/UncontrolledObject.hpp b/intern/itasc/UncontrolledObject.hpp
index 81445538fa6..aa3d7f17b46 100644
--- a/intern/itasc/UncontrolledObject.hpp
+++ b/intern/itasc/UncontrolledObject.hpp
@@ -1,4 +1,3 @@
-/*
* UncontrolledObject.h
*
* Created on: Jan 5, 2009
diff --git a/intern/itasc/WDLSSolver.cpp b/intern/itasc/WDLSSolver.cpp
index d03c38396c7..22ebe93351b 100644
--- a/intern/itasc/WDLSSolver.cpp
+++ b/intern/itasc/WDLSSolver.cpp
@@ -1,7 +1,6 @@
/** \file itasc/WDLSSolver.cpp
* \ingroup itasc
*/
-/*
* WDLSSolver.hpp.cpp
*
* Created on: Jan 8, 2009
@@ -65,10 +64,10 @@ bool WDLSSolver::solve(const e_matrix& A, const e_vector& Wy, const e_vector& yd
if(ret<0)
return false;
- m_WqV.noalias() = Wq*m_V;
+ m_WqV = (Wq*m_V).lazy();
//Wy*ydot
- m_Wy_ydot = Wy.array() * ydot.array();
+ m_Wy_ydot = Wy.cwise() * ydot;
//S^-1*U'*Wy*ydot
e_scalar maxDeltaS = e_scalar(0.0);
e_scalar prevS = e_scalar(0.0);
@@ -85,7 +84,7 @@ bool WDLSSolver::solve(const e_matrix& A, const e_vector& Wy, const e_vector& yd
}
lambda = (S < m_epsilon) ? (e_scalar(1.0)-KDL::sqr(S/m_epsilon))*m_lambda*m_lambda : e_scalar(0.0);
alpha = m_U.col(i).dot(m_Wy_ydot)*S/(S*S+lambda);
- vmax = m_WqV.col(i).array().abs().maxCoeff();
+ vmax = m_WqV.col(i).cwise().abs().maxCoeff();
norm = fabs(alpha*vmax);
if (norm > m_qmax) {
qdot += m_WqV.col(i)*(alpha*m_qmax/norm);
diff --git a/intern/itasc/WDLSSolver.hpp b/intern/itasc/WDLSSolver.hpp
index 4e72490cf1b..1373145e325 100644
--- a/intern/itasc/WDLSSolver.hpp
+++ b/intern/itasc/WDLSSolver.hpp
@@ -1,4 +1,3 @@
-/*
* WDLSSolver.hpp
*
* Created on: Jan 8, 2009
diff --git a/intern/itasc/WSDLSSolver.cpp b/intern/itasc/WSDLSSolver.cpp
index 6fdd8e6e06c..c9c4b4b1839 100644
--- a/intern/itasc/WSDLSSolver.cpp
+++ b/intern/itasc/WSDLSSolver.cpp
@@ -1,7 +1,6 @@
/** \file itasc/WSDLSSolver.cpp
* \ingroup itasc
*/
-/*
* WDLSSolver.hpp.cpp
*
* Created on: Jan 8, 2009
@@ -60,7 +59,7 @@ bool WSDLSSolver::solve(const e_matrix& A, const e_vector& Wy, const e_vector& y
e_scalar N, M;
// Create the Weighted jacobian
- m_AWq.noalias() = A*Wq;
+ m_AWq = (A*Wq).lazy();
for (i=0; i<m_nc; i++)
m_WyAWq.row(i) = Wy(i)*m_AWq.row(i);
@@ -75,8 +74,8 @@ bool WSDLSSolver::solve(const e_matrix& A, const e_vector& Wy, const e_vector& y
if(ret<0)
return false;
- m_Wy_ydot = Wy.array() * ydot.array();
- m_WqV.noalias() = Wq*m_V;
+ m_Wy_ydot = Wy.cwise() * ydot;
+ m_WqV = (Wq*m_V).lazy();
qdot.setZero();
e_scalar maxDeltaS = e_scalar(0.0);
e_scalar prevS = e_scalar(0.0);
@@ -121,7 +120,7 @@ bool WSDLSSolver::solve(const e_matrix& A, const e_vector& Wy, const e_vector& y
M *= Sinv;
alpha = m_U.col(i).dot(m_Wy_ydot);
_qmax = (N < M) ? m_qmax*N/M : m_qmax;
- vmax = m_WqV.col(i).array().abs().maxCoeff();
+ vmax = m_WqV.col(i).cwise().abs().maxCoeff();
norm = fabs(Sinv*alpha*vmax);
if (norm > _qmax) {
damp = Sinv*alpha*_qmax/norm;
diff --git a/intern/itasc/WSDLSSolver.hpp b/intern/itasc/WSDLSSolver.hpp
index e6516031428..1a0ec4c59b1 100644
--- a/intern/itasc/WSDLSSolver.hpp
+++ b/intern/itasc/WSDLSSolver.hpp
@@ -1,4 +1,3 @@
-/*
* WSDLSSolver.hpp
*
* Created on: Mar 26, 2009
diff --git a/intern/itasc/WorldObject.cpp b/intern/itasc/WorldObject.cpp
index cabe13fe379..e279966154a 100644
--- a/intern/itasc/WorldObject.cpp
+++ b/intern/itasc/WorldObject.cpp
@@ -1,7 +1,6 @@
/** \file itasc/WorldObject.cpp
* \ingroup itasc
*/
-/*
* WorldObject.cpp
*
* Created on: Feb 10, 2009
diff --git a/intern/itasc/WorldObject.hpp b/intern/itasc/WorldObject.hpp
index 99756dcd684..26d57d61d77 100644
--- a/intern/itasc/WorldObject.hpp
+++ b/intern/itasc/WorldObject.hpp
@@ -1,4 +1,3 @@
-/*
* WorldObject.h
*
* Created on: Feb 10, 2009
diff --git a/intern/itasc/eigen_types.cpp b/intern/itasc/eigen_types.cpp
index a2ec68ca8e4..d983c975975 100644
--- a/intern/itasc/eigen_types.cpp
+++ b/intern/itasc/eigen_types.cpp
@@ -1,7 +1,6 @@
/** \file itasc/eigen_types.cpp
* \ingroup itasc
*/
-/*
* eigen_types.cpp
*
* Created on: March 19, 2009
diff --git a/intern/itasc/eigen_types.hpp b/intern/itasc/eigen_types.hpp
index 601b69274d9..e83d11cc165 100644
--- a/intern/itasc/eigen_types.hpp
+++ b/intern/itasc/eigen_types.hpp
@@ -1,4 +1,3 @@
-/*
* eigen_types.hpp
*
* Created on: March 6, 2009
diff --git a/intern/itasc/kdl/frameacc.inl b/intern/itasc/kdl/frameacc.inl
index 667664f2079..a8ea35ad436 100644
--- a/intern/itasc/kdl/frameacc.inl
+++ b/intern/itasc/kdl/frameacc.inl
@@ -12,6 +12,7 @@
* - $log$
*
* \par Release
+ * $Id: frameacc.inl 19905 2009-04-23 13:29:54Z ben2610 $
* $Name: $
****************************************************************************/
diff --git a/intern/itasc/kdl/framevel.inl b/intern/itasc/kdl/framevel.inl
index d0872b8869b..994b3d2028e 100644
--- a/intern/itasc/kdl/framevel.inl
+++ b/intern/itasc/kdl/framevel.inl
@@ -12,6 +12,7 @@
* - $log$
*
* \par Release
+ * $Id: framevel.inl 19905 2009-04-23 13:29:54Z ben2610 $
* $Name: $
****************************************************************************/
diff --git a/intern/itasc/kdl/inertia.cpp b/intern/itasc/kdl/inertia.cpp
index 783bb04db70..362b8310a52 100644
--- a/intern/itasc/kdl/inertia.cpp
+++ b/intern/itasc/kdl/inertia.cpp
@@ -24,7 +24,7 @@
#include "inertia.hpp"
-#include <Eigen/Core>
+#include <Eigen/Array>
namespace KDL {
using namespace Eigen;
diff --git a/intern/itasc/kdl/inertia.hpp b/intern/itasc/kdl/inertia.hpp
index f37d9972883..9f33859671c 100644
--- a/intern/itasc/kdl/inertia.hpp
+++ b/intern/itasc/kdl/inertia.hpp
@@ -22,7 +22,7 @@
#ifndef KDLINERTIA_HPP
#define KDLINERTIA_HPP
-#include <Eigen/Core>
+#include <Eigen/Array>
#include "frames.hpp"
namespace KDL {
diff --git a/intern/itasc/kdl/utilities/svd_eigen_HH.hpp b/intern/itasc/kdl/utilities/svd_eigen_HH.hpp
index f4b46963813..2bbb8df521f 100644
--- a/intern/itasc/kdl/utilities/svd_eigen_HH.hpp
+++ b/intern/itasc/kdl/utilities/svd_eigen_HH.hpp
@@ -25,7 +25,7 @@
#define SVD_EIGEN_HH_HPP
-#include <Eigen/Core>
+#include <Eigen/Array>
#include <algorithm>
namespace KDL
diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h
index 5194c97fd78..7f858c323c0 100644
--- a/intern/memutil/MEM_CacheLimiter.h
+++ b/intern/memutil/MEM_CacheLimiter.h
@@ -125,10 +125,6 @@ class MEM_CacheLimiter {
public:
typedef typename std::list<MEM_CacheLimiterHandle<T> *,
MEM_Allocator<MEM_CacheLimiterHandle<T> *> >::iterator iterator;
- typedef intptr_t (*MEM_CacheLimiter_DataSize_Func) (void *data);
- MEM_CacheLimiter(MEM_CacheLimiter_DataSize_Func getDataSize_)
- : getDataSize(getDataSize_) {
- }
~MEM_CacheLimiter() {
for (iterator it = queue.begin(); it != queue.end(); it++) {
delete *it;
@@ -147,36 +143,17 @@ public:
}
void enforce_limits() {
intptr_t max = MEM_CacheLimiter_get_maximum();
- intptr_t mem_in_use, cur_size;
+ intptr_t mem_in_use= MEM_get_memory_in_use();
+ intptr_t mmap_in_use= MEM_get_mapped_memory_in_use();
if (max == 0) {
return;
}
-
- if(getDataSize) {
- mem_in_use = total_size();
- } else {
- mem_in_use = MEM_get_memory_in_use();
- }
-
for (iterator it = queue.begin();
- it != queue.end() && mem_in_use > max;) {
+ it != queue.end() && mem_in_use + mmap_in_use > max;) {
iterator jt = it;
++it;
-
- if(getDataSize) {
- cur_size= getDataSize((*jt)->get()->get_data());
- } else {
- cur_size= mem_in_use;
- }
-
(*jt)->destroy_if_possible();
-
- if(getDataSize) {
- mem_in_use-= cur_size;
- } else {
- mem_in_use-= cur_size - MEM_get_memory_in_use();
- }
}
}
void touch(MEM_CacheLimiterHandle<T> * handle) {
@@ -187,17 +164,8 @@ public:
handle->me = it;
}
private:
- intptr_t total_size() {
- intptr_t size = 0;
- for (iterator it = queue.begin(); it != queue.end(); it++) {
- size+= getDataSize((*it)->get()->get_data());
- }
- return size;
- }
-
std::list<MEM_CacheLimiterHandle<T>*,
MEM_Allocator<MEM_CacheLimiterHandle<T> *> > queue;
- MEM_CacheLimiter_DataSize_Func getDataSize;
};
#endif // MEM_CACHELIMITER_H
diff --git a/intern/memutil/MEM_CacheLimiterC-Api.h b/intern/memutil/MEM_CacheLimiterC-Api.h
index 768842caee6..72645b9ce7b 100644
--- a/intern/memutil/MEM_CacheLimiterC-Api.h
+++ b/intern/memutil/MEM_CacheLimiterC-Api.h
@@ -41,9 +41,6 @@ typedef struct MEM_CacheLimiterHandle_s MEM_CacheLimiterHandleC;
/* function used to remove data from memory */
typedef void(*MEM_CacheLimiter_Destruct_Func)(void*);
-/* function used to measure stored data element size */
-typedef intptr_t(*MEM_CacheLimiter_DataSize_Func) (void*);
-
#ifndef MEM_CACHELIMITER_H
extern void MEM_CacheLimiter_set_maximum(int m);
extern int MEM_CacheLimiter_get_maximum(void);
@@ -57,8 +54,7 @@ extern int MEM_CacheLimiter_get_maximum(void);
*/
extern MEM_CacheLimiterC * new_MEM_CacheLimiter(
- MEM_CacheLimiter_Destruct_Func data_destructor,
- MEM_CacheLimiter_DataSize_Func data_size);
+ MEM_CacheLimiter_Destruct_Func data_destructor);
/**
* Delete MEM_CacheLimiter
diff --git a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
index cc8d2497f37..1bc011a5be0 100644
--- a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
+++ b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
@@ -54,8 +54,8 @@ typedef std::list<MEM_CacheLimiterHandleCClass*,
class MEM_CacheLimiterCClass {
public:
- MEM_CacheLimiterCClass(MEM_CacheLimiter_Destruct_Func data_destructor_, MEM_CacheLimiter_DataSize_Func data_size)
- : data_destructor(data_destructor_), cache(data_size) {
+ MEM_CacheLimiterCClass(MEM_CacheLimiter_Destruct_Func data_destructor_)
+ : data_destructor(data_destructor_) {
}
~MEM_CacheLimiterCClass();
@@ -142,12 +142,10 @@ static inline handle_t* cast(MEM_CacheLimiterHandleC * l)
}
MEM_CacheLimiterC * new_MEM_CacheLimiter(
- MEM_CacheLimiter_Destruct_Func data_destructor,
- MEM_CacheLimiter_DataSize_Func data_size)
+ MEM_CacheLimiter_Destruct_Func data_destructor)
{
return (MEM_CacheLimiterC*) new MEM_CacheLimiterCClass(
- data_destructor,
- data_size);
+ data_destructor);
}
void delete_MEM_CacheLimiter(MEM_CacheLimiterC * This)
diff --git a/intern/moto/CMakeLists.txt b/intern/moto/CMakeLists.txt
index 8075c66b847..bc965e20418 100644
--- a/intern/moto/CMakeLists.txt
+++ b/intern/moto/CMakeLists.txt
@@ -68,16 +68,6 @@ set(SRC
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
- include/MT_Vector2.inl
- include/MT_Vector3.inl
- include/MT_Vector4.inl
)
blender_add_lib(bf_intern_moto "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/opennl/CMakeLists.txt b/intern/opennl/CMakeLists.txt
index f146a96928e..b0c236911a3 100644
--- a/intern/opennl/CMakeLists.txt
+++ b/intern/opennl/CMakeLists.txt
@@ -40,7 +40,6 @@ add_definitions(
set(INC
extern
superlu
- ../../extern/colamd/Include
)
set(INC_SYS
@@ -49,6 +48,7 @@ set(INC_SYS
set(SRC
intern/opennl.c
+ superlu/colamd.c
superlu/get_perm_c.c
superlu/heap_relax_snode.c
superlu/lsame.c
@@ -83,6 +83,7 @@ set(SRC
extern/ONL_opennl.h
superlu/superlu_sys_types.h
superlu/Cnames.h
+ superlu/colamd.h
superlu/ssp_defs.h
superlu/supermatrix.h
superlu/util.h
diff --git a/intern/opennl/SConscript b/intern/opennl/SConscript
index 502df1891d5..ff66b4ad6e1 100644
--- a/intern/opennl/SConscript
+++ b/intern/opennl/SConscript
@@ -3,7 +3,7 @@ Import ('env')
sources = env.Glob('intern/*.c') + env.Glob('superlu/*.c')
-incs = 'extern superlu ../../extern/colamd/Include'
+incs = 'extern superlu'
if (env['OURPLATFORM'] == 'win32-mingw'):
env.BlenderLib ('bf_intern_opennl', sources, Split(incs), [], libtype=['core','intern'], priority=[1,80] )
diff --git a/intern/opennl/extern/ONL_opennl.h b/intern/opennl/extern/ONL_opennl.h
index 721da202c13..7f25a7c4237 100644
--- a/intern/opennl/extern/ONL_opennl.h
+++ b/intern/opennl/extern/ONL_opennl.h
@@ -2,6 +2,8 @@
* \ingroup opennlextern
*/
/*
+ * $Id$
+ *
* OpenNL: Numerical Library
* Copyright (C) 2004 Bruno Levy
*
diff --git a/intern/opennl/intern/opennl.c b/intern/opennl/intern/opennl.c
index c3fb7135fcb..a9172fb1d2c 100644
--- a/intern/opennl/intern/opennl.c
+++ b/intern/opennl/intern/opennl.c
@@ -2,6 +2,7 @@
* \ingroup opennlintern
*/
/*
+ * $Id$
*
* OpenNL: Numerical Library
* Copyright (C) 2004 Bruno Levy
diff --git a/intern/opennl/superlu/colamd.c b/intern/opennl/superlu/colamd.c
new file mode 100644
index 00000000000..51f5ed4c659
--- /dev/null
+++ b/intern/opennl/superlu/colamd.c
@@ -0,0 +1,2586 @@
+/** \file opennl/superlu/colamd.c
+ * \ingroup opennl
+ */
+/* ========================================================================== */
+/* === colamd - a sparse matrix column ordering algorithm =================== */
+/* ========================================================================== */
+
+/*
+ colamd: An approximate minimum degree column ordering algorithm.
+
+ 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 user-contributed software for Matlab 5.2,
+ available from MathWorks, Inc. (http://www.mathworks.com). This
+ routine can be used in place of COLMMD in Matlab. By default, the \
+ and / operators in Matlab perform a column ordering (using COLMMD)
+ prior to LU factorization using sparse partial pivoting, in the
+ built-in Matlab LU(A) routine.
+
+ Authors:
+
+ The authors of the code itself are Stefan I. Larimore and Timothy A.
+ Davis (davis@cise.ufl.edu), University of Florida. The algorithm was
+ developed in collaboration with John Gilbert, Xerox PARC, and Esmond
+ Ng, Oak Ridge National Laboratory.
+
+ Date:
+
+ August 3, 1998. Version 1.0.
+
+ Acknowledgements:
+
+ This work was supported by the National Science Foundation, under
+ grants DMS-9504974 and DMS-9803599.
+
+ Notice:
+
+ Copyright (c) 1998 by the University of Florida. 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 or copy this program for any
+ purpose, provided the above notices are retained on all copies.
+ User documentation of any code that uses this code must cite the
+ Authors, the Copyright, and "Used by permission." If this code is
+ accessible from within Matlab, then typing "help colamd" or "colamd"
+ (with no arguments) must cite the Authors. Permission to modify the
+ code and to distribute modified code is granted, provided the above
+ notices are retained, and a notice that the code was modified is
+ included with the above copyright notice. You must also retain the
+ Availability information below, of the original version.
+
+ This software is provided free of charge.
+
+ Availability:
+
+ This file is located at
+
+ http://www.cise.ufl.edu/~davis/colamd/colamd.c
+
+ The colamd.h file is required, located in the same directory.
+ The colamdmex.c file provides a Matlab interface for colamd.
+ The symamdmex.c file provides a Matlab interface for symamd, which is
+ a symmetric ordering based on this code, colamd.c. All codes are
+ purely ANSI C compliant (they use no Unix-specific routines, include
+ files, etc.).
+*/
+
+/* ========================================================================== */
+/* === Description of user-callable routines ================================ */
+/* ========================================================================== */
+
+/*
+ Each user-callable routine (declared as PUBLIC) is briefly described below.
+ Refer to the comments preceding each routine for more details.
+
+ ----------------------------------------------------------------------------
+ colamd_recommended:
+ ----------------------------------------------------------------------------
+
+ Usage:
+
+ Alen = colamd_recommended (nnz, n_row, n_col) ;
+
+ Purpose:
+
+ Returns recommended value of Alen for use by colamd. Returns -1
+ if any input argument is negative.
+
+ 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:
+ ----------------------------------------------------------------------------
+
+ Usage:
+
+ colamd_set_defaults (knobs) ;
+
+ Purpose:
+
+ Sets the default parameters.
+
+ Arguments:
+
+ double knobs [COLAMD_KNOBS] ; Output only.
+
+ Rows with more than (knobs [COLAMD_DENSE_ROW] * n_col) entries
+ are removed prior to ordering. Columns with more than
+ (knobs [COLAMD_DENSE_COL] * n_row) entries are removed
+ prior to ordering, and placed last in the output column
+ ordering. Default values of these two knobs are both 0.5.
+ 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.
+
+ ----------------------------------------------------------------------------
+ colamd:
+ ----------------------------------------------------------------------------
+
+ Usage:
+
+ colamd (n_row, n_col, Alen, A, p, knobs) ;
+
+ 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.
+
+ Arguments:
+
+ int n_row ;
+
+ Number of rows in the matrix A.
+ Restriction: n_row >= 0.
+ Colamd returns FALSE if n_row is negative.
+
+ int n_col ;
+
+ Number of columns in the matrix A.
+ Restriction: n_col >= 0.
+ Colamd returns FALSE if n_col is negative.
+
+ int Alen ;
+
+ Restriction (see note):
+ Alen >= 2*nnz + 6*(n_col+1) + 4*(n_row+1) + n_col + COLAMD_STATS
+ Colamd returns FALSE if these conditions are not met.
+
+ Note: this restriction makes an modest assumption regarding
+ the size of the two typedef'd structures, below. We do,
+ however, guarantee that
+ Alen >= colamd_recommended (nnz, n_row, n_col)
+ will be sufficient.
+
+ int A [Alen] ; Input argument, stats 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 thus
+ undefined on output with the exception of a few statistics
+ about the ordering (A [0..COLAMD_STATS-1]):
+ A [0]: number of dense or empty rows ignored.
+ A [1]: number of dense or empty columns ignored (and ordered
+ last in the output permutation p)
+ A [2]: number of garbage collections performed.
+ A [3]: 0, if all row indices in each column were in sorted
+ order, and no duplicates were present.
+ 1, otherwise (in which case colamd had to do more work)
+ 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.
+ Future versions may return more statistics in A, but the usage
+ of these 4 entries in A will remain unchanged.
+
+ 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 only.
+
+ See colamd_set_defaults for a description. If the knobs array
+ is not present (that is, if a (double *) NULL pointer is passed
+ in its place), then the default values of the parameters are
+ used instead.
+
+*/
+
+
+/* ========================================================================== */
+/* === Include files ======================================================== */
+/* ========================================================================== */
+
+/* limits.h: the largest positive integer (INT_MAX) */
+#include <limits.h>
+
+/* colamd.h: knob array size, stats output size, and global prototypes */
+#include "colamd.h"
+
+/* ========================================================================== */
+/* === Scaffolding code definitions ======================================== */
+/* ========================================================================== */
+
+/* Ensure that debugging is turned off: */
+#ifndef NDEBUG
+#define NDEBUG
+#endif
+
+/* assert.h: the assert macro (no debugging if NDEBUG is defined) */
+#include <assert.h>
+
+/*
+ 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...
+
+ To enable debugging, comment out the "#define NDEBUG" above. 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).
+*/
+
+/* ========================================================================== */
+/* === Row and Column structures ============================================ */
+/* ========================================================================== */
+
+typedef struct ColInfo_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 ;
+
+} ColInfo ;
+
+typedef struct RowInfo_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 ;
+
+} RowInfo ;
+
+/* ========================================================================== */
+/* === Definitions ========================================================== */
+/* ========================================================================== */
+
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+#define ONES_COMPLEMENT(r) (-(r)-1)
+
+#define TRUE (1)
+#define FALSE (0)
+#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 ; }
+
+/* Routines are either PUBLIC (user-callable) or PRIVATE (not user-callable) */
+#define PUBLIC
+#define PRIVATE static
+
+/* ========================================================================== */
+/* === Prototypes of PRIVATE routines ======================================= */
+/* ========================================================================== */
+
+PRIVATE int init_rows_cols
+(
+ int n_row,
+ int n_col,
+ RowInfo Row [],
+ ColInfo Col [],
+ int A [],
+ int p []
+) ;
+
+PRIVATE void init_scoring
+(
+ int n_row,
+ int n_col,
+ RowInfo Row [],
+ ColInfo 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,
+ RowInfo Row [],
+ ColInfo Col [],
+ int A [],
+ int head [],
+ int n_col2,
+ int max_deg,
+ int pfree
+) ;
+
+PRIVATE void order_children
+(
+ int n_col,
+ ColInfo Col [],
+ int p []
+) ;
+
+PRIVATE void detect_super_cols
+(
+#ifndef NDEBUG
+ int n_col,
+ RowInfo Row [],
+#endif
+ ColInfo Col [],
+ int A [],
+ int head [],
+ int row_start,
+ int row_length
+) ;
+
+PRIVATE int garbage_collection
+(
+ int n_row,
+ int n_col,
+ RowInfo Row [],
+ ColInfo Col [],
+ int A [],
+ int *pfree
+) ;
+
+PRIVATE int clear_mark
+(
+ int n_row,
+ RowInfo Row []
+) ;
+
+/* ========================================================================== */
+/* === Debugging definitions ================================================ */
+/* ========================================================================== */
+
+#ifndef NDEBUG
+
+/* === With debugging ======================================================= */
+
+/* stdlib.h: for getenv and atoi, to get debugging level from environment */
+#include <stdlib.h>
+
+/* stdio.h: for printf (no printing if debugging is turned off) */
+#include <stdio.h>
+
+PRIVATE void debug_deg_lists
+(
+ int n_row,
+ int n_col,
+ RowInfo Row [],
+ ColInfo Col [],
+ int head [],
+ int min_score,
+ int should,
+ int max_deg
+) ;
+
+PRIVATE void debug_mark
+(
+ int n_row,
+ RowInfo Row [],
+ int tag_mark,
+ int max_mark
+) ;
+
+PRIVATE void debug_matrix
+(
+ int n_row,
+ int n_col,
+ RowInfo Row [],
+ ColInfo Col [],
+ int A []
+) ;
+
+PRIVATE void debug_structures
+(
+ int n_row,
+ int n_col,
+ RowInfo Row [],
+ ColInfo Col [],
+ int A [],
+ int n_col2
+) ;
+
+/* the following is the *ONLY* global variable in this file, and is only */
+/* present when debugging */
+
+PRIVATE int debug_colamd ; /* debug print level */
+
+#define DEBUG0(params) { (void) printf params ; }
+#define DEBUG1(params) { if (debug_colamd >= 1) (void) printf params ; }
+#define DEBUG2(params) { if (debug_colamd >= 2) (void) printf params ; }
+#define DEBUG3(params) { if (debug_colamd >= 3) (void) printf params ; }
+#define DEBUG4(params) { if (debug_colamd >= 4) (void) printf params ; }
+
+#else
+
+/* === No debugging ========================================================= */
+
+#define DEBUG0(params) ;
+#define DEBUG1(params) ;
+#define DEBUG2(params) ;
+#define DEBUG3(params) ;
+#define DEBUG4(params) ;
+
+#endif
+
+/* ========================================================================== */
+
+
+/* ========================================================================== */
+/* === 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.
+*/
+
+PUBLIC int 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 */
+)
+{
+ /* === Local variables ================================================== */
+
+ int minimum ; /* bare minimum requirements */
+ int recommended ; /* recommended value of Alen */
+
+ if (nnz < 0 || n_row < 0 || n_col < 0)
+ {
+ /* return -1 if any input argument is corrupted */
+ DEBUG0 (("colamd_recommended error!")) ;
+ DEBUG0 ((" nnz: %d, n_row: %d, n_col: %d\n", nnz, n_row, n_col)) ;
+ return (-1) ;
+ }
+
+ minimum =
+ 2 * (nnz) /* for A */
+ + (((n_col) + 1) * sizeof (ColInfo) / sizeof (int)) /* for Col */
+ + (((n_row) + 1) * sizeof (RowInfo) / sizeof (int)) /* for Row */
+ + n_col /* minimum elbow room to guarrantee success */
+ + COLAMD_STATS ; /* for output statistics */
+
+ /* recommended is equal to the minumum plus enough memory to keep the */
+ /* number garbage collections low */
+ recommended = minimum + nnz/5 ;
+
+ return (recommended) ;
+}
+
+
+/* ========================================================================== */
+/* === colamd_set_defaults ================================================== */
+/* ========================================================================== */
+
+/*
+ The colamd_set_defaults routine sets the default values of the user-
+ controllable parameters for colamd:
+
+ knobs [0] rows with knobs[0]*n_col entries or more are removed
+ prior to ordering.
+
+ knobs [1] columns with knobs[1]*n_row entries or more are removed
+ prior to ordering, and placed last in the column
+ permutation.
+
+ knobs [2..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] = 0.5 ; /* ignore rows over 50% dense */
+ knobs [COLAMD_DENSE_COL] = 0.5 ; /* ignore columns over 50% dense */
+}
+
+
+/* ========================================================================== */
+/* === 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.
+
+ On input, the nonzero patterns of the columns of A are stored in the
+ array A, in order 0 to n_col-1. A is held in 0-based form (rows in the
+ range 0 to n_row-1 and columns in the range 0 to n_col-1). Row indices
+ for column c are located in A [(p [c]) ... (p [c+1]-1)], where p [0] = 0,
+ and thus p [n_col] is the number of entries in A. The matrix is
+ destroyed on output. The row indices within each column do not have to
+ be sorted (from small to large row indices), and duplicate row indices
+ may be present. However, colamd will work a little faster if columns are
+ sorted and no duplicates are present. Matlab 5.2 always passes the matrix
+ with sorted columns, and no duplicates.
+
+ The integer array A is of size Alen. Alen must be at least of size
+ (where nnz is the number of entries in A):
+
+ nnz for the input column form of A
+ + nnz for a row form of A that colamd generates
+ + 6*(n_col+1) for a ColInfo Col [0..n_col] array
+ (this assumes sizeof (ColInfo) is 6 int's).
+ + 4*(n_row+1) for a RowInfo Row [0..n_row] array
+ (this assumes sizeof (RowInfo) is 4 int's).
+ + elbow_room must be at least n_col. We recommend at least
+ nnz/5 in addition to that. If sufficient,
+ changes in the elbow room affect the ordering
+ time only, not the ordering itself.
+ + COLAMD_STATS for the output statistics
+
+ Colamd returns FALSE is memory is insufficient, or TRUE otherwise.
+
+ On input, the caller must specify:
+
+ n_row the number of rows of A
+ n_col the number of columns of A
+ Alen the size of the array A
+ A [0 ... nnz-1] the row indices, where nnz = p [n_col]
+ A [nnz ... Alen-1] (need not be initialized by the user)
+ p [0 ... n_col] the column pointers, p [0] = 0, and p [n_col]
+ is the number of entries in A. Column c of A
+ is stored in A [p [c] ... p [c+1]-1].
+ knobs [0 ... 19] a set of parameters that control the behavior
+ of colamd. If knobs is a NULL pointer the
+ defaults are used. The user-callable
+ colamd_set_defaults routine sets the default
+ parameters. See that routine for a description
+ of the user-controllable parameters.
+
+ If the return value of Colamd is TRUE, then on output:
+
+ p [0 ... n_col-1] the column permutation. p [0] is the first
+ column index, and p [n_col-1] is the last.
+ That is, p [k] = j means that column j of A
+ is the kth column of AQ.
+
+ A is undefined on output (the matrix pattern is
+ destroyed), except for the following statistics:
+
+ A [0] the number of dense (or empty) rows ignored
+ A [1] the number of dense (or empty) columms. These
+ are ordered last, in their natural order.
+ A [2] the number of garbage collections performed.
+ If this is excessive, then you would have
+ gotten your results faster if Alen was larger.
+ A [3] 0, if all row indices in each column were in
+ sorted order and no duplicates were present.
+ 1, if there were unsorted or duplicate row
+ indices in the input. You would have gotten
+ your results faster if A [3] was returned as 0.
+
+ If the return value of Colamd is FALSE, then A and p are undefined on
+ output.
+*/
+
+PUBLIC int colamd /* returns TRUE if successful */
+(
+ /* === 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) */
+)
+{
+ /* === Local variables ================================================== */
+
+ int i ; /* loop index */
+ int nnz ; /* nonzeros in A */
+ int Row_size ; /* size of Row [], in integers */
+ int Col_size ; /* size of Col [], in integers */
+ int elbow_room ; /* remaining free space */
+ RowInfo *Row ; /* pointer into A of Row [0..n_row] array */
+ ColInfo *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 knobs array */
+ int init_result ; /* return code from initialization */
+
+#ifndef NDEBUG
+ debug_colamd = 0 ; /* no debug printing */
+ /* get "D" environment variable, which gives the debug printing level */
+ if (getenv ("D")) debug_colamd = atoi (getenv ("D")) ;
+ DEBUG0 (("debug version, D = %d (THIS WILL BE SLOOOOW!)\n", debug_colamd)) ;
+#endif
+
+ /* === Check the input arguments ======================================== */
+
+ if (n_row < 0 || n_col < 0 || !A || !p)
+ {
+ /* n_row and n_col must be non-negative, A and p must be present */
+ DEBUG0 (("colamd error! %d %d %d\n", n_row, n_col, Alen)) ;
+ return (FALSE) ;
+ }
+ nnz = p [n_col] ;
+ if (nnz < 0 || p [0] != 0)
+ {
+ /* nnz must be non-negative, and p [0] must be zero */
+ DEBUG0 (("colamd error! %d %d\n", nnz, p [0])) ;
+ return (FALSE) ;
+ }
+
+ /* === If no knobs, set default parameters ============================== */
+
+ if (!knobs)
+ {
+ knobs = default_knobs ;
+ colamd_set_defaults (knobs) ;
+ }
+
+ /* === Allocate the Row and Col arrays from array A ===================== */
+
+ Col_size = (n_col + 1) * sizeof (ColInfo) / sizeof (int) ;
+ Row_size = (n_row + 1) * sizeof (RowInfo) / sizeof (int) ;
+ elbow_room = Alen - (2*nnz + Col_size + Row_size) ;
+ if (elbow_room < n_col + COLAMD_STATS)
+ {
+ /* not enough space in array A to perform the ordering */
+ DEBUG0 (("colamd error! elbow_room %d, %d\n", elbow_room,n_col)) ;
+ return (FALSE) ;
+ }
+ Alen = 2*nnz + elbow_room ;
+ Col = (ColInfo *) &A [Alen] ;
+ Row = (RowInfo *) &A [Alen + Col_size] ;
+
+ /* === Construct the row and column data structures ===================== */
+
+ init_result = init_rows_cols (n_row, n_col, Row, Col, A, p) ;
+ if (init_result == -1)
+ {
+ /* input matrix is invalid */
+ DEBUG0 (("colamd error! 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) ;
+
+ /* === Order the non-principal columns ================================== */
+
+ order_children (n_col, Col, p) ;
+
+ /* === Return statistics in A =========================================== */
+
+ for (i = 0 ; i < COLAMD_STATS ; i++)
+ {
+ A [i] = 0 ;
+ }
+ A [COLAMD_DENSE_ROW] = n_row - n_row2 ;
+ A [COLAMD_DENSE_COL] = n_col - n_col2 ;
+ A [COLAMD_DEFRAG_COUNT] = ngarbage ;
+ A [COLAMD_JUMBLED_COLS] = init_result ;
+
+ return (TRUE) ;
+}
+
+
+/* ========================================================================== */
+/* === 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 -1 on error, 1 if columns jumbled,
+ or 0 if columns not jumbled. Not user-callable.
+*/
+
+PRIVATE int init_rows_cols /* returns status code */
+(
+ /* === Parameters ======================================================= */
+
+ int n_row, /* number of rows of A */
+ int n_col, /* number of columns of A */
+ RowInfo Row [], /* of size n_row+1 */
+ ColInfo 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 */
+)
+{
+ /* === 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_start ; /* start index of previous column in A */
+ int start ; /* start index of column in A */
+ int last_row ; /* previous row */
+ int jumbled_columns ; /* indicates if columns are jumbled */
+
+ /* === Initialize columns, and check column pointers ==================== */
+
+ last_start = 0 ;
+ for (col = 0 ; col < n_col ; col++)
+ {
+ start = p [col] ;
+ if (start < last_start)
+ {
+ /* column pointers must be non-decreasing */
+ DEBUG0 (("colamd error! last p %d p [col] %d\n",last_start,start));
+ return (-1) ;
+ }
+ Col [col].start = start ;
+ Col [col].length = p [col+1] - start ;
+ Col [col].shared1.thickness = 1 ;
+ Col [col].shared2.score = 0 ;
+ Col [col].shared3.prev = EMPTY ;
+ Col [col].shared4.degree_next = EMPTY ;
+ last_start = start ;
+ }
+ /* must check the end pointer for last column */
+ if (p [n_col] < last_start)
+ {
+ /* column pointers must be non-decreasing */
+ DEBUG0 (("colamd error! last p %d p [n_col] %d\n",p[col],last_start)) ;
+ return (-1) ;
+ }
+
+ /* p [0..n_col] no longer needed, used as "head" in subsequent routines */
+
+ /* === Scan columns, compute row degrees, and check row indices ========= */
+
+ jumbled_columns = FALSE ;
+
+ 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)
+ {
+ DEBUG0 (("colamd error! col %d row %d last_row %d\n",
+ col, row, last_row)) ;
+ return (-1) ;
+ }
+ else if (row <= last_row)
+ {
+ /* row indices are not sorted or repeated, thus cols */
+ /* are jumbled */
+ jumbled_columns = TRUE ;
+ }
+ /* prevent repeated row from being counted */
+ if (Row [row].shared2.mark != col)
+ {
+ Row [row].length++ ;
+ Row [row].shared2.mark = col ;
+ last_row = row ;
+ }
+ else
+ {
+ /* this is a repeated entry in the column, */
+ /* it will be removed */
+ Col [col].length-- ;
+ }
+ }
+ }
+
+ /* === 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 (jumbled_columns)
+ {
+ /* 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 (jumbled_columns)
+ {
+
+#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
+
+ /* === 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 ;
+ }
+ }
+ return (1) ;
+ }
+ else
+ {
+ /* no columns jumbled (this is faster) */
+ return (0) ;
+ }
+}
+
+
+/* ========================================================================== */
+/* === 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 */
+ RowInfo Row [], /* of size n_row+1 */
+ ColInfo 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 (# entries) 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
+
+ /* === Extract knobs ==================================================== */
+
+ dense_row_count = MAX (0, MIN (knobs [COLAMD_DENSE_ROW] * n_col, n_col)) ;
+ dense_col_count = MAX (0, MIN (knobs [COLAMD_DENSE_COL] * n_row, n_row)) ;
+ DEBUG0 (("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, 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) ;
+ }
+ }
+ DEBUG0 (("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) ;
+ }
+ }
+ DEBUG0 (("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) ;
+ }
+ }
+ DEBUG0 (("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) */
+ DEBUG0 (("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 ;
+ }
+ }
+ DEBUG0 (("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
+
+ /* === Initialize degree lists ========================================== */
+
+#ifndef NDEBUG
+ debug_count = 0 ;
+#endif
+
+ /* 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
+ }
+ }
+
+#ifndef NDEBUG
+ DEBUG0 (("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
+
+ /* === 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 + elbow_room or larger */
+ RowInfo Row [], /* of size n_row+1 */
+ ColInfo 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) */
+)
+{
+ /* === 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 ; /* # of columns in pivot row */
+ int pivot_row_length ; /* # 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" (# 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
+
+ /* === Initialization and clear mark ==================================== */
+
+ max_mark = INT_MAX - n_col ; /* INT_MAX defined in <limits.h> */
+ tag_mark = clear_mark (n_row, Row) ;
+ min_score = 0 ;
+ ngarbage = 0 ;
+ DEBUG0 (("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)
+ {
+ DEBUG0 (("\n... Step k: %d out of n_col2: %d\n", k, n_col2)) ;
+ }
+ else
+ {
+ DEBUG1 (("\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
+
+ /* === 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
+
+ /* 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)) ;
+ DEBUG3 (("Pivot col: %d\n", 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) ;
+
+ /* === 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 (n_row, Row) ;
+#ifndef NDEBUG
+ debug_matrix (n_row, n_col, Row, Col, A) ;
+#endif
+ }
+
+ /* === 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_DEAD (row))
+ {
+ continue ;
+ }
+ 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
+
+ /* === 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++ ;
+ DEBUG2 (("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] ;
+ DEBUG2 (("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 ====================================== */
+
+ DEBUG1 (("** Computing set differences phase. **\n")) ;
+
+ /* pivot row is currently dead - it will be revived later. */
+
+ DEBUG2 (("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) ;
+ DEBUG2 (("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)
+ {
+ DEBUG1 (("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
+
+ /* === Add up set differences for each column ======================= */
+
+ DEBUG1 (("** 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 ;
+
+ DEBUG2 (("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))
+ {
+ continue ;
+ }
+ 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)
+ {
+ DEBUG1 (("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 ==================== */
+
+ DEBUG2 (("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 ;
+
+ DEBUG2 ((" Hash = %d, n_col = %d.\n", hash, n_col)) ;
+ assert (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 ======================================== */
+
+ DEBUG1 (("** Supercolumn detection phase. **\n")) ;
+
+ detect_super_cols (
+#ifndef NDEBUG
+ n_col, Row,
+#endif
+ Col, A, head, pivot_row_start, pivot_row_length) ;
+
+ /* === Kill the pivotal column ====================================== */
+
+ KILL_PRINCIPAL_COL (pivot_col) ;
+
+ /* === Clear mark =================================================== */
+
+ tag_mark += (max_deg + 1) ;
+ if (tag_mark >= max_mark)
+ {
+ DEBUG1 (("clearing tag_mark\n")) ;
+ tag_mark = clear_mark (n_row, Row) ;
+ }
+#ifndef NDEBUG
+ DEBUG3 (("check3\n")) ;
+ debug_mark (n_row, Row, tag_mark, max_mark) ;
+#endif
+
+ /* === Finalize the new pivot row, and column scores ================ */
+
+ DEBUG1 (("** 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
+
+ /* === 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]) ;
+ Row [pivot_row].shared1.degree = pivot_row_degree ;
+ Row [pivot_row].shared2.mark = 0 ;
+ /* pivot row is no longer dead */
+ }
+ }
+
+ /* === 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 */
+ ColInfo 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 */
+ RowInfo Row [], /* of size n_row+1 */
+#endif
+ ColInfo 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 # 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 */
+ RowInfo Row [], /* row info */
+ ColInfo 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 ;
+ DEBUG0 (("Defrag..\n")) ;
+ for (psrc = &A[0] ; psrc < pfree ; psrc++) assert (*psrc >= 0) ;
+ debug_rows = 0 ;
+#endif
+
+ /* === 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_ALIVE (r))
+ {
+ if (Row [r].length == 0)
+ {
+ /* this row is of zero length. cannot compact it, so kill it */
+ DEBUG0 (("Defrag row kill\n")) ;
+ 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
+ }
+ }
+ }
+
+ /* === 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)) ;
+
+ /* 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]) ;
+#ifndef NDEBUG
+ debug_rows-- ;
+#endif
+ }
+ }
+ /* 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 n_row, /* number of rows in A */
+ RowInfo Row [] /* Row [0 ... n_row-1].shared2.mark is set to zero */
+)
+{
+ /* === Local variables ================================================== */
+
+ int r ;
+
+ DEBUG0 (("Clear mark\n")) ;
+ for (r = 0 ; r < n_row ; r++)
+ {
+ if (ROW_IS_ALIVE (r))
+ {
+ Row [r].shared2.mark = 0 ;
+ }
+ }
+ return (1) ;
+}
+
+
+/* ========================================================================== */
+/* === 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,
+ RowInfo Row [],
+ ColInfo 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,
+ RowInfo Row [],
+ ColInfo 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 && debug_colamd <= 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 && debug_colamd <= 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,
+ RowInfo 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 && debug_colamd <= 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,
+ RowInfo Row [],
+ ColInfo 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 (debug_colamd < 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++ ;
+ DEBUG3 ((" %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++ ;
+ DEBUG3 ((" %d row %d\n", ROW_IS_ALIVE (r), r)) ;
+ }
+ }
+}
+
+#endif
+
diff --git a/intern/opennl/superlu/colamd.h b/intern/opennl/superlu/colamd.h
new file mode 100644
index 00000000000..00f670ce01f
--- /dev/null
+++ b/intern/opennl/superlu/colamd.h
@@ -0,0 +1,70 @@
+/** \file opennl/superlu/colamd.h
+ * \ingroup opennl
+ */
+/* ========================================================================== */
+/* === colamd prototypes and definitions ==================================== */
+/* ========================================================================== */
+
+/*
+ This is the colamd include file,
+
+ http://www.cise.ufl.edu/~davis/colamd/colamd.h
+
+ for use in the colamd.c, colamdmex.c, and symamdmex.c files located at
+
+ http://www.cise.ufl.edu/~davis/colamd/
+
+ See those files for a description of colamd and symamd, and for the
+ copyright notice, which also applies to this file.
+
+ August 3, 1998. Version 1.0.
+*/
+
+/* ========================================================================== */
+/* === Definitions ========================================================== */
+/* ========================================================================== */
+
+/* size of the knobs [ ] array. Only knobs [0..1] are currently used. */
+#define COLAMD_KNOBS 20
+
+/* number of output statistics. Only A [0..2] are currently used. */
+#define COLAMD_STATS 20
+
+/* knobs [0] and A [0]: dense row knob and output statistic. */
+#define COLAMD_DENSE_ROW 0
+
+/* knobs [1] and A [1]: dense column knob and output statistic. */
+#define COLAMD_DENSE_COL 1
+
+/* A [2]: memory defragmentation count output statistic */
+#define COLAMD_DEFRAG_COUNT 2
+
+/* A [3]: whether or not the input columns were jumbled or had duplicates */
+#define COLAMD_JUMBLED_COLS 3
+
+/* ========================================================================== */
+/* === Prototypes of user-callable routines ================================= */
+/* ========================================================================== */
+
+int colamd_recommended /* returns recommended value of Alen */
+(
+ int nnz, /* nonzeros in A */
+ int n_row, /* number of rows in A */
+ int 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 */
+) ;
+
+int colamd /* returns TRUE if successful, FALSE 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 */
+) ;
+
diff --git a/intern/opennl/superlu/get_perm_c.c b/intern/opennl/superlu/get_perm_c.c
index 2eb0aea678e..c08d79af81a 100644
--- a/intern/opennl/superlu/get_perm_c.c
+++ b/intern/opennl/superlu/get_perm_c.c
@@ -27,7 +27,6 @@ get_colamd(
{
int Alen, *A, i, info, *p;
double *knobs;
- int stats[COLAMD_STATS];
Alen = colamd_recommended(nnz, m, n);
@@ -41,7 +40,7 @@ get_colamd(
ABORT("Malloc fails for p[]");
for (i = 0; i <= n; ++i) p[i] = colptr[i];
for (i = 0; i < nnz; ++i) A[i] = rowind[i];
- info = colamd(m, n, Alen, A, p, knobs, stats);
+ info = colamd(m, n, Alen, A, p, knobs);
if ( info == FALSE ) ABORT("COLAMD failed");
for (i = 0; i < n; ++i) perm_c[p[i]] = i;
diff --git a/intern/smoke/CMakeLists.txt b/intern/smoke/CMakeLists.txt
index 9524f7b2935..6e1d3eb0ab4 100644
--- a/intern/smoke/CMakeLists.txt
+++ b/intern/smoke/CMakeLists.txt
@@ -1,3 +1,4 @@
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/po/check_po.py b/po/check_po.py
index a2b19d57428..a402c2b592c 100755
--- a/po/check_po.py
+++ b/po/check_po.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/po/clean_po.py b/po/clean_po.py
index 95bac39b42e..685ec585ffd 100755
--- a/po/clean_po.py
+++ b/po/clean_po.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/po/merge_po.py b/po/merge_po.py
index dcbe9fc9890..b0b29a3ac8e 100755
--- a/po/merge_po.py
+++ b/po/merge_po.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/po/update_mo.py b/po/update_mo.py
index 50e99c7eeaa..a0173b2d059 100755
--- a/po/update_mo.py
+++ b/po/update_mo.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/po/update_msg.py b/po/update_msg.py
index 21d727922d4..7cc7ee50b63 100644
--- a/po/update_msg.py
+++ b/po/update_msg.py
@@ -1,3 +1,4 @@
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/po/update_po.py b/po/update_po.py
index 0aab8c75646..3dcaa9d8f1b 100755
--- a/po/update_po.py
+++ b/po/update_po.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/po/update_pot.py b/po/update_pot.py
index c5f9acb9f42..4e202026444 100755
--- a/po/update_pot.py
+++ b/po/update_pot.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/release/bin/blender-softwaregl b/release/bin/blender-softwaregl
deleted file mode 100755
index 3cd96d2ff34..00000000000
--- a/release/bin/blender-softwaregl
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/sh
-BF_DIST_BIN=`dirname "$0"`
-BF_PROGRAM="blender" # BF_PROGRAM=`basename "$0"`-bin
-exitcode=0
-
-LD_LIBRARY_PATH=${BF_DIST_BIN}/lib:${LD_LIBRARY_PATH}
-
-if [ -n "$LD_LIBRARYN32_PATH" ]; then
- LD_LIBRARYN32_PATH=${BF_DIST_BIN}/lib:${LD_LIBRARYN32_PATH}
-fi
-if [ -n "$LD_LIBRARYN64_PATH" ]; then
- LD_LIBRARYN64_PATH=${BF_DIST_BIN}/lib:${LD_LIBRARYN64_PATH}
-fi
-if [ -n "$LD_LIBRARY_PATH_64" ]; then
- LD_LIBRARY_PATH_64=${BF_DIST_BIN}/lib:${LD_LIBRARY_PATH_64}
-fi
-
-export LD_LIBRARY_PATH LD_LIBRARYN32_PATH LD_LIBRARYN64_PATH LD_LIBRARY_PATH_64 LD_PRELOAD
-
-"$BF_DIST_BIN/$BF_PROGRAM" ${1+"$@"}
-exitcode=$?
-exit $exitcode
diff --git a/release/datafiles/LICENSE-bfont.ttf.txt b/release/datafiles/LICENSE-bfont.ttf.txt
index 4aa22365c83..754089661b0 100644
--- a/release/datafiles/LICENSE-bfont.ttf.txt
+++ b/release/datafiles/LICENSE-bfont.ttf.txt
@@ -98,3 +98,4 @@ dealings in this Font Software without prior written authorization
from Tavmjong Bah. For further information, contact: tavmjong @ free
. fr.
+$Id$
diff --git a/release/plugins/Makefile b/release/plugins/Makefile
index 353e559e622..ee7086b331d 100644
--- a/release/plugins/Makefile
+++ b/release/plugins/Makefile
@@ -1,3 +1,6 @@
+#
+# $Id$
+#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/release/plugins/bmake b/release/plugins/bmake
index e2f9e9cc596..9740bfa716a 100644
--- a/release/plugins/bmake
+++ b/release/plugins/bmake
@@ -1,5 +1,7 @@
#!/bin/sh
#
+# $Id$
+#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/release/plugins/sequence/Makefile b/release/plugins/sequence/Makefile
deleted file mode 100644
index 2b12e62d24a..00000000000
--- a/release/plugins/sequence/Makefile
+++ /dev/null
@@ -1,32 +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 *****
-
-all: plugins
-
-plugins:
- @/bin/sh -c 'for i in *.c; do ../bmake $$i; done;'
-
-clean:
- rm -rf *.o *.so
diff --git a/release/plugins/sequence/blur.c b/release/plugins/sequence/blur.c
index e95c243b558..cec3351e976 100644
--- a/release/plugins/sequence/blur.c
+++ b/release/plugins/sequence/blur.c
@@ -1,4 +1,5 @@
/**
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/release/plugins/sequence/scatter.c b/release/plugins/sequence/scatter.c
index 73e97e165ca..4741b33ce0e 100644
--- a/release/plugins/sequence/scatter.c
+++ b/release/plugins/sequence/scatter.c
@@ -1,4 +1,5 @@
/**
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/release/plugins/texture/Makefile b/release/plugins/texture/Makefile
index 2b12e62d24a..ab847adf5fe 100644
--- a/release/plugins/texture/Makefile
+++ b/release/plugins/texture/Makefile
@@ -1,3 +1,6 @@
+#
+# $Id$
+#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
diff --git a/release/plugins/texture/clouds2.c b/release/plugins/texture/clouds2.c
index 454e8e28206..d38913951c3 100644
--- a/release/plugins/texture/clouds2.c
+++ b/release/plugins/texture/clouds2.c
@@ -1,4 +1,5 @@
/**
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/release/plugins/texture/tiles.c b/release/plugins/texture/tiles.c
index c7af6e58fa4..3b533d456b4 100644
--- a/release/plugins/texture/tiles.c
+++ b/release/plugins/texture/tiles.c
@@ -1,4 +1,5 @@
/**
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 088e239e9a5..bb1e9988ec2 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -202,7 +202,7 @@ class _GenericBone:
@property
def center(self):
"""The midpoint between the head and the tail."""
- return (self.head + self.tail) * 0.5
+ return self.head.lerp(self.tail, 0.5)
@property
def length(self):
@@ -373,7 +373,8 @@ class Mesh(bpy_types.ID):
"""
self.vertices.add(len(vertices))
self.edges.add(len(edges))
- self.faces.add(len(faces))
+ self.loops.add(sum((len(f) for f in faces)))
+ self.polygons.add(len(faces))
vertices_flat = [f for v in vertices for f in v]
self.vertices.foreach_set("co", vertices_flat)
@@ -383,19 +384,15 @@ class Mesh(bpy_types.ID):
self.edges.foreach_set("vertices", edges_flat)
del edges_flat
- def treat_face(f):
- if len(f) == 3:
- if f[2] == 0:
- return f[2], f[0], f[1], 0
- else:
- return f[0], f[1], f[2], 0
- elif f[2] == 0 or f[3] == 0:
- return f[2], f[3], f[0], f[1]
- return f
-
- faces_flat = [v for f in faces for v in treat_face(f)]
- self.faces.foreach_set("vertices_raw", faces_flat)
- del faces_flat
+ # this is different in bmesh
+ loop_index = 0
+ for i, p in enumerate(self.polygons):
+ f = faces[i]
+ loop_len = len(f)
+ p.loop_start = loop_index
+ p.loop_total = loop_len
+ p.vertices = f
+ loop_index += loop_len
@property
def edge_keys(self):
@@ -639,7 +636,7 @@ class _GenericUI:
draw_funcs = cls._dyn_ui_initialize()
try:
draw_funcs.remove(draw_func)
- except:
+ except ValueError:
pass
diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py
index 87f4791ec51..176266704eb 100644
--- a/release/scripts/presets/keyconfig/maya.py
+++ b/release/scripts/presets/keyconfig/maya.py
@@ -344,9 +344,7 @@ kmi = km.keymap_items.new('mesh.split', 'Y', 'PRESS')
kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', ctrl=True)
kmi = km.keymap_items.new('mesh.delete', 'X', 'PRESS')
kmi = km.keymap_items.new('mesh.delete', 'DEL', 'PRESS')
-kmi = km.keymap_items.new('mesh.knife_cut', 'LEFTMOUSE', 'PRESS', key_modifier='K')
-kmi = km.keymap_items.new('mesh.knife_cut', 'LEFTMOUSE', 'PRESS', shift=True, key_modifier='K')
-kmi.properties.type = 'MIDPOINTS'
+kmi = km.keymap_items.new('mesh.knifetool', 'K', 'PRESS')
kmi = km.keymap_items.new('object.vertex_parent_set', 'P', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('wm.call_menu', 'W', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_specials'
diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
index 66d0d72efc1..1248fc24ed7 100644
--- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py
+++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
@@ -1105,8 +1105,8 @@ from bpy.props import FloatProperty
class SmartProject(Operator):
- '''This script projection unwraps the selected faces of a mesh ''' \
- '''(it operates on all selected mesh objects, and can be used to unwrap selected faces, or all faces)'''
+ '''This script projection unwraps the selected faces of a mesh. ''' \
+ '''it operates on all selected mesh objects, and can be used unwrap selected faces, or all faces'''
bl_idname = "uv.smart_project"
bl_label = "Smart UV Project"
bl_options = {'REGISTER', 'UNDO'}
diff --git a/release/scripts/startup/bl_operators/vertexpaint_dirt.py b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
index ea58864f7c2..5fb5c7f39cf 100644
--- a/release/scripts/startup/bl_operators/vertexpaint_dirt.py
+++ b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
@@ -159,7 +159,7 @@ class VertexPaintDirt(Operator):
)
blur_iterations = IntProperty(
name="Blur Iterations",
- description="Number of times to blur the colors (higher blurs more)",
+ description="Number times to blur the colors (higher blurs more)",
min=0, max=40,
default=1,
)
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 1e469275e77..a539e2693c1 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -1179,31 +1179,7 @@ class WM_OT_copy_prev_settings(Operator):
return {'CANCELLED'}
-class WM_OT_blenderplayer_start(Operator):
- '''Launches the Blenderplayer with the current blendfile'''
- bl_idname = "wm.blenderplayer_start"
- bl_label = "Start"
-
- import os
- blender_bin_path = bpy.app.binary_path
- blender_bin_dir = os.path.dirname(blender_bin_path)
- ext = os.path.splitext(blender_bin_path)[-1]
- player_path = os.path.join(blender_bin_dir, 'blenderplayer' + ext)
-
- def execute(self, context):
- import sys
- import subprocess
- import os
-
- if sys.platform == 'darwin':
- self.player_path = os.path.join(self.blender_bin_dir, '../../../blenderplayer.app/Contents/MacOS/blenderplayer')
-
- filepath = bpy.app.tempdir + "game.blend"
- bpy.ops.wm.save_as_mainfile(filepath=filepath, check_existing=False, copy=True)
- subprocess.call([self.player_path, filepath])
- return {'FINISHED'}
-
class WM_OT_keyconfig_test(Operator):
"Test keyconfig for conflicts"
bl_idname = "wm.keyconfig_test"
@@ -1475,7 +1451,7 @@ class WM_OT_operator_cheat_sheet(Operator):
class WM_OT_addon_enable(Operator):
"Enable an addon"
bl_idname = "wm.addon_enable"
- bl_label = "Enable Addon"
+ bl_label = "Enable Add-On"
module = StringProperty(
name="Module",
@@ -1506,7 +1482,7 @@ class WM_OT_addon_enable(Operator):
class WM_OT_addon_disable(Operator):
"Disable an addon"
bl_idname = "wm.addon_disable"
- bl_label = "Disable Addon"
+ bl_label = "Disable Add-On"
module = StringProperty(
name="Module",
@@ -1523,7 +1499,7 @@ class WM_OT_addon_disable(Operator):
class WM_OT_addon_install(Operator):
"Install an addon"
bl_idname = "wm.addon_install"
- bl_label = "Install Addon..."
+ bl_label = "Install Add-On..."
overwrite = BoolProperty(
name="Overwrite",
@@ -1691,7 +1667,7 @@ class WM_OT_addon_install(Operator):
class WM_OT_addon_remove(Operator):
"Disable an addon"
bl_idname = "wm.addon_remove"
- bl_label = "Remove Addon"
+ bl_label = "Remove Add-On"
module = StringProperty(
name="Module",
@@ -1746,7 +1722,7 @@ class WM_OT_addon_remove(Operator):
class WM_OT_addon_expand(Operator):
- "Display more information on this addon"
+ "Display more information on this add-on"
bl_idname = "wm.addon_expand"
bl_label = ""
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index 682341cbf2f..2e54631afa3 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -110,7 +110,7 @@ def register():
WindowManager.addon_filter = EnumProperty(
items=addon_filter_items,
name="Category",
- description="Filter addons by category",
+ description="Filter add-ons by category",
)
WindowManager.addon_support = EnumProperty(
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index e4b152834fc..4456731523f 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -46,7 +46,11 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
# the mt.type enum is (ab)used for a lookup on function names
# ...to avoid lengthy if statements
# so each type must have a function here.
-
+
+ def NGONINTERP(self, layout, ob, md):
+ split = layout.split()
+ split.prop(md, "resolution")
+
def ARMATURE(self, layout, ob, md):
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index 2216d2b2170..0e7fccae8df 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -76,21 +76,15 @@ class ParticleButtonsPanel():
class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- # COMPAT_ENGINES = {'BLENDER_RENDER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
- return (context.particle_system or context.object or context.space_data.pin_id)# and (engine in cls.COMPAT_ENGINES)
+ return (context.particle_system or context.object or context.space_data.pin_id) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
-
- if context.scene.render.engine == "BLENDER_GAME":
- layout.label("The Blender particle system is")
- layout.label("not available for use in the")
- layout.label("Blender Game Engine")
- return
ob = context.object
psys = context.particle_system
@@ -151,7 +145,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
#row.label(text="Render")
if part.is_fluid:
- layout.label(text="{} fluid particles for this frame".format(str(part.count)))
+ layout.label(text=str(part.count) + " fluid particles for this frame")
return
row = col.row()
@@ -510,7 +504,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
col.label(text="Fluid properties:")
col.prop(fluid, "stiffness", text="Stiffness")
col.prop(fluid, "linear_viscosity", text="Viscosity")
- col.prop(fluid, "buoyancy", text="Buoyancy", slider=True)
+ col.prop(fluid, "buoyancy", text="Buoancy", slider=True)
col = split.column()
col.label(text="Advanced:")
@@ -1168,7 +1162,7 @@ class PARTICLE_PT_force_fields(ParticleButtonsPanel, Panel):
class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, Panel):
- bl_label = "Vertex Groups"
+ bl_label = "Vertexgroups"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index efb760c0b43..c25b42e298e 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -206,7 +206,7 @@ class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, Panel):
col = split.column()
if scene.use_gravity:
- col.label(text="Use Scene Gravity", icon="SCENE_DATA")
+ col.label(text="Using Scene Gravity", icon="SCENE_DATA")
sub = col.column()
sub.enabled = False
sub.prop(fluid, "gravity", text="")
@@ -215,7 +215,7 @@ class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, Panel):
col.prop(fluid, "gravity", text="")
if scene.unit_settings.system != 'NONE':
- col.label(text="Use Scene Size Units", icon="SCENE_DATA")
+ col.label(text="Using Scene Size Units", icon="SCENE_DATA")
sub = col.column()
sub.enabled = False
sub.prop(fluid, "simulation_scale", text="Metres")
diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py
index 2d22a398624..eaf88fbd295 100644
--- a/release/scripts/startup/bl_ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -170,6 +170,8 @@ class INFO_MT_file_export(Menu):
if hasattr(bpy.types, "WM_OT_collada_export"):
self.layout.operator("wm.collada_export", text="COLLADA (.dae)")
+ self.layout.operator("export_mesh.wavefront", text="Wavefront (.obj), BMesh")
+
class INFO_MT_file_external_data(Menu):
bl_label = "External Data"
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index c6c4a8f3335..96a08e57157 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -762,7 +762,7 @@ class USERPREF_MT_ndof_settings(Menu):
layout.prop(input_prefs, "ndof_show_guide")
layout.separator()
- layout.label(text="Orbit options")
+ layout.label(text="orbit options")
if input_prefs.view_rotate_method == 'TRACKBALL':
layout.prop(input_prefs, "ndof_roll_invert_axis")
layout.prop(input_prefs, "ndof_tilt_invert_axis")
@@ -771,13 +771,13 @@ class USERPREF_MT_ndof_settings(Menu):
layout.prop(input_prefs, "ndof_orbit_invert_axes")
layout.separator()
- layout.label(text="Pan options")
+ layout.label(text="pan options")
layout.prop(input_prefs, "ndof_panx_invert_axis")
layout.prop(input_prefs, "ndof_pany_invert_axis")
layout.prop(input_prefs, "ndof_panz_invert_axis")
layout.separator()
- layout.label(text="Fly options")
+ layout.label(text="fly options")
layout.prop(input_prefs, "ndof_fly_helicopter", icon='NDOF_FLY')
layout.prop(input_prefs, "ndof_lock_horizon", icon='NDOF_DOM')
@@ -966,7 +966,7 @@ class USERPREF_PT_addons(Panel):
if info["support"] not in support:
continue
- # check if addon should be visible with current filters
+ # check if add-on should be visible with current filters
if (filter == "All") or \
(filter == info["category"]) or \
(filter == "Enabled" and is_enabled) or \
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 1170bce2c14..802b97a48a8 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -521,11 +521,10 @@ class VIEW3D_MT_select_edit_mesh(Menu):
layout.separator()
- layout.operator("mesh.select_by_number_vertices", text="Triangles").type = 'TRIANGLES'
- layout.operator("mesh.select_by_number_vertices", text="Quads").type = 'QUADS'
+ layout.operator("mesh.select_by_number_vertices", text = "By Number of Verts")
if context.scene.tool_settings.mesh_select_mode[2] == False:
layout.operator("mesh.select_non_manifold", text="Non Manifold")
- layout.operator("mesh.select_by_number_vertices", text="Loose Verts/Edges").type = 'OTHER'
+ layout.operator("mesh.select_loose_verts", text = "Loose Verts/Edges")
layout.operator("mesh.select_similar", text="Similar")
layout.separator()
@@ -1497,7 +1496,9 @@ class VIEW3D_MT_edit_mesh_specials(Menu):
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("mesh.subdivide", text="Subdivide")
+ """
layout.operator("mesh.subdivide", text="Subdivide Smooth").smoothness = 1.0
+ """
layout.operator("mesh.merge", text="Merge...")
layout.operator("mesh.remove_doubles")
layout.operator("mesh.hide", text="Hide")
@@ -1505,7 +1506,7 @@ class VIEW3D_MT_edit_mesh_specials(Menu):
layout.operator("mesh.select_inverse")
layout.operator("mesh.flip_normals")
layout.operator("mesh.vertices_smooth", text="Smooth")
- # layout.operator("mesh.bevel", text="Bevel")
+ layout.operator("mesh.bevel", text="Bevel")
layout.operator("mesh.faces_shade_smooth")
layout.operator("mesh.faces_shade_flat")
layout.operator("mesh.blend_from_shape")
@@ -1627,6 +1628,10 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
layout.separator()
+ layout.operator("mesh.bridge_edge_loops", text="Bridge Two Edge Loops")
+
+ layout.separator()
+
layout.operator("TRANSFORM_OT_edge_slide")
layout.operator("TRANSFORM_OT_edge_crease")
layout.operator("mesh.loop_multi_select", text="Edge Loop")
diff --git a/release/text/readme.html b/release/text/readme.html
index 8c5ead49036..e0bef8a50e1 100644
--- a/release/text/readme.html
+++ b/release/text/readme.html
@@ -36,7 +36,7 @@
<p class="body"><b>Linux, FreeBSD, Solaris: </b>Unpack the archive, Then run the Blender executable.</p>
<p class="body"><b>Mac OS X: </b>The downloaded package includes blender.app. Optionally copy this to your Applications folder, and add it to the dock by dragging it from there to the dock.</p>
<p></p>
-<p class="body"><b>Installing Addons (all systems)</b> Addons can be installed from the user preferences addons section, download an addon as a .py or .zip file, then press the "Install Addon" button and select the file to install it.</p>
+<p class="body"><b>Installing Add-ons (all systems)</b> Add-ons can be installed from the user preferences addons section, download an addon as a .py or .zip file, then press the "Install Add-on" button and select the file to install it.</p>
<p><br></p>
<p class="header"><b>Getting Started</b></p>
<p class="body">When opening Blender, you’ll see large 3D view in the center, a Toolbar on the left, a Properties area and an Outliner area on the right and a Timeline at the bottom.</p>
diff --git a/release/windows/installer/00.sconsblender.nsi b/release/windows/installer/00.sconsblender.nsi
index eb9b6629108..eddd215c64d 100644
--- a/release/windows/installer/00.sconsblender.nsi
+++ b/release/windows/installer/00.sconsblender.nsi
@@ -1,4 +1,5 @@
;
+; $Id$
;
; Blender Self-Installer for Windows (NSIS - http://nsis.sourceforge.net)
;
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 934579b8a8a..5280d26cc3d 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -88,6 +88,7 @@ add_subdirectory(editors)
add_subdirectory(windowmanager)
add_subdirectory(blenkernel)
add_subdirectory(blenlib)
+add_subdirectory(bmesh)
add_subdirectory(render)
add_subdirectory(blenfont)
add_subdirectory(blenloader)
diff --git a/source/blender/SConscript b/source/blender/SConscript
index 969bd2966fc..e6cd6b09c20 100644
--- a/source/blender/SConscript
+++ b/source/blender/SConscript
@@ -3,6 +3,7 @@ Import ('env')
import sys
SConscript(['avi/SConscript',
+ 'bmesh/SConscript',
'blenkernel/SConscript',
'blenlib/SConscript',
'blenloader/SConscript',
diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c
index 9548febab27..79610f9c10b 100644
--- a/source/blender/blenfont/intern/blf_lang.c
+++ b/source/blender/blenfont/intern/blf_lang.c
@@ -94,7 +94,6 @@ static const char *locales[] = {
"korean", "ko_KR",
"nepali", "ne_NP",
"persian", "fa_PE",
- "indonesian", "id_ID"
};
void BLF_lang_init(void)
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 5e403849289..338fa63142d 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -28,21 +28,49 @@
#ifndef BKE_DERIVEDMESH_H
#define BKE_DERIVEDMESH_H
-/** \file BKE_DerivedMesh.h
- * \ingroup bke
- *
- * \todo
- * - Make drawMapped* functions take a predicate function that
- * determines whether to draw the edge (this predicate can
- * also set color, etc). This will be slightly more general
- * and allow some of the functions to be collapsed.
- * - Once accessor functions are added then single element draw
- * functions can be implemented using primitive accessors.
- * - Add function to dispatch to renderer instead of using
- * conversion to DLM.
+/*
+ Basic design of the DerivedMesh system:
+
+ DerivedMesh is a common set of interfaces for mesh systems.
+
+ There are three main mesh data structures in Blender: Mesh, CDDM, and BMesh.
+ These, and a few others, all implement DerivedMesh interfaces,
+ which contains unified drawing interfaces, a few utility interfaces,
+ and a bunch of read-only interfaces intended mostly for conversion from
+ one format to another.
+
+ All Mesh structures in blender make use of CustomData, which is used to store
+ per-element attributes and interpolate them (e.g. uvs, vcols, vgroups, etc).
+
+ Mesh is the "serialized" structure, used for storing object-mode mesh data
+ and also for saving stuff to disk. It's interfaces are also what DerivedMesh
+ uses to communicate with.
+
+ CDDM is a little mesh library, that uses Mesh data structures in the backend.
+ It's mostly used for modifiers, and has the advantages of not taking much
+ resources.
+
+ BMesh is a full-on brep, used for editmode, some modifiers, etc. It's much
+ more capable (if memory-intensive) then CDDM.
+
+ DerivedMesh is somewhat hackish. Many places assumes that a DerivedMesh is
+ a CDDM (most of the time by simply copying it and converting it to one).
+ CDDM is the original structure for modifiers, but has since been superseded
+ by BMesh, at least for the foreseeable future.
+*/
+
+/*
+ * Note: This sturcture is read-only, for all practical purposes.
+ * At some point in the future, we may want to consider
+ * creating a replacement structure that implements a proper
+ * abstract mesh kernel interface. Or, we can leave this
+ * as it is and stick with using BMesh and CDDM.
*/
+
#include "DNA_customdata_types.h"
+#include "DNA_meshdata_types.h"
+
#include "BKE_customdata.h"
#include "BKE_bvhutils.h"
@@ -53,20 +81,26 @@ struct MTFace;
struct Object;
struct Scene;
struct Mesh;
-struct EditMesh;
+struct BMEditMesh;
struct KeyBlock;
struct ModifierData;
struct MCol;
struct ColorBand;
struct GPUVertexAttribs;
struct GPUDrawObject;
+struct BMEditMesh;
struct ListBase;
struct PBVH;
/* number of sub-elements each mesh element has (for interpolation) */
#define SUB_ELEMS_VERT 0
#define SUB_ELEMS_EDGE 2
-#define SUB_ELEMS_FACE 4
+#define SUB_ELEMS_FACE 50
+
+/*
+Note: all mface interfaces now officially operate on tesselated data.
+ Also, the mface origindex layer indexes mpolys, not mfaces.
+*/
typedef struct DMGridData {
float co[3];
@@ -80,15 +114,15 @@ typedef struct DMGridAdjacency {
typedef enum DerivedMeshType {
DM_TYPE_CDDM,
- DM_TYPE_EDITMESH,
+ DM_TYPE_EDITBMESH,
DM_TYPE_CCGDM
} DerivedMeshType;
typedef struct DerivedMesh DerivedMesh;
struct DerivedMesh {
/* Private DerivedMesh data, only for internal DerivedMesh use */
- CustomData vertData, edgeData, faceData;
- int numVertData, numEdgeData, numFaceData;
+ CustomData vertData, edgeData, faceData, loopData, polyData;
+ int numVertData, numEdgeData, numFaceData, numLoopData, numPolyData;
int needsFree; /* checked on ->release, is set to 0 for cached results */
int deformedOnly; /* set by modifier stack if only deformed from original */
BVHCache bvhCache;
@@ -96,22 +130,24 @@ struct DerivedMesh {
DerivedMeshType type;
/* Misc. Queries */
+
+ /*recalculates mesh tesselation*/
+ void (*recalcTesselation)(DerivedMesh *dm);
/* Also called in Editmode */
int (*getNumVerts)(DerivedMesh *dm);
- /* Also called in Editmode */
- int (*getNumFaces)(DerivedMesh *dm);
-
int (*getNumEdges)(DerivedMesh *dm);
+ int (*getNumTessFaces)(DerivedMesh *dm);
+ int (*getNumFaces) (DerivedMesh *dm);
- /* copy a single vert/edge/face from the derived mesh into
+ /* copy a single vert/edge/tesselated face from the derived mesh into
* *{vert/edge/face}_r. note that the current implementation
* of this function can be quite slow, iterating over all
* elements (editmesh)
*/
void (*getVert)(DerivedMesh *dm, int index, struct MVert *vert_r);
void (*getEdge)(DerivedMesh *dm, int index, struct MEdge *edge_r);
- void (*getFace)(DerivedMesh *dm, int index, struct MFace *face_r);
+ void (*getTessFace)(DerivedMesh *dm, int index, struct MFace *face_r);
/* return a pointer to the entire array of verts/edges/face from the
* derived mesh. if such an array does not exist yet, it will be created,
@@ -120,21 +156,27 @@ struct DerivedMesh {
*/
struct MVert *(*getVertArray)(DerivedMesh *dm);
struct MEdge *(*getEdgeArray)(DerivedMesh *dm);
- struct MFace *(*getFaceArray)(DerivedMesh *dm);
+ struct MFace *(*getTessFaceArray)(DerivedMesh *dm);
+ struct MLoop *(*getLoopArray)(DerivedMesh *dm);
+ struct MPoly *(*getPolyArray)(DerivedMesh *dm);
/* copy all verts/edges/faces from the derived mesh into
* *{vert/edge/face}_r (must point to a buffer large enough)
*/
void (*copyVertArray)(DerivedMesh *dm, struct MVert *vert_r);
void (*copyEdgeArray)(DerivedMesh *dm, struct MEdge *edge_r);
- void (*copyFaceArray)(DerivedMesh *dm, struct MFace *face_r);
+ void (*copyTessFaceArray)(DerivedMesh *dm, struct MFace *face_r);
+ void (*copyLoopArray)(DerivedMesh *dm, struct MLoop *loop_r);
+ void (*copyPolyArray)(DerivedMesh *dm, struct MPoly *poly_r);
/* return a copy of all verts/edges/faces from the derived mesh
* it is the caller's responsibility to free the returned pointer
*/
struct MVert *(*dupVertArray)(DerivedMesh *dm);
struct MEdge *(*dupEdgeArray)(DerivedMesh *dm);
- struct MFace *(*dupFaceArray)(DerivedMesh *dm);
+ struct MFace *(*dupTessFaceArray)(DerivedMesh *dm);
+ struct MLoop *(*dupLoopArray)(DerivedMesh *dm);
+ struct MPoly *(*dupPolyArray)(DerivedMesh *dm);
/* return a pointer to a single element of vert/edge/face custom data
* from the derived mesh (this gives a pointer to the actual data, not
@@ -142,7 +184,7 @@ struct DerivedMesh {
*/
void *(*getVertData)(DerivedMesh *dm, int index, int type);
void *(*getEdgeData)(DerivedMesh *dm, int index, int type);
- void *(*getFaceData)(DerivedMesh *dm, int index, int type);
+ void *(*getTessFaceData)(DerivedMesh *dm, int index, int type);
/* return a pointer to the entire array of vert/edge/face custom data
* from the derived mesh (this gives a pointer to the actual data, not
@@ -150,8 +192,21 @@ struct DerivedMesh {
*/
void *(*getVertDataArray)(DerivedMesh *dm, int type);
void *(*getEdgeDataArray)(DerivedMesh *dm, int type);
- void *(*getFaceDataArray)(DerivedMesh *dm, int type);
-
+ void *(*getTessFaceDataArray)(DerivedMesh *dm, int type);
+
+ /*retrieves the base CustomData structures for
+ verts/edges/tessfaces/loops/facdes*/
+ CustomData *(*getVertDataLayout)(DerivedMesh *dm);
+ CustomData *(*getEdgeDataLayout)(DerivedMesh *dm);
+ CustomData *(*getTessFaceDataLayout)(DerivedMesh *dm);
+ CustomData *(*getLoopDataLayout)(DerivedMesh *dm);
+ CustomData *(*getFaceDataLayout)(DerivedMesh *dm);
+
+ /*copies all customdata for an element source into dst at index dest*/
+ void (*copyFromVertCData)(DerivedMesh *dm, int source, CustomData *dst, int dest);
+ void (*copyFromEdgeCData)(DerivedMesh *dm, int source, CustomData *dst, int dest);
+ void (*copyFromFaceCData)(DerivedMesh *dm, int source, CustomData *dst, int dest);
+
/* optional grid access for subsurf */
int (*getNumGrids)(DerivedMesh *dm);
int (*getGridSize)(DerivedMesh *dm);
@@ -254,8 +309,8 @@ struct DerivedMesh {
* o Drawing options too complicated to enumerate, look at code.
*/
void (*drawFacesTex)(DerivedMesh *dm,
- int (*setDrawOptions)(struct MTFace *tface,
- int has_mcol, int matnr));
+ int (*setDrawOptions)(struct MTFace *tface,
+ int has_vcol, int matnr));
/* Draw all faces with GLSL materials
* o setMaterial is called for every different material nr
@@ -338,15 +393,16 @@ void DM_init_funcs(DerivedMesh *dm);
* of vertices, edges and faces (doesn't allocate memory for them, just
* sets up the custom data layers)
*/
-void DM_init(DerivedMesh *dm, DerivedMeshType type,
- int numVerts, int numEdges, int numFaces);
+void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges,
+ int numFaces, int numLoops, int numPolys);
/* utility function to initialise a DerivedMesh for the desired number
* of vertices, edges and faces, with a layer setup copied from source
*/
void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
- DerivedMeshType type,
- int numVerts, int numEdges, int numFaces);
+ DerivedMeshType type,
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys);
/* utility function to release a DerivedMesh's layers
* returns 1 if DerivedMesh has to be released by the backend, 0 otherwise
@@ -355,7 +411,7 @@ int DM_release(DerivedMesh *dm);
/* utility function to convert a DerivedMesh to a Mesh
*/
-void DM_to_mesh(DerivedMesh *dm, struct Mesh *me);
+void DM_to_mesh(DerivedMesh *dm, struct Mesh *me, struct Object *ob);
/* utility function to convert a DerivedMesh to a shape key block
*/
@@ -376,6 +432,8 @@ void DM_add_vert_layer(struct DerivedMesh *dm, int type, int alloctype,
void *layer);
void DM_add_edge_layer(struct DerivedMesh *dm, int type, int alloctype,
void *layer);
+void DM_add_tessface_layer(struct DerivedMesh *dm, int type, int alloctype,
+ void *layer);
void DM_add_face_layer(struct DerivedMesh *dm, int type, int alloctype,
void *layer);
@@ -395,6 +453,7 @@ void *DM_get_face_data(struct DerivedMesh *dm, int index, int type);
*/
void *DM_get_vert_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_edge_data_layer(struct DerivedMesh *dm, int type);
+void *DM_get_tessface_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_face_data_layer(struct DerivedMesh *dm, int type);
/* custom data setting functions
@@ -413,6 +472,10 @@ void DM_copy_vert_data(struct DerivedMesh *source, struct DerivedMesh *dest,
int source_index, int dest_index, int count);
void DM_copy_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest,
int source_index, int dest_index, int count);
+void DM_copy_tessface_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+ int source_index, int dest_index, int count);
+void DM_copy_loop_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+ int source_index, int dest_index, int count);
void DM_copy_face_data(struct DerivedMesh *source, struct DerivedMesh *dest,
int source_index, int dest_index, int count);
@@ -422,8 +485,13 @@ void DM_copy_face_data(struct DerivedMesh *source, struct DerivedMesh *dest,
*/
void DM_free_vert_data(struct DerivedMesh *dm, int index, int count);
void DM_free_edge_data(struct DerivedMesh *dm, int index, int count);
+void DM_free_tessface_data(struct DerivedMesh *dm, int index, int count);
+void DM_free_loop_data(struct DerivedMesh *dm, int index, int count);
void DM_free_face_data(struct DerivedMesh *dm, int index, int count);
+/*sets up mpolys for a DM based on face iterators in source*/
+void DM_DupPolys(DerivedMesh *source, DerivedMesh *target);
+
/* interpolates vertex data from the vertices indexed by src_indices in the
* source mesh using the given weights and stores the result in the vertex
* indexed by dest_index in the dest mesh
@@ -453,12 +521,20 @@ void DM_interp_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest,
* vert_weights[i] multiplied by weights[i].
*/
typedef float FaceVertWeight[SUB_ELEMS_FACE][SUB_ELEMS_FACE];
-void DM_interp_face_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+void DM_interp_tessface_data(struct DerivedMesh *source, struct DerivedMesh *dest,
int *src_indices,
float *weights, FaceVertWeight *vert_weights,
int count, int dest_index);
-void DM_swap_face_data(struct DerivedMesh *dm, int index, const int *corner_indices);
+void DM_swap_tessface_data(struct DerivedMesh *dm, int index, const int *corner_indices);
+
+void DM_interp_loop_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+ int *src_indices,
+ float *weights, int count, int dest_index);
+
+void DM_interp_face_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+ int *src_indices,
+ float *weights, int count, int dest_index);
/* Temporary? A function to give a colorband to derivedmesh for vertexcolor ranges */
void vDM_ColorBand_store(struct ColorBand *coba);
@@ -474,11 +550,15 @@ DerivedMesh *mesh_get_derived_final(struct Scene *scene, struct Object *ob,
DerivedMesh *mesh_get_derived_deform(struct Scene *scene, struct Object *ob,
CustomDataMask dataMask);
-DerivedMesh *mesh_create_derived_for_modifier(struct Scene *scene, struct Object *ob, struct ModifierData *md);
+DerivedMesh *mesh_create_derived_for_modifier(struct Scene *scene, struct Object *ob,
+ struct ModifierData *md, int build_shapekey_layers);
DerivedMesh *mesh_create_derived_render(struct Scene *scene, struct Object *ob,
CustomDataMask dataMask);
+DerivedMesh *getEditDerivedBMesh(struct BMEditMesh *em, struct Object *ob,
+ float (*vertexCos)[3]);
+
DerivedMesh *mesh_create_derived_index_render(struct Scene *scene, struct Object *ob, CustomDataMask dataMask, int index);
/* same as above but wont use render settings */
@@ -497,20 +577,21 @@ DerivedMesh *mesh_create_derived_no_virtual(struct Scene *scene, struct Object *
DerivedMesh *mesh_create_derived_physics(struct Scene *scene, struct Object *ob, float (*vertCos)[3],
CustomDataMask dataMask);
-DerivedMesh *editmesh_get_derived(struct EditMesh *em, float (*vertexCos)[3]);
-DerivedMesh *editmesh_get_derived_base(struct Object *, struct EditMesh *em);
-DerivedMesh *editmesh_get_derived_cage(struct Scene *scene, struct Object *,
- struct EditMesh *em, CustomDataMask dataMask);
-DerivedMesh *editmesh_get_derived_cage_and_final(struct Scene *scene, struct Object *,
- struct EditMesh *em, DerivedMesh **final_r,
+DerivedMesh *editbmesh_get_derived(struct BMEditMesh *em, float (*vertexCos)[3]);
+DerivedMesh *editbmesh_get_derived_base(struct Object *, struct BMEditMesh *em);
+DerivedMesh *editbmesh_get_derived_cage(struct Scene *scene, struct Object *,
+ struct BMEditMesh *em, CustomDataMask dataMask);
+DerivedMesh *editbmesh_get_derived_cage_and_final(struct Scene *scene, struct Object *,
+ struct BMEditMesh *em, DerivedMesh **final_r,
CustomDataMask dataMask);
-float (*editmesh_get_vertex_cos(struct EditMesh *em, int *numVerts_r))[3];
-int editmesh_modifier_is_enabled(struct Scene *scene, struct ModifierData *md, DerivedMesh *dm);
-void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct EditMesh *em, CustomDataMask dataMask);
+float (*editbmesh_get_vertex_cos(struct BMEditMesh *em, int *numVerts_r))[3];
+int editbmesh_modifier_is_enabled(struct Scene *scene, struct ModifierData *md, DerivedMesh *dm);
+void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct BMEditMesh *em,
+ CustomDataMask dataMask, int build_shapekey_layers);
/* returns an array of deform matrices for crazyspace correction, and the
number of modifiers left */
-int editmesh_get_first_deform_matrices(struct Scene *, struct Object *, struct EditMesh *em,
+int editbmesh_get_first_deform_matrices(struct Scene *, struct Object *, struct BMEditMesh *em,
float (**deformmats)[3][3], float (**deformcos)[3]);
/* returns an array of deform matrices for crazyspace correction when sculpting,
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 71771b6077d..a6b98749eda 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -88,6 +88,7 @@ extern void BKE_reset_undo(void);
extern char *BKE_undo_menu_string(void);
extern void BKE_undo_number(struct bContext *C, int nr);
extern char *BKE_undo_get_name(int nr, int *active);
+void BKE_undo_save(char *fname);
extern void BKE_undo_save_quit(void);
extern struct Main *BKE_undo_get_main(struct Scene **scene);
diff --git a/source/blender/blenkernel/BKE_bmesh.h b/source/blender/blenkernel/BKE_bmesh.h
index 9739a5eacf2..cddc42315b7 100644
--- a/source/blender/blenkernel/BKE_bmesh.h
+++ b/source/blender/blenkernel/BKE_bmesh.h
@@ -54,6 +54,7 @@ struct BME_Edge;
struct BME_Poly;
struct BME_Loop;
+/*NOTE: this is the bmesh 1.0 code. it's completely outdated.*/
/*Notes on further structure Cleanup:
-Remove the tflags, they belong in custom data layers
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
index c71c86e110d..affeca2b007 100644
--- a/source/blender/blenkernel/BKE_cdderivedmesh.h
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -38,12 +38,17 @@
#include "BKE_DerivedMesh.h"
struct DerivedMesh;
+struct BMEditMesh;
struct EditMesh;
struct Mesh;
struct Object;
/* creates a new CDDerivedMesh */
-struct DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces);
+struct DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys);
+
+/*tests if a given DerivedMesh is a CDDM*/
+int CDDM_Check(struct DerivedMesh *dm);
/* creates a CDDerivedMesh from the given Mesh, this will reference the
original data in Mesh, but it is safe to apply vertex coordinates or
@@ -51,8 +56,11 @@ struct DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces);
data to not overwrite the original */
struct DerivedMesh *CDDM_from_mesh(struct Mesh *mesh, struct Object *ob);
-/* creates a CDDerivedMesh from the given EditMesh */
-struct DerivedMesh *CDDM_from_editmesh(struct EditMesh *em, struct Mesh *me);
+/* creates a CDDerivedMesh from the given BMEditMesh */
+DerivedMesh *CDDM_from_BMEditMesh(struct BMEditMesh *em, struct Mesh *me, int use_mdisps);
+
+/* merge verts */
+DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, int *vtargetmap);
/* creates a CDDerivedMesh from the given curve object */
struct DerivedMesh *CDDM_from_curve(struct Object *ob);
@@ -61,17 +69,26 @@ struct DerivedMesh *CDDM_from_curve(struct Object *ob);
/* useful for OrcoDM creation for curves with constructive modifiers */
DerivedMesh *CDDM_from_curve_customDB(struct Object *ob, struct ListBase *dispbase);
+struct BMEditMesh *CDDM_To_BMesh(struct Object *ob, struct DerivedMesh *dm, struct BMEditMesh *existing);
+
+
/* Copies the given DerivedMesh with verts, faces & edges stored as
* custom element data.
*/
-struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm);
+struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm, int faces_from_tessfaces);
/* creates a CDDerivedMesh with the same layer stack configuration as the
* given DerivedMesh and containing the requested numbers of elements.
* elements are initialised to all zeros
*/
struct DerivedMesh *CDDM_from_template(struct DerivedMesh *source,
- int numVerts, int numEdges, int numFaces);
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys);
+
+/*converts mfaces to mpolys. note things may break if there are not valid
+ *medges surrounding each mface.
+ */
+void CDDM_tessfaces_to_faces(struct DerivedMesh *dm);
/* applies vertex coordinates or normals to a CDDerivedMesh. if the MVert
* layer is a referenced layer, it will be duplicate to not overwrite the
@@ -86,9 +103,20 @@ void CDDM_calc_normals(struct DerivedMesh *dm);
/* calculates edges for a CDDerivedMesh (from face data)
* this completely replaces the current edge data in the DerivedMesh
+ * builds edges from the tesselated face data.
*/
void CDDM_calc_edges(struct DerivedMesh *dm);
+/* same as CDDM_calc_edges only makes edges from ngon faces instead of tesselation
+ faces*/
+void CDDM_calc_edges_poly(struct DerivedMesh *dm);
+
+/*reconstitute face triangulation. if orig_use_polyorig is nonzero, sets
+ the mface origindex layer to copy to the origindex values of the
+ parent mpolys; otherwise the mface origindex will point to the index of
+ the parent mpoly*/
+void CDDM_recalc_tesselation(struct DerivedMesh *dm, int orig_use_polyorig);
+
/* lowers the number of vertices/edges/faces in a CDDerivedMesh
* the layer data stays the same size
*/
@@ -102,7 +130,9 @@ void CDDM_lower_num_faces(struct DerivedMesh *dm, int numFaces);
*/
struct MVert *CDDM_get_vert(struct DerivedMesh *dm, int index);
struct MEdge *CDDM_get_edge(struct DerivedMesh *dm, int index);
-struct MFace *CDDM_get_face(struct DerivedMesh *dm, int index);
+struct MFace *CDDM_get_tessface(struct DerivedMesh *dm, int index);
+struct MLoop *CDDM_get_loop(struct DerivedMesh *dm, int index);
+struct MPoly *CDDM_get_face(struct DerivedMesh *dm, int index);
/* vertex/edge/face array access functions - return the array holding the
* desired data
@@ -111,6 +141,18 @@ struct MFace *CDDM_get_face(struct DerivedMesh *dm, int index);
*/
struct MVert *CDDM_get_verts(struct DerivedMesh *dm);
struct MEdge *CDDM_get_edges(struct DerivedMesh *dm);
-struct MFace *CDDM_get_faces(struct DerivedMesh *dm);
+struct MFace *CDDM_get_tessfaces(struct DerivedMesh *dm);
+struct MLoop *CDDM_get_loops(struct DerivedMesh *dm);
+struct MPoly *CDDM_get_polys(struct DerivedMesh *dm);
+
+/*Assigns news m*** layers to the cddm. Note that you must handle
+ freeing the old ones yourself. Also you must ensure dm->num****Data
+ is correct.*/
+void CDDM_set_mvert(struct DerivedMesh *dm, struct MVert *mvert);
+void CDDM_set_medge(struct DerivedMesh *dm, struct MEdge *medge);
+void CDDM_set_mface(struct DerivedMesh *dm, struct MFace *mface);
+void CDDM_set_mloop(struct DerivedMesh *dm, struct MLoop *mloop);
+void CDDM_set_mpoly(struct DerivedMesh *dm, struct MPoly *mpoly);
+
#endif
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index f3922f43cbc..7ccfcebb48e 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -38,11 +38,15 @@
extern "C" {
#endif
+struct BMesh;
struct ID;
struct CustomData;
struct CustomDataLayer;
typedef unsigned int CustomDataMask;
+/*a data type large enough to hold 1 element from any customdata layer type*/
+typedef struct {unsigned char data[64];} CDBlockBytes;
+
extern const CustomDataMask CD_MASK_BAREMESH;
extern const CustomDataMask CD_MASK_MESH;
extern const CustomDataMask CD_MASK_EDITMESH;
@@ -65,17 +69,45 @@ extern const CustomDataMask CD_MASK_FACECORNERS;
#define CD_DUPLICATE 4 /* do a full copy of all layers, only allowed if source
has same number of elements */
+/* Checks if the layer at physical offset layern (in data->layers) support math
+ * the below operations.
+ */
+int CustomData_layer_has_math(struct CustomData *data, int layern);
+
+/*copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
+ another, while not overwriting anything else (e.g. flags). probably only
+ implemented for mloopuv/mloopcol, for now.*/
+void CustomData_data_copy_value(int type, void *source, void *dest);
+
+/* compares if data1 is equal to data2. type is a valid CustomData type
+ * enum (e.g. CD_MLOOPUV). the layer type's equal function is used to compare
+ * the data, if it exists, otherwise memcmp is used.*/
+int CustomData_data_equals(int type, void *data1, void *data2);
+void CustomData_data_initminmax(int type, void *min, void *max);
+void CustomData_data_dominmax(int type, void *data, void *min, void *max);
+void CustomData_data_multiply(int type, void *data, float fac);
+void CustomData_data_add(int type, void *data1, void *data2);
+
/* initialises a CustomData object with the same layer setup as source.
* mask is a bitfield where (mask & (1 << (layer type))) indicates
* if a layer should be copied or not. alloctype must be one of the above. */
void CustomData_copy(const struct CustomData *source, struct CustomData *dest,
CustomDataMask mask, int alloctype, int totelem);
+/* BMESH_TODO, not really a public function but readfile.c needs it */
+void CustomData_update_typemap(struct CustomData *data);
+
/* same as the above, except that this will preserve existing layers, and only
* add the layers that were not there yet */
void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
CustomDataMask mask, int alloctype, int totelem);
+/*bmesh version of CustomData_merge; merges the layouts of source and dest,
+ then goes through the mesh and makes sure all the customdata blocks are
+ consistent with the new layout.*/
+void CustomData_bmesh_merge(struct CustomData *source, struct CustomData *dest,
+ int mask, int alloctype, struct BMesh *bm, int type);
+
/* frees data associated with a CustomData object (doesn't free the object
* itself, though)
*/
@@ -140,12 +172,13 @@ void CustomData_set_only_copy(const struct CustomData *data,
void CustomData_copy_data(const struct CustomData *source,
struct CustomData *dest, int source_index,
int dest_index, int count);
+void CustomData_copy_elements(int type, void *source, void *dest, int count);
void CustomData_em_copy_data(const struct CustomData *source,
struct CustomData *dest, void *src_block,
void **dest_block);
void CustomData_bmesh_copy_data(const struct CustomData *source,
- struct CustomData *dest,void *src_block,
- void **dest_block);
+ struct CustomData *dest, void *src_block,
+ void **dest_block);
void CustomData_em_validate_data(struct CustomData *data, void *block, int sub_elements);
/* frees data in a CustomData object
@@ -187,11 +220,18 @@ void CustomData_swap(struct CustomData *data, int index, const int *corner_indic
* returns NULL if there is no layer of type
*/
void *CustomData_get(const struct CustomData *data, int index, int type);
+void *CustomData_get_n(const struct CustomData *data, int type, int index, int n);
void *CustomData_em_get(const struct CustomData *data, void *block, int type);
void *CustomData_em_get_n(const struct CustomData *data, void *block, int type, int n);
void *CustomData_bmesh_get(const struct CustomData *data, void *block, int type);
void *CustomData_bmesh_get_n(const struct CustomData *data, void *block, int type, int n);
+/* gets the layer at physical index n, with no type checking.
+ */
+void *CustomData_bmesh_get_layer_n(const struct CustomData *data, void *block, int n);
+
+int CustomData_set_layer_name(const struct CustomData *data, int type, int n, const char *name);
+
/* gets a pointer to the active or first layer of type
* returns NULL if there is no layer of type
*/
@@ -199,8 +239,8 @@ void *CustomData_get_layer(const struct CustomData *data, int type);
void *CustomData_get_layer_n(const struct CustomData *data, int type, int n);
void *CustomData_get_layer_named(const struct CustomData *data, int type,
const char *name);
-
int CustomData_get_layer_index(const struct CustomData *data, int type);
+int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n);
int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name);
int CustomData_get_active_layer_index(const struct CustomData *data, int type);
int CustomData_get_render_layer_index(const struct CustomData *data, int type);
@@ -227,6 +267,11 @@ void CustomData_bmesh_set(const struct CustomData *data, void *block, int type,
void CustomData_bmesh_set_n(struct CustomData *data, void *block, int type, int n,
void *source);
+/*sets the data of the block at physical layer n. no real type checking
+ *is performed.
+ */
+void CustomData_bmesh_set_layer_n(struct CustomData *data, void *block, int n,
+ void *source);
/* set the pointer of to the first layer of type. the old data is not freed.
* returns the value of ptr if the layer is found, NULL otherwise
@@ -283,7 +328,8 @@ void CustomData_set_layer_unique_name(struct CustomData *data, int index);
int CustomData_verify_versions(struct CustomData *data, int index);
/*BMesh specific customdata stuff*/
-void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata);
+void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata,
+ struct CustomData *ldata, int totloop, int totpoly);
void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata, int total);
void CustomData_bmesh_init_pool(struct CustomData *data, int allocsize);
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 27e9140ba77..b5e4cde53ca 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -213,12 +213,10 @@ struct FCurve *rna_get_fcurve(struct PointerRNA *ptr, struct PropertyRNA *prop,
int binarysearch_bezt_index(struct BezTriple array[], float frame, int arraylen, short *replace);
/* get the time extents for F-Curve */
-void calc_fcurve_range(struct FCurve *fcu, float *min, float *max,
- const short do_sel_only, const short do_min_length);
+void calc_fcurve_range(struct FCurve *fcu, float *min, float *max, const short selOnly);
/* get the bounding-box extents for F-Curve */
-void calc_fcurve_bounds(struct FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax,
- const short do_sel_only);
+void calc_fcurve_bounds(struct FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax, const short selOnly);
/* .............. */
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index c7e269a3b75..4db92757969 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -61,9 +61,7 @@ int BKE_imtype_is_movie(int imtype);
struct anim *openanim(char * name, int flags, int streamindex);
void image_de_interlace(struct Image *ima, int odd);
-
-void make_local_image(struct Image *ima);
-
+
void tag_image_time(struct Image *ima);
void free_old_images(void);
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index c055bb2004b..529d0680cf9 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -48,8 +48,10 @@ extern "C" {
#endif
void free_key(struct Key *sc);
+void free_key_nolib(struct Key *key);
struct Key *add_key(struct ID *id);
struct Key *copy_key(struct Key *key);
+struct Key *copy_key_nolib(struct Key *key);
void make_local_key(struct Key *key);
void sort_keys(struct Key *key);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 77ce7a50956..a44618dcbe8 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -50,7 +50,6 @@ void *copy_libblock(void *rt);
void copy_libblock_data(struct ID *id, const struct ID *id_from, const short do_action);
void id_lib_extern(struct ID *id);
-void BKE_library_filepath_set(struct Library *lib, const char *filepath);
void id_us_plus(struct ID *id);
void id_us_min(struct ID *id);
int id_make_local(struct ID *id, int test);
@@ -59,7 +58,6 @@ int id_copy(struct ID *id, struct ID **newid, int test);
int id_unlink(struct ID *id, int test);
int new_id(struct ListBase *lb, struct ID *id, const char *name);
-void id_clear_lib_data(struct ListBase *lb, struct ID *id);
struct ListBase *which_libbase(struct Main *mainlib, short type);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 07c6fb8b09c..7fff07c0b41 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -36,12 +36,15 @@
struct BoundBox;
struct DispList;
struct ListBase;
-struct EditMesh;
-struct MDeformVert;
+struct BMEditMesh;
+struct BMesh;
struct Mesh;
+struct MPoly;
+struct MLoop;
struct MFace;
struct MEdge;
struct MVert;
+struct MDeformVert;
struct MCol;
struct Object;
struct MTFace;
@@ -54,14 +57,35 @@ struct Scene;
extern "C" {
#endif
-struct EditMesh *BKE_mesh_get_editmesh(struct Mesh *me);
-void BKE_mesh_end_editmesh(struct Mesh *me, struct EditMesh *em);
+struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me, struct Object *ob);
+
+/*
+ this function recreates a tesselation.
+ returns number of tesselation faces.
+
+ use_poly_origindex sets whether or not the tesselation faces' origindex
+ layer should point to original poly indices or real poly indices.
+
+ use_face_origindex sets the tesselation faces' origindex layer
+ to point to the tesselation faces themselves, not the polys.
+
+ if both of the above are 0, it'll use the indices of the mpolys of the MPoly
+ data in pdata, and ignore the origindex layer altogether.
+ */
+int mesh_recalcTesselation(struct CustomData *fdata, struct CustomData *ldata,
+ struct CustomData *pdata, struct MVert *mvert, int totface,
+ int totloop, int totpoly, int use_poly_origindex, int use_face_origindex);
+
+/*calculates a face normal.*/
+void mesh_calc_poly_normal(struct MPoly *mpoly, struct MLoop *loopstart,
+ struct MVert *mvarray, float *no);
void unlink_mesh(struct Mesh *me);
-void free_mesh(struct Mesh *me);
+void free_mesh(struct Mesh *me, int unlink);
struct Mesh *add_mesh(const char *name);
struct Mesh *copy_mesh(struct Mesh *me);
void mesh_update_customdata_pointers(struct Mesh *me);
+
void make_local_mesh(struct Mesh *me);
void boundbox_mesh(struct Mesh *me, float *loc, float *size);
void tex_space_mesh(struct Mesh *me);
@@ -71,17 +95,26 @@ int test_index_face(struct MFace *mface, struct CustomData *mfdata, int mfindex,
struct Mesh *get_mesh(struct Object *ob);
void set_mesh(struct Object *ob, struct Mesh *me);
void mball_to_mesh(struct ListBase *lb, struct Mesh *me);
-int nurbs_to_mdata(struct Object *ob, struct MVert **allvert, int *_totvert,
- struct MEdge **alledge, int *_totedge, struct MFace **allface, int *_totface);
-int nurbs_to_mdata_customdb(struct Object *ob, struct ListBase *dispbase,
- struct MVert **allvert, int *_totvert, struct MEdge **alledge, int *_totedge,
- struct MFace **allface, int *_totface);
+int nurbs_to_mdata(struct Object *ob, struct MVert **allvert, int *totvert,
+ struct MEdge **alledge, int *totedge, struct MFace **allface, struct MLoop **allloop, struct MPoly **allpoly,
+ int *totface, int *totloop, int *totpoly);
+int nurbs_to_mdata_customdb(struct Object *ob, struct ListBase *dispbase, struct MVert **allvert, int *_totvert,
+ struct MEdge **alledge, int *_totedge, struct MFace **allface, struct MLoop **allloop, struct MPoly **allpoly,
+ int *_totface, int *_totloop, int *_totpoly);
void nurbs_to_mesh(struct Object *ob);
void mesh_to_curve(struct Scene *scene, struct Object *ob);
void free_dverts(struct MDeformVert *dvert, int totvert);
void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */
void mesh_delete_material_index(struct Mesh *me, short index);
void mesh_set_smooth_flag(struct Object *meshOb, int enableSmooth);
+void convert_mfaces_to_mpolys(struct Mesh *mesh);
+void mesh_calc_tessface_normals(struct MVert *mverts, int numVerts,struct MFace *mfaces, int numFaces, float (*faceNors_r)[3]);
+
+/*used for unit testing; compares two meshes, checking only
+ differences we care about. should be usable with leaf's
+ testing framework I get RNA work done, will use hackish
+ testing code for now.*/
+const char *mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh);
struct BoundBox *mesh_get_bb(struct Object *ob);
void mesh_get_texspace(struct Mesh *me, float *loc_r, float *rot_r, float *size_r);
@@ -95,7 +128,9 @@ void mesh_strip_loose_edges(struct Mesh *me);
/* Calculate vertex and face normals, face normals are returned in *faceNors_r if non-NULL
* and vertex normals are stored in actual mverts.
*/
-void mesh_calc_normals(struct MVert *mverts, int numVerts, struct MFace *mfaces, int numFaces, float (*faceNors_r)[3]);
+void mesh_calc_normals(struct MVert *mverts, int numVerts, struct MLoop *mloop,
+ struct MPoly *mpolys, int numLoops, int numPolys, float (*polyNors_r)[3],
+ struct MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3]);
/* Return a newly MEM_malloc'd array of all the mesh vertex locations
* (_numVerts_r_ may be NULL) */
@@ -159,6 +194,11 @@ void BKE_mesh_calc_edges(struct Mesh *mesh, int update);
void BKE_mesh_ensure_navmesh(struct Mesh *me);
+/*convert a triangle of loop facedata to mface facedata*/
+void mesh_loops_to_tri_corners(struct CustomData *fdata, struct CustomData *ldata,
+ struct CustomData *pdata, int lindex[3], int findex,
+ int polyindex);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index a47cefe6f65..db57f2e30fa 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -45,6 +45,7 @@ struct ListBase;
struct LinkNode;
struct bArmature;
struct ModifierData;
+struct BMEditMesh;
typedef enum {
/* Should not be used, only for None modifier type */
@@ -146,13 +147,13 @@ typedef struct ModifierTypeInfo {
*/
void (*deformVertsEM)(
struct ModifierData *md, struct Object *ob,
- struct EditMesh *editData, struct DerivedMesh *derivedData,
+ struct BMEditMesh *editData, struct DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts);
/* Set deform matrix per vertex for crazyspace correction */
void (*deformMatricesEM)(
struct ModifierData *md, struct Object *ob,
- struct EditMesh *editData, struct DerivedMesh *derivedData,
+ struct BMEditMesh *editData, struct DerivedMesh *derivedData,
float (*vertexCos)[3], float (*defMats)[3][3], int numVerts);
/********************* Non-deform modifier functions *********************/
@@ -190,7 +191,7 @@ typedef struct ModifierTypeInfo {
*/
struct DerivedMesh *(*applyModifierEM)(
struct ModifierData *md, struct Object *ob,
- struct EditMesh *editData,
+ struct BMEditMesh *editData,
struct DerivedMesh *derivedData);
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 4f1262cd523..ce6e12345e8 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -71,6 +71,14 @@ int multiresModifier_reshapeFromDeformMod(struct Scene *scene, struct MultiresMo
void multires_stitch_grids(struct Object *);
+/*switch mdisp data in dm between tangent and object space*/
+enum {
+ MULTIRES_SPACE_TANGENT,
+ MULTIRES_SPACE_OBJECT,
+ MULTIRES_SPACE_ABSOLUTE,
+};
+void multires_set_space(struct DerivedMesh *dm, struct Object *ob, int from, int to);
+
/* Related to the old multires */
void multires_free(struct Multires *mr);
void multires_load_old(struct Object *ob, struct Mesh *me);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index e14db31607a..453612749c6 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -86,7 +86,7 @@ typedef struct SculptSession {
/* Partial redraw */
int partial_redraw;
-
+
/* Used to cache the render of the active texture */
unsigned int texcache_side, *texcache, texcache_actual;
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index e64de965db5..759060d408e 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -215,7 +215,9 @@ typedef enum {
SEQ_STRIPELEM_IBUF_ENDSTILL
} seq_stripelem_ibuf_t;
+void seq_stripelem_cache_init(void);
void seq_stripelem_cache_destruct(void);
+
void seq_stripelem_cache_cleanup(void);
/* returned ImBuf is properly refed and has to be freed */
diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h
index dcbd045f62d..5c878102bc2 100644
--- a/source/blender/blenkernel/BKE_subsurf.h
+++ b/source/blender/blenkernel/BKE_subsurf.h
@@ -46,6 +46,10 @@ struct _CCGEdge;
struct _CCGFace;
struct _CCGSubsurf;
struct _CCGVert;
+struct EdgeHash;
+struct PBVH;
+struct DMGridData;
+struct DMGridAdjacency;
/**************************** External *****************************/
@@ -74,6 +78,8 @@ typedef struct CCGDerivedMesh {
short *edgeFlags;
char *faceFlags;
+ int *reverseFaceMap;
+
struct PBVH *pbvh;
struct ListBase *fmap;
struct IndexNode *fmap_mem;
@@ -95,6 +101,8 @@ typedef struct CCGDerivedMesh {
void (*update)(DerivedMesh*);
} multires;
+
+ struct EdgeHash *ehash;
} CCGDerivedMesh;
#endif
diff --git a/source/blender/blenkernel/BKE_tessmesh.h b/source/blender/blenkernel/BKE_tessmesh.h
new file mode 100644
index 00000000000..601d95de268
--- /dev/null
+++ b/source/blender/blenkernel/BKE_tessmesh.h
@@ -0,0 +1,71 @@
+#ifndef _BKE_TESSMESH_H
+#define _BKE_TESSMESH_H
+
+#include "bmesh.h"
+
+struct BMesh;
+struct BMLoop;
+struct BMFace;
+struct Mesh;
+struct DerivedMesh;
+
+/*
+ok: the EDBM module is for editmode bmesh stuff. in contrast, the
+ BMEdit module is for code shared with blenkernel that concerns
+ the BMEditMesh structure.
+*/
+
+/*this structure replaces EditMesh.
+
+ through this, you get access to both the edit bmesh,
+ it's tesselation, and various stuff that doesn't belong in the BMesh
+ struct itself.
+
+ the entire derivedmesh and modifier system works with this structure,
+ and not BMesh. Mesh->edit_bmesh stores a pointer to this structure.*/
+typedef struct BMEditMesh {
+ struct BMesh *bm;
+
+ /*this is for undoing failed operations*/
+ struct BMEditMesh *emcopy;
+ int emcopyusers;
+
+ /*we store tesselations as triplets of three loops,
+ which each define a triangle.*/
+ struct BMLoop *(*looptris)[3];
+ int tottri;
+
+ /*derivedmesh stuff*/
+ struct DerivedMesh *derivedFinal, *derivedCage;
+ int lastDataMask;
+
+ /*retopo data pointer*/
+ struct RetopoPaintData *retopo_paint_data;
+
+ /*index tables, to map indices to elements via
+ EDBM_init_index_arrays and associated functions. don't
+ touch this or read it directly.*/
+ struct BMVert **vert_index;
+ struct BMEdge **edge_index;
+ struct BMFace **face_index;
+
+ /*selection mode*/
+ short selectmode;
+ short mat_nr;
+
+ /*Mesh structure this editmesh came from, if it came from one*/
+ struct Mesh *me;
+ struct Object *ob;
+
+ /*temp variables for x-mirror editing*/
+ int mirror_cdlayer;
+ int mirr_free_arrays;
+} BMEditMesh;
+
+void BMEdit_RecalcTesselation(BMEditMesh *tm);
+BMEditMesh *BMEdit_Create(BMesh *bm);
+BMEditMesh *BMEdit_Copy(BMEditMesh *tm);
+void BMEdit_Free(BMEditMesh *em);
+void BMEdit_UpdateLinkedCustomData(BMEditMesh *em);
+
+#endif /* _BKE_TESSMESH_H */
diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h
index 3222167c56e..b5b3c7e67eb 100644
--- a/source/blender/blenkernel/BKE_utildefines.h
+++ b/source/blender/blenkernel/BKE_utildefines.h
@@ -36,6 +36,10 @@
#ifndef BKE_UTILDEFINES_H
#define BKE_UTILDEFINES_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* these values need to be hardcoded in structs, dna does not recognize defines */
/* also defined in DNA_space_types.h */
#ifndef FILE_MAXDIR
@@ -81,6 +85,8 @@
/* bit-row */
#define BROW(min, max) (((max)>=31? 0xFFFFFFFF: (1<<(max+1))-1) - ((min)? ((1<<(min))-1):0) )
-#define BMEMSET(mem, val, size) {unsigned int _i; char *_c = (char*) mem; for (_i=0; _i<size; _i++) *_c++ = val;}
+#ifdef __cplusplus
+}
+#endif
#endif // BKE_UTILDEFINES_H
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 1930e7223f9..83f9f014b0a 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -23,6 +23,11 @@
#
# ***** END GPL LICENSE BLOCK *****
+if(WITH_CODEC_FFMPEG)
+ # FFMPEG gives warnigns which are hard to avoid across multiple versions.
+ remove_strict_flags()
+endif()
+
set(INC
.
../avi
@@ -34,6 +39,7 @@ set(INC
../imbuf
../makesdna
../makesrna
+ ../bmesh
../modifiers
../nodes
../render/extern/include
@@ -89,6 +95,7 @@ set(SRC
intern/depsgraph.c
intern/displist.c
intern/effect.c
+ intern/editderivedbmesh.c
intern/fcurve.c
intern/fluidsim.c
intern/fmodifier.c
@@ -110,6 +117,7 @@ set(SRC
intern/mesh.c
intern/mesh_validate.c
intern/modifier.c
+ intern/modifiers_bmesh.c
intern/multires.c
intern/nla.c
intern/node.c
@@ -216,6 +224,7 @@ set(SRC
BKE_speaker.h
BKE_subsurf.h
BKE_suggestions.h
+ BKE_tessmesh.h
BKE_text.h
BKE_texture.h
BKE_unit.h
@@ -299,10 +308,6 @@ if(WITH_CODEC_FFMPEG)
${FFMPEG_INCLUDE_DIRS}
)
add_definitions(-DWITH_FFMPEG)
-
- remove_strict_flags_file(
- intern/writeffmpeg.c
- )
endif()
if(WITH_PYTHON)
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index 512eec4021f..2998d7bda5c 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -12,6 +12,7 @@ incs += ' #/intern/iksolver/extern ../blenloader'
incs += ' #/extern/bullet2/src'
incs += ' #/intern/opennl/extern #/intern/bsp/extern'
incs += ' ../gpu #/extern/glew/include'
+incs += ' ../bmesh'
incs += ' #/intern/smoke/extern'
incs += ' #/intern/mikktspace'
incs += ' #/intern/audaspace/intern'
diff --git a/source/blender/blenkernel/intern/BME_Customdata.c b/source/blender/blenkernel/intern/BME_Customdata.c
index 8a6426eb3d5..94307968933 100644
--- a/source/blender/blenkernel/intern/BME_Customdata.c
+++ b/source/blender/blenkernel/intern/BME_Customdata.c
@@ -1,4 +1,5 @@
-/*
+#if 0
+/**
* BME_customdata.c jan 2007
*
* Custom Data functions for Bmesh
@@ -86,7 +87,7 @@ void BME_CD_Create(BME_CustomData *data, BME_CustomDataInit *init, int initalloc
if(data->totlayer){
/*alloc memory*/
data->layers = MEM_callocN(sizeof(BME_CustomDataLayer)*data->totlayer, "BMesh Custom Data Layers");
- data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc, 0);
+ data->pool = BLI_mempool_create(data->totsize, initalloc, initalloc, 1);
/*initialize layer data*/
for(i=0; i < BME_CD_NUMTYPES; i++){
if(init->layout[i]){
@@ -199,3 +200,4 @@ void BME_CD_set_default(BME_CustomData *data, void **block)
typeInfo->set_default((char*)*block + offset, 1);
}
}
+#endif
diff --git a/source/blender/blenkernel/intern/BME_conversions.c b/source/blender/blenkernel/intern/BME_conversions.c
index ce1da6132cd..65a8ee8e0bb 100644
--- a/source/blender/blenkernel/intern/BME_conversions.c
+++ b/source/blender/blenkernel/intern/BME_conversions.c
@@ -1,4 +1,5 @@
-/*
+#if 0
+/**
* BME_mesh.c jan 2007
*
* BMesh mesh level functions.
@@ -267,7 +268,7 @@ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) {
CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
/*copy face corner data*/
- CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata);
+ CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata, 0, 0);
/*initialize memory pools*/
CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
@@ -462,7 +463,7 @@ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm)
CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
/*copy face corner data*/
- CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata);
+ CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata, 0, 0);
/*initialize memory pools*/
CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
@@ -474,10 +475,10 @@ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm)
totvert = dm->getNumVerts(dm);
totedge = dm->getNumEdges(dm);
- totface = dm->getNumFaces(dm);
+ totface = dm->getNumTessFaces(dm);
mvert = dm->getVertArray(dm);
medge = dm->getEdgeArray(dm);
- mface = dm->getFaceArray(dm);
+ mface = dm->getTessFaceArray(dm);
vert_array = MEM_mallocN(sizeof(*vert_array)*totvert,"BME_derivedmesh_to_bmesh BME_Vert* array");
@@ -574,7 +575,8 @@ DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm)
}
/*convert back to mesh*/
- result = CDDM_from_template(dm,totvert,totedge,totface);
+ /*BMESH_TODO this should add in mloops and mpolys as well*/
+ result = CDDM_from_template(dm,totvert,totedge,totface, 0, 0);
CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_BMESH, CD_CALLOC, totvert);
CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_BMESH, CD_CALLOC, totedge);
CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_BMESH, CD_CALLOC, totface);
@@ -617,7 +619,7 @@ DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm)
}
}
if(totface){
- mface = CDDM_get_faces(result);
+ mface = CDDM_get_tessfaces(result);
origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
/*make faces*/
for(i=0,f=bm->polys.first;f;f=f->next){
@@ -646,3 +648,4 @@ DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm)
BLI_edgehash_free(edge_hash, NULL);
return result;
}
+#endif
diff --git a/source/blender/blenkernel/intern/BME_eulers.c b/source/blender/blenkernel/intern/BME_eulers.c
index 25970dd8d91..215493fb6cf 100644
--- a/source/blender/blenkernel/intern/BME_eulers.c
+++ b/source/blender/blenkernel/intern/BME_eulers.c
@@ -1,4 +1,5 @@
-/*
+#if 0
+/**
* BME_eulers.c jan 2007
*
* BMesh Euler construction API.
@@ -131,13 +132,13 @@ BME_Edge *BME_ME(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2){
#ifndef BME_FASTEULER
/*count valance of v1*/
- if(v1->edge){
- d1 = BME_disk_getpointer(v1->edge,v1);
+ if(v1->e){
+ d1 = BME_disk_getpointer(v1->e,v1);
if(d1) valance1 = BME_cycle_length(d1);
else BME_error();
}
- if(v2->edge){
- d2 = BME_disk_getpointer(v2->edge,v2);
+ if(v2->e){
+ d2 = BME_disk_getpointer(v2->e,v2);
if(d2) valance2 = BME_cycle_length(d2);
else BME_error();
}
@@ -205,7 +206,7 @@ BME_Poly *BME_MF(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge **elist, int
elist[i]->eflag1 |= MF_CANDIDATE;
/*if elist[i] has a loop, count its radial length*/
- if(elist[i]->loop) elist[i]->eflag2 = BME_cycle_length(&(elist[i]->loop->radial));
+ if(elist[i]->loop) elist[i]->eflag2 = BME_cycle_length(&(elist[i]->l->radial));
else elist[i]->eflag2 = 0;
}
@@ -275,8 +276,8 @@ BME_Poly *BME_MF(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge **elist, int
for(i=0;i<len;i++){
curvert = vlist[i];
l = BME_create_loop(bm,curvert,NULL,f,NULL);
- if(!(f->loopbase)) f->loopbase = l;
- BME_cycle_append(f->loopbase, l);
+ if(!(f->loopbase)) f->lbase = l;
+ BME_cycle_append(f->lbase, l);
}
/*take care of edge pointers and radial cycle*/
@@ -300,7 +301,7 @@ BME_Poly *BME_MF(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge **elist, int
f->len = len;
/*Validation Loop cycle*/
- edok = BME_cycle_validate(len, f->loopbase);
+ edok = BME_cycle_validate(len, f->lbase);
if(!edok) BME_error();
for(i=0, l = f->loopbase; i<len; i++, l=l->next){
/*validate loop vert pointers*/
@@ -328,7 +329,7 @@ BME_Poly *BME_MF(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge **elist, int
*/
int BME_KV(BME_Mesh *bm, BME_Vert *v){
- if(v->edge == NULL){
+ if(v->e == NULL){
BLI_remlink(&(bm->verts), v);
BME_free_vert(bm,v);
return 1;
@@ -351,7 +352,7 @@ int BME_KE(BME_Mesh *bm, BME_Edge *e){
int edok;
/*Make sure that no faces!*/
- if(e->loop == NULL){
+ if(e->l == NULL){
BME_disk_remove_edge(e, e->v1);
BME_disk_remove_edge(e, e->v2);
@@ -387,14 +388,14 @@ int BME_KF(BME_Mesh *bm, BME_Poly *bply){
/*add validation to make sure that radial cycle is cleaned up ok*/
/*deal with radial cycle first*/
- len = BME_cycle_length(bply->loopbase);
+ len = BME_cycle_length(bply->lbase);
for(i=0, curloop=bply->loopbase; i < len; i++, curloop = curloop->next)
BME_radial_remove_loop(curloop, curloop->e);
/*now deallocate the editloops*/
for(i=0; i < len; i++){
- newbase = bply->loopbase->next;
- oldbase = bply->loopbase;
+ newbase = bply->lbase->next;
+ oldbase = bply->lbase;
BME_cycle_remove(oldbase, oldbase);
BME_free_loop(bm, oldbase);
bply->loopbase = newbase;
@@ -454,24 +455,24 @@ BME_Vert *BME_SEMV(BME_Mesh *bm, BME_Vert *tv, BME_Edge *e, BME_Edge **re){
/*add ne to tv's disk cycle*/
BME_disk_append_edge(ne, tv);
/*verify disk cycles*/
- diskbase = BME_disk_getpointer(ov->edge,ov);
+ diskbase = BME_disk_getpointer(ov->e,ov);
edok = BME_cycle_validate(valance1, diskbase);
if(!edok) BME_error();
- diskbase = BME_disk_getpointer(tv->edge,tv);
+ diskbase = BME_disk_getpointer(tv->e,tv);
edok = BME_cycle_validate(valance2, diskbase);
if(!edok) BME_error();
- diskbase = BME_disk_getpointer(nv->edge,nv);
+ diskbase = BME_disk_getpointer(nv->e,nv);
edok = BME_cycle_validate(2, diskbase);
if(!edok) BME_error();
/*Split the radial cycle if present*/
- if(e->loop){
+ if(e->l){
BME_Loop *nl,*l;
BME_CycleNode *radEBase=NULL, *radNEBase=NULL;
- int radlen = BME_cycle_length(&(e->loop->radial));
+ int radlen = BME_cycle_length(&(e->l->radial));
/*Take the next loop. Remove it from radial. Split it. Append to appropriate radials.*/
- while(e->loop){
- l=e->loop;
+ while(e->l){
+ l=e->l;
l->f->len++;
BME_radial_remove_loop(l,e);
@@ -524,17 +525,17 @@ BME_Vert *BME_SEMV(BME_Mesh *bm, BME_Vert *tv, BME_Edge *e, BME_Edge **re){
}
- e->loop = radEBase->data;
- ne->loop = radNEBase->data;
+ e->l = radEBase->data;
+ ne->l = radNEBase->data;
/*verify length of radial cycle*/
- edok = BME_cycle_validate(radlen,&(e->loop->radial));
+ edok = BME_cycle_validate(radlen,&(e->l->radial));
if(!edok) BME_error();
- edok = BME_cycle_validate(radlen,&(ne->loop->radial));
+ edok = BME_cycle_validate(radlen,&(ne->l->radial));
if(!edok) BME_error();
/*verify loop->v and loop->next->v pointers for e*/
- for(i=0,l=e->loop; i < radlen; i++, l = l->radial.next->data){
+ for(i=0,l=e->l; i < radlen; i++, l = l->radial_next){
if(!(l->e == e)) BME_error();
if(!(l->radial.data == l)) BME_error();
if(l->prev->e != ne && l->next->e != ne) BME_error();
@@ -543,11 +544,11 @@ BME_Vert *BME_SEMV(BME_Mesh *bm, BME_Vert *tv, BME_Edge *e, BME_Edge **re){
if(l->v == l->next->v) BME_error();
if(l->e == l->next->e) BME_error();
/*verify loop cycle for kloop->f*/
- edok = BME_cycle_validate(l->f->len, l->f->loopbase);
+ edok = BME_cycle_validate(l->f->len, l->f->lbase);
if(!edok) BME_error();
}
/*verify loop->v and loop->next->v pointers for ne*/
- for(i=0,l=ne->loop; i < radlen; i++, l = l->radial.next->data){
+ for(i=0,l=ne->l; i < radlen; i++, l = l->radial_next){
if(!(l->e == ne)) BME_error();
if(!(l->radial.data == l)) BME_error();
if(l->prev->e != e && l->next->e != e) BME_error();
@@ -556,7 +557,7 @@ BME_Vert *BME_SEMV(BME_Mesh *bm, BME_Vert *tv, BME_Edge *e, BME_Edge **re){
if(l->v == l->next->v) BME_error();
if(l->e == l->next->e) BME_error();
/*verify loop cycle for kloop->f. Redundant*/
- edok = BME_cycle_validate(l->f->len, l->f->loopbase);
+ edok = BME_cycle_validate(l->f->len, l->f->lbase);
if(!edok) BME_error();
}
}
@@ -601,7 +602,7 @@ BME_Poly *BME_SFME(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Lo
/*verify that v1 and v2 are in face.*/
- len = BME_cycle_length(f->loopbase);
+ len = BME_cycle_length(f->lbase);
for(i = 0, curloop = f->loopbase; i < len; i++, curloop = curloop->next){
if(curloop->v == v1) v1loop = curloop;
else if(curloop->v == v2) v2loop = curloop;
@@ -635,7 +636,7 @@ BME_Poly *BME_SFME(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Lo
/*I dont know how many loops are supposed to be in each face at this point! FIXME!*/
/*go through all of f2's loops and make sure they point to it properly.*/
- f2len = BME_cycle_length(f2->loopbase);
+ f2len = BME_cycle_length(f2->lbase);
for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = curloop->next) curloop->f = f2;
/*link up the new loops into the new edges radial*/
@@ -645,7 +646,7 @@ BME_Poly *BME_SFME(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Lo
f2->len = f2len;
- f1len = BME_cycle_length(f->loopbase);
+ f1len = BME_cycle_length(f->lbase);
f->len = f1len;
if(rl) *rl = f2loop;
@@ -693,7 +694,7 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv)
int len,radlen=0, halt = 0, i, valance1, valance2,edok;
if(BME_vert_in_edge(ke,kv) == 0) return 0;
- diskbase = BME_disk_getpointer(kv->edge, kv);
+ diskbase = BME_disk_getpointer(kv->e, kv);
len = BME_cycle_length(diskbase);
if(len == 2){
@@ -706,9 +707,9 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv)
else{
/*For verification later, count valance of ov and tv*/
- diskbase = BME_disk_getpointer(ov->edge, ov);
+ diskbase = BME_disk_getpointer(ov->e, ov);
valance1 = BME_cycle_length(diskbase);
- diskbase = BME_disk_getpointer(tv->edge, tv);
+ diskbase = BME_disk_getpointer(tv->e, tv);
valance2 = BME_cycle_length(diskbase);
/*remove oe from kv's disk cycle*/
@@ -723,10 +724,10 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv)
/*deal with radial cycle of ke*/
- if(ke->loop){
+ if(ke->l){
/*first step, fix the neighboring loops of all loops in ke's radial cycle*/
- radlen = BME_cycle_length(&(ke->loop->radial));
- for(i=0,killoop = ke->loop; i<radlen; i++, killoop = BME_radial_nextloop(killoop)){
+ radlen = BME_cycle_length(&(ke->l->radial));
+ for(i=0,killoop = ke->l; i<radlen; i++, killoop = BME_radial_nextloop(killoop)){
/*relink loops and fix vertex pointer*/
killoop->next->prev = killoop->prev;
killoop->prev->next = killoop->next;
@@ -734,11 +735,11 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv)
/*fix len attribute of face*/
killoop->f->len--;
- if(killoop->f->loopbase == killoop) killoop->f->loopbase = killoop->next;
+ if(killoop->f->loopbase == killoop) killoop->f->lbase = killoop->next;
}
/*second step, remove all the hanging loops attached to ke*/
- killoop = ke->loop;
- radlen = BME_cycle_length(&(ke->loop->radial));
+ killoop = ke->l;
+ radlen = BME_cycle_length(&(ke->l->radial));
/*make sure we have enough room in bm->lpar*/
if(bm->lparlen < radlen){
MEM_freeN(bm->lpar);
@@ -749,7 +750,7 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv)
i=0;
while(i<radlen){
bm->lpar[i] = killoop;
- killoop = killoop->radial.next->data;
+ killoop = killoop->radial_next;
i++;
}
i=0;
@@ -758,22 +759,22 @@ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv)
i++;
}
/*Validate radial cycle of oe*/
- edok = BME_cycle_validate(radlen,&(oe->loop->radial));
+ edok = BME_cycle_validate(radlen,&(oe->l->radial));
}
/*Validate disk cycles*/
- diskbase = BME_disk_getpointer(ov->edge,ov);
+ diskbase = BME_disk_getpointer(ov->e,ov);
edok = BME_cycle_validate(valance1, diskbase);
if(!edok) BME_error();
- diskbase = BME_disk_getpointer(tv->edge,tv);
+ diskbase = BME_disk_getpointer(tv->e,tv);
edok = BME_cycle_validate(valance2, diskbase);
if(!edok) BME_error();
/*Validate loop cycle of all faces attached to oe*/
- for(i=0,nextl = oe->loop; i<radlen; i++, nextl = BME_radial_nextloop(nextl)){
- edok = BME_cycle_validate(nextl->f->len,nextl->f->loopbase);
+ for(i=0,nextl = oe->l; i<radlen; i++, nextl = BME_radial_nextloop(nextl)){
+ edok = BME_cycle_validate(nextl->f->len,nextl->f->lbase);
if(!edok) BME_error();
}
/*deallocate edge*/
@@ -903,8 +904,8 @@ BME_Poly *BME_JFKE(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e)
if(f1 == f2) return NULL; //can't join a face to itself
/*verify that e is in both f1 and f2*/
- f1len = BME_cycle_length(f1->loopbase);
- f2len = BME_cycle_length(f2->loopbase);
+ f1len = BME_cycle_length(f1->lbase);
+ f2len = BME_cycle_length(f2->lbase);
for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = curloop->next){
if(curloop->e == e){
f1loop = curloop;
@@ -943,19 +944,19 @@ BME_Poly *BME_JFKE(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e)
f2loop->prev->next = f1loop->next;
/*if f1loop was baseloop, give f1loop->next the base.*/
- if(f1->loopbase == f1loop) f1->loopbase = f1loop->next;
+ if(f1->loopbase == f1loop) f1->lbase = f1loop->next;
/*validate the new loop*/
- loopok = BME_cycle_validate((f1len+f2len)-2, f1->loopbase);
+ loopok = BME_cycle_validate((f1len+f2len)-2, f1->lbase);
if(!loopok) BME_error();
/*make sure each loop points to the proper face*/
- newlen = BME_cycle_length(f1->loopbase);
+ newlen = BME_cycle_length(f1->lbase);
for(i = 0, curloop = f1->loopbase; i < newlen; i++, curloop = curloop->next) curloop->f = f1;
f1->len = newlen;
- edok = BME_cycle_validate(f1->len, f1->loopbase);
+ edok = BME_cycle_validate(f1->len, f1->lbase);
if(!edok) BME_error();
/*remove edge from the disk cycle of its two vertices.*/
@@ -971,3 +972,4 @@ BME_Poly *BME_JFKE(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e)
BME_free_poly(bm, f2);
return f1;
}
+#endif
diff --git a/source/blender/blenkernel/intern/BME_mesh.c b/source/blender/blenkernel/intern/BME_mesh.c
index 1b5761fb94e..89f9a6bc945 100644
--- a/source/blender/blenkernel/intern/BME_mesh.c
+++ b/source/blender/blenkernel/intern/BME_mesh.c
@@ -1,4 +1,5 @@
-/*
+#if 0
+/**
* BME_mesh.c jan 2007
*
* BMesh mesh level functions.
@@ -55,10 +56,10 @@ BME_Mesh *BME_make_mesh(int allocsize[4])
/*allocate the structure*/
BME_Mesh *bm = MEM_callocN(sizeof(BME_Mesh),"BMesh");
/*allocate the memory pools for the mesh elements*/
- bm->vpool = BLI_mempool_create(sizeof(BME_Vert), allocsize[0], allocsize[0], 0);
- bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1], 0);
- bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2], 0);
- bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3], 0);
+ bm->vpool = BLI_mempool_create(sizeof(BME_Vert), allocsize[0], allocsize[0], 1, 0);
+ bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1], 1, 0);
+ bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2], 1, 0);
+ bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3], 1, 0);
return bm;
}
/*
@@ -82,7 +83,7 @@ void BME_free_mesh(BME_Mesh *bm)
do{
CustomData_bmesh_free_block(&bm->ldata, &l->data);
l = l->next;
- }while(l!=f->loopbase);
+ }while(l!=f->lbase);
}
/*Free custom data pools, This should probably go in CustomData_free?*/
@@ -196,9 +197,9 @@ int BME_validate_mesh(struct BME_Mesh *bm, int halt)
if(e->v1 == e->v2) VHALT(halt);
/*validate e->d1.data and e->d2.data*/
if(e->d1.data != e || e->d2.data != e) VHALT(halt);
- /*validate e->loop->e*/
- if(e->loop){
- if(e->loop->e != e) VHALT(halt);
+ /*validate e->l->e*/
+ if(e->l){
+ if(e->l->e != e) VHALT(halt);
}
}
@@ -210,17 +211,17 @@ int BME_validate_mesh(struct BME_Mesh *bm, int halt)
}
/*Validate vertices and disk cycle*/
for(v=bm->verts.first; v; v=v->next){
- /*validate v->edge pointer*/
+ /*validate v->e pointer*/
if(v->tflag1){
- if(v->edge){
- ok = BME_vert_in_edge(v->edge,v);
+ if(v->e){
+ ok = BME_vert_in_edge(v->e,v);
if(!ok) VHALT(halt);
/*validate length of disk cycle*/
- diskbase = BME_disk_getpointer(v->edge, v);
+ diskbase = BME_disk_getpointer(v->e, v);
ok = BME_cycle_validate(v->tflag1, diskbase);
if(!ok) VHALT(halt);
/*validate that each edge in disk cycle contains V*/
- for(i=0, e=v->edge; i < v->tflag1; i++, e = BME_disk_nextedge(e,v)){
+ for(i=0, e=v->e; i < v->tflag1; i++, e = BME_disk_nextedge(e,v)){
ok = BME_vert_in_edge(e, v);
if(!ok) VHALT(halt);
}
@@ -242,7 +243,7 @@ int BME_validate_mesh(struct BME_Mesh *bm, int halt)
for(e=bm->edges.first; e; e=e->next) e->tflag2 = 0; //store incident faces
/*Validate the loop cycle integrity.*/
for(f=bm->polys.first; f; f=f->next){
- ok = BME_cycle_length(f->loopbase);
+ ok = BME_cycle_length(f->lbase);
if(ok > 1){
f->tflag1 = ok;
}
@@ -253,11 +254,11 @@ int BME_validate_mesh(struct BME_Mesh *bm, int halt)
if(!ok) VHALT(halt);
/*verify radial node data pointer*/
if(l->radial.data != l) VHALT(halt);
- /*validate l->e->loop poitner*/
- if(l->e->loop == NULL) VHALT(halt);
+ /*validate l->e->l poitner*/
+ if(l->e->l == NULL) VHALT(halt);
/*validate l->f pointer*/
if(l->f != f) VHALT(halt);
- /*see if l->e->loop is actually in radial cycle*/
+ /*see if l->e->l is actually in radial cycle*/
l->e->tflag2++;
}
@@ -265,8 +266,8 @@ int BME_validate_mesh(struct BME_Mesh *bm, int halt)
/*validate length of radial cycle*/
for(e=bm->edges.first; e; e=e->next){
- if(e->loop){
- ok = BME_cycle_validate(e->tflag2,&(e->loop->radial));
+ if(e->l){
+ ok = BME_cycle_validate(e->tflag2,&(e->l->radial));
if(!ok) VHALT(halt);
}
}
@@ -283,3 +284,4 @@ int BME_validate_mesh(struct BME_Mesh *bm, int halt)
void BME_error(void){
printf("BME modelling error!");
}
+#endif
diff --git a/source/blender/blenkernel/intern/BME_structure.c b/source/blender/blenkernel/intern/BME_structure.c
index 6d8a8339e46..789812a99c8 100644
--- a/source/blender/blenkernel/intern/BME_structure.c
+++ b/source/blender/blenkernel/intern/BME_structure.c
@@ -1,4 +1,5 @@
-/*
+#if 0
+/**
* BME_structure.c jan 2007
*
* Low level routines for manipulating the BMesh structure.
@@ -30,7 +31,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
-
+#if 0
/** \file blender/blenkernel/intern/BME_structure.c
* \ingroup bke
*/
@@ -90,7 +91,7 @@ BME_Vert *BME_addvertlist(BME_Mesh *bm, BME_Vert *example){
v->EID = bm->nextv;
v->co[0] = v->co[1] = v->co[2] = 0.0f;
v->no[0] = v->no[1] = v->no[2] = 0.0f;
- v->edge = NULL;
+ v->e = NULL;
v->data = NULL;
v->eflag1 = v->eflag2 = v->tflag1 = v->tflag2 = 0;
v->flag = v->h = 0;
@@ -118,7 +119,7 @@ BME_Edge *BME_addedgelist(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge *ex
e->d1.next = e->d1.prev = e->d2.next = e->d2.prev = NULL;
e->d1.data = e;
e->d2.data = e;
- e->loop = NULL;
+ e->l = NULL;
e->data = NULL;
e->eflag1 = e->eflag2 = e->tflag1 = e->tflag2 = 0;
e->flag = e->h = 0;
@@ -243,7 +244,7 @@ void BME_free_loop(BME_Mesh *bm, BME_Loop *l){
* BME_disk_getpointer
*
* 2: The Radial Cycle - A circle of face edges (BME_Loop) around an edge
- * Base: edge->loop->radial structure.
+ * Base: edge->l->radial structure.
*
* The radial cycle is similar to the radial cycle in the radial edge data structure.*
* Unlike the radial edge however, the radial cycle does not require a large amount of memory
@@ -259,7 +260,7 @@ void BME_free_loop(BME_Mesh *bm, BME_Loop *l){
*
*
* 3: The Loop Cycle - A circle of face edges around a polygon.
- * Base: polygon->loopbase.
+ * Base: polygon->lbase.
*
* The loop cycle keeps track of a faces vertices and edges. It should be noted that the
* direction of a loop cycle is either CW or CCW depending on the face normal, and is
@@ -447,15 +448,15 @@ int BME_disk_append_edge(BME_Edge *e, BME_Vert *v)
if(BME_vert_in_edge(e, v) == 0) return 0; /*check to make sure v is in e*/
/*check for loose vert first*/
- if(v->edge == NULL){
- v->edge = e;
+ if(v->e == NULL){
+ v->e = e;
base = tail = BME_disk_getpointer(e, v);
BME_cycle_append(base, tail); /*circular reference is ok!*/
return 1;
}
- /*insert e at the end of disk cycle and make it the new v->edge*/
- base = BME_disk_getpointer(v->edge, v);
+ /*insert e at the end of disk cycle and make it the new v->e*/
+ base = BME_disk_getpointer(v->e, v);
tail = BME_disk_getpointer(e, v);
BME_cycle_append(base, tail);
return 1;
@@ -478,18 +479,18 @@ void BME_disk_remove_edge(BME_Edge *e, BME_Vert *v)
BME_Edge *newbase;
int len;
- base = BME_disk_getpointer(v->edge, v);
+ base = BME_disk_getpointer(v->e, v);
remnode = BME_disk_getpointer(e, v);
- /*first deal with v->edge pointer...*/
+ /*first deal with v->e pointer...*/
len = BME_cycle_length(base);
if(len == 1) newbase = NULL;
- else if(v->edge == e) newbase = base->next-> data;
- else newbase = v->edge;
+ else if(v->e == e) newbase = base->next-> data;
+ else newbase = v->e;
/*remove and rebase*/
BME_cycle_remove(base, remnode);
- v->edge = newbase;
+ v->e = newbase;
}
/**
@@ -542,12 +543,12 @@ int BME_disk_count_edgeflag(BME_Vert *v, int eflag, int tflag){
BME_Edge *curedge;
int i, len=0, count=0;
- if(v->edge){
+ if(v->e){
if(eflag && tflag) return 0; /*tflag and eflag are reserved for different functions!*/
- diskbase = BME_disk_getpointer(v->edge, v);
+ diskbase = BME_disk_getpointer(v->e, v);
len = BME_cycle_length(diskbase);
- for(i = 0, curedge=v->edge; i<len; i++){
+ for(i = 0, curedge=v->e; i<len; i++){
if(tflag){
if(curedge->tflag1 == tflag) count++;
}
@@ -565,11 +566,11 @@ int BME_disk_hasedge(BME_Vert *v, BME_Edge *e){
BME_Edge *curedge;
int i, len=0;
- if(v->edge){
- diskbase = BME_disk_getpointer(v->edge,v);
+ if(v->e){
+ diskbase = BME_disk_getpointer(v->e,v);
len = BME_cycle_length(diskbase);
- for(i = 0, curedge=v->edge; i<len; i++){
+ for(i = 0, curedge=v->e; i<len; i++){
if(curedge == e) return 1;
else curedge=BME_disk_nextedge(curedge, v);
}
@@ -579,12 +580,12 @@ int BME_disk_hasedge(BME_Vert *v, BME_Edge *e){
/*end disk cycle routines*/
BME_Loop *BME_radial_nextloop(BME_Loop *l){
- return (BME_Loop*)(l->radial.next->data);
+ return (BME_Loop*)(l->radial_next);
}
void BME_radial_append(BME_Edge *e, BME_Loop *l){
- if(e->loop == NULL) e->loop = l;
- BME_cycle_append(&(e->loop->radial), &(l->radial));
+ if(e->l == NULL) e->l = l;
+ BME_cycle_append(&(e->l->radial), &(l->radial));
}
void BME_radial_remove_loop(BME_Loop *l, BME_Edge *e)
@@ -592,15 +593,15 @@ void BME_radial_remove_loop(BME_Loop *l, BME_Edge *e)
BME_Loop *newbase;
int len;
- /*deal with edge->loop pointer*/
- len = BME_cycle_length(&(e->loop->radial));
+ /*deal with edge->l pointer*/
+ len = BME_cycle_length(&(e->l->radial));
if(len == 1) newbase = NULL;
- else if(e->loop == l) newbase = e->loop->radial.next->data;
- else newbase = e->loop;
+ else if(e->l == l) newbase = e->l->radial_next;
+ else newbase = e->l;
/*remove and rebase*/
- BME_cycle_remove(&(e->loop->radial), &(l->radial));
- e->loop = newbase;
+ BME_cycle_remove(&(e->l->radial), &(l->radial));
+ e->l = newbase;
}
int BME_radial_find_face(BME_Edge *e,BME_Poly *f)
@@ -609,8 +610,8 @@ int BME_radial_find_face(BME_Edge *e,BME_Poly *f)
BME_Loop *curloop;
int i, len;
- len = BME_cycle_length(&(e->loop->radial));
- for(i = 0, curloop = e->loop; i < len; i++, curloop = curloop->radial.next->data){
+ len = BME_cycle_length(&(e->l->radial));
+ for(i = 0, curloop = e->l; i < len; i++, curloop = curloop->radial_next){
if(curloop->f == f) return 1;
}
return 0;
@@ -620,9 +621,11 @@ struct BME_Loop *BME_loop_find_loop(struct BME_Poly *f, struct BME_Vert *v) {
BME_Loop *l;
int i, len;
- len = BME_cycle_length(f->loopbase);
+ len = BME_cycle_length(f->lbase);
for (i = 0, l=f->loopbase; i < len; i++, l=l->next) {
if (l->v == v) return l;
}
return NULL;
}
+#endif
+#endif
diff --git a/source/blender/blenkernel/intern/BME_tools.c b/source/blender/blenkernel/intern/BME_tools.c
index d1c258cbc93..01bef563835 100644
--- a/source/blender/blenkernel/intern/BME_tools.c
+++ b/source/blender/blenkernel/intern/BME_tools.c
@@ -1,4 +1,5 @@
-/*
+#if 0
+/**
* BME_tools.c jan 2007
*
* Functions for changing the topology of a mesh.
@@ -118,20 +119,20 @@ static int BME_is_nonmanifold_vert(BME_Mesh *UNUSED(bm), BME_Vert *v) {
BME_Loop *l;
int len, count, flag;
- if (v->edge == NULL) {
+ if (v->e == NULL) {
/* loose vert */
return 1;
}
/* count edges while looking for non-manifold edges */
- oe = v->edge;
- for (len=0,e=v->edge; e != oe || (e == oe && len == 0); len++,e=BME_disk_nextedge(e,v)) {
- if (e->loop == NULL) {
+ oe = v->e;
+ for (len=0,e=v->e; e != oe || (e == oe && len == 0); len++,e=BME_disk_nextedge(e,v)) {
+ if (e->l == NULL) {
/* loose edge */
return 1;
}
- if (BME_cycle_length(&(e->loop->radial)) > 2) {
+ if (BME_cycle_length(&(e->l->radial)) > 2) {
/* edge shared by more than two faces */
return 1;
}
@@ -140,28 +141,28 @@ static int BME_is_nonmanifold_vert(BME_Mesh *UNUSED(bm), BME_Vert *v) {
count = 1;
flag = 1;
e = NULL;
- oe = v->edge;
- l = oe->loop;
+ oe = v->e;
+ l = oe->l;
while(e != oe) {
if (l->v == v) l = l->prev;
else l = l->next;
e = l->e;
count++; /* count the edges */
- if (flag && l->radial.next->data == l) {
+ if (flag && l->radial_next == l) {
/* we've hit the edge of an open mesh, reset once */
flag = 0;
count = 1;
oe = e;
e = NULL;
- l = oe->loop;
+ l = oe->l;
}
- else if (l->radial.next->data == l) {
+ else if (l->radial_next == l) {
/* break the loop */
e = oe;
}
else {
- l = l->radial.next->data;
+ l = l->radial_next;
}
}
@@ -178,8 +179,8 @@ static int BME_is_nonmanifold_vert(BME_Mesh *UNUSED(bm), BME_Vert *v) {
static BME_Poly *BME_JFKE_safe(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e) {
BME_Loop *l1, *l2;
- l1 = e->loop;
- l2 = l1->radial.next->data;
+ l1 = e->l;
+ l2 = l1->radial_next;
if (l1->v == l2->v) {
BME_loop_reverse(bm, f2);
}
@@ -231,8 +232,8 @@ static void BME_data_facevert_edgesplit(BME_Mesh *bm, BME_Vert *v1, BME_Vert *UN
w[0] = 1.0f - fac;
w[1] = fac;
- if(!e1->loop) return;
- l = e1->loop;
+ if(!e1->l) return;
+ l = e1->l;
do{
if(l->v == v1){
v1loop = l;
@@ -249,8 +250,8 @@ static void BME_data_facevert_edgesplit(BME_Mesh *bm, BME_Vert *v1, BME_Vert *UN
src[1] = v2loop->data;
CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, vloop->data);
- l = l->radial.next->data;
- }while(l!=e1->loop);
+ l = l->radial_next;
+ }while(l!=e1->l);
}
@@ -287,8 +288,8 @@ static void BME_collapse_vert(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv, float fa
w[0] = 1.0f - fac;
w[1] = fac;
- if(ke->loop){
- l = ke->loop;
+ if(ke->l){
+ l = ke->l;
do{
if(l->v == tv && l->next->v == kv){
tvloop = l;
@@ -298,8 +299,8 @@ static void BME_collapse_vert(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv, float fa
src[1] = tvloop->data;
CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, kvloop->data);
}
- l=l->radial.next->data;
- }while(l!=ke->loop);
+ l=l->radial_next;
+ }while(l!=ke->l);
}
BME_JEKV(bm,ke,kv);
}
@@ -405,12 +406,12 @@ static BME_Vert *BME_bevel_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Vert *v1, B
* so... here we walk around edges to find the needed verts */
forward = 1;
/* is_split_vert = 0; */ /* UNUSED */
- if (v->edge == NULL) {
+ if (v->e == NULL) {
//printf("We can't split a loose vert's edge!\n");
return NULL;
}
- e1 = v->edge; /* we just use the first two edges */
- e2 = BME_disk_nextedge(v->edge, v);
+ e1 = v->e; /* we just use the first two edges */
+ e2 = BME_disk_nextedge(v->e, v);
if (e1 == e2) {
//printf("You need at least two edges to use BME_bevel_split_edge()\n");
return NULL;
@@ -591,8 +592,8 @@ static float BME_bevel_set_max(BME_Vert *v1, BME_Vert *v2, float value, BME_Tran
static BME_Vert *BME_bevel_wire(BME_Mesh *bm, BME_Vert *v, float value, int res, int UNUSED(options), BME_TransData_Head *td) {
BME_Vert *ov1, *ov2, *v1, *v2;
- ov1 = BME_edge_getothervert(v->edge, v);
- ov2 = BME_edge_getothervert(BME_disk_nextedge(v->edge, v), v);
+ ov1 = BME_edge_getothervert(v->e, v);
+ ov2 = BME_edge_getothervert(BME_disk_nextedge(v->e, v), v);
/* split the edges */
v1 = BME_bevel_split_edge(bm,v,ov1,NULL,NULL,value,td);
@@ -607,7 +608,7 @@ static BME_Vert *BME_bevel_wire(BME_Mesh *bm, BME_Vert *v, float value, int res,
/* remove the original vert */
if (res) {
- BME_JEKV(bm,v->edge,v);
+ BME_JEKV(bm,v->e,v);
}
return v1;
@@ -632,7 +633,7 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUS
/* first, check to see if this edge was inset previously */
if ((l->prev->e->tflag1 & BME_BEVEL_ORIG) == 0
&& (l->v->tflag1 & BME_BEVEL_NONMAN) == 0) {
- kl = l->prev->radial.next->data;
+ kl = l->prev->radial_next;
if (kl->v == l->v) kl = kl->prev;
else kl = kl->next;
kv = l->v;
@@ -652,14 +653,14 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUS
l = l->next;
if (kl->v == kv) {
BME_split_face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e);
- BME_JFKE(bm,((BME_Loop*)kl->prev->radial.next->data)->f,kl->f,kl->prev->e);
+ BME_JFKE(bm,((BME_Loop*)kl->prev->radial_next)->f,kl->f,kl->prev->e);
BME_collapse_vert(bm, kl->e, kv, 1.0);
//BME_JEKV(bm,kl->e,kv);
}
else {
BME_split_face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e);
- BME_JFKE(bm,((BME_Loop*)kl->next->radial.next->data)->f,kl->f,kl->next->e);
+ BME_JFKE(bm,((BME_Loop*)kl->next->radial_next)->f,kl->f,kl->next->e);
BME_collapse_vert(bm, kl->e, kv, 1.0);
//BME_JEKV(bm,kl->e,kv);
}
@@ -670,7 +671,7 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUS
/* first, check to see if this edge was inset previously */
if ((l->next->e->tflag1 & BME_BEVEL_ORIG) == 0
&& (l->next->v->tflag1 & BME_BEVEL_NONMAN) == 0) {
- kl = l->next->radial.next->data;
+ kl = l->next->radial_next;
if (kl->v == l->next->v) kl = kl->prev;
else kl = kl->next;
kv = l->next->v;
@@ -689,13 +690,13 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUS
if (kv) {
if (kl->v == kv) {
BME_split_face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e);
- BME_JFKE(bm,((BME_Loop*)kl->prev->radial.next->data)->f,kl->f,kl->prev->e);
+ BME_JFKE(bm,((BME_Loop*)kl->prev->radial_next)->f,kl->f,kl->prev->e);
BME_collapse_vert(bm, kl->e, kv, 1.0);
//BME_JEKV(bm,kl->e,kv);
}
else {
BME_split_face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e);
- BME_JFKE(bm,((BME_Loop*)kl->next->radial.next->data)->f,kl->f,kl->next->e);
+ BME_JFKE(bm,((BME_Loop*)kl->next->radial_next)->f,kl->f,kl->next->e);
BME_collapse_vert(bm, kl->e, kv, 1.0);
//BME_JEKV(bm,kl->e,kv);
}
@@ -704,7 +705,7 @@ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUS
if ((v1->tflag1 & BME_BEVEL_NONMAN)==0 || (v2->tflag1 & BME_BEVEL_NONMAN)==0) {
BME_split_face(bm,f,v2,v1,&l,e);
l->e->tflag1 = BME_BEVEL_BEVEL;
- l = l->radial.next->data;
+ l = l->radial_next;
}
if (l->f != f){
@@ -870,8 +871,8 @@ static float BME_bevel_get_angle(BME_Mesh *UNUSED(bm), BME_Edge *e, BME_Vert *v)
BME_Loop *l1, *l2;
float vec1[3], vec2[3], vec3[3], vec4[3];
- l1 = e->loop;
- l2 = e->loop->radial.next->data;
+ l1 = e->l;
+ l2 = e->l->radial_next;
if (l1->v == v) {
v1 = l1->prev->v;
v2 = l1->next->v;
@@ -910,7 +911,7 @@ static int BME_face_sharededges(BME_Poly *f1, BME_Poly *f2){
do{
if(BME_radial_find_face(l->e,f2)) count++;
l = l->next;
- }while(l != f1->loopbase);
+ }while(l != f1->lbase);
return count;
}
@@ -955,11 +956,11 @@ static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int UNUSED(defg
*/
/* get disk cycle length */
- if (v->edge == NULL) {
+ if (v->e == NULL) {
len = 0;
}
else {
- len = BME_cycle_length(BME_disk_getpointer(v->edge,v));
+ len = BME_cycle_length(BME_disk_getpointer(v->e,v));
/* we'll assign a default transform data to every vert (except the loose ones) */
/* vtd = */ /* UNUSED */ BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 0, -1, -1, NULL);
}
@@ -1026,13 +1027,13 @@ static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int UNUSED(defg
* i.e. the vert's weight is the average of the weights of its weighted edges
*/
- if (e->loop == NULL) {
+ if (e->l == NULL) {
len = 0;
e->v1->tflag1 |= BME_BEVEL_NONMAN;
e->v2->tflag1 |= BME_BEVEL_NONMAN;
}
else {
- len = BME_cycle_length(&(e->loop->radial));
+ len = BME_cycle_length(&(e->l->radial));
}
if (len > 2) {
@@ -1096,7 +1097,7 @@ static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int UNUSED(defg
for (e=bm->edges.first; e; e=e->next){
if(e->tflag1 & BME_BEVEL_BEVEL){
int count = 0;
- count = BME_face_sharededges(e->loop->f, ((BME_Loop*)e->loop->radial.next->data)->f);
+ count = BME_face_sharededges(e->l->f, ((BME_Loop*)e->l->radial_next)->f);
if(count > 1){
e->tflag1 &= ~BME_BEVEL_BEVEL;
}
@@ -1146,26 +1147,26 @@ static void bmesh_dissolve_disk(BME_Mesh *bm, BME_Vert *v){
BME_Edge *e;
int done, len;
- if(v->edge){
+ if(v->e){
done = 0;
while(!done){
done = 1;
- e = v->edge; /*loop the edge looking for a edge to dissolve*/
+ e = v->e; /*loop the edge looking for a edge to dissolve*/
do{
f = NULL;
- len = BME_cycle_length(&(e->loop->radial));
+ len = BME_cycle_length(&(e->l->radial));
if(len == 2){
- f = BME_JFKE_safe(bm,e->loop->f, ((BME_Loop*)(e->loop->radial.next->data))->f, e);
+ f = BME_JFKE_safe(bm,e->l->f, ((BME_Loop*)(e->l->radial_next))->f, e);
}
if(f){
done = 0;
break;
}
e = BME_disk_nextedge(e,v);
- }while(e != v->edge);
+ }while(e != v->e);
}
- BME_collapse_vert(bm, v->edge, v, 1.0);
- //BME_JEKV(bm,v->edge,v);
+ BME_collapse_vert(bm, v->e, v, 1.0);
+ //BME_JEKV(bm,v->e,v);
}
}
static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, int UNUSED(defgrp_index), BME_TransData_Head *td) {
@@ -1191,7 +1192,7 @@ static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options,
else if (res && ((v->tflag1 & BME_BEVEL_BEVEL) && (v->tflag1 & BME_BEVEL_ORIG))) {
int count = 0;
/* first, make sure we're not sitting on an edge to be removed */
- oe = v->edge;
+ oe = v->e;
e = BME_disk_nextedge(oe,v);
while ((e->tflag1 & BME_BEVEL_BEVEL) && (e->tflag1 & BME_BEVEL_ORIG)) {
e = BME_disk_nextedge(e,v);
@@ -1205,7 +1206,7 @@ static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options,
while ( (e = BME_disk_next_edgeflag(oe, v, 0, BME_BEVEL_ORIG | BME_BEVEL_BEVEL)) ) {
count++;
/* join the faces (we'll split them later) */
- f = BME_JFKE_safe(bm,e->loop->f,((BME_Loop*)e->loop->radial.next->data)->f,e);
+ f = BME_JFKE_safe(bm,e->l->f,((BME_Loop*)e->l->radial_next)->f,e);
if (!f){
//printf("Non-manifold geometry not getting tagged right?\n");
}
@@ -1216,10 +1217,10 @@ static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options,
/* all original edges marked to be beveled have been removed;
* now we need to link up the edges for this "corner" */
- len = BME_cycle_length(BME_disk_getpointer(v->edge, v));
- for (i=0,e=v->edge; i < len; i++,e=BME_disk_nextedge(e,v)) {
- l = e->loop;
- l2 = l->radial.next->data;
+ len = BME_cycle_length(BME_disk_getpointer(v->e, v));
+ for (i=0,e=v->e; i < len; i++,e=BME_disk_nextedge(e,v)) {
+ l = e->l;
+ l2 = l->radial_next;
if (l->v != v) l = l->next;
if (l2->v != v) l2 = l2->next;
/* look for faces that have had the original edges removed via JFKE */
@@ -1325,3 +1326,4 @@ BME_Mesh *BME_bevel(BME_Mesh *bm, float value, int res, int options, int defgrp_
BME_free_transdata(td);
return bm;
}
+#endif
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 0c99735f73e..769f6b04cf4 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -31,7 +31,7 @@
#include <string.h>
-
+#include "limits.h"
#include "MEM_guardedalloc.h"
@@ -46,6 +46,7 @@
#include "BLI_editVert.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
+#include "BLI_array.h"
#include "BLI_pbvh.h"
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
@@ -60,6 +61,9 @@
#include "BKE_texture.h"
#include "BKE_multires.h"
#include "BKE_armature.h"
+#include "BKE_particle.h"
+#include "BKE_tessmesh.h"
+#include "BKE_bvhutils.h"
#ifdef WITH_GAMEENGINE
#include "BKE_navmesh_conversion.h"
@@ -77,6 +81,9 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
+static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *ob);
+static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid);
+
///////////////////////////////////
///////////////////////////////////
@@ -114,14 +121,42 @@ static MFace *dm_getFaceArray(DerivedMesh *dm)
if (!mface) {
mface = CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL,
- dm->getNumFaces(dm));
+ dm->getNumTessFaces(dm));
CustomData_set_layer_flag(&dm->faceData, CD_MFACE, CD_FLAG_TEMPORARY);
- dm->copyFaceArray(dm, mface);
+ dm->copyTessFaceArray(dm, mface);
}
return mface;
}
+static MLoop *dm_getLoopArray(DerivedMesh *dm)
+{
+ MLoop *mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
+
+ if (!mloop) {
+ mloop = CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL,
+ dm->numLoopData);
+ CustomData_set_layer_flag(&dm->loopData, CD_MLOOP, CD_FLAG_TEMPORARY);
+ dm->copyLoopArray(dm, mloop);
+ }
+
+ return mloop;
+}
+
+static MPoly *dm_getPolyArray(DerivedMesh *dm)
+{
+ MPoly *mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
+
+ if (!mpoly) {
+ mpoly = CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL,
+ dm->getNumFaces(dm));
+ CustomData_set_layer_flag(&dm->polyData, CD_MPOLY, CD_FLAG_TEMPORARY);
+ dm->copyPolyArray(dm, mpoly);
+ }
+
+ return mpoly;
+}
+
static MVert *dm_dupVertArray(DerivedMesh *dm)
{
MVert *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumVerts(dm),
@@ -144,41 +179,98 @@ static MEdge *dm_dupEdgeArray(DerivedMesh *dm)
static MFace *dm_dupFaceArray(DerivedMesh *dm)
{
- MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumFaces(dm),
+ MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumTessFaces(dm),
"dm_dupFaceArray tmp");
- if(tmp) dm->copyFaceArray(dm, tmp);
+ if(tmp) dm->copyTessFaceArray(dm, tmp);
+
+ return tmp;
+}
+
+static MLoop *dm_dupLoopArray(DerivedMesh *dm)
+{
+ MLoop *tmp = MEM_callocN(sizeof(*tmp) * dm->numLoopData,
+ "dm_dupLoopArray tmp");
+
+ if(tmp) dm->copyLoopArray(dm, tmp);
return tmp;
}
+static MPoly *dm_dupPolyArray(DerivedMesh *dm)
+{
+ MPoly *tmp = MEM_callocN(sizeof(*tmp) * dm->numFaceData,
+ "dm_dupPolyArray tmp");
+
+ if(tmp) dm->copyPolyArray(dm, tmp);
+
+ return tmp;
+}
+
+static CustomData *dm_getVertCData(DerivedMesh *dm)
+{
+ return &dm->vertData;
+}
+
+static CustomData *dm_getEdgeCData(DerivedMesh *dm)
+{
+ return &dm->edgeData;
+}
+
+static CustomData *dm_getFaceCData(DerivedMesh *dm)
+{
+ return &dm->faceData;
+}
+
+static CustomData *dm_getLoopCData(DerivedMesh *dm)
+{
+ return &dm->loopData;
+}
+
+static CustomData *dm_getPolyCData(DerivedMesh *dm)
+{
+ return &dm->polyData;
+}
+
void DM_init_funcs(DerivedMesh *dm)
{
/* default function implementations */
dm->getVertArray = dm_getVertArray;
dm->getEdgeArray = dm_getEdgeArray;
- dm->getFaceArray = dm_getFaceArray;
+ dm->getTessFaceArray = dm_getFaceArray;
+ dm->getLoopArray = dm_getLoopArray;
+ dm->getPolyArray = dm_getPolyArray;
dm->dupVertArray = dm_dupVertArray;
dm->dupEdgeArray = dm_dupEdgeArray;
- dm->dupFaceArray = dm_dupFaceArray;
+ dm->dupTessFaceArray = dm_dupFaceArray;
+ dm->dupLoopArray = dm_dupLoopArray;
+ dm->dupPolyArray = dm_dupPolyArray;
+
+ dm->getVertDataLayout = dm_getVertCData;
+ dm->getEdgeDataLayout = dm_getEdgeCData;
+ dm->getTessFaceDataLayout = dm_getFaceCData;
+ dm->getLoopDataLayout = dm_getLoopCData;
+ dm->getFaceDataLayout = dm_getPolyCData;
dm->getVertData = DM_get_vert_data;
dm->getEdgeData = DM_get_edge_data;
- dm->getFaceData = DM_get_face_data;
+ dm->getTessFaceData = DM_get_face_data;
dm->getVertDataArray = DM_get_vert_data_layer;
dm->getEdgeDataArray = DM_get_edge_data_layer;
- dm->getFaceDataArray = DM_get_face_data_layer;
+ dm->getTessFaceDataArray = DM_get_tessface_data_layer;
bvhcache_init(&dm->bvhCache);
}
-void DM_init(DerivedMesh *dm, DerivedMeshType type,
- int numVerts, int numEdges, int numFaces)
+void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges,
+ int numFaces, int numLoops, int numPoly)
{
dm->type = type;
dm->numVertData = numVerts;
dm->numEdgeData = numEdges;
dm->numFaceData = numFaces;
+ dm->numLoopData = numLoops;
+ dm->numPolyData = numPoly;
DM_init_funcs(dm);
@@ -186,7 +278,8 @@ void DM_init(DerivedMesh *dm, DerivedMeshType type,
}
void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
- int numVerts, int numEdges, int numFaces)
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys)
{
CustomData_copy(&source->vertData, &dm->vertData, CD_MASK_DERIVEDMESH,
CD_CALLOC, numVerts);
@@ -194,11 +287,17 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type
CD_CALLOC, numEdges);
CustomData_copy(&source->faceData, &dm->faceData, CD_MASK_DERIVEDMESH,
CD_CALLOC, numFaces);
+ CustomData_copy(&source->loopData, &dm->loopData, CD_MASK_DERIVEDMESH,
+ CD_CALLOC, numLoops);
+ CustomData_copy(&source->polyData, &dm->polyData, CD_MASK_DERIVEDMESH,
+ CD_CALLOC, numPolys);
dm->type = type;
dm->numVertData = numVerts;
dm->numEdgeData = numEdges;
dm->numFaceData = numFaces;
+ dm->numLoopData = numLoops;
+ dm->numPolyData = numPolys;
DM_init_funcs(dm);
@@ -213,6 +312,8 @@ int DM_release(DerivedMesh *dm)
CustomData_free(&dm->vertData, dm->numVertData);
CustomData_free(&dm->edgeData, dm->numEdgeData);
CustomData_free(&dm->faceData, dm->numFaceData);
+ CustomData_free(&dm->loopData, dm->numLoopData);
+ CustomData_free(&dm->polyData, dm->numPolyData);
return 1;
}
@@ -220,29 +321,82 @@ int DM_release(DerivedMesh *dm)
CustomData_free_temporary(&dm->vertData, dm->numVertData);
CustomData_free_temporary(&dm->edgeData, dm->numEdgeData);
CustomData_free_temporary(&dm->faceData, dm->numFaceData);
+ CustomData_free_temporary(&dm->loopData, dm->numLoopData);
+ CustomData_free_temporary(&dm->polyData, dm->numPolyData);
return 0;
}
}
-void DM_to_mesh(DerivedMesh *dm, Mesh *me)
+void DM_DupPolys(DerivedMesh *source, DerivedMesh *target)
+{
+ CustomData_copy(&source->loopData, &target->loopData, CD_MASK_DERIVEDMESH, CD_CALLOC, source->numLoopData);
+ CustomData_copy(&source->polyData, &target->polyData, CD_MASK_DERIVEDMESH, CD_CALLOC, source->numPolyData);
+
+ target->numLoopData = source->numLoopData;
+ target->numPolyData = source->numPolyData;
+
+ if (!CustomData_has_layer(&target->polyData, CD_MPOLY)) {
+ MPoly *mpoly;
+ MLoop *mloop;
+
+ mloop = source->dupLoopArray(source);
+ mpoly = source->dupPolyArray(source);
+ CustomData_add_layer(&target->loopData, CD_MLOOP, CD_ASSIGN, mloop, source->numLoopData);
+ CustomData_add_layer(&target->polyData, CD_MPOLY, CD_ASSIGN, mpoly, source->numPolyData);
+ }
+}
+
+void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
{
/* dm might depend on me, so we need to do everything with a local copy */
Mesh tmp = *me;
- int totvert, totedge, totface;
-
+ int totvert, totedge, totface, totloop, totpoly;
+ int did_shapekeys=0;
+
memset(&tmp.vdata, 0, sizeof(tmp.vdata));
memset(&tmp.edata, 0, sizeof(tmp.edata));
memset(&tmp.fdata, 0, sizeof(tmp.fdata));
+ memset(&tmp.ldata, 0, sizeof(tmp.ldata));
+ memset(&tmp.pdata, 0, sizeof(tmp.pdata));
totvert = tmp.totvert = dm->getNumVerts(dm);
totedge = tmp.totedge = dm->getNumEdges(dm);
- totface = tmp.totface = dm->getNumFaces(dm);
+ totface = tmp.totface = dm->getNumTessFaces(dm);
+ totpoly = tmp.totpoly = dm->getNumFaces(dm);
+ totloop = tmp.totloop = dm->numLoopData;
CustomData_copy(&dm->vertData, &tmp.vdata, CD_MASK_MESH, CD_DUPLICATE, totvert);
CustomData_copy(&dm->edgeData, &tmp.edata, CD_MASK_MESH, CD_DUPLICATE, totedge);
CustomData_copy(&dm->faceData, &tmp.fdata, CD_MASK_MESH, CD_DUPLICATE, totface);
+ CustomData_copy(&dm->loopData, &tmp.ldata, CD_MASK_MESH, CD_DUPLICATE, totloop);
+ CustomData_copy(&dm->polyData, &tmp.pdata, CD_MASK_MESH, CD_DUPLICATE, totpoly);
+ if (CustomData_has_layer(&dm->vertData, CD_SHAPEKEY)) {
+ KeyBlock *kb;
+ int i=0;
+
+ if (ob) {
+ for (kb=me->key->block.first; kb; kb=kb->next, i++) {
+ if (i == ob->shapenr-1) {
+ i = kb->uid;
+ break;
+ }
+ }
+
+ if (!kb) {
+ printf("error in DM_to_mesh: could not find active shapekey! eek!!\n");
+ i = INT_MAX;
+ }
+ } else {
+ /*if no object, set to INT_MAX so we don't mess up any shapekey layers*/
+ i = INT_MAX;
+ }
+
+ shapekey_layers_to_keyblocks(dm, me, i);
+ did_shapekeys = 1;
+ }
+
/* not all DerivedMeshes store their verts/edges/faces in CustomData, so
we set them here in case they are missing */
if(!CustomData_has_layer(&tmp.vdata, CD_MVERT))
@@ -250,14 +404,21 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me)
if(!CustomData_has_layer(&tmp.edata, CD_MEDGE))
CustomData_add_layer(&tmp.edata, CD_MEDGE, CD_ASSIGN, dm->dupEdgeArray(dm), totedge);
if(!CustomData_has_layer(&tmp.fdata, CD_MFACE))
- CustomData_add_layer(&tmp.fdata, CD_MFACE, CD_ASSIGN, dm->dupFaceArray(dm), totface);
+ CustomData_add_layer(&tmp.fdata, CD_MFACE, CD_ASSIGN, dm->dupTessFaceArray(dm), totface);
+ if(!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) {
+ tmp.mloop = dm->dupLoopArray(dm);
+ tmp.mpoly = dm->dupPolyArray(dm);
+
+ CustomData_add_layer(&tmp.ldata, CD_MLOOP, CD_ASSIGN, tmp.mloop, tmp.totloop);
+ CustomData_add_layer(&tmp.pdata, CD_MPOLY, CD_ASSIGN, tmp.mpoly, tmp.totpoly);
+ }
/* object had got displacement layer, should copy this layer to save sculpted data */
/* NOTE: maybe some other layers should be copied? nazgul */
- if(CustomData_has_layer(&me->fdata, CD_MDISPS)) {
- if (totface == me->totface) {
- MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
- CustomData_add_layer(&tmp.fdata, CD_MDISPS, CD_DUPLICATE, mdisps, totface);
+ if(CustomData_has_layer(&me->ldata, CD_MDISPS)) {
+ if (totloop == me->totloop) {
+ MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
+ CustomData_add_layer(&tmp.ldata, CD_MDISPS, CD_DUPLICATE, mdisps, totloop);
}
}
@@ -266,9 +427,14 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me)
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
-
- /* if the number of verts has changed, remove invalid data */
- if(tmp.totvert != me->totvert) {
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
+
+ /* ok, this should now use new CD shapekey data,
+ which shouuld be fed through the modifier
+ stack*/
+ if(tmp.totvert != me->totvert && !did_shapekeys && me->key) {
+ printf("YEEK! this should be recoded! Shape key loss!!!\n");
if(tmp.key) tmp.key->id.us--;
tmp.key = NULL;
}
@@ -313,11 +479,21 @@ void DM_add_edge_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
CustomData_add_layer(&dm->edgeData, type, alloctype, layer, dm->numEdgeData);
}
-void DM_add_face_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
+void DM_add_tessface_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
{
CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numFaceData);
}
+static void DM_add_loop_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
+{
+ CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData);
+}
+
+void DM_add_face_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
+{
+ CustomData_add_layer(&dm->polyData, type, alloctype, layer, dm->numPolyData);
+}
+
void *DM_get_vert_data(DerivedMesh *dm, int index, int type)
{
return CustomData_get(&dm->vertData, index, type);
@@ -349,14 +525,19 @@ void *DM_get_edge_data_layer(DerivedMesh *dm, int type)
return CustomData_get_layer(&dm->edgeData, type);
}
-void *DM_get_face_data_layer(DerivedMesh *dm, int type)
+void *DM_get_tessface_data_layer(DerivedMesh *dm, int type)
{
if(type == CD_MFACE)
- return dm->getFaceArray(dm);
+ return dm->getTessFaceArray(dm);
return CustomData_get_layer(&dm->faceData, type);
}
+void *DM_get_face_data_layer(DerivedMesh *dm, int type)
+{
+ return CustomData_get_layer(&dm->polyData, type);
+}
+
void DM_set_vert_data(DerivedMesh *dm, int index, int type, void *data)
{
CustomData_set(&dm->vertData, index, type, data);
@@ -386,13 +567,27 @@ void DM_copy_edge_data(DerivedMesh *source, DerivedMesh *dest,
source_index, dest_index, count);
}
-void DM_copy_face_data(DerivedMesh *source, DerivedMesh *dest,
+void DM_copy_tessface_data(DerivedMesh *source, DerivedMesh *dest,
int source_index, int dest_index, int count)
{
CustomData_copy_data(&source->faceData, &dest->faceData,
source_index, dest_index, count);
}
+void DM_copy_loop_data(DerivedMesh *source, DerivedMesh *dest,
+ int source_index, int dest_index, int count)
+{
+ CustomData_copy_data(&source->loopData, &dest->loopData,
+ source_index, dest_index, count);
+}
+
+void DM_copy_face_data(DerivedMesh *source, DerivedMesh *dest,
+ int source_index, int dest_index, int count)
+{
+ CustomData_copy_data(&source->polyData, &dest->polyData,
+ source_index, dest_index, count);
+}
+
void DM_free_vert_data(struct DerivedMesh *dm, int index, int count)
{
CustomData_free_elem(&dm->vertData, index, count);
@@ -403,11 +598,21 @@ void DM_free_edge_data(struct DerivedMesh *dm, int index, int count)
CustomData_free_elem(&dm->edgeData, index, count);
}
-void DM_free_face_data(struct DerivedMesh *dm, int index, int count)
+void DM_free_tessface_data(struct DerivedMesh *dm, int index, int count)
{
CustomData_free_elem(&dm->faceData, index, count);
}
+void DM_free_loop_data(struct DerivedMesh *dm, int index, int count)
+{
+ CustomData_free_elem(&dm->loopData, index, count);
+}
+
+void DM_free_face_data(struct DerivedMesh *dm, int index, int count)
+{
+ CustomData_free_elem(&dm->polyData, index, count);
+}
+
void DM_interp_vert_data(DerivedMesh *source, DerivedMesh *dest,
int *src_indices, float *weights,
int count, int dest_index)
@@ -425,7 +630,7 @@ void DM_interp_edge_data(DerivedMesh *source, DerivedMesh *dest,
weights, (float*)vert_weights, count, dest_index);
}
-void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest,
+void DM_interp_tessface_data(DerivedMesh *source, DerivedMesh *dest,
int *src_indices,
float *weights, FaceVertWeight *vert_weights,
int count, int dest_index)
@@ -434,13 +639,28 @@ void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest,
weights, (float*)vert_weights, count, dest_index);
}
-void DM_swap_face_data(DerivedMesh *dm, int index, const int *corner_indices)
+void DM_swap_tessface_data(DerivedMesh *dm, int index, const int *corner_indices)
{
CustomData_swap(&dm->faceData, index, corner_indices);
}
-///
+void DM_interp_loop_data(DerivedMesh *source, DerivedMesh *dest,
+ int *src_indices,
+ float *weights, int count, int dest_index)
+{
+ CustomData_interp(&source->loopData, &dest->loopData, src_indices,
+ weights, NULL, count, dest_index);
+}
+
+void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest,
+ int *src_indices,
+ float *weights, int count, int dest_index)
+{
+ CustomData_interp(&source->polyData, &dest->polyData, src_indices,
+ weights, NULL, count, dest_index);
+}
+///
DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3])
{
DerivedMesh *dm = CDDM_from_mesh(me, ob);
@@ -456,1046 +676,10 @@ DerivedMesh *mesh_create_derived(Mesh *me, Object *ob, float (*vertCos)[3])
return dm;
}
-///
-
-typedef struct {
- DerivedMesh dm;
-
- EditMesh *em;
- float (*vertexCos)[3];
- float (*vertexNos)[3];
- float (*faceNos)[3];
-} EditMeshDerivedMesh;
-
-static void emDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
- EditVert *eve;
- int i;
-
- for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
- if (emdm->vertexCos) {
- func(userData, i, emdm->vertexCos[i], emdm->vertexNos[i], NULL);
- } else {
- func(userData, i, eve->co, eve->no, NULL);
- }
- }
-}
-static void emDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
- EditEdge *eed;
- int i;
-
- if (emdm->vertexCos) {
- EditVert *eve;
-
- for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
- eve->tmp.l = (intptr_t) i++;
- for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next)
- func(userData, i, emdm->vertexCos[(int) eed->v1->tmp.l], emdm->vertexCos[(int) eed->v2->tmp.l]);
- } else {
- for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next)
- func(userData, i, eed->v1->co, eed->v2->co);
- }
-}
-static void emDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
- EditEdge *eed;
- int i;
-
- if (emdm->vertexCos) {
- EditVert *eve;
-
- for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
- eve->tmp.l = (intptr_t) i++;
-
- glBegin(GL_LINES);
- for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
- if(!setDrawOptions || setDrawOptions(userData, i)) {
- glVertex3fv(emdm->vertexCos[(int) eed->v1->tmp.l]);
- glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]);
- }
- }
- glEnd();
- } else {
- glBegin(GL_LINES);
- for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
- if(!setDrawOptions || setDrawOptions(userData, i)) {
- glVertex3fv(eed->v1->co);
- glVertex3fv(eed->v2->co);
- }
- }
- glEnd();
- }
-}
-static void emDM_drawEdges(DerivedMesh *dm, int UNUSED(drawLooseEdges), int UNUSED(drawAllEdges))
-{
- emDM_drawMappedEdges(dm, NULL, NULL);
-}
-static void emDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
- EditEdge *eed;
- int i;
-
- if (emdm->vertexCos) {
- EditVert *eve;
-
- for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
- eve->tmp.l = (intptr_t) i++;
-
- glBegin(GL_LINES);
- for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
- if(!setDrawOptions || setDrawOptions(userData, i)) {
- setDrawInterpOptions(userData, i, 0.0);
- glVertex3fv(emdm->vertexCos[(int) eed->v1->tmp.l]);
- setDrawInterpOptions(userData, i, 1.0);
- glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]);
- }
- }
- glEnd();
- } else {
- glBegin(GL_LINES);
- for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
- if(!setDrawOptions || setDrawOptions(userData, i)) {
- setDrawInterpOptions(userData, i, 0.0);
- glVertex3fv(eed->v1->co);
- setDrawInterpOptions(userData, i, 1.0);
- glVertex3fv(eed->v2->co);
- }
- }
- glEnd();
- }
-}
-
-static void emDM_drawUVEdges(DerivedMesh *dm)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
- EditFace *efa;
- MTFace *tf;
-
- glBegin(GL_LINES);
- for(efa= emdm->em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&emdm->em->fdata, efa->data, CD_MTFACE);
-
- if(tf && !(efa->h)) {
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
-
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
-
- if (!efa->v4) {
- glVertex2fv(tf->uv[2]);
- glVertex2fv(tf->uv[0]);
- } else {
- glVertex2fv(tf->uv[2]);
- glVertex2fv(tf->uv[3]);
- glVertex2fv(tf->uv[3]);
- glVertex2fv(tf->uv[0]);
- }
- }
- }
- glEnd();
-}
-
-static void emDM__calcFaceCent(EditFace *efa, float cent[3], float (*vertexCos)[3])
-{
- if (vertexCos) {
- VECCOPY(cent, vertexCos[(int) efa->v1->tmp.l]);
- add_v3_v3(cent, vertexCos[(int) efa->v2->tmp.l]);
- add_v3_v3(cent, vertexCos[(int) efa->v3->tmp.l]);
- if (efa->v4) add_v3_v3(cent, vertexCos[(int) efa->v4->tmp.l]);
- } else {
- VECCOPY(cent, efa->v1->co);
- add_v3_v3(cent, efa->v2->co);
- add_v3_v3(cent, efa->v3->co);
- if (efa->v4) add_v3_v3(cent, efa->v4->co);
- }
-
- if (efa->v4) {
- mul_v3_fl(cent, 0.25f);
- } else {
- mul_v3_fl(cent, 0.33333333333f);
- }
-}
-static void emDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
- EditVert *eve;
- EditFace *efa;
- float cent[3];
- int i;
-
- if (emdm->vertexCos) {
- for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
- eve->tmp.l = (intptr_t) i++;
- }
-
- for(i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
- emDM__calcFaceCent(efa, cent, emdm->vertexCos);
- func(userData, i, cent, emdm->vertexCos?emdm->faceNos[i]:efa->n);
- }
-}
-
-/* note, material function is ignored for now. */
-static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int UNUSED(useColors), int (*setMaterial)(int, void *attribs),
- int (*compareDrawOptions)(void *userData, int cur_index, int next_index))
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
- EditFace *efa;
- int i, draw;
- const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
-
- /* GL_ZERO is used to detect if drawing has started or not */
- GLenum poly_prev= GL_ZERO;
- GLenum shade_prev= GL_ZERO;
-
- (void)setMaterial; /* unused */
-
- /* currently unused -- each original face is handled separately */
- (void)compareDrawOptions;
-
- if (emdm->vertexCos) {
- /* add direct access */
- float (*vertexCos)[3]= emdm->vertexCos;
- float (*vertexNos)[3]= emdm->vertexNos;
- float (*faceNos)[3]= emdm->faceNos;
- EditVert *eve;
-
- for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
- eve->tmp.l = (intptr_t) i++;
-
- for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
- int drawSmooth = (efa->flag & ME_SMOOTH);
- draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth);
- if(draw) {
- const GLenum poly_type= efa->v4 ? GL_QUADS:GL_TRIANGLES;
- if (draw==2) { /* enabled with stipple */
-
- if(poly_prev != GL_ZERO) glEnd();
- poly_prev= GL_ZERO; /* force glBegin */
-
- glEnable(GL_POLYGON_STIPPLE);
- glPolygonStipple(stipple_quarttone);
- }
-
- if(skip_normals) {
- if(poly_type != poly_prev) {
- if(poly_prev != GL_ZERO) glEnd();
- glBegin((poly_prev= poly_type));
- }
- glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
- if(poly_type == GL_QUADS) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
- }
- else {
- const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
- if (shade_type != shade_prev) {
- if(poly_prev != GL_ZERO) glEnd();
- glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
- glBegin((poly_prev= poly_type));
- }
- else if(poly_type != poly_prev) {
- if(poly_prev != GL_ZERO) glEnd();
- glBegin((poly_prev= poly_type));
- }
-
- if (!drawSmooth) {
- glNormal3fv(faceNos[i]);
- glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
- if(poly_type == GL_QUADS) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
- } else {
- glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
- glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
- glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
- if(poly_type == GL_QUADS) {
- glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
- }
- }
- }
-
-
- if (draw==2) {
- glEnd();
- poly_prev= GL_ZERO; /* force glBegin */
-
- glDisable(GL_POLYGON_STIPPLE);
- }
- }
- }
- }
- else {
- for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
- int drawSmooth = (efa->flag & ME_SMOOTH);
- draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth);
- if(draw) {
- const GLenum poly_type= efa->v4 ? GL_QUADS:GL_TRIANGLES;
- if (draw==2) { /* enabled with stipple */
-
- if(poly_prev != GL_ZERO) glEnd();
- poly_prev= GL_ZERO; /* force glBegin */
-
- glEnable(GL_POLYGON_STIPPLE);
- glPolygonStipple(stipple_quarttone);
- }
-
- if(skip_normals) {
- if(poly_type != poly_prev) {
- if(poly_prev != GL_ZERO) glEnd();
- glBegin((poly_prev= poly_type));
- }
- glVertex3fv(efa->v1->co);
- glVertex3fv(efa->v2->co);
- glVertex3fv(efa->v3->co);
- if(poly_type == GL_QUADS) glVertex3fv(efa->v4->co);
- }
- else {
- const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
- if (shade_type != shade_prev) {
- if(poly_prev != GL_ZERO) glEnd();
- glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
- glBegin((poly_prev= poly_type));
- }
- else if(poly_type != poly_prev) {
- if(poly_prev != GL_ZERO) glEnd();
- glBegin((poly_prev= poly_type));
- }
-
- if (!drawSmooth) {
- glNormal3fv(efa->n);
- glVertex3fv(efa->v1->co);
- glVertex3fv(efa->v2->co);
- glVertex3fv(efa->v3->co);
- if(poly_type == GL_QUADS) glVertex3fv(efa->v4->co);
- } else {
- glNormal3fv(efa->v1->no);
- glVertex3fv(efa->v1->co);
- glNormal3fv(efa->v2->no);
- glVertex3fv(efa->v2->co);
- glNormal3fv(efa->v3->no);
- glVertex3fv(efa->v3->co);
- if(poly_type == GL_QUADS) {
- glNormal3fv(efa->v4->no);
- glVertex3fv(efa->v4->co);
- }
- }
- }
-
-
- if (draw==2) {
- glEnd();
- poly_prev= GL_ZERO;
-
- glDisable(GL_POLYGON_STIPPLE);
- }
- }
- }
- }
-
- /* if non zero we know a face was rendered */
- if(poly_prev != GL_ZERO) glEnd();
-}
-
-static void emDM_drawFacesTex_common(DerivedMesh *dm,
- int (*drawParams)(MTFace *tface, int has_mcol, int matnr),
- int (*drawParamsMapped)(void *userData, int index),
- void *userData)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
- EditMesh *em= emdm->em;
- float (*vertexCos)[3]= emdm->vertexCos;
- float (*vertexNos)[3]= emdm->vertexNos;
- EditFace *efa;
- int i;
-
- /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
- glShadeModel(GL_SMOOTH);
-
- if (vertexCos) {
- EditVert *eve;
-
- for (i=0,eve=em->verts.first; eve; eve= eve->next)
- eve->tmp.l = (intptr_t) i++;
-
- for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
- MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- MCol *mcol= CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
- unsigned char *cp= NULL;
- int drawSmooth= (efa->flag & ME_SMOOTH);
- int flag;
-
- if(drawParams)
- flag= drawParams(tf, (mcol != NULL), efa->mat_nr);
- else if(drawParamsMapped)
- flag= drawParamsMapped(userData, i);
- else
- flag= 1;
-
- if(flag != 0) { /* flag 0 == the face is hidden or invisible */
-
- /* we always want smooth here since otherwise vertex colors dont interpolate */
- if (mcol) {
- if (flag==1) {
- cp= (unsigned char*)mcol;
- }
- } else {
- glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
- }
-
- glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
- if (!drawSmooth) {
- glNormal3fv(emdm->faceNos[i]);
-
- if(tf) glTexCoord2fv(tf->uv[0]);
- if(cp) glColor3ub(cp[3], cp[2], cp[1]);
- glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
-
- if(tf) glTexCoord2fv(tf->uv[1]);
- if(cp) glColor3ub(cp[7], cp[6], cp[5]);
- glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
-
- if(tf) glTexCoord2fv(tf->uv[2]);
- if(cp) glColor3ub(cp[11], cp[10], cp[9]);
- glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
-
- if(efa->v4) {
- if(tf) glTexCoord2fv(tf->uv[3]);
- if(cp) glColor3ub(cp[15], cp[14], cp[13]);
- glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
- }
- } else {
- if(tf) glTexCoord2fv(tf->uv[0]);
- if(cp) glColor3ub(cp[3], cp[2], cp[1]);
- glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
-
- if(tf) glTexCoord2fv(tf->uv[1]);
- if(cp) glColor3ub(cp[7], cp[6], cp[5]);
- glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
-
- if(tf) glTexCoord2fv(tf->uv[2]);
- if(cp) glColor3ub(cp[11], cp[10], cp[9]);
- glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
-
- if(efa->v4) {
- if(tf) glTexCoord2fv(tf->uv[3]);
- if(cp) glColor3ub(cp[15], cp[14], cp[13]);
- glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
- }
- }
- glEnd();
- }
- }
- } else {
- for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
- MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- MCol *mcol= CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
- unsigned char *cp= NULL;
- int drawSmooth= (efa->flag & ME_SMOOTH);
- int flag;
-
- if(drawParams)
- flag= drawParams(tf, (mcol != NULL), efa->mat_nr);
- else if(drawParamsMapped)
- flag= drawParamsMapped(userData, i);
- else
- flag= 1;
-
- if(flag != 0) { /* flag 0 == the face is hidden or invisible */
- /* we always want smooth here since otherwise vertex colors dont interpolate */
- if (mcol) {
- if (flag==1) {
- cp= (unsigned char*)mcol;
- }
- } else {
- glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
- }
-
- glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
- if (!drawSmooth) {
- glNormal3fv(efa->n);
-
- if(tf) glTexCoord2fv(tf->uv[0]);
- if(cp) glColor3ub(cp[3], cp[2], cp[1]);
- glVertex3fv(efa->v1->co);
-
- if(tf) glTexCoord2fv(tf->uv[1]);
- if(cp) glColor3ub(cp[7], cp[6], cp[5]);
- glVertex3fv(efa->v2->co);
-
- if(tf) glTexCoord2fv(tf->uv[2]);
- if(cp) glColor3ub(cp[11], cp[10], cp[9]);
- glVertex3fv(efa->v3->co);
-
- if(efa->v4) {
- if(tf) glTexCoord2fv(tf->uv[3]);
- if(cp) glColor3ub(cp[15], cp[14], cp[13]);
- glVertex3fv(efa->v4->co);
- }
- } else {
- if(tf) glTexCoord2fv(tf->uv[0]);
- if(cp) glColor3ub(cp[3], cp[2], cp[1]);
- glNormal3fv(efa->v1->no);
- glVertex3fv(efa->v1->co);
-
- if(tf) glTexCoord2fv(tf->uv[1]);
- if(cp) glColor3ub(cp[7], cp[6], cp[5]);
- glNormal3fv(efa->v2->no);
- glVertex3fv(efa->v2->co);
-
- if(tf) glTexCoord2fv(tf->uv[2]);
- if(cp) glColor3ub(cp[11], cp[10], cp[9]);
- glNormal3fv(efa->v3->no);
- glVertex3fv(efa->v3->co);
-
- if(efa->v4) {
- if(tf) glTexCoord2fv(tf->uv[3]);
- if(cp) glColor3ub(cp[15], cp[14], cp[13]);
- glNormal3fv(efa->v4->no);
- glVertex3fv(efa->v4->co);
- }
- }
- glEnd();
- }
- }
- }
-}
-
-static void emDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr))
-{
- emDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
-}
-
-static void emDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
-{
- emDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
-}
-
-static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
- int (*setMaterial)(int, void *attribs),
- int (*setDrawOptions)(void *userData, int index), void *userData)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
- EditMesh *em= emdm->em;
- float (*vertexCos)[3]= emdm->vertexCos;
- float (*vertexNos)[3]= emdm->vertexNos;
- EditVert *eve;
- EditFace *efa;
- DMVertexAttribs attribs= {{{0}}};
- GPUVertexAttribs gattribs;
- /* int tfoffset; */ /* UNUSED */
- int i, b, matnr, new_matnr, dodraw /* , layer */ /* UNUSED */;
-
- dodraw = 0;
- matnr = -1;
-
- /* layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE); */ /* UNUSED */
- /* tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset; */ /* UNUSED */
-
- /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
- glShadeModel(GL_SMOOTH);
-
- for (i=0,eve=em->verts.first; eve; eve= eve->next)
- eve->tmp.l = (intptr_t) i++;
-
-#define PASSATTRIB(efa, eve, vert) { \
- if(attribs.totorco) { \
- float *orco = attribs.orco.array[eve->tmp.l]; \
- glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \
- } \
- for(b = 0; b < attribs.tottface; b++) { \
- MTFace *_tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset); \
- glVertexAttrib2fvARB(attribs.tface[b].glIndex, _tf->uv[vert]); \
- } \
- for(b = 0; b < attribs.totmcol; b++) { \
- MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset); \
- GLubyte col[4]; \
- col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \
- glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \
- } \
- if(attribs.tottang) { \
- float *tang = attribs.tang.array[i*4 + vert]; \
- glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \
- } \
-}
-
- for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
- int drawSmooth= (efa->flag & ME_SMOOTH);
-
- if(setDrawOptions && !setDrawOptions(userData, i))
- continue;
-
- new_matnr = efa->mat_nr + 1;
- if(new_matnr != matnr) {
- dodraw = setMaterial(matnr = new_matnr, &gattribs);
- if(dodraw)
- DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
- }
-
- if(dodraw) {
- glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
- if (!drawSmooth) {
- if(vertexCos) glNormal3fv(emdm->faceNos[i]);
- else glNormal3fv(efa->n);
-
- PASSATTRIB(efa, efa->v1, 0);
- if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
- else glVertex3fv(efa->v1->co);
-
- PASSATTRIB(efa, efa->v2, 1);
- if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
- else glVertex3fv(efa->v2->co);
-
- PASSATTRIB(efa, efa->v3, 2);
- if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
- else glVertex3fv(efa->v3->co);
-
- if(efa->v4) {
- PASSATTRIB(efa, efa->v4, 3);
- if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
- else glVertex3fv(efa->v4->co);
- }
- } else {
- PASSATTRIB(efa, efa->v1, 0);
- if(vertexCos) {
- glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
- }
- else {
- glNormal3fv(efa->v1->no);
- glVertex3fv(efa->v1->co);
- }
-
- PASSATTRIB(efa, efa->v2, 1);
- if(vertexCos) {
- glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
- }
- else {
- glNormal3fv(efa->v2->no);
- glVertex3fv(efa->v2->co);
- }
-
- PASSATTRIB(efa, efa->v3, 2);
- if(vertexCos) {
- glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
- }
- else {
- glNormal3fv(efa->v3->no);
- glVertex3fv(efa->v3->co);
- }
-
- if(efa->v4) {
- PASSATTRIB(efa, efa->v4, 3);
- if(vertexCos) {
- glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
- glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
- }
- else {
- glNormal3fv(efa->v4->no);
- glVertex3fv(efa->v4->co);
- }
- }
- }
- glEnd();
- }
- }
-#undef PASSATTRIB
-}
-
-static void emDM_drawFacesGLSL(DerivedMesh *dm,
- int (*setMaterial)(int, void *attribs))
-{
- dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
-}
-
-static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
- EditVert *eve;
- int i;
-
- if (emdm->em->verts.first) {
- for (i=0,eve= emdm->em->verts.first; eve; i++,eve= eve->next) {
- if (emdm->vertexCos) {
- DO_MINMAX(emdm->vertexCos[i], min_r, max_r);
- } else {
- DO_MINMAX(eve->co, min_r, max_r);
- }
- }
- } else {
- min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
- }
-}
-static int emDM_getNumVerts(DerivedMesh *dm)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-
- return BLI_countlist(&emdm->em->verts);
-}
-
-static int emDM_getNumEdges(DerivedMesh *dm)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-
- return BLI_countlist(&emdm->em->edges);
-}
-
-static int emDM_getNumFaces(DerivedMesh *dm)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-
- return BLI_countlist(&emdm->em->faces);
-}
-
-static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
- EditVert *eve;
- int i;
-
- for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
- if (emdm->vertexCos) {
- copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
- } else {
- copy_v3_v3(cos_r[i], eve->co);
- }
- }
-}
-
-static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
-{
- EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first;
- int i;
-
- for(i = 0; i < index; ++i) ev = ev->next;
-
- VECCOPY(vert_r->co, ev->co);
-
- normal_float_to_short_v3(vert_r->no, ev->no);
-
- /* TODO what to do with vert_r->flag? */
- vert_r->bweight = (unsigned char) (ev->bweight*255.0f);
-}
-
-static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
-{
- EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
- EditEdge *ee = em->edges.first;
- EditVert *ev, *v1, *v2;
- int i;
-
- for(i = 0; i < index; ++i) ee = ee->next;
-
- edge_r->crease = (unsigned char) (ee->crease*255.0f);
- edge_r->bweight = (unsigned char) (ee->bweight*255.0f);
- /* TODO what to do with edge_r->flag? */
- edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
- if (ee->seam) edge_r->flag |= ME_SEAM;
- if (ee->sharp) edge_r->flag |= ME_SHARP;
-#if 0
- /* this needs setup of f2 field */
- if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
-#endif
-
- /* goddamn, we have to search all verts to find indices */
- v1 = ee->v1;
- v2 = ee->v2;
- for(i = 0, ev = em->verts.first; v1 || v2; i++, ev = ev->next) {
- if(ev == v1) {
- edge_r->v1 = i;
- v1 = NULL;
- }
- if(ev == v2) {
- edge_r->v2 = i;
- v2 = NULL;
- }
- }
-}
-
-static void emDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
-{
- EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
- EditFace *ef = em->faces.first;
- EditVert *ev, *v1, *v2, *v3, *v4;
- int i;
-
- for(i = 0; i < index; ++i) ef = ef->next;
-
- face_r->mat_nr = ef->mat_nr;
- face_r->flag = ef->flag;
-
- /* goddamn, we have to search all verts to find indices */
- v1 = ef->v1;
- v2 = ef->v2;
- v3 = ef->v3;
- v4 = ef->v4;
- if(!v4) face_r->v4 = 0;
-
- for(i = 0, ev = em->verts.first; v1 || v2 || v3 || v4;
- i++, ev = ev->next) {
- if(ev == v1) {
- face_r->v1 = i;
- v1 = NULL;
- }
- if(ev == v2) {
- face_r->v2 = i;
- v2 = NULL;
- }
- if(ev == v3) {
- face_r->v3 = i;
- v3 = NULL;
- }
- if(ev == v4) {
- face_r->v4 = i;
- v4 = NULL;
- }
- }
-
- test_index_face(face_r, NULL, 0, ef->v4?4:3);
-}
-
-static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
- EditVert *ev = emdm->em->verts.first;
- int i;
-
- for(i=0; ev; ev = ev->next, ++vert_r, ++i) {
- if(emdm->vertexCos)
- copy_v3_v3(vert_r->co, emdm->vertexCos[i]);
- else
- copy_v3_v3(vert_r->co, ev->co);
-
- normal_float_to_short_v3(vert_r->no, ev->no);
-
- /* TODO what to do with vert_r->flag? */
- vert_r->flag = 0;
- vert_r->bweight = (unsigned char) (ev->bweight*255.0f);
- }
-}
-
-static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
-{
- EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
- EditEdge *ee = em->edges.first;
- EditVert *ev;
- int i;
-
- /* store vertex indices in tmp union */
- for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
- ev->tmp.l = (intptr_t) i;
-
- for( ; ee; ee = ee->next, ++edge_r) {
- edge_r->crease = (unsigned char) (ee->crease*255.0f);
- edge_r->bweight = (unsigned char) (ee->bweight*255.0f);
- /* TODO what to do with edge_r->flag? */
- edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
- if (ee->seam) edge_r->flag |= ME_SEAM;
- if (ee->sharp) edge_r->flag |= ME_SHARP;
-#if 0
- /* this needs setup of f2 field */
- if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
-#endif
-
- edge_r->v1 = (int)ee->v1->tmp.l;
- edge_r->v2 = (int)ee->v2->tmp.l;
- }
-}
-
-static void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
-{
- EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
- EditFace *ef = em->faces.first;
- EditVert *ev;
- int i;
-
- /* store vertexes indices in tmp union */
- for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
- ev->tmp.l = (intptr_t) i;
-
- for( ; ef; ef = ef->next, ++face_r) {
- face_r->mat_nr = ef->mat_nr;
- face_r->flag = ef->flag;
-
- face_r->v1 = (int)ef->v1->tmp.l;
- face_r->v2 = (int)ef->v2->tmp.l;
- face_r->v3 = (int)ef->v3->tmp.l;
- if(ef->v4) face_r->v4 = (int)ef->v4->tmp.l;
- else face_r->v4 = 0;
-
- test_index_face(face_r, NULL, 0, ef->v4?4:3);
- }
-}
-
-static void *emDM_getFaceDataArray(DerivedMesh *dm, int type)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
- EditMesh *em= emdm->em;
- EditFace *efa;
- char *data, *emdata;
- void *datalayer;
- int index, size;
-
- datalayer = DM_get_face_data_layer(dm, type);
- if(datalayer)
- return datalayer;
-
- /* layers are store per face for editmesh, we convert to a temporary
- * data layer array in the derivedmesh when these are requested */
- if(type == CD_MTFACE || type == CD_MCOL) {
- index = CustomData_get_layer_index(&em->fdata, type);
-
- if(index != -1) {
- /* int offset = em->fdata.layers[index].offset; */ /* UNUSED */
- size = CustomData_sizeof(type);
-
- DM_add_face_layer(dm, type, CD_CALLOC, NULL);
- index = CustomData_get_layer_index(&dm->faceData, type);
- dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
-
- data = datalayer = DM_get_face_data_layer(dm, type);
- for(efa=em->faces.first; efa; efa=efa->next, data+=size) {
- emdata = CustomData_em_get(&em->fdata, efa->data, type);
- memcpy(data, emdata, size);
- }
- }
- }
-
- return datalayer;
-}
-
-static void emDM_release(DerivedMesh *dm)
-{
- EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-
- if (DM_release(dm)) {
- if (emdm->vertexCos) {
- MEM_freeN(emdm->vertexCos);
- MEM_freeN(emdm->vertexNos);
- MEM_freeN(emdm->faceNos);
- }
-
- MEM_freeN(emdm);
- }
-}
-
-DerivedMesh *editmesh_get_derived(EditMesh *em, float (*vertexCos)[3])
-{
- EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm");
-
- DM_init(&emdm->dm, DM_TYPE_EDITMESH, BLI_countlist(&em->verts),
- BLI_countlist(&em->edges), BLI_countlist(&em->faces));
-
- emdm->dm.getMinMax = emDM_getMinMax;
-
- emdm->dm.getNumVerts = emDM_getNumVerts;
- emdm->dm.getNumEdges = emDM_getNumEdges;
- emdm->dm.getNumFaces = emDM_getNumFaces;
-
- emdm->dm.getVertCos = emDM_getVertCos;
-
- emdm->dm.getVert = emDM_getVert;
- emdm->dm.getEdge = emDM_getEdge;
- emdm->dm.getFace = emDM_getFace;
- emdm->dm.copyVertArray = emDM_copyVertArray;
- emdm->dm.copyEdgeArray = emDM_copyEdgeArray;
- emdm->dm.copyFaceArray = emDM_copyFaceArray;
- emdm->dm.getFaceDataArray = emDM_getFaceDataArray;
-
- emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
- emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
- emdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
-
- emdm->dm.drawEdges = emDM_drawEdges;
- emdm->dm.drawMappedEdges = emDM_drawMappedEdges;
- emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
- emdm->dm.drawMappedFaces = emDM_drawMappedFaces;
- emdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
- emdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
- emdm->dm.drawFacesTex = emDM_drawFacesTex;
- emdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
- emdm->dm.drawUVEdges = emDM_drawUVEdges;
-
- emdm->dm.release = emDM_release;
-
- emdm->em = em;
- emdm->vertexCos = vertexCos;
-
- if(CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) {
- EditVert *eve;
- int i;
-
- DM_add_vert_layer(&emdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
-
- for(eve = em->verts.first, i = 0; eve; eve = eve->next, ++i)
- DM_set_vert_data(&emdm->dm, i, CD_MDEFORMVERT,
- CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT));
- }
-
- if(vertexCos) {
- EditVert *eve;
- EditFace *efa;
- int totface = BLI_countlist(&em->faces);
- int i;
-
- for (i=0,eve=em->verts.first; eve; eve= eve->next)
- eve->tmp.l = (intptr_t) i++;
-
- emdm->vertexNos = MEM_callocN(sizeof(*emdm->vertexNos)*i, "emdm_vno");
- emdm->faceNos = MEM_mallocN(sizeof(*emdm->faceNos)*totface, "emdm_vno");
-
- for(i=0, efa= em->faces.first; efa; i++, efa=efa->next) {
- float *v1 = vertexCos[(int) efa->v1->tmp.l];
- float *v2 = vertexCos[(int) efa->v2->tmp.l];
- float *v3 = vertexCos[(int) efa->v3->tmp.l];
- float *no = emdm->faceNos[i];
-
- if(efa->v4) {
- float *v4 = vertexCos[(int) efa->v4->tmp.l];
-
- normal_quad_v3( no,v1, v2, v3, v4);
- add_v3_v3(emdm->vertexNos[(int) efa->v4->tmp.l], no);
- }
- else {
- normal_tri_v3( no,v1, v2, v3);
- }
-
- add_v3_v3(emdm->vertexNos[(int) efa->v1->tmp.l], no);
- add_v3_v3(emdm->vertexNos[(int) efa->v2->tmp.l], no);
- add_v3_v3(emdm->vertexNos[(int) efa->v3->tmp.l], no);
- }
-
- for(i=0, eve= em->verts.first; eve; i++, eve=eve->next) {
- float *no = emdm->vertexNos[i];
- /* following Mesh convention; we use vertex coordinate itself
- * for normal in this case */
- if (normalize_v3(no) == 0.0f) {
- normalize_v3_v3(no, vertexCos[i]);
- }
- }
- }
-
- return (DerivedMesh*) emdm;
-}
-
/***/
-DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, ModifierData *md)
+DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob,
+ ModifierData *md, int build_shapekey_layers)
{
Mesh *me = ob->data;
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -1505,7 +689,11 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, Modifier
if (!(md->mode&eModifierMode_Realtime)) return NULL;
if (mti->isDisabled && mti->isDisabled(md, 0)) return NULL;
-
+
+ if (build_shapekey_layers && me->key && ob->shapenr <= BLI_countlist(&me->key->block)) {
+ key_to_mesh(BLI_findlink(&me->key->block, ob->shapenr-1), me);
+ }
+
if (mti->type==eModifierTypeType_OnlyDeform) {
int numVerts;
float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts);
@@ -1513,9 +701,16 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, Modifier
mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, 0, 0);
dm = mesh_create_derived(me, ob, deformedVerts);
+ if (build_shapekey_layers)
+ add_shapekey_layers(dm, me, ob);
+
MEM_freeN(deformedVerts);
} else {
DerivedMesh *tdm = mesh_create_derived(me, ob, NULL);
+
+ if (build_shapekey_layers)
+ add_shapekey_layers(tdm, me, ob);
+
dm = mti->applyModifier(md, ob, tdm, 0, 0);
if(tdm != dm) tdm->release(tdm);
@@ -1524,30 +719,29 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, Modifier
return dm;
}
-static float *get_editmesh_orco_verts(EditMesh *em)
+static float *get_editbmesh_orco_verts(BMEditMesh *em)
{
- EditVert *eve;
+ BMIter iter;
+ BMVert *eve;
float *orco;
int a, totvert;
/* these may not really be the orco's, but it's only for preview.
* could be solver better once, but isn't simple */
- totvert= 0;
- for(eve=em->verts.first; eve; eve=eve->next)
- totvert++;
+ totvert= em->bm->totvert;
orco = MEM_mallocN(sizeof(float)*3*totvert, "EditMesh Orco");
- for(a=0, eve=em->verts.first; eve; eve=eve->next, a+=3)
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for (a=0; eve; eve=BMIter_Step(&iter), a+=3)
VECCOPY(orco+a, eve->co);
return orco;
}
/* orco custom data layer */
-
-static void *get_orco_coords_dm(Object *ob, EditMesh *em, int layer, int *free)
+static void *get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free)
{
*free= 0;
@@ -1556,7 +750,7 @@ static void *get_orco_coords_dm(Object *ob, EditMesh *em, int layer, int *free)
*free= 1;
if(em)
- return (float(*)[3])get_editmesh_orco_verts(em);
+ return (float(*)[3])get_editbmesh_orco_verts(em);
else
return (float(*)[3])get_mesh_orco_verts(ob);
}
@@ -1565,10 +759,12 @@ static void *get_orco_coords_dm(Object *ob, EditMesh *em, int layer, int *free)
by a more flexible customdata system, but not simple */
if(!em) {
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
- KeyBlock *kb= key_get_keyblock(ob_get_key(ob), clmd->sim_parms->shapekey_rest);
-
- if(kb->data)
- return kb->data;
+ if (clmd) {
+ KeyBlock *kb= key_get_keyblock(ob_get_key(ob), clmd->sim_parms->shapekey_rest);
+
+ if(kb->data)
+ return kb->data;
+ }
}
return NULL;
@@ -1577,13 +773,13 @@ static void *get_orco_coords_dm(Object *ob, EditMesh *em, int layer, int *free)
return NULL;
}
-static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em, int layer)
+static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, BMEditMesh *em, int layer)
{
DerivedMesh *dm;
float (*orco)[3];
int free;
- if(em) dm= CDDM_from_editmesh(em, me);
+ if(em) dm= CDDM_from_BMEditMesh(em, me, 0);
else dm= CDDM_from_mesh(me, ob);
orco= get_orco_coords_dm(ob, em, layer, &free);
@@ -1598,7 +794,8 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em, int layer
return dm;
}
-static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *orcodm, int layer)
+static void add_orco_dm(Object *ob, BMEditMesh *em, DerivedMesh *dm,
+ DerivedMesh *orcodm, int layer)
{
float (*orco)[3], (*layerorco)[3];
int totvert, free;
@@ -1745,21 +942,28 @@ void vDM_ColorBand_store(ColorBand *coba)
static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag)
{
- Mesh *me = ob->data;
- MFace *mf = me->mface;
+ // Mesh *me = ob->data; // UNUSED
+ MFace *mf = dm->getTessFaceArray(dm);
+ MLoop *mloop = dm->getLoopArray(dm), *ml;
+ MPoly *mp = dm->getPolyArray(dm);
ColorBand *coba= stored_cb; /* warning, not a local var */
unsigned char *wtcol;
- int i;
-
+ unsigned char(*wlcol)[4] = NULL;
+ BLI_array_declare(wlcol);
+ int i, j, totface=dm->getNumTessFaces(dm), totloop;
+ int *origIndex = dm->getVertDataArray(dm, CD_ORIGINDEX);
+
int defbase_len = BLI_countlist(&ob->defbase);
char *defbase_sel = MEM_mallocN(defbase_len * sizeof(char), __func__);
int selected = get_selected_defgroups(ob, defbase_sel, defbase_len);
int unselected = defbase_len - selected;
- wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
+ wtcol = MEM_callocN (sizeof (unsigned char) * totface*4*4, "weightmap");
- memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
- for (i=0; i<me->totface; i++, mf++) {
+ /*first add colors to the tesselation faces*/
+ memset(wtcol, 0x55, sizeof (unsigned char) * totface*4*4);
+ for (i=0; i<totface; i++, mf++) {
+ /*origindex being NULL means we're operating on original mesh data*/
calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4], defbase_sel, selected, unselected, draw_flag);
calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4], defbase_sel, selected, unselected, draw_flag);
calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4], defbase_sel, selected, unselected, draw_flag);
@@ -1767,9 +971,110 @@ static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag)
calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4], defbase_sel, selected, unselected, draw_flag);
}
+ CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, totface);
+
+ /*now add to loops, so the data can be passed through the modifier stack*/
+ totloop = 0;
+ for (i=0; i<dm->numPolyData; i++, mp++) {
+ ml = mloop + mp->loopstart;
+
+ for (j=0; j<mp->totloop; j++, ml++, totloop++) {
+ BLI_array_growone(wlcol);
+
+ calc_weightpaint_vert_color(ob, coba, origIndex ? origIndex[ml->v] : ml->v,
+ (unsigned char *)&wlcol[totloop], defbase_sel, selected, unselected, draw_flag);
+ }
+ }
+
MEM_freeN(defbase_sel);
- CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, dm->numFaceData);
+ CustomData_add_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL, CD_ASSIGN, wlcol, totloop);
+}
+
+
+static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid)
+{
+ KeyBlock *kb;
+ int i, j, tot;
+
+ if (!me->key)
+ return;
+
+ tot = CustomData_number_of_layers(&dm->vertData, CD_SHAPEKEY);
+ for (i=0; i<tot; i++) {
+ CustomDataLayer *layer = &dm->vertData.layers[CustomData_get_layer_index_n(&dm->vertData, CD_SHAPEKEY, i)];
+ float (*cos)[3], (*kbcos)[3];
+
+ for (kb=me->key->block.first; kb; kb=kb->next) {
+ if (kb->uid == layer->uid)
+ break;
+ }
+
+ if (!kb) {
+ kb = add_keyblock(me->key, layer->name);
+ kb->uid = layer->uid;
+ }
+
+ if (kb->data)
+ MEM_freeN(kb->data);
+
+ cos = CustomData_get_layer_n(&dm->vertData, CD_SHAPEKEY, i);
+ kb->totelem = dm->numVertData;
+
+ kb->data = kbcos = MEM_mallocN(sizeof(float)*3*kb->totelem, "kbcos DerivedMesh.c");
+ if (kb->uid == actshape_uid) {
+ MVert *mvert = dm->getVertArray(dm);
+
+ for (j=0; j<dm->numVertData; j++, kbcos++, mvert++) {
+ copy_v3_v3(*kbcos, mvert->co);
+ }
+ } else {
+ for (j=0; j<kb->totelem; j++, cos++, kbcos++) {
+ copy_v3_v3(*kbcos, *cos);
+ }
+ }
+ }
+
+ for (kb=me->key->block.first; kb; kb=kb->next) {
+ if (kb->totelem != dm->numVertData) {
+ if (kb->data)
+ MEM_freeN(kb->data);
+
+ kb->totelem = dm->numVertData;
+ kb->data = MEM_callocN(sizeof(float)*3*kb->totelem, "kb->data derivedmesh.c");
+ fprintf(stderr, "%s: lost a shapekey layer! (bmesh internal error)\n", __func__);
+ }
+ }
+}
+
+static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *UNUSED(ob))
+{
+ KeyBlock *kb;
+ Key *key = me->key;
+ int a, b;
+
+ if (!me->key)
+ return;
+
+ if (dm->numVertData != me->totvert) {
+ printf("error in add_shapekey_layers: dm isn't the same size as me\n");
+ return;
+ }
+
+ for (a=0, kb=key->block.first; kb; kb=kb->next, a++) {
+ float (*cos)[3] = CustomData_add_layer_named(&dm->vertData, CD_SHAPEKEY, CD_CALLOC, NULL, dm->numVertData, kb->name);
+ int ci = CustomData_get_layer_index_n(&dm->vertData, CD_SHAPEKEY, a);
+
+ dm->vertData.layers[ci].uid = kb->uid;
+ if (kb->totelem != dm->numVertData) {
+ printf("error in add_shapekey_layers: totelem and totvert don't match");
+ continue;
+ }
+
+ for (b=0; b<kb->totelem; b++, cos++) {
+ copy_v3_v3((float *)cos, ((float*)kb->data)+b*3);
+ }
+ }
}
/* new value for useDeform -1 (hack for the gameengine):
@@ -1780,14 +1085,15 @@ static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag)
static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos)[3],
DerivedMesh **deform_r, DerivedMesh **final_r,
int useRenderParams, int useDeform,
- int needMapping, CustomDataMask dataMask, int index, int useCache)
+ int needMapping, CustomDataMask dataMask,
+ int index, int useCache, int build_shapekey_layers)
{
Mesh *me = ob->data;
ModifierData *firstmd, *md;
LinkNode *datamasks, *curr;
CustomDataMask mask, nextmask;
float (*deformedVerts)[3] = NULL;
- DerivedMesh *dm, *orcodm, *clothorcodm, *finaldm;
+ DerivedMesh *dm=NULL, *orcodm, *clothorcodm, *finaldm;
int numVerts = me->totvert;
int required_mode;
int isPrevDeform= FALSE;
@@ -1858,7 +1164,10 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
*/
if (deform_r) {
*deform_r = CDDM_from_mesh(me, ob);
-
+
+ if (build_shapekey_layers)
+ add_shapekey_layers(dm, me, ob);
+
if(deformedVerts) {
CDDM_apply_vert_coords(*deform_r, deformedVerts);
CDDM_calc_normals(*deform_r);
@@ -1941,7 +1250,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
/* if this is not the last modifier in the stack then recalculate the normals
* to avoid giving bogus normals to the next modifier see: [#23673] */
- if(isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
+ if(dm && isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
/* XXX, this covers bug #23673, but we may need normal calc for other types */
if(dm && dm->type == DM_TYPE_CDDM) {
CDDM_apply_vert_coords(dm, deformedVerts);
@@ -1962,7 +1271,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
/* apply vertex coordinates or build a DerivedMesh as necessary */
if(dm) {
if(deformedVerts) {
- DerivedMesh *tdm = CDDM_copy(dm);
+ DerivedMesh *tdm = CDDM_copy(dm, 0);
dm->release(dm);
dm = tdm;
@@ -1972,14 +1281,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
} else {
dm = CDDM_from_mesh(me, ob);
+ if (build_shapekey_layers)
+ add_shapekey_layers(dm, me, ob);
+
if(deformedVerts) {
CDDM_apply_vert_coords(dm, deformedVerts);
CDDM_calc_normals(dm);
}
- if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
- add_weight_mcol_dm(ob, dm, draw_flag);
-
/* Constructive modifiers need to have an origindex
* otherwise they wont have anywhere to copy the data from.
*
@@ -1995,8 +1304,12 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
range_vni(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0);
range_vni(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0);
- range_vni(DM_get_face_data_layer(dm, CD_ORIGINDEX), dm->numFaceData, 0);
+ range_vni(DM_get_face_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0);
}
+
+ if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
+ add_weight_mcol_dm(ob, dm, draw_flag);
+
}
@@ -2013,7 +1326,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
/* add an origspace layer if needed */
if(((CustomDataMask)GET_INT_FROM_POINTER(curr->link)) & CD_MASK_ORIGSPACE)
if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE))
- DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL);
+ DM_add_tessface_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL);
ndm = mti->applyModifier(md, ob, dm, useRenderParams, useCache);
@@ -2082,7 +1395,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
* DerivedMesh then we need to build one.
*/
if(dm && deformedVerts) {
- finaldm = CDDM_copy(dm);
+ finaldm = CDDM_copy(dm, 0);
dm->release(dm);
@@ -2094,13 +1407,23 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
} else if(dm) {
finaldm = dm;
} else {
- finaldm = CDDM_from_mesh(me, ob);
+ int recalc_normals= 0;
+ finaldm = CDDM_from_mesh(me, ob);
+
+ if(build_shapekey_layers) {
+ add_shapekey_layers(finaldm, me, ob);
+ recalc_normals= 1;
+ }
+
if(deformedVerts) {
CDDM_apply_vert_coords(finaldm, deformedVerts);
- CDDM_calc_normals(finaldm);
+ recalc_normals= 1;
}
+ if(recalc_normals)
+ CDDM_calc_normals(finaldm);
+
if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
add_weight_mcol_dm(ob, finaldm, draw_flag);
}
@@ -2138,21 +1461,24 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
BLI_linklist_free(datamasks, NULL);
}
-float (*editmesh_get_vertex_cos(EditMesh *em, int *numVerts_r))[3]
+float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *numVerts_r))[3]
{
- int i, numVerts = *numVerts_r = BLI_countlist(&em->verts);
+ int i, numVerts = *numVerts_r = em->bm->totvert;
float (*cos)[3];
- EditVert *eve;
+ BMIter iter;
+ BMVert *eve;
+
+ cos = MEM_mallocN(sizeof(float)*3*numVerts, "vertexcos");
- cos = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos");
- for (i=0,eve=em->verts.first; i<numVerts; i++,eve=eve->next) {
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++) {
VECCOPY(cos[i], eve->co);
}
return cos;
}
-int editmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm)
+int editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm)
{
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
@@ -2166,7 +1492,7 @@ int editmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *dm
return 1;
}
-static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, DerivedMesh **cage_r,
+static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, DerivedMesh **cage_r,
DerivedMesh **final_r,
CustomDataMask dataMask)
{
@@ -2181,7 +1507,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
modifiers_clearErrors(ob);
if(cage_r && cageIndex == -1) {
- *cage_r = editmesh_get_derived(em, NULL);
+ *cage_r = getEditDerivedBMesh(em, ob, NULL);
}
dm = NULL;
@@ -2195,7 +1521,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
md->scene= scene;
- if(!editmesh_modifier_is_enabled(scene, md, dm))
+ if(!editbmesh_modifier_is_enabled(scene, md, dm))
continue;
/* add an orco layer if needed by this modifier */
@@ -2223,7 +1549,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
MEM_mallocN(sizeof(*deformedVerts) * numVerts, "dfmv");
dm->getVertCos(dm, deformedVerts);
} else {
- deformedVerts = editmesh_get_vertex_cos(em, &numVerts);
+ deformedVerts = editbmesh_get_vertex_cos(em, &numVerts);
}
}
@@ -2236,7 +1562,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
/* apply vertex coordinates or build a DerivedMesh as necessary */
if(dm) {
if(deformedVerts) {
- DerivedMesh *tdm = CDDM_copy(dm);
+ DerivedMesh *tdm = CDDM_copy(dm, 0);
if(!(cage_r && dm == *cage_r)) dm->release(dm);
dm = tdm;
@@ -2245,11 +1571,11 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
} else if(cage_r && dm == *cage_r) {
/* dm may be changed by this modifier, so we need to copy it
*/
- dm = CDDM_copy(dm);
+ dm = CDDM_copy(dm, 0);
}
} else {
- dm = CDDM_from_editmesh(em, ob->data);
+ dm = CDDM_from_BMEditMesh(em, ob->data, 0);
if(deformedVerts) {
CDDM_apply_vert_coords(dm, deformedVerts);
@@ -2285,7 +1611,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
if(mask & CD_MASK_ORIGSPACE)
if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE))
- DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL);
+ DM_add_tessface_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL);
if (mti->applyModifierEM)
ndm = mti->applyModifierEM(md, ob, em, dm);
@@ -2307,13 +1633,13 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
if(cage_r && i == cageIndex) {
if(dm && deformedVerts) {
- *cage_r = CDDM_copy(dm);
+ *cage_r = CDDM_copy(dm, 0);
CDDM_apply_vert_coords(*cage_r, deformedVerts);
} else if(dm) {
*cage_r = dm;
} else {
*cage_r =
- editmesh_get_derived(em,
+ getEditDerivedBMesh(em, ob,
deformedVerts ? MEM_dupallocN(deformedVerts) : NULL);
}
}
@@ -2326,7 +1652,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
* then we need to build one.
*/
if(dm && deformedVerts) {
- *final_r = CDDM_copy(dm);
+ *final_r = CDDM_copy(dm, 0);
if(!(cage_r && dm == *cage_r)) dm->release(dm);
@@ -2337,7 +1663,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
} else if (!deformedVerts && cage_r && *cage_r) {
*final_r = *cage_r;
} else {
- *final_r = editmesh_get_derived(em, deformedVerts);
+ *final_r = getEditDerivedBMesh(em, ob, deformedVerts);
deformedVerts = NULL;
}
@@ -2384,10 +1710,11 @@ static void clear_mesh_caches(Object *ob)
}
}
-static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask)
+static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask,
+ int build_shapekey_layers)
{
Object *obact = scene->basact?scene->basact->object:NULL;
- int editing = paint_facesel_test(ob) || paint_vertsel_test(ob);/* paint_vertsel_test */
+ int editing = paint_facesel_test(ob);
/* weight paint and face select need original indices because of selection buffer drawing */
int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT)));
@@ -2395,7 +1722,7 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask)
mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform,
&ob->derivedFinal, 0, 1,
- needMapping, dataMask, -1, 1);
+ needMapping, dataMask, -1, 1, build_shapekey_layers);
DM_set_object_boundbox (ob, ob->derivedFinal);
@@ -2404,7 +1731,7 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask)
ob->lastDataMask = dataMask;
}
-static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, CustomDataMask dataMask)
+static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask)
{
clear_mesh_caches(obedit);
@@ -2421,7 +1748,7 @@ static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, Cust
em->derivedCage = NULL;
}
- editmesh_calc_modifiers(scene, obedit, em, &em->derivedCage, &em->derivedFinal, dataMask);
+ editbmesh_calc_modifiers(scene, obedit, em, &em->derivedCage, &em->derivedFinal, dataMask);
DM_set_object_boundbox (obedit, em->derivedFinal);
em->lastDataMask = dataMask;
@@ -2429,12 +1756,13 @@ static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, Cust
em->derivedCage->needsFree = 0;
}
-void makeDerivedMesh(Scene *scene, Object *ob, EditMesh *em, CustomDataMask dataMask)
+void makeDerivedMesh(Scene *scene, Object *ob, BMEditMesh *em,
+ CustomDataMask dataMask, int build_shapekey_layers)
{
if (em) {
- editmesh_build_data(scene, ob, em, dataMask);
+ editbmesh_build_data(scene, ob, em, dataMask);
} else {
- mesh_build_data(scene, ob, dataMask);
+ mesh_build_data(scene, ob, dataMask, build_shapekey_layers);
}
}
@@ -2446,7 +1774,7 @@ DerivedMesh *mesh_get_derived_final(Scene *scene, Object *ob, CustomDataMask dat
* the data we need, rebuild the derived mesh
*/
if(!ob->derivedFinal || (dataMask & ob->lastDataMask) != dataMask)
- mesh_build_data(scene, ob, dataMask);
+ mesh_build_data(scene, ob, dataMask, 0);
return ob->derivedFinal;
}
@@ -2457,7 +1785,7 @@ DerivedMesh *mesh_get_derived_deform(Scene *scene, Object *ob, CustomDataMask da
* the data we need, rebuild the derived mesh
*/
if(!ob->derivedDeform || (dataMask & ob->lastDataMask) != dataMask)
- mesh_build_data(scene, ob, dataMask);
+ mesh_build_data(scene, ob, dataMask, 0);
return ob->derivedDeform;
}
@@ -2466,7 +1794,7 @@ DerivedMesh *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask
{
DerivedMesh *final;
- mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, -1, 0);
+ mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, -1, 0, 0);
return final;
}
@@ -2475,7 +1803,7 @@ DerivedMesh *mesh_create_derived_index_render(Scene *scene, Object *ob, CustomDa
{
DerivedMesh *final;
- mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, index, 0);
+ mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, index, 0, 0);
return final;
}
@@ -2484,7 +1812,7 @@ DerivedMesh *mesh_create_derived_view(Scene *scene, Object *ob, CustomDataMask d
{
DerivedMesh *final;
- mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 0, 1, 0, dataMask, -1, 0);
+ mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 0, 1, 0, dataMask, -1, 0, 0);
return final;
}
@@ -2494,7 +1822,7 @@ DerivedMesh *mesh_create_derived_no_deform(Scene *scene, Object *ob, float (*ver
{
DerivedMesh *final;
- mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, 0, 0, dataMask, -1, 0);
+ mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, 0, 0, dataMask, -1, 0, 0);
return final;
}
@@ -2504,7 +1832,7 @@ DerivedMesh *mesh_create_derived_no_virtual(Scene *scene, Object *ob, float (*ve
{
DerivedMesh *final;
- mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 0, dataMask, -1, 0);
+ mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 0, dataMask, -1, 0, 0);
return final;
}
@@ -2514,7 +1842,7 @@ DerivedMesh *mesh_create_derived_physics(Scene *scene, Object *ob, float (*vertC
{
DerivedMesh *final;
- mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 1, dataMask, -1, 0);
+ mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 1, dataMask, -1, 0, 0);
return final;
}
@@ -2525,14 +1853,14 @@ DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob,
{
DerivedMesh *final;
- mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 1, 0, 0, dataMask, -1, 0);
+ mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 1, 0, 0, dataMask, -1, 0, 0);
return final;
}
/***/
-DerivedMesh *editmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, EditMesh *em, DerivedMesh **final_r,
+DerivedMesh *editbmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, BMEditMesh *em, DerivedMesh **final_r,
CustomDataMask dataMask)
{
/* if there's no derived mesh or the last data mask used doesn't include
@@ -2540,27 +1868,27 @@ DerivedMesh *editmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, E
*/
if(!em->derivedCage ||
(em->lastDataMask & dataMask) != dataMask)
- editmesh_build_data(scene, obedit, em, dataMask);
+ editbmesh_build_data(scene, obedit, em, dataMask);
*final_r = em->derivedFinal;
return em->derivedCage;
}
-DerivedMesh *editmesh_get_derived_cage(Scene *scene, Object *obedit, EditMesh *em, CustomDataMask dataMask)
+DerivedMesh *editbmesh_get_derived_cage(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask)
{
/* if there's no derived mesh or the last data mask used doesn't include
* the data we need, rebuild the derived mesh
*/
if(!em->derivedCage ||
(em->lastDataMask & dataMask) != dataMask)
- editmesh_build_data(scene, obedit, em, dataMask);
+ editbmesh_build_data(scene, obedit, em, dataMask);
return em->derivedCage;
}
-DerivedMesh *editmesh_get_derived_base(Object *UNUSED(obedit), EditMesh *em)
+DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em)
{
- return editmesh_get_derived(em, NULL);
+ return getEditDerivedBMesh(em, obedit, NULL);
}
@@ -2600,7 +1928,7 @@ float *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
if(ob->type!=OB_MESH || me->totvert==0)
return NULL;
- dm= mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ dm= mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH|CD_MASK_ORIGINDEX);
vertexcosnos= MEM_callocN(6*sizeof(float)*me->totvert, "vertexcosnos map");
if(dm->foreachMappedVert) {
@@ -2729,15 +2057,15 @@ void DM_add_tangent_layer(DerivedMesh *dm)
if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1)
return;
- nors = dm->getFaceDataArray(dm, CD_NORMAL);
+ nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
/* check we have all the needed layers */
totvert= dm->getNumVerts(dm);
- totface= dm->getNumFaces(dm);
+ totface= dm->getNumTessFaces(dm);
mvert= dm->getVertArray(dm);
- mface= dm->getFaceArray(dm);
- mtface= dm->getFaceDataArray(dm, CD_MTFACE);
+ mface= dm->getTessFaceArray(dm);
+ mtface= dm->getTessFaceDataArray(dm, CD_MTFACE);
if(!mtface) {
orco= dm->getVertDataArray(dm, CD_ORCO);
@@ -2746,8 +2074,8 @@ void DM_add_tangent_layer(DerivedMesh *dm)
}
/* create tangent layer */
- DM_add_face_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
- tangent= DM_get_face_data_layer(dm, CD_TANGENT);
+ DM_add_tessface_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
+ tangent= DM_get_tessface_data_layer(dm, CD_TANGENT);
/* allocate some space */
arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "tangent layer arena");
@@ -2868,15 +2196,8 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
memset(attribs, 0, sizeof(DMVertexAttribs));
vdata = &dm->vertData;
- fdata = &dm->faceData;
-
- /* ugly hack, editmesh derivedmesh doesn't copy face data, this way we
- * can use offsets instead */
- if(dm->release == emDM_release)
- tfdata = &((EditMeshDerivedMesh*)dm)->em->fdata;
- else
- tfdata = fdata;
-
+ fdata = tfdata = dm->getTessFaceDataLayout(dm);
+
/* add a tangent layer if necessary */
for(b = 0; b < gattribs->totlayer; b++)
if(gattribs->layer[b].type == CD_TANGENT)
@@ -2898,8 +2219,26 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
attribs->tface[a].array = tfdata->layers[layer].data;
attribs->tface[a].emOffset = tfdata->layers[layer].offset;
attribs->tface[a].glIndex = gattribs->layer[b].glindex;
- attribs->tface[a].glTexco = gattribs->layer[b].gltexco;
- }
+ } /*else {
+ int player;
+ CustomData *pdata = dm->getFaceDataLayout(dm);
+
+ if(gattribs->layer[b].name[0])
+ player = CustomData_get_named_layer_index(pdata, CD_MTEXPOLY,
+ gattribs->layer[b].name);
+ else
+ player = CustomData_get_active_layer_index(pdata, CD_MTEXPOLY);
+
+ if (player != -1) {
+ a = attribs->tottface++;
+
+ attribs->tface[a].array = NULL;
+ attribs->tface[a].emOffset = pdata->layers[layer].offset;
+ attribs->tface[a].glIndex = gattribs->layer[b].glindex;
+ attribs->tface[a].glTexco = gattribs->layer[b].gltexco;
+
+ }
+ }*/
}
else if(gattribs->layer[b].type == CD_MCOL) {
/* vertex colors */
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index ac0697ddbf9..8d18a1c27e7 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -137,14 +137,19 @@ void make_local_action(bAction *act)
// XXX: double-check this; it used to be just single-user check, but that was when fake-users were still default
if ((act->id.flag & LIB_FAKEUSER) && (act->id.us<=1)) {
- id_clear_lib_data(&bmain->action, (ID *)act);
+ act->id.lib= NULL;
+ act->id.flag= LIB_LOCAL;
+ new_id(&bmain->action, (ID *)act, NULL);
return;
}
BKE_animdata_main_cb(bmain, make_localact_init_cb, &mlac);
if (mlac.local && mlac.lib==0) {
- id_clear_lib_data(&bmain->action, (ID *)act);
+ act->id.lib= NULL;
+ act->id.flag= LIB_LOCAL;
+ //make_local_action_channels(act);
+ new_id(&bmain->action, (ID *)act, NULL);
}
else if (mlac.local && mlac.lib) {
mlac.actn= copy_action(act);
@@ -876,7 +881,7 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_
/* get extents for this curve */
// TODO: allow enabling/disabling this?
- calc_fcurve_range(fcu, &nmin, &nmax, FALSE, TRUE);
+ calc_fcurve_range(fcu, &nmin, &nmax, FALSE);
/* compare to the running tally */
min= MIN2(min, nmin);
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 716f3ed2726..2bb54e54600 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -65,6 +65,7 @@
#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
#include "BKE_depsgraph.h"
#include "BKE_anim.h"
@@ -888,7 +889,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
Scene *sce = NULL;
Group *group = NULL;
GroupObject * go = NULL;
- EditMesh *em;
+ BMEditMesh *em;
float vec[3], no[3], pmat[4][4];
int totvert, a, oblay;
unsigned int lay;
@@ -898,11 +899,10 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
/* simple preventing of too deep nested groups */
if(level>MAX_DUPLI_RECUR) return;
- em = BKE_mesh_get_editmesh(me);
+ em = me->edit_btmesh;
if(em) {
- dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
- BKE_mesh_end_editmesh(me, em);
+ dm= editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
} else
dm= mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH);
@@ -964,7 +964,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
/* mballs have a different dupli handling */
if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */
- if(me->edit_mesh) {
+ if(me->edit_btmesh) {
dm->foreachMappedVert(dm, vertex_dupli__mapFunc, (void*) &vdd);
}
else {
@@ -1013,34 +1013,31 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
Scene *sce = NULL;
Group *group = NULL;
GroupObject *go = NULL;
- EditMesh *em;
+ BMEditMesh *em;
float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */
/* simple preventing of too deep nested groups */
if(level>MAX_DUPLI_RECUR) return;
copy_m4_m4(pmat, par->obmat);
-
- em = BKE_mesh_get_editmesh(me);
+ em = me->edit_btmesh;
+
if(em) {
int totvert;
+ dm= editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
- dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
-
- totface= dm->getNumFaces(dm);
+ totface= dm->getNumTessFaces(dm);
mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp");
- dm->copyFaceArray(dm, mface);
+ dm->copyTessFaceArray(dm, mface);
totvert= dm->getNumVerts(dm);
mvert= MEM_mallocN(sizeof(MVert)*totvert, "mvert temp");
dm->copyVertArray(dm, mvert);
-
- BKE_mesh_end_editmesh(me, em);
}
else {
dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH);
- totface= dm->getNumFaces(dm);
- mface= dm->getFaceArray(dm);
+ totface= dm->getNumTessFaces(dm);
+ mface= dm->getTessFaceArray(dm);
mvert= dm->getVertArray(dm);
}
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index c1675faf053..1149d8eee25 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -141,7 +141,9 @@ void make_local_armature(bArmature *arm)
if (arm->id.lib==NULL) return;
if (arm->id.us==1) {
- id_clear_lib_data(&bmain->armature, (ID *)arm);
+ arm->id.lib= NULL;
+ arm->id.flag= LIB_LOCAL;
+ new_id(&bmain->armature, (ID*)arm, NULL);
return;
}
@@ -153,7 +155,9 @@ void make_local_armature(bArmature *arm)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->armature, (ID *)arm);
+ arm->id.lib= NULL;
+ arm->id.flag= LIB_LOCAL;
+ new_id(&bmain->armature, (ID *)arm, NULL);
}
else if(local && lib) {
bArmature *armn= copy_armature(arm);
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 4cbdbeb890d..fddff49f6c5 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -57,11 +57,11 @@
#include "BLI_blenlib.h"
#include "BLI_bpath.h"
#include "BLI_dynstr.h"
+#include "BLI_path_util.h"
#include "BLI_utildefines.h"
#include "BLI_callbacks.h"
#include "IMB_imbuf.h"
-#include "IMB_moviecache.h"
#include "BKE_blender.h"
#include "BKE_context.h"
@@ -112,7 +112,6 @@ void free_blender(void)
BLI_cb_finalize();
seq_stripelem_cache_destruct();
- IMB_moviecache_destruct();
free_nodesystem();
}
@@ -702,10 +701,18 @@ char *BKE_undo_menu_string(void)
/* saves quit.blend */
void BKE_undo_save_quit(void)
{
+ char str[FILE_MAXDIR+FILE_MAXFILE];
+
+ BLI_make_file_string("/", str, BLI_temporary_dir(), "quit.blend");
+
+ BKE_undo_save(str);
+}
+
+void BKE_undo_save(char *fname)
+{
UndoElem *uel;
MemFileChunk *chunk;
int file;
- char str[FILE_MAXDIR+FILE_MAXFILE];
if( (U.uiflag & USER_GLOBALUNDO)==0) return;
@@ -718,9 +725,7 @@ void BKE_undo_save_quit(void)
/* no undo state to save */
if(undobase.first==undobase.last) return;
- BLI_make_file_string("/", str, BLI_temporary_dir(), "quit.blend");
-
- file = open(str,O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
+ file = open(fname, O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
if(file == -1) {
//XXX error("Unable to save %s, check you have permissions", str);
return;
@@ -734,8 +739,8 @@ void BKE_undo_save_quit(void)
close(file);
- if(chunk) ; //XXX error("Unable to save %s, internal error", str);
- else printf("Saved session recovery to %s\n", str);
+ if(chunk) ; //XXX error("Unable to save %s, internal error", fname);
+ else printf("Saved session recovery to %s\n", fname);
}
/* sets curscene */
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 45558329d4d..b5cdbc58807 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -181,7 +181,6 @@ void free_brush(Brush *brush)
static void extern_local_brush(Brush *brush)
{
id_lib_extern((ID *)brush->mtex.tex);
- id_lib_extern((ID *)brush->clone.image);
}
void make_local_brush(Brush *brush)
@@ -199,9 +198,10 @@ void make_local_brush(Brush *brush)
if(brush->id.lib==NULL) return;
if(brush->clone.image) {
- /* special case: ima always local immediately. Clone image should only
- have one user anyway. */
- id_clear_lib_data(&bmain->brush, (ID *)brush->clone.image);
+ /* special case: ima always local immediately */
+ brush->clone.image->id.lib= NULL;
+ brush->clone.image->id.flag= LIB_LOCAL;
+ new_id(&bmain->brush, (ID *)brush->clone.image, NULL);
extern_local_brush(brush);
}
@@ -213,7 +213,9 @@ void make_local_brush(Brush *brush)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->brush, (ID *)brush);
+ brush->id.lib= NULL;
+ brush->id.flag= LIB_LOCAL;
+ new_id(&bmain->brush, (ID *)brush, NULL);
extern_local_brush(brush);
/* enable fake user by default */
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index ee160a13fa2..f5113b3ef58 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -41,7 +41,7 @@
#include "BLI_linklist.h"
#include "BKE_DerivedMesh.h"
-
+#include "BKE_tessmesh.h"
#include "BLI_math.h"
#include "MEM_guardedalloc.h"
@@ -556,7 +556,7 @@ BVHTree* bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float
data->mesh = mesh;
data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
- data->face = mesh->getFaceDataArray(mesh, CD_MFACE);
+ data->face = mesh->getTessFaceDataArray(mesh, CD_MFACE);
data->sphere_radius = epsilon;
}
@@ -573,45 +573,91 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float
if(tree == NULL)
{
int i;
- int numFaces= mesh->getNumFaces(mesh);
- MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT);
- MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE);
+ int numFaces= mesh->getNumTessFaces(mesh);
- if(vert != NULL && face != NULL)
+ if(numFaces != 0)
{
/* Create a bvh-tree of the given target */
tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis);
if(tree != NULL)
{
- /* XXX, for snap only, em & dm are assumed to be aligned, since dm is the em's cage */
- EditMesh *em= data->em_evil;
+ BMEditMesh *em= data->em_evil;
if(em) {
- EditFace *efa= em->faces.first;
- for(i = 0; i < numFaces; i++, efa= efa->next) {
- if(!(efa->f & 1) && efa->h==0 && !((efa->v1->f&1)+(efa->v2->f&1)+(efa->v3->f&1)+(efa->v4?efa->v4->f&1:0))) {
+ /*data->em_evil is only set for snapping, and only for the mesh of the object
+ which is currently open in edit mode. When set, the bvhtree should not contain
+ faces that will interfere with snapping (e.g. faces that are hidden/selected
+ or faces that have selected verts).*/
+
+ /* XXX, for snap only, em & dm are assumed to be aligned, since dm is the em's cage */
+
+ /*Insert BMesh-tesselation triangles into the bvh tree, unless they are hidden
+ and/or selected. Even if the faces themselves are not selected for the snapped
+ transform, having a vertex selected means the face (and thus it's tesselated
+ triangles) will be moving and will not be a good snap targets.*/
+ for (i = 0; i < em->tottri; i++) {
+ BMLoop **tri = em->looptris[i];
+ BMFace *f;
+ BMVert *v;
+ BMIter iter;
+ int insert;
+
+ /*Each loop of the triangle points back to the BMFace it was tesselated from.
+ All three should point to the same face, so just use the face from the first
+ loop.*/
+ f = tri[0]->f;
+
+ /*If the looptris is ordered such that all triangles tesselated from a single
+ faces are consecutive elements in the array, then we could speed up the tests
+ below by using the insert value from the previous iteration.*/
+
+ /*Start with the assumption the triangle should be included for snapping.*/
+ insert = 1;
+
+ if (BM_TestHFlag(f, BM_SELECT) || BM_TestHFlag(f, BM_HIDDEN)) {
+ /*Don't insert triangles tesselated from faces that are hidden
+ or selected*/
+ insert = 0;
+ }
+ else {
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_FACE, f) {
+ if (BM_TestHFlag(v, BM_SELECT)) {
+ /*Don't insert triangles tesselated from faces that have
+ any selected verts.*/
+ insert = 0;
+ }
+ }
+ }
+
+ if (insert)
+ {
+ /*No reason found to block hit-testing the triangle for snap,
+ so insert it now.*/
+ float co[4][3];
+ VECCOPY(co[0], tri[0]->v->co);
+ VECCOPY(co[1], tri[1]->v->co);
+ VECCOPY(co[2], tri[2]->v->co);
+
+ BLI_bvhtree_insert(tree, i, co[0], 3);
+ }
+ }
+ }
+ else {
+ MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT);
+ MFace *face = mesh->getTessFaceDataArray(mesh, CD_MFACE);
+
+ if (vert != NULL && face != NULL) {
+ for(i = 0; i < numFaces; i++) {
float co[4][3];
VECCOPY(co[0], vert[ face[i].v1 ].co);
VECCOPY(co[1], vert[ face[i].v2 ].co);
VECCOPY(co[2], vert[ face[i].v3 ].co);
if(face[i].v4)
VECCOPY(co[3], vert[ face[i].v4 ].co);
-
+
BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
}
}
}
- else {
- for(i = 0; i < numFaces; i++) {
- float co[4][3];
- VECCOPY(co[0], vert[ face[i].v1 ].co);
- VECCOPY(co[1], vert[ face[i].v2 ].co);
- VECCOPY(co[2], vert[ face[i].v3 ].co);
- if(face[i].v4)
- VECCOPY(co[3], vert[ face[i].v4 ].co);
-
- BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
- }
- }
BLI_bvhtree_balance(tree);
//Save on cache for later use
@@ -639,7 +685,7 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float
data->mesh = mesh;
data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
- data->face = mesh->getFaceDataArray(mesh, CD_MFACE);
+ data->face = mesh->getTessFaceDataArray(mesh, CD_MFACE);
data->sphere_radius = epsilon;
}
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 25f9f17f201..aaceab8912e 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -1,4 +1,4 @@
-/*
+ /*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -36,11 +36,23 @@
#include "GL/glew.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_paint.h"
+#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
+
+#include "BLI_editVert.h"
+#include "BLI_scanfill.h"
+#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_edgehash.h"
#include "BLI_editVert.h"
#include "BLI_math.h"
#include "BLI_pbvh.h"
+#include "BLI_array.h"
+#include "BLI_smallhash.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
@@ -72,6 +84,8 @@ typedef struct {
MVert *mvert;
MEdge *medge;
MFace *mface;
+ MLoop *mloop;
+ MPoly *mpoly;
/* Cached */
struct PBVH *pbvh;
@@ -93,11 +107,16 @@ static int cdDM_getNumEdges(DerivedMesh *dm)
return dm->numEdgeData;
}
-static int cdDM_getNumFaces(DerivedMesh *dm)
+static int cdDM_getNumTessFaces(DerivedMesh *dm)
{
return dm->numFaceData;
}
+static int cdDM_getNumFaces(DerivedMesh *dm)
+{
+ return dm->numPolyData;
+}
+
static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
@@ -134,6 +153,18 @@ static void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData);
}
+static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
+ memcpy(loop_r, cddm->mloop, sizeof(*loop_r) * dm->numLoopData);
+}
+
+static void cdDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
+ memcpy(poly_r, cddm->mpoly, sizeof(*poly_r) * dm->numPolyData);
+}
+
static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
@@ -203,7 +234,7 @@ static int can_pbvh_draw(Object *ob, DerivedMesh *dm)
if(deformed)
return 0;
- return (cddm->mvert == me->mvert) || ob->sculpt->kb;
+ return cddm->mvert == me->mvert || ob->sculpt->kb;
}
static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
@@ -292,7 +323,7 @@ static void cdDM_drawUVEdges(DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
MFace *mf = cddm->mface;
- MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
+ MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
int i;
if(mf) {
@@ -463,7 +494,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
MVert *mvert = cddm->mvert;
MFace *mface = cddm->mface;
- float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
+ float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
#define PASSVERT(index) { \
@@ -651,15 +682,15 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
{
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
MVert *mv = cddm->mvert;
- MFace *mf = DM_get_face_data_layer(dm, CD_MFACE);
- MCol *realcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL);
- float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
- MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
- int i, j, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
+ MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
+ MCol *realcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL);
+ float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
+ MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ int i, j, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
int startFace = 0, lastFlag = 0xdeadbeef;
- MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
+ MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
if(!mcol)
- mcol = dm->getFaceDataArray(dm, CD_MCOL);
+ mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
cdDM_update_normals_from_pbvh(dm);
@@ -751,8 +782,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
}
if( col != 0 ) {*/
- unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
- for( i=0; i < dm->getNumFaces(dm); i++ ) {
+ unsigned char *colors = MEM_mallocN(dm->getNumTessFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
+ for( i=0; i < dm->getNumTessFaces(dm); i++ ) {
for( j=0; j < 4; j++ ) {
/* bgr -> rgb is intentional (and stupid), but how its stored internally */
colors[i*12+j*3] = col[i*4+j].b;
@@ -846,14 +877,14 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
MVert *mv = cddm->mvert;
MFace *mf = cddm->mface;
MCol *mc;
- float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
- int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
+ float *nors= DM_get_tessface_data_layer(dm, CD_NORMAL);
+ int i, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
- mc = DM_get_face_data_layer(dm, CD_ID_MCOL);
+ mc = DM_get_tessface_data_layer(dm, CD_ID_MCOL);
if(!mc)
- mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
+ mc = DM_get_tessface_data_layer(dm, CD_WEIGHT_MCOL);
if(!mc)
- mc = DM_get_face_data_layer(dm, CD_MCOL);
+ mc = DM_get_tessface_data_layer(dm, CD_MCOL);
cdDM_update_normals_from_pbvh(dm);
@@ -923,7 +954,9 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
}
glEnd();
- }
+ } /*else {
+ printf("eek in cddm draw mapped faces!\n");
+ }*/
if (nors) nors += 3;
}
@@ -1063,10 +1096,10 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo
DMVertexAttribs attribs;
MVert *mvert = cddm->mvert;
MFace *mface = cddm->mface;
- /* MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
- float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
+ /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
+ float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
int a, b, dodraw, matnr, new_matnr;
- int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
cdDM_update_normals_from_pbvh(dm);
@@ -1425,10 +1458,13 @@ static void cdDM_foreachMappedFaceCenter(
{
CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
MVert *mv = cddm->mvert;
- MFace *mf = cddm->mface;
- int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
+ MPoly *mf = cddm->mpoly;
+ MLoop *ml = cddm->mloop;
+ int i, j, orig, *index;
- for(i = 0; i < dm->numFaceData; i++, mf++) {
+ index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
+ mf = cddm->mpoly;
+ for(i = 0; i < dm->numPolyData; i++, mf++) {
float cent[3];
float no[3];
@@ -1438,22 +1474,56 @@ static void cdDM_foreachMappedFaceCenter(
}
else
orig = i;
+
+ ml = &cddm->mloop[mf->loopstart];
+ cent[0] = cent[1] = cent[2] = 0.0f;
+ for (j=0; j<mf->totloop; j++, ml++) {
+ add_v3_v3v3(cent, cent, mv[ml->v].co);
+ }
+ mul_v3_fl(cent, 1.0f / (float)j);
- VECCOPY(cent, mv[mf->v1].co);
- add_v3_v3(cent, mv[mf->v2].co);
- add_v3_v3(cent, mv[mf->v3].co);
-
- if (mf->v4) {
- normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
- add_v3_v3(cent, mv[mf->v4].co);
- mul_v3_fl(cent, 0.25f);
+ ml = &cddm->mloop[mf->loopstart];
+ if (j > 3) {
+ normal_quad_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
+ mv[(ml+2)->v].co, mv[(ml+3)->v].co);
} else {
- normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
- mul_v3_fl(cent, 0.33333333333f);
+ normal_tri_v3(no, mv[ml->v].co, mv[(ml+1)->v].co, mv[(ml+2)->v].co);
}
func(userData, orig, cent, no);
}
+
+}
+
+static void cdDM_recalcTesselation(DerivedMesh *dm)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+
+ dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData,
+ &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData,
+ dm->numPolyData, 1, 0);
+
+ cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
+}
+
+/*ignores original poly origindex layer*/
+static void cdDM_recalcTesselation2(DerivedMesh *dm)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+
+ dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData,
+ &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData,
+ dm->numPolyData, 0, 0);
+
+ cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
+}
+
+void CDDM_recalc_tesselation(DerivedMesh *dm, int orig_use_polyorig)
+{
+ if (orig_use_polyorig)
+ cdDM_recalcTesselation(dm);
+ else
+ cdDM_recalcTesselation2(dm);
}
static void cdDM_free_internal(CDDerivedMesh *cddm)
@@ -1472,6 +1542,11 @@ static void cdDM_release(DerivedMesh *dm)
}
}
+int CDDM_Check(DerivedMesh *dm)
+{
+ return dm && dm->getMinMax == cdDM_getMinMax;
+}
+
/**************** CDDM interface functions ****************/
static CDDerivedMesh *cdDM_create(const char *desc)
{
@@ -1484,21 +1559,27 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->getMinMax = cdDM_getMinMax;
dm->getNumVerts = cdDM_getNumVerts;
- dm->getNumFaces = cdDM_getNumFaces;
dm->getNumEdges = cdDM_getNumEdges;
+ dm->getNumTessFaces = cdDM_getNumTessFaces;
+ dm->getNumFaces = cdDM_getNumFaces;
dm->getVert = cdDM_getVert;
dm->getEdge = cdDM_getEdge;
- dm->getFace = cdDM_getFace;
+ dm->getTessFace = cdDM_getFace;
dm->copyVertArray = cdDM_copyVertArray;
dm->copyEdgeArray = cdDM_copyEdgeArray;
- dm->copyFaceArray = cdDM_copyFaceArray;
+ dm->copyTessFaceArray = cdDM_copyFaceArray;
+ dm->copyLoopArray = cdDM_copyLoopArray;
+ dm->copyPolyArray = cdDM_copyPolyArray;
dm->getVertData = DM_get_vert_data;
dm->getEdgeData = DM_get_edge_data;
- dm->getFaceData = DM_get_face_data;
+ dm->getTessFaceData = DM_get_face_data;
dm->getVertDataArray = DM_get_vert_data_layer;
dm->getEdgeDataArray = DM_get_edge_data_layer;
- dm->getFaceDataArray = DM_get_face_data_layer;
+ dm->getTessFaceDataArray = DM_get_tessface_data_layer;
+
+ //doesn't work yet for all cases
+ //dm->recalcTesselation = cdDM_recalcTesselation;
dm->getVertCos = cdDM_getVertCos;
dm->getVertCo = cdDM_getVertCo;
@@ -1531,24 +1612,29 @@ static CDDerivedMesh *cdDM_create(const char *desc)
return cddm;
}
-DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
+DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, int numPolys)
{
CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
DerivedMesh *dm = &cddm->dm;
- DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
+ DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
+ CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys);
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
+ CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
+ CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
+ cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
+ cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
return dm;
}
@@ -1562,7 +1648,8 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
/* this does a referenced copy, with an exception for fluidsim */
- DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface);
+ DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface,
+ mesh->totloop, mesh->totpoly);
dm->deformedOnly = 1;
@@ -1572,21 +1659,30 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
mesh->totvert);
CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
mesh->totedge);
- CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
+ CustomData_merge(&mesh->fdata, &dm->faceData, mask|CD_MASK_ORIGINDEX, alloctype,
mesh->totface);
+ CustomData_merge(&mesh->ldata, &dm->loopData, mask, alloctype,
+ mesh->totloop);
+ CustomData_merge(&mesh->pdata, &dm->polyData, mask, alloctype,
+ mesh->totpoly);
cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
+ cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
+ cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
+ if (!CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX))
+ CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface);
+
return dm;
}
-DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
+static DerivedMesh *disabled__CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
{
DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
- BLI_countlist(&em->edges),
- BLI_countlist(&em->faces));
+ BLI_countlist(&em->edges),
+ BLI_countlist(&em->faces), 0, 0);
CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
EditVert *eve;
EditEdge *eed;
@@ -1604,6 +1700,8 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
CD_CALLOC, dm->numEdgeData); */
CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
CD_CALLOC, dm->numFaceData);
+ CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
+ CD_CALLOC, dm->numFaceData);
/* set eve->hash to vert index */
for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
@@ -1657,7 +1755,7 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
/* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
}
- index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
for(i = 0, efa = em->faces.first; i < dm->numFaceData;
i++, efa = efa->next, index++) {
MFace *mf = &mface[i];
@@ -1690,15 +1788,17 @@ DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
MVert *allvert;
MEdge *alledge;
MFace *allface;
- int totvert, totedge, totface;
+ MLoop *allloop;
+ MPoly *allpoly;
+ int totvert, totedge, totface, totloop, totpoly;
if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
- &totedge, &allface, &totface) != 0) {
+ &totedge, &allface, &allloop, &allpoly, &totface, &totloop, &totpoly) != 0) {
/* Error initializing mdata. This often happens when curve is empty */
- return CDDM_new(0, 0, 0);
+ return CDDM_new(0, 0, 0, 0, 0);
}
- dm = CDDM_new(totvert, totedge, totface);
+ dm = CDDM_new(totvert, totedge, totface, totloop, totpoly);
dm->deformedOnly = 1;
cddm = (CDDerivedMesh*)dm;
@@ -1706,29 +1806,245 @@ DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
memcpy(cddm->mface, allface, totface*sizeof(MFace));
+ memcpy(cddm->mloop, allloop, totloop*sizeof(MLoop));
+ memcpy(cddm->mpoly, allpoly, totpoly*sizeof(MPoly));
MEM_freeN(allvert);
MEM_freeN(alledge);
MEM_freeN(allface);
+ MEM_freeN(allloop);
+ MEM_freeN(allpoly);
return dm;
}
-DerivedMesh *CDDM_copy(DerivedMesh *source)
+static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata,
+ int cdindex, BMLoop *l3[3],
+ int numCol, int numTex)
+{
+ BMLoop *l;
+ BMFace *f = l3[0]->f;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ int i, j, hasWCol = CustomData_has_layer(&bm->ldata, CD_WEIGHT_MLOOPCOL);
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i);
+ texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
+
+ texface->tpage = texpoly->tpage;
+ texface->flag = texpoly->flag;
+ texface->transp = texpoly->transp;
+ texface->mode = texpoly->mode;
+ texface->tile = texpoly->tile;
+ texface->unwrap = texpoly->unwrap;
+
+ for (j=0; j<3; j++) {
+ l = l3[j];
+ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
+ texface->uv[j][0] = mloopuv->uv[0];
+ texface->uv[j][1] = mloopuv->uv[1];
+ }
+ }
+
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_get_n(facedata, CD_MCOL, cdindex, i);
+
+ for (j=0; j<3; j++) {
+ l = l3[j];
+ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
+ }
+
+ if (hasWCol) {
+ mcol = CustomData_get(facedata, cdindex, CD_WEIGHT_MCOL);
+
+ for (j=0; j<3; j++) {
+ l = l3[j];
+ mloopcol = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_WEIGHT_MLOOPCOL);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
+ }
+}
+
+DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *UNUSED(me), int use_mdisps)
+{
+ DerivedMesh *dm = CDDM_new(em->bm->totvert, em->bm->totedge,
+ em->tottri, em->bm->totloop, em->bm->totface);
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+ BMesh *bm = em->bm;
+ BMIter iter, liter;
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+ MVert *mvert = cddm->mvert;
+ MEdge *medge = cddm->medge;
+ MFace *mface = cddm->mface;
+ MLoop *mloop = cddm->mloop;
+ MPoly *mpoly = cddm->mpoly;
+ int numCol = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL);
+ int numTex = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
+ int i, j, *index, add_orig;
+ int has_crease, has_edge_bweight, has_vert_bweight;
+ int flag;
+
+ has_edge_bweight = CustomData_has_layer(&em->bm->edata, CD_BWEIGHT);
+ has_vert_bweight = CustomData_has_layer(&em->bm->vdata, CD_BWEIGHT);
+ has_crease = CustomData_has_layer(&em->bm->edata, CD_CREASE);
+
+ dm->deformedOnly = 1;
+
+ /*don't add origindex layer if one already exists*/
+ add_orig = !CustomData_has_layer(&em->bm->pdata, CD_ORIGINDEX);
+
+ flag = use_mdisps ? CD_MASK_DERIVEDMESH|CD_MASK_MDISPS : CD_MASK_DERIVEDMESH;
+
+ /*don't process shapekeys, we only feed them through the modifier stack as needed,
+ e.g. for applying modifiers or the like*/
+ flag &= ~CD_SHAPEKEY;
+ CustomData_merge(&em->bm->vdata, &dm->vertData, flag,
+ CD_CALLOC, dm->numVertData);
+ CustomData_merge(&em->bm->edata, &dm->edgeData, flag,
+ CD_CALLOC, dm->numEdgeData);
+ CustomData_merge(&em->bm->ldata, &dm->loopData, flag,
+ CD_CALLOC, dm->numLoopData);
+ CustomData_merge(&em->bm->pdata, &dm->polyData, flag,
+ CD_CALLOC, dm->numPolyData);
+
+ /*add tesselation mface layers*/
+ CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em->tottri);
+
+ /* set vert index */
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++)
+ BM_SetIndex(eve, i);
+
+ index = dm->getVertDataArray(dm, CD_ORIGINDEX);
+
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++, index++) {
+ MVert *mv = &mvert[i];
+
+ VECCOPY(mv->co, eve->co);
+
+ BM_SetIndex(eve, i);
+
+ mv->no[0] = eve->no[0] * 32767.0;
+ mv->no[1] = eve->no[1] * 32767.0;
+ mv->no[2] = eve->no[2] * 32767.0;
+
+ mv->flag = BMFlags_To_MEFlags(eve);
+
+ if (has_vert_bweight)
+ mv->bweight = (unsigned char)(BM_GetCDf(&bm->vdata, eve, CD_BWEIGHT)*255.0f);
+
+ if (add_orig) *index = i;
+
+ CustomData_from_bmesh_block(&bm->vdata, &dm->vertData, eve->head.data, i);
+ }
+
+ index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
+ eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
+ for (i=0; eed; eed=BMIter_Step(&iter), i++, index++) {
+ MEdge *med = &medge[i];
+
+ BM_SetIndex(eed, i);
+
+ med->v1 = BM_GetIndex(eed->v1);
+ med->v2 = BM_GetIndex(eed->v2);
+
+ if (has_crease)
+ med->crease = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_CREASE)*255.0f);
+ if (has_edge_bweight)
+ med->bweight = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_BWEIGHT)*255.0f);
+
+ med->flag = BMFlags_To_MEFlags(eed);
+
+ CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i);
+ if (add_orig) *index = i;
+ }
+
+ efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
+ for (i=0; efa; i++, efa=BMIter_Step(&iter)) {
+ BM_SetIndex(efa, i);
+ }
+
+ index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ for(i = 0; i < dm->numFaceData; i++, index++) {
+ MFace *mf = &mface[i];
+ BMLoop **l = em->looptris[i];
+ efa = l[0]->f;
+
+ mf->v1 = BM_GetIndex(l[0]->v);
+ mf->v2 = BM_GetIndex(l[1]->v);
+ mf->v3 = BM_GetIndex(l[2]->v);
+ mf->v4 = 0;
+ mf->mat_nr = efa->mat_nr;
+ mf->flag = BMFlags_To_MEFlags(efa);
+
+ *index = add_orig ? BM_GetIndex(efa) : *(int*)CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_ORIGINDEX);
+
+ loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex);
+ test_index_face(mf, &dm->faceData, i, 3);
+ }
+
+ index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
+ j = 0;
+ efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
+ for (i=0; efa; i++, efa=BMIter_Step(&iter), index++) {
+ BMLoop *l;
+ MPoly *mp = &mpoly[i];
+
+ mp->totloop = efa->len;
+ mp->flag = BMFlags_To_MEFlags(efa);
+ mp->loopstart = j;
+ mp->mat_nr = efa->mat_nr;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
+ mloop->v = BM_GetIndex(l->v);
+ mloop->e = BM_GetIndex(l->e);
+ CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l->head.data, j);
+
+ j++;
+ mloop++;
+ }
+
+ CustomData_from_bmesh_block(&bm->pdata, &dm->polyData, efa->head.data, i);
+
+ if (add_orig) *index = i;
+ }
+
+ return dm;
+}
+
+DerivedMesh *CDDM_copy(DerivedMesh *source, int faces_from_tessfaces)
{
CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
DerivedMesh *dm = &cddm->dm;
int numVerts = source->numVertData;
int numEdges = source->numEdgeData;
int numFaces = source->numFaceData;
+ int numLoops = source->numLoopData;
+ int numPolys = source->numPolyData;
/* ensure these are created if they are made on demand */
source->getVertDataArray(source, CD_ORIGINDEX);
source->getEdgeDataArray(source, CD_ORIGINDEX);
- source->getFaceDataArray(source, CD_ORIGINDEX);
+ source->getTessFaceDataArray(source, CD_ORIGINDEX);
/* this initializes dm, and copies all non mvert/medge/mface layers */
- DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
+ DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces,
+ numLoops, numPolys);
dm->deformedOnly = source->deformedOnly;
CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
@@ -1738,19 +2054,30 @@ DerivedMesh *CDDM_copy(DerivedMesh *source)
/* now add mvert/medge/mface layers */
cddm->mvert = source->dupVertArray(source);
cddm->medge = source->dupEdgeArray(source);
- cddm->mface = source->dupFaceArray(source);
+ cddm->mface = source->dupTessFaceArray(source);
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
+
+ if (!faces_from_tessfaces)
+ DM_DupPolys(source, dm);
+ else
+ CDDM_tessfaces_to_faces(dm);
+ cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
+ cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
+
+ cdDM_recalcTesselation((DerivedMesh *)cddm);
+
return dm;
}
/* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
* relationship betwen mesh data this needs to be set by the caller. */
DerivedMesh *CDDM_from_template(DerivedMesh *source,
- int numVerts, int numEdges, int numFaces)
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys)
{
CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
DerivedMesh *dm = &cddm->dm;
@@ -1758,15 +2085,17 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source,
/* ensure these are created if they are made on demand */
source->getVertDataArray(source, CD_ORIGINDEX);
source->getEdgeDataArray(source, CD_ORIGINDEX);
- source->getFaceDataArray(source, CD_ORIGINDEX);
+ source->getTessFaceDataArray(source, CD_ORIGINDEX);
/* this does a copy of all non mvert/medge/mface layers */
- DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
+ DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
/* now add mvert/medge/mface layers */
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
+ CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
+ CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
@@ -1778,6 +2107,8 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source,
cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
+ cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
+ cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
return dm;
}
@@ -1813,22 +2144,228 @@ void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
void CDDM_calc_normals(DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
- float (*face_nors)[3];
-
+ float (*face_nors)[3] = NULL;
+
if(dm->numVertData == 0) return;
/* we don't want to overwrite any referenced layers */
cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
+
+ /*set tesselation origindex values to map to poly indices, rather then poly
+ poly origindex values*/
+ cdDM_recalcTesselation2(dm);
+
+ face_nors = MEM_mallocN(sizeof(float)*3*dm->numFaceData, "face_nors");
+
+ /* calculate face normals */
+ mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm),
+ dm->numLoopData, dm->numPolyData, NULL, cddm->mface, dm->numFaceData,
+ CustomData_get_layer(&dm->faceData, CD_ORIGINDEX), face_nors);
+
+ /*restore tesselation origindex indices to poly origindex indices*/
+ cdDM_recalcTesselation(dm);
- /* make a face normal layer if not present */
- face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
- if(!face_nors)
- face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
- NULL, dm->numFaceData);
+ CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN,
+ face_nors, dm->numFaceData);
+}
- /* calculate face normals */
- mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_faces(dm), dm->numFaceData, face_nors);
+#if 1
+/*merge verts
+
+ vtargetmap is a table that maps vertices to target vertices. a value of -1
+ indicates a vertex is a target, and is to be kept.
+
+ this frees dm, and returns a new one.
+
+ this is a really horribly written function. ger. - joeedh
+
+ */
+DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, int *vtargetmap)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+ CDDerivedMesh *cddm2 = NULL;
+ MVert *mv, *mvert = NULL;
+ BLI_array_declare(mvert);
+ MEdge *me, *medge = NULL;
+ BLI_array_declare(medge);
+ MPoly *mp, *mpoly = NULL;
+ BLI_array_declare(mpoly);
+ MLoop *ml, *mloop = NULL;
+ BLI_array_declare(mloop);
+ EdgeHash *ehash = BLI_edgehash_new();
+ int *newv = NULL, *newe = NULL, *newl = NULL;
+ int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL;
+ BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp);
+ int i, j, c, totloop, totpoly;
+
+ totloop = dm->numLoopData;
+ totpoly = dm->numPolyData;
+
+ newv = MEM_callocN(sizeof(int)*dm->numVertData, "newv vtable CDDM_merge_verts");
+ newe = MEM_callocN(sizeof(int)*dm->numEdgeData, "newv etable CDDM_merge_verts");
+ newl = MEM_callocN(sizeof(int)*totloop, "newv ltable CDDM_merge_verts");
+
+ /*fill newl with destination vertex indices*/
+ mv = cddm->mvert;
+ c = 0;
+ for (i=0; i<dm->numVertData; i++, mv++) {
+ if (vtargetmap[i] == -1) {
+ BLI_array_append(oldv, i);
+ newv[i] = c++;
+ BLI_array_append(mvert, *mv);
+ }
+ }
+
+ /*now link target vertices to destination indices*/
+ for (i=0; i<dm->numVertData; i++) {
+ if (vtargetmap[i] != -1) {
+ newv[i] = newv[vtargetmap[i]];
+ }
+ }
+
+ /*find-replace merged vertices with target vertices*/
+ ml = cddm->mloop;
+ c = 0;
+ for (i=0; i<totloop; i++, ml++) {
+ if (ml->v == -1)
+ continue;
+
+ if (vtargetmap[ml->v] != -1)
+ ml->v = vtargetmap[ml->v];
+ }
+
+ /*now go through and fix edges and faces*/
+ me = cddm->medge;
+ c = 0;
+ for (i=0; i<dm->numEdgeData; i++, me++) {
+ int v1, v2;
+
+ if (me->v1 == me->v2) {
+ newe[i] = -1;
+ continue;
+ }
+
+ if (vtargetmap[me->v1] != -1)
+ v1 = vtargetmap[me->v1];
+ else
+ v1 = me->v1;
+
+ if (vtargetmap[me->v2] != -1)
+ v2 = vtargetmap[me->v2];
+ else
+ v2 = me->v2;
+
+ if (BLI_edgehash_haskey(ehash, v1, v2)) {
+ newe[i] = GET_INT_FROM_POINTER(BLI_edgehash_lookup(ehash, v1, v2));
+ } else {
+ BLI_array_append(olde, i);
+ newe[i] = c;
+ BLI_array_append(medge, *me);
+ BLI_edgehash_insert(ehash, v1, v2, SET_INT_IN_POINTER(c));
+ c++;
+ }
+ }
+
+ mp = cddm->mpoly;
+ for (i=0; i<totpoly; i++, mp++) {
+ MPoly *mp2;
+
+ ml = cddm->mloop + mp->loopstart;
+
+ c = 0;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ if (ml->v == -1)
+ continue;
+
+ me = cddm->medge + ml->e;
+ if (me->v1 != me->v2) {
+ BLI_array_append(oldl, j+mp->loopstart);
+ BLI_array_append(mloop, *ml);
+ newl[j+mp->loopstart] = BLI_array_count(mloop)-1;
+ c++;
+ }
+ }
+
+ if (!c)
+ continue;
+
+ mp2 = BLI_array_append(mpoly, *mp);
+ mp2->totloop = c;
+ mp2->loopstart = BLI_array_count(mloop) - c;
+
+ BLI_array_append(oldp, i);
+ }
+
+ /*create new cddm*/
+ cddm2 = (CDDerivedMesh*) CDDM_from_template((DerivedMesh*)cddm, BLI_array_count(mvert), BLI_array_count(medge), 0, BLI_array_count(mloop), BLI_array_count(mpoly));
+
+ /*update edge indices and copy customdata*/
+ me = medge;
+ for (i=0; i<cddm2->dm.numEdgeData; i++, me++) {
+ if (newv[me->v1] != -1)
+ me->v1 = newv[me->v1];
+ if (newv[me->v2] != -1)
+ me->v2 = newv[me->v2];
+
+ CustomData_copy_data(&dm->edgeData, &cddm2->dm.edgeData, olde[i], i, 1);
+ }
+
+ /*update loop indices and copy customdata*/
+ ml = mloop;
+ for (i=0; i<cddm2->dm.numLoopData; i++, ml++) {
+ if (newe[ml->e] != -1)
+ ml->e = newe[ml->e];
+ if (newv[ml->v] != -1)
+ ml->v = newv[ml->v];
+
+ CustomData_copy_data(&dm->loopData, &cddm2->dm.loopData, oldl[i], i, 1);
+ }
+
+ /*copy vertex customdata*/
+ mv = mvert;
+ for (i=0; i<cddm2->dm.numVertData; i++, mv++) {
+ CustomData_copy_data(&dm->vertData, &cddm2->dm.vertData, oldv[i], i, 1);
+ }
+
+ /*copy poly customdata*/
+ mp = mpoly;
+ for (i=0; i<cddm2->dm.numPolyData; i++, mp++) {
+ CustomData_copy_data(&dm->polyData, &cddm2->dm.polyData, oldp[i], i, 1);
+ }
+
+ /*copy over data. CustomData_add_layer can do this, need to look it up.*/
+ memcpy(cddm2->mvert, mvert, sizeof(MVert)*BLI_array_count(mvert));
+ memcpy(cddm2->medge, medge, sizeof(MEdge)*BLI_array_count(medge));
+ memcpy(cddm2->mloop, mloop, sizeof(MLoop)*BLI_array_count(mloop));
+ memcpy(cddm2->mpoly, mpoly, sizeof(MPoly)*BLI_array_count(mpoly));
+ BLI_array_free(mvert); BLI_array_free(medge); BLI_array_free(mloop); BLI_array_free(mpoly);
+
+ CDDM_recalc_tesselation((DerivedMesh*)cddm2, 1);
+
+ if (newv)
+ MEM_freeN(newv);
+ if (newe)
+ MEM_freeN(newe);
+ if (newl)
+ MEM_freeN(newl);
+ if (oldv)
+ MEM_freeN(oldv);
+ if (olde)
+ MEM_freeN(olde);
+ if (oldl)
+ MEM_freeN(oldl);
+ if (oldp)
+ MEM_freeN(oldp);
+ if (ehash)
+ BLI_edgehash_free(ehash, NULL);
+
+ /*free old derivedmesh*/
+ dm->needsFree = 1;
+ dm->release(dm);
+
+ return (DerivedMesh*)cddm2;
}
+#endif
void CDDM_calc_edges(DerivedMesh *dm)
{
@@ -1886,6 +2423,83 @@ void CDDM_calc_edges(DerivedMesh *dm)
BLI_edgehash_free(eh, NULL);
}
+
+void CDDM_calc_edges_poly(DerivedMesh *dm)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+ CustomData edgeData;
+ EdgeHashIterator *ehi;
+ MPoly *mp = cddm->mpoly;
+ MLoop *ml;
+ MEdge *med;
+ EdgeHash *eh = BLI_edgehash_new();
+ int v1, v2;
+ int *eindex;
+ int i, j, k, *index, numEdges = cddm->dm.numEdgeData, maxFaces = dm->numPolyData;
+
+ eindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
+
+ med = cddm->medge;
+ if (med) {
+ for (i=0; i < numEdges; i++, med++) {
+ BLI_edgehash_insert(eh, med->v1, med->v2, SET_INT_IN_POINTER(i+1));
+ }
+ }
+
+ for (i=0; i < maxFaces; i++, mp++) {
+ ml = cddm->mloop + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ v1 = ml->v;
+ v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
+ if (!BLI_edgehash_haskey(eh, v1, v2)) {
+ BLI_edgehash_insert(eh, v1, v2, NULL);
+ }
+ }
+ }
+
+ k = numEdges;
+ numEdges = BLI_edgehash_size(eh);
+
+ /* write new edges into a temporary CustomData */
+ memset(&edgeData, 0, sizeof(edgeData));
+ CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
+ CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
+
+ ehi = BLI_edgehashIterator_new(eh);
+ med = CustomData_get_layer(&edgeData, CD_MEDGE);
+ index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
+ for(i = 0; !BLI_edgehashIterator_isDone(ehi);
+ BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
+ BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
+ j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
+
+ med->flag = ME_EDGEDRAW|ME_EDGERENDER;
+ *index = j==0 ? ORIGINDEX_NONE : eindex[j-1];
+
+ BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i));
+ }
+ BLI_edgehashIterator_free(ehi);
+
+ /* free old CustomData and assign new one */
+ CustomData_free(&dm->edgeData, dm->numEdgeData);
+ dm->edgeData = edgeData;
+ dm->numEdgeData = numEdges;
+
+ cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
+
+ mp = cddm->mpoly;
+ for (i=0; i < maxFaces; i++, mp++) {
+ ml = cddm->mloop + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ v1 = ml->v;
+ v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
+ ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, v1, v2));
+ }
+ }
+
+ BLI_edgehash_free(eh, NULL);
+}
+
void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
{
if (numVerts < dm->numVertData)
@@ -1920,7 +2534,7 @@ MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
return &((CDDerivedMesh*)dm)->medge[index];
}
-MFace *CDDM_get_face(DerivedMesh *dm, int index)
+MFace *CDDM_get_tessface(DerivedMesh *dm, int index)
{
return &((CDDerivedMesh*)dm)->mface[index];
}
@@ -1935,8 +2549,125 @@ MEdge *CDDM_get_edges(DerivedMesh *dm)
return ((CDDerivedMesh*)dm)->medge;
}
-MFace *CDDM_get_faces(DerivedMesh *dm)
+MFace *CDDM_get_tessfaces(DerivedMesh *dm)
{
return ((CDDerivedMesh*)dm)->mface;
}
+MLoop *CDDM_get_loops(DerivedMesh *dm)
+{
+ return ((CDDerivedMesh*)dm)->mloop;
+}
+
+MPoly *CDDM_get_polys(DerivedMesh *dm)
+{
+ return ((CDDerivedMesh*)dm)->mpoly;
+}
+
+void CDDM_tessfaces_to_faces(DerivedMesh *dm)
+{
+ /*converts mfaces to mpolys/mloops*/
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+ MFace *mf;
+ MEdge *me;
+ MLoop *ml;
+ MPoly *mp;
+ EdgeHash *eh = BLI_edgehash_new();
+ int i, l, totloop, *index1, *index2;
+
+ /*ensure we have all the edges we need*/
+ CDDM_calc_edges(dm);
+
+ /*build edge hash*/
+ me = cddm->medge;
+ for (i=0; i<cddm->dm.numEdgeData; i++, me++) {
+ BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i));
+ }
+
+ mf = cddm->mface;
+ totloop = 0;
+ for (i=0; i<cddm->dm.numFaceData; i++, mf++) {
+ totloop += mf->v4 ? 4 : 3;
+ }
+
+ CustomData_free(&cddm->dm.polyData, cddm->dm.numPolyData);
+ CustomData_free(&cddm->dm.loopData, cddm->dm.numLoopData);
+
+ cddm->dm.numLoopData = totloop;
+ cddm->dm.numPolyData = cddm->dm.numFaceData;
+
+ if (!totloop) return;
+
+ cddm->mloop = MEM_callocN(sizeof(MLoop)*totloop, "cddm->mloop in CDDM_tessfaces_to_faces");
+ cddm->mpoly = MEM_callocN(sizeof(MPoly)*cddm->dm.numFaceData, "cddm->mpoly in CDDM_tessfaces_to_faces");
+
+ CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, cddm->mloop, totloop);
+ CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, cddm->mpoly, cddm->dm.numPolyData);
+ CustomData_merge(&cddm->dm.faceData, &cddm->dm.polyData,
+ CD_MASK_ORIGINDEX, CD_DUPLICATE, cddm->dm.numFaceData);
+
+ index1 = CustomData_get_layer(&cddm->dm.faceData, CD_ORIGINDEX);
+ index2 = CustomData_get_layer(&cddm->dm.polyData, CD_ORIGINDEX);
+
+ mf = cddm->mface;
+ mp = cddm->mpoly;
+ ml = cddm->mloop;
+ l = 0;
+ for (i=0; i<cddm->dm.numFaceData; i++, mf++, mp++) {
+ mp->flag = mf->flag;
+ mp->loopstart = l;
+ mp->mat_nr = mf->mat_nr;
+ mp->totloop = mf->v4 ? 4 : 3;
+
+ ml->v = mf->v1;
+ ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2));
+ ml++, l++;
+
+ ml->v = mf->v2;
+ ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v2, mf->v3));
+ ml++, l++;
+
+ ml->v = mf->v3;
+ ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v3, mf->v4?mf->v4:mf->v1));
+ ml++, l++;
+
+ if (mf->v4) {
+ ml->v = mf->v4;
+ ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v4, mf->v1));
+ ml++, l++;
+ }
+
+ }
+
+ BLI_edgehash_free(eh, NULL);
+}
+
+void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+
+ if (!CustomData_has_layer(&dm->vertData, CD_MVERT))
+ CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, mvert, dm->numVertData);
+
+ cddm->mvert = mvert;
+}
+
+void CDDM_set_medge(DerivedMesh *dm, MEdge *medge)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+
+ if (!CustomData_has_layer(&dm->edgeData, CD_MEDGE))
+ CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, medge, dm->numEdgeData);
+
+ cddm->medge = medge;
+}
+
+void CDDM_set_mface(DerivedMesh *dm, MFace *mface)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
+
+ if (!CustomData_has_layer(&dm->faceData, CD_MFACE))
+ CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, mface, dm->numFaceData);
+
+ cddm->mface = mface;
+}
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 444d17ad004..00a31fb77a7 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -35,6 +35,7 @@
#include "DNA_object_types.h"
#include "DNA_meshdata_types.h"
+#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
#include "BLI_utildefines.h"
@@ -439,7 +440,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
clmd->scene= scene; /* nice to pass on later :) */
framenr= (int)scene->r.cfra;
cache= clmd->point_cache;
- result = CDDM_copy(dm);
+ result = CDDM_copy(dm, 0);
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
@@ -933,8 +934,8 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm )
{
unsigned int numverts = dm->getNumVerts ( dm );
- unsigned int numfaces = dm->getNumFaces ( dm );
- MFace *mface = dm->getFaceArray( dm );
+ unsigned int numfaces = dm->getNumTessFaces ( dm );
+ MFace *mface = dm->getTessFaceArray( dm );
unsigned int i = 0;
/* Allocate our vertices. */
@@ -1046,9 +1047,9 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
unsigned int i = 0;
unsigned int numverts = (unsigned int)dm->getNumVerts ( dm );
unsigned int numedges = (unsigned int)dm->getNumEdges ( dm );
- unsigned int numfaces = (unsigned int)dm->getNumFaces ( dm );
+ unsigned int numfaces = (unsigned int)dm->getNumTessFaces ( dm );
MEdge *medge = dm->getEdgeArray ( dm );
- MFace *mface = dm->getFaceArray ( dm );
+ MFace *mface = dm->getTessFaceArray ( dm );
int index2 = 0; // our second vertex index
LinkNode **edgelist = NULL;
EdgeHash *edgehash = NULL;
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 09030575438..72bebd6bb85 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -42,6 +42,7 @@
#include "DNA_scene_types.h"
#include "DNA_meshdata_types.h"
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index c244c26ad7f..60111e9f01d 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -70,8 +70,10 @@
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_idprop.h"
+#include "BKE_mesh.h"
#include "BKE_shrinkwrap.h"
#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
#ifdef WITH_PYTHON
#include "BPY_extern.h"
@@ -425,7 +427,7 @@ static void contarget_get_mesh_mat (Object *ob, const char *substring, float mat
{
DerivedMesh *dm = NULL;
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
+ BMEditMesh *em = me->edit_btmesh;
float vec[3] = {0.0f, 0.0f, 0.0f};
float normal[3] = {0.0f, 0.0f, 0.0f}, plane[3];
float imat[3][3], tmat[3][3];
@@ -442,7 +444,7 @@ static void contarget_get_mesh_mat (Object *ob, const char *substring, float mat
/* get DerivedMesh */
if (em) {
/* target is in editmode, so get a special derived mesh */
- dm = CDDM_from_editmesh(em, ob->data);
+ dm = CDDM_from_BMEditMesh(em, ob->data, 0);
freeDM= 1;
}
else {
@@ -514,8 +516,6 @@ static void contarget_get_mesh_mat (Object *ob, const char *substring, float mat
/* free temporary DerivedMesh created (in EditMode case) */
if (dm && freeDM)
dm->release(dm);
- if (em)
- BKE_mesh_end_editmesh(me, em);
}
/* function that sets the given matrix based on given vertex group in lattice */
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 4d93f2cba05..022c31c00f6 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -48,6 +48,7 @@
#include "DNA_key_types.h"
#include "DNA_scene_types.h"
#include "DNA_vfont_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "BKE_animsys.h"
@@ -255,7 +256,10 @@ void make_local_curve(Curve *cu)
if(cu->id.lib==NULL) return;
if(cu->id.us==1) {
- id_clear_lib_data(&bmain->curve, (ID *)cu);
+ cu->id.lib= NULL;
+ cu->id.flag= LIB_LOCAL;
+
+ new_id(&bmain->curve, (ID *)cu, NULL);
extern_local_curve(cu);
return;
}
@@ -268,7 +272,10 @@ void make_local_curve(Curve *cu)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->curve, (ID *)cu);
+ cu->id.lib= NULL;
+ cu->id.flag= LIB_LOCAL;
+
+ new_id(&bmain->curve, (ID *)cu, NULL);
extern_local_curve(cu);
}
else if(local && lib) {
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index f2f3ade52bb..5f97a5ae3dc 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -44,19 +44,25 @@
#include "DNA_meshdata_types.h"
#include "DNA_ID.h"
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_mempool.h"
+#include "BLI_cellalloc.h"
#include "BLI_utildefines.h"
#include "BKE_customdata.h"
#include "BKE_customdata_file.h"
#include "BKE_global.h"
#include "BKE_main.h"
-#include "BKE_utildefines.h"
#include "BKE_multires.h"
+#include "bmesh.h"
+
+#include <math.h>
+#include <string.h>
+
/* number of layers to add when growing a CustomData object */
#define CUSTOMDATA_GROW 5
@@ -99,6 +105,14 @@ typedef struct LayerTypeInfo {
default is assumed to be all zeros */
void (*set_default)(void *data, int count);
+ /* functions necassary for geometry collapse*/
+ int (*equal)(void *data1, void *data2);
+ void (*multiply)(void *data, float fac);
+ void (*initminmax)(void *min, void *max);
+ void (*add)(void *data1, void *data2);
+ void (*dominmax)(void *data1, void *min, void *max);
+ void (*copyvalue)(void *source, void *dest);
+
/* a function to read data from a cdf file */
int (*read)(CDataFile *cdf, void *data, int count);
@@ -125,7 +139,7 @@ static void layerCopy_mdeformvert(const void *source, void *dest,
MDeformVert *dvert = (MDeformVert *)((char *)dest + i * size);
if(dvert->totweight) {
- MDeformWeight *dw = MEM_callocN(dvert->totweight * sizeof(*dw),
+ MDeformWeight *dw = BLI_cellalloc_calloc(dvert->totweight * sizeof(*dw),
"layerCopy_mdeformvert dw");
memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw));
@@ -144,7 +158,7 @@ static void layerFree_mdeformvert(void *data, int count, int size)
MDeformVert *dvert = (MDeformVert *)((char *)data + i * size);
if(dvert->dw) {
- MEM_freeN(dvert->dw);
+ BLI_cellalloc_free(dvert->dw);
dvert->dw = NULL;
dvert->totweight = 0;
}
@@ -153,7 +167,7 @@ static void layerFree_mdeformvert(void *data, int count, int size)
static void linklist_free_simple(void *link)
{
- MEM_freeN(link);
+ BLI_cellalloc_free(link);
}
static void layerInterp_mdeformvert(void **sources, float *weights,
@@ -186,7 +200,7 @@ static void layerInterp_mdeformvert(void **sources, float *weights,
/* if this def_nr is not in the list, add it */
if(!node) {
- MDeformWeight *tmp_dw = MEM_callocN(sizeof(*tmp_dw),
+ MDeformWeight *tmp_dw = BLI_cellalloc_calloc(sizeof(*tmp_dw),
"layerInterp_mdeformvert tmp_dw");
tmp_dw->def_nr = dw->def_nr;
tmp_dw->weight = dw->weight * interp_weight;
@@ -197,10 +211,10 @@ static void layerInterp_mdeformvert(void **sources, float *weights,
}
/* now we know how many unique deform weights there are, so realloc */
- if(dvert->dw) MEM_freeN(dvert->dw);
+ if(dvert->dw) BLI_cellalloc_free(dvert->dw);
if(totweight) {
- dvert->dw = MEM_callocN(sizeof(*dvert->dw) * totweight,
+ dvert->dw = BLI_cellalloc_calloc(sizeof(*dvert->dw) * totweight,
"layerInterp_mdeformvert dvert->dw");
dvert->totweight = totweight;
@@ -331,6 +345,24 @@ static void layerDefault_tface(void *data, int count)
tf[i] = default_tf;
}
+static void layerCopy_propFloat(const void *source, void *dest,
+ int count)
+{
+ memcpy(dest, source, sizeof(MFloatProperty)*count);
+}
+
+static void layerCopy_propInt(const void *source, void *dest,
+ int count)
+{
+ memcpy(dest, source, sizeof(MIntProperty)*count);
+}
+
+static void layerCopy_propString(const void *source, void *dest,
+ int count)
+{
+ memcpy(dest, source, sizeof(MStringProperty)*count);
+}
+
static void layerCopy_origspace_face(const void *source, void *dest, int count)
{
const OrigSpaceFace *source_tf = (const OrigSpaceFace*)source;
@@ -419,22 +451,39 @@ static void layerSwap_mdisps(void *data, const int *ci)
/* happens when face changed vertex count in edit mode
if it happened, just forgot displacement */
- MEM_freeN(s->disps);
+ BLI_cellalloc_free(s->disps);
s->totdisp= (s->totdisp/corners)*nverts;
- s->disps= MEM_callocN(s->totdisp*sizeof(float)*3, "mdisp swap");
+ s->disps= BLI_cellalloc_calloc(s->totdisp*sizeof(float)*3, "mdisp swap");
return;
}
- d= MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap");
+ d= BLI_cellalloc_calloc(sizeof(float) * 3 * s->totdisp, "mdisps swap");
for(S = 0; S < corners; S++)
memcpy(d + cornersize*S, s->disps + cornersize*ci[S], cornersize*3*sizeof(float));
- MEM_freeN(s->disps);
+ BLI_cellalloc_free(s->disps);
s->disps= d;
}
}
+#if 1 /* BMESH_TODO: place holder function, dont actually interp */
+static void layerInterp_mdisps(void **sources, float *UNUSED(weights),
+ float *UNUSED(sub_weights), int UNUSED(count), void *dest)
+{
+ MDisps *d = dest;
+
+ /* happens when flipping normals of newly created mesh */
+ if(!d->totdisp) {
+ d->totdisp = ((MDisps*)sources[0])->totdisp;
+ }
+
+ if (!d->disps && d->totdisp)
+ d->disps = BLI_cellalloc_calloc(sizeof(float)*3*d->totdisp, "blank mdisps in layerInterp_mdisps");
+}
+
+#else // BMESH_TODO
+
static void layerInterp_mdisps(void **sources, float *UNUSED(weights),
float *sub_weights, int count, void *dest)
{
@@ -547,6 +596,7 @@ static void layerInterp_mdisps(void **sources, float *UNUSED(weights),
MEM_freeN(d->disps);
d->disps = disps;
}
+#endif // BMESH_TODO
static void layerCopy_mdisps(const void *source, void *dest, int count)
{
@@ -556,7 +606,7 @@ static void layerCopy_mdisps(const void *source, void *dest, int count)
for(i = 0; i < count; ++i) {
if(s[i].disps) {
- d[i].disps = MEM_dupallocN(s[i].disps);
+ d[i].disps = BLI_cellalloc_dupalloc(s[i].disps);
d[i].totdisp = s[i].totdisp;
}
else {
@@ -569,6 +619,10 @@ static void layerCopy_mdisps(const void *source, void *dest, int count)
static void layerValidate_mdisps(void *data, int sub_elements)
{
+#if 1 /*BMESH_TODO*/
+ (void)data;
+ (void)sub_elements;
+#else
MDisps *disps = data;
if(disps->disps) {
int corners = multires_mdisp_corners(disps);
@@ -576,9 +630,10 @@ static void layerValidate_mdisps(void *data, int sub_elements)
if(corners != sub_elements) {
MEM_freeN(disps->disps);
disps->totdisp = disps->totdisp / corners * sub_elements;
- disps->disps = MEM_callocN(3*disps->totdisp*sizeof(float), "layerValidate_mdisps");
+ disps->disps = BLI_cellalloc_calloc(3*disps->totdisp*sizeof(float), "layerValidate_mdisps");
}
}
+#endif
}
static void layerFree_mdisps(void *data, int count, int UNUSED(size))
@@ -588,7 +643,7 @@ static void layerFree_mdisps(void *data, int count, int UNUSED(size))
for(i = 0; i < count; ++i) {
if(d[i].disps)
- MEM_freeN(d[i].disps);
+ BLI_cellalloc_free(d[i].disps);
d[i].disps = NULL;
d[i].totdisp = 0;
}
@@ -601,7 +656,7 @@ static int layerRead_mdisps(CDataFile *cdf, void *data, int count)
for(i = 0; i < count; ++i) {
if(!d[i].disps)
- d[i].disps = MEM_callocN(sizeof(float)*3*d[i].totdisp, "mdisps read");
+ d[i].disps = BLI_cellalloc_calloc(sizeof(float)*3*d[i].totdisp, "mdisps read");
if(!cdf_read_data(cdf, d[i].totdisp*3*sizeof(float), d[i].disps)) {
printf("failed to read multires displacement %d/%d %d\n", i, count, d[i].totdisp);
@@ -640,10 +695,83 @@ static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), void *data, int count
}
/* --------- */
+static void layerCopyValue_mloopcol(void *source, void *dest)
+{
+ MLoopCol *m1 = source, *m2 = dest;
+
+ m2->r = m1->r;
+ m2->g = m1->g;
+ m2->b = m1->b;
+ m2->a = m1->a;
+}
+
+static int layerEqual_mloopcol(void *data1, void *data2)
+{
+ MLoopCol *m1 = data1, *m2 = data2;
+ float r, g, b, a;
+
+ r = m1->r - m2->r;
+ g = m1->g - m2->g;
+ b = m1->b - m2->b;
+ a = m1->a - m2->a;
+
+ return r*r + g*g + b*b + a*a < 0.001;
+}
+
+static void layerMultiply_mloopcol(void *data, float fac)
+{
+ MLoopCol *m = data;
+
+ m->r = (float)m->r * fac;
+ m->g = (float)m->g * fac;
+ m->b = (float)m->b * fac;
+ m->a = (float)m->a * fac;
+}
+
+static void layerAdd_mloopcol(void *data1, void *data2)
+{
+ MLoopCol *m = data1, *m2 = data2;
+
+ m->r += m2->r;
+ m->g += m2->g;
+ m->b += m2->b;
+ m->a += m2->a;
+}
+
+static void layerDoMinMax_mloopcol(void *data, void *vmin, void *vmax)
+{
+ MLoopCol *m = data;
+ MLoopCol *min = vmin, *max = vmax;
+
+ if (m->r < min->r) min->r = m->r;
+ if (m->g < min->g) min->g = m->g;
+ if (m->b < min->b) min->b = m->b;
+ if (m->a < min->a) min->a = m->a;
+
+ if (m->r > max->r) max->r = m->r;
+ if (m->g > max->g) max->g = m->g;
+ if (m->b > max->b) max->b = m->b;
+ if (m->a > max->a) max->a = m->a;
+}
+
+static void layerInitMinMax_mloopcol(void *vmin, void *vmax)
+{
+ MLoopCol *min = vmin, *max = vmax;
+
+ min->r = 255;
+ min->g = 255;
+ min->b = 255;
+ min->a = 255;
+
+ max->r = 0;
+ max->g = 0;
+ max->b = 0;
+ max->a = 0;
+}
static void layerDefault_mloopcol(void *data, int count)
{
- static MLoopCol default_mloopcol = {255,255,255,255};
+ MLoopCol default_mloopcol = {255,255,255,255};
MLoopCol *mlcol = (MLoopCol*)data;
int i;
for(i = 0; i < count; i++)
@@ -695,6 +823,56 @@ static void layerInterp_mloopcol(void **sources, float *weights,
mc->g = (int)col.g;
mc->b = (int)col.b;
}
+
+static void layerCopyValue_mloopuv(void *source, void *dest)
+{
+ MLoopUV *luv1 = source, *luv2 = dest;
+
+ luv2->uv[0] = luv1->uv[0];
+ luv2->uv[1] = luv1->uv[1];
+}
+
+static int layerEqual_mloopuv(void *data1, void *data2)
+{
+ MLoopUV *luv1 = data1, *luv2 = data2;
+ float u, v;
+
+ u = luv1->uv[0] - luv2->uv[0];
+ v = luv1->uv[1] - luv2->uv[1];
+
+ return u*u + v*v < 0.00001;
+}
+
+static void layerMultiply_mloopuv(void *data, float fac)
+{
+ MLoopUV *luv = data;
+
+ luv->uv[0] *= fac;
+ luv->uv[1] *= fac;
+}
+
+static void layerInitMinMax_mloopuv(void *vmin, void *vmax)
+{
+ MLoopUV *min = vmin, *max = vmax;
+
+ INIT_MINMAX2(min->uv, max->uv);
+}
+
+static void layerDoMinMax_mloopuv(void *data, void *vmin, void *vmax)
+{
+ MLoopUV *min = vmin, *max = vmax, *luv = data;
+
+ DO_MINMAX2(luv->uv, min->uv, max->uv);
+}
+
+static void layerAdd_mloopuv(void *data1, void *data2)
+{
+ MLoopUV *l1 = data1, *l2 = data2;
+
+ l1->uv[0] += l2->uv[0];
+ l1->uv[1] += l2->uv[1];
+}
+
static void layerInterp_mloopuv(void **sources, float *weights,
float *sub_weights, int count, void *dest)
{
@@ -802,7 +980,48 @@ static void layerDefault_mcol(void *data, int count)
mcol[i] = default_mcol;
}
+static void layerInterp_bweight(void **sources, float *weights,
+ float *UNUSED(sub_weights), int count, void *dest)
+{
+ float *f = dest, *src;
+ float **in = (float **)sources;
+ int i;
+
+ if(count <= 0) return;
+
+ *f = 0.0f;
+
+ for(i = 0; i < count; ++i) {
+ float weight = weights ? weights[i] : 1.0f;
+
+ src = in[i];
+ *f += *src * weight;
+ }
+}
+
+static void layerInterp_shapekey(void **sources, float *weights,
+ float *UNUSED(sub_weights), int count, void *dest)
+{
+ float *co = dest, *src;
+ float **in = (float **)sources;
+ int i;
+
+ if(count <= 0) return;
+
+ memset(co, 0, sizeof(float)*3);
+
+ for(i = 0; i < count; ++i) {
+ float weight = weights ? weights[i] : 1.0f;
+
+ src = in[i];
+ co[0] += src[0] * weight;
+ co[1] += src[1] * weight;
+ co[2] += src[2] * weight;
+ }
+}
+/* note, these numbered comments below are copied from trunk,
+ * while _most_ match, some at the end need adding and are out of sync */
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */
@@ -828,15 +1047,15 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 8: CD_NORMAL */
/* 3 floats per normal vector */
- {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
+ {sizeof(float)*3, "vec3f", 1, NULL, NULL, NULL, NULL, NULL, NULL},
/* 9: CD_FLAGS */
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 10: CD_PROP_FLT */
- {sizeof(MFloatProperty), "MFloatProperty",1,"Float",NULL,NULL,NULL,NULL},
+ {sizeof(MFloatProperty), "MFloatProperty",1,"Float", layerCopy_propFloat,NULL,NULL,NULL},
/* 11: CD_PROP_INT */
- {sizeof(MIntProperty), "MIntProperty",1,"Int",NULL,NULL,NULL,NULL},
+ {sizeof(MIntProperty), "MIntProperty",1,"Int",layerCopy_propInt,NULL,NULL,NULL},
/* 12: CD_PROP_STR */
- {sizeof(MStringProperty), "MStringProperty",1,"String",NULL,NULL,NULL,NULL},
+ {sizeof(MStringProperty), "MStringProperty",1,"String",layerCopy_propString,NULL,NULL,NULL},
/* 13: CD_ORIGSPACE */
{sizeof(OrigSpaceFace), "OrigSpaceFace", 1, "UVTex", layerCopy_origspace_face, NULL,
layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face},
@@ -845,58 +1064,79 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 15: CD_MTEXPOLY */
{sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL},
/* 16: CD_MLOOPUV */
- {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL},
+ {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL,
+ layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv,
+ layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv},
/* 17: CD_MLOOPCOL */
- {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol},
- /* 18: CD_TANGENT */
+ {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL,
+ layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol,
+ layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol},
{sizeof(float)*4*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 19: CD_MDISPS */
{sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps,
- layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps,
- layerFilesize_mdisps, layerValidate_mdisps},
+ layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps, layerValidate_mdisps},
/* 20: CD_WEIGHT_MCOL */
{sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol},
+ {sizeof(MPoly), "MPoly", 1, "NGon Face", NULL, NULL, NULL, NULL, NULL},
+ {sizeof(MLoop), "MLoop", 1, "NGon Face-Vertex", NULL, NULL, NULL, NULL, NULL},
+ {sizeof(float)*3, "", 0, "ClothOrco", NULL, NULL, layerInterp_shapekey},
/* 21: CD_ID_MCOL */
{sizeof(MCol)*4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol},
- /* 22: CD_TEXTURE_MCOL */
- {sizeof(MCol)*4, "MCol", 4, "TexturedCol", NULL, NULL, layerInterp_mcol,
+ {sizeof(MCol)*4, "MCol", 4, "TextureCol", NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol},
- /* 23: CD_CLOTH_ORCO */
- {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
+ {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
+ {sizeof(float)*3, "", 0, "ShapeKey", NULL, NULL, layerInterp_shapekey},
+ {sizeof(float), "", 0, "BevelWeight", NULL, NULL, layerInterp_bweight},
+ {sizeof(float), "", 0, "SubSurfCrease", NULL, NULL, layerInterp_bweight},
+ {sizeof(MLoopCol), "MLoopCol", 1, "WeightLoopCol", NULL, NULL, layerInterp_mloopcol, NULL,
+ layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol,
+ layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol},
/* 24: CD_RECAST */
{sizeof(MRecast), "MRecast", 1,"Recast",NULL,NULL,NULL,NULL}
};
+/* note, numbers are from trunk and need updating for bmesh */
+
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
- /* 0-4 */ "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace",
- /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags",
- /* 10-14 */ "CDMFloatProperty", "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco",
- /* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps",
- /* 20-24 */"CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco", "CDMRecast"
+ /* 0-4 */ "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace",
+ /* 5-9 */ "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty",
+ /* 10-14 */ "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV",
+ /* 15-19 */ "CDMloopCol", "CDTangent", "CDMDisps", "CDWeightMCol", "CDMPoly",
+ /* 20-24 */ "CDMLoop", "CDMClothOrco", "CDMLoopCol", "CDIDCol", "CDTextureCol",
+ /* ?-? */ "CDShapeKeyIndex", "CDShapeKey", "CDBevelWeight", "CDSubSurfCrease", "CDMRecast"
};
+
const CustomDataMask CD_MASK_BAREMESH =
- CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE;
+ CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MLOOP | CD_MASK_MPOLY | CD_MASK_BWEIGHT;
const CustomDataMask CD_MASK_MESH =
CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE |
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL |
- CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | CD_MASK_RECAST;
+ CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS |
+ CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MPOLY | CD_MASK_MLOOP |
+ CD_MASK_MTEXPOLY | CD_MASK_NORMAL | CD_MASK_MDISPS | CD_MASK_RECAST;
const CustomDataMask CD_MASK_EDITMESH =
- CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
- CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | CD_MASK_RECAST;
+ CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MLOOPUV |
+ CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_SHAPE_KEYINDEX |
+ CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR |
+ CD_MASK_MDISPS | CD_MASK_SHAPEKEY | CD_MASK_RECAST;
const CustomDataMask CD_MASK_DERIVEDMESH =
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO |
- CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT | CD_MASK_WEIGHT_MCOL | CD_MASK_RECAST;
-const CustomDataMask CD_MASK_BMESH =
- CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR;
+ CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_WEIGHT_MLOOPCOL |
+ CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT |
+ CD_MASK_WEIGHT_MCOL | CD_MASK_NORMAL | CD_MASK_SHAPEKEY | CD_MASK_RECAST;
+const CustomDataMask CD_MASK_BMESH = CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
+ CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
+ CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_MDISPS;
const CustomDataMask CD_MASK_FACECORNERS =
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
CD_MASK_MLOOPCOL;
-
static const LayerTypeInfo *layerType_getInfo(int type)
{
if(type < 0 || type >= CD_NUMTYPES) return NULL;
@@ -917,6 +1157,22 @@ static void customData_update_offsets(CustomData *data);
static CustomDataLayer *customData_add_layer__internal(CustomData *data,
int type, int alloctype, void *layerdata, int totelem, const char *name);
+void CustomData_update_typemap(CustomData *data)
+{
+ int i, lasttype = -1;
+
+ for (i=0; i<CD_NUMTYPES; i++) {
+ data->typemap[i] = -1;
+ }
+
+ for (i=0; i<data->totlayer; i++) {
+ if (data->layers[i].type != lasttype) {
+ data->typemap[data->layers[i].type] = i;
+ }
+ lasttype = data->layers[i].type;
+ }
+}
+
void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
CustomDataMask mask, int alloctype, int totelem)
{
@@ -954,6 +1210,8 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
layer->data, totelem, layer->name);
if(newlayer) {
+ newlayer->uid = layer->uid;
+
newlayer->active = lastactive;
newlayer->active_rnd = lastrender;
newlayer->active_clone = lastclone;
@@ -961,6 +1219,8 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
newlayer->flag |= lastflag & (CD_FLAG_EXTERNAL|CD_FLAG_IN_MEMORY);
}
}
+
+ CustomData_update_typemap(dest);
}
void CustomData_copy(const struct CustomData *source, struct CustomData *dest,
@@ -1025,6 +1285,7 @@ static void customData_update_offsets(CustomData *data)
}
data->totsize = offset;
+ CustomData_update_typemap(data);
}
int CustomData_get_layer_index(const CustomData *data, int type)
@@ -1038,6 +1299,17 @@ int CustomData_get_layer_index(const CustomData *data, int type)
return -1;
}
+int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n)
+{
+ int i;
+
+ for(i=0; i < data->totlayer; ++i)
+ if(data->layers[i].type == type)
+ return i + n;
+
+ return -1;
+}
+
int CustomData_get_named_layer_index(const CustomData *data, int type, const char *name)
{
int i;
@@ -1051,11 +1323,12 @@ int CustomData_get_named_layer_index(const CustomData *data, int type, const cha
int CustomData_get_active_layer_index(const CustomData *data, int type)
{
- int i;
+ if (!data->totlayer)
+ return -1;
- for(i=0; i < data->totlayer; ++i)
- if(data->layers[i].type == type)
- return i + data->layers[i].active;
+ if (data->typemap[type] != -1) {
+ return data->typemap[type] + data->layers[data->typemap[type]].active;
+ }
return -1;
}
@@ -1254,7 +1527,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
return NULL;
}
- if (alloctype == CD_DUPLICATE) {
+ if (alloctype == CD_DUPLICATE && layerdata) {
if(typeInfo->copy)
typeInfo->copy(layerdata, newlayerdata, totelem);
else
@@ -1284,6 +1557,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
data->layers[index].type = type;
data->layers[index].flag = flag;
data->layers[index].data = newlayerdata;
+
if(name || (name=typeInfo->defaultname)) {
BLI_strncpy(data->layers[index].name, name, 32);
CustomData_set_layer_unique_name(data, index);
@@ -1316,6 +1590,7 @@ void *CustomData_add_layer(CustomData *data, int type, int alloctype,
layer = customData_add_layer__internal(data, type, alloctype, layerdata,
totelem, typeInfo->defaultname);
+ CustomData_update_typemap(data);
if(layer)
return layer->data;
@@ -1331,6 +1606,7 @@ void *CustomData_add_layer_named(CustomData *data, int type, int alloctype,
layer = customData_add_layer__internal(data, type, alloctype, layerdata,
totelem, name);
+ CustomData_update_typemap(data);
if(layer)
return layer->data;
@@ -1369,6 +1645,7 @@ int CustomData_free_layer(CustomData *data, int type, int totelem, int index)
customData_resize(data, -CUSTOMDATA_GROW);
customData_update_offsets(data);
+ CustomData_update_typemap(data);
return 1;
}
@@ -1478,6 +1755,16 @@ void CustomData_set_only_copy(const struct CustomData *data,
data->layers[i].flag |= CD_FLAG_NOCOPY;
}
+void CustomData_copy_elements(int type, void *source, void *dest, int count)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (typeInfo->copy)
+ typeInfo->copy(source, dest, count);
+ else
+ memcpy(dest, source, typeInfo->size*count);
+}
+
void CustomData_copy_data(const CustomData *source, CustomData *dest,
int source_index, int dest_index, int count)
{
@@ -1509,7 +1796,12 @@ void CustomData_copy_data(const CustomData *source, CustomData *dest,
src_offset = source_index * typeInfo->size;
dest_offset = dest_index * typeInfo->size;
-
+
+ if (!src_data || !dest_data) {
+ printf("eek! null data in CustomData_copy_data!\n");
+ continue;
+ }
+
if(typeInfo->copy)
typeInfo->copy(src_data + src_offset,
dest_data + dest_offset,
@@ -1637,6 +1929,19 @@ void *CustomData_get(const CustomData *data, int index, int type)
return (char *)data->layers[layer_index].data + offset;
}
+void *CustomData_get_n(const CustomData *data, int type, int index, int n)
+{
+ int layer_index;
+ int offset;
+
+ /* get the layer index of the first layer of type */
+ layer_index = data->typemap[type];
+ if(layer_index < 0) return NULL;
+
+ offset = layerType_getInfo(type)->size * index;
+ return (char *)data->layers[layer_index+n].data + offset;
+}
+
void *CustomData_get_layer(const CustomData *data, int type)
{
/* get the layer index of the active layer of type */
@@ -1664,6 +1969,20 @@ void *CustomData_get_layer_named(const struct CustomData *data, int type,
return data->layers[layer_index].data;
}
+
+int CustomData_set_layer_name(const CustomData *data, int type, int n, const char *name)
+{
+ /* get the layer index of the first layer of type */
+ int layer_index = CustomData_get_layer_index_n(data, type, n);
+
+ if(layer_index < 0) return 0;
+ if (!name) return 0;
+
+ strcpy(data->layers[layer_index].name, name);
+
+ return 1;
+}
+
void *CustomData_set_layer(const CustomData *data, int type, void *ptr)
{
/* get the layer index of the first layer of type */
@@ -1983,33 +2302,89 @@ void CustomData_from_em_block(const CustomData *source, CustomData *dest,
/*Bmesh functions*/
/*needed to convert to/from different face reps*/
-void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata)
+void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata,
+ int totloop, int totpoly)
{
int i;
for(i=0; i < fdata->totlayer; i++){
if(fdata->layers[i].type == CD_MTFACE){
- CustomData_add_layer(pdata, CD_MTEXPOLY, CD_CALLOC, &(fdata->layers[i].name), 0);
- CustomData_add_layer(ldata, CD_MLOOPUV, CD_CALLOC, &(fdata->layers[i].name), 0);
+ CustomData_add_layer(pdata, CD_MTEXPOLY, CD_CALLOC, &(fdata->layers[i].name), totpoly);
+ CustomData_add_layer(ldata, CD_MLOOPUV, CD_CALLOC, &(fdata->layers[i].name), totloop);
}
else if(fdata->layers[i].type == CD_MCOL)
- CustomData_add_layer(ldata, CD_MLOOPCOL, CD_CALLOC, &(fdata->layers[i].name), 0);
- }
+ CustomData_add_layer(ldata, CD_MLOOPCOL, CD_CALLOC, &(fdata->layers[i].name), totloop);
+ else if(fdata->layers[i].type == CD_MDISPS)
+ CustomData_add_layer(ldata, CD_MDISPS, CD_CALLOC, &(fdata->layers[i].name), totloop);
+ }
}
void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total){
int i;
for(i=0; i < pdata->totlayer; i++){
if(pdata->layers[i].type == CD_MTEXPOLY)
- CustomData_add_layer(fdata, CD_MTFACE, CD_CALLOC, &(pdata->layers[i].name), total);
+ CustomData_add_layer_named(fdata, CD_MTFACE, CD_CALLOC, NULL, total, pdata->layers[i].name);
}
for(i=0; i < ldata->totlayer; i++){
if(ldata->layers[i].type == CD_MLOOPCOL)
- CustomData_add_layer(fdata, CD_MCOL, CD_CALLOC, &(ldata->layers[i].name), total);
+ CustomData_add_layer_named(fdata, CD_MCOL, CD_CALLOC, NULL, total, ldata->layers[i].name);
+ if (ldata->layers[i].type == CD_WEIGHT_MLOOPCOL)
+ CustomData_add_layer_named(fdata, CD_WEIGHT_MCOL, CD_CALLOC, NULL, total, ldata->layers[i].name);
}
}
void CustomData_bmesh_init_pool(CustomData *data, int allocsize){
- if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize, 0);
+ if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize, 1, 0);
+}
+
+void CustomData_bmesh_merge(CustomData *source, CustomData *dest,
+ int mask, int alloctype, BMesh *bm, int type)
+{
+ BMHeader *h;
+ BMIter iter;
+ CustomData destold = *dest;
+ void *tmp;
+ int t;
+
+ CustomData_merge(source, dest, mask, alloctype, 0);
+ CustomData_bmesh_init_pool(dest, 512);
+
+ switch (type) {
+ case BM_VERT:
+ t = BM_VERTS_OF_MESH; break;
+ case BM_EDGE:
+ t = BM_EDGES_OF_MESH; break;
+ case BM_LOOP:
+ t = BM_LOOPS_OF_FACE; break;
+ case BM_FACE:
+ t = BM_FACES_OF_MESH; break;
+ default: /* should never happen */
+ BLI_assert(!"invalid type given");
+ t = BM_VERTS_OF_MESH;
+ }
+
+ if (t != BM_LOOPS_OF_FACE) {
+ /*ensure all current elements follow new customdata layout*/
+ BM_ITER(h, &iter, bm, t, NULL) {
+ CustomData_bmesh_copy_data(&destold, dest, h->data, &tmp);
+ CustomData_bmesh_free_block(&destold, &h->data);
+ h->data = tmp;
+ }
+ } else {
+ BMFace *f;
+ BMLoop *l;
+ BMIter liter;
+
+ /*ensure all current elements follow new customdata layout*/
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ CustomData_bmesh_copy_data(&destold, dest, l->head.data, &tmp);
+ CustomData_bmesh_free_block(&destold, &l->head.data);
+ l->head.data = tmp;
+ }
+ }
+ }
+
+ if (destold.pool) BLI_mempool_destroy(destold.pool);
}
void CustomData_bmesh_free_block(CustomData *data, void **block)
@@ -2029,7 +2404,9 @@ void CustomData_bmesh_free_block(CustomData *data, void **block)
}
}
- BLI_mempool_free(data->pool, *block);
+ if (data->totsize)
+ BLI_mempool_free(data->pool, *block);
+
*block = NULL;
}
@@ -2040,7 +2417,7 @@ static void CustomData_bmesh_alloc_block(CustomData *data, void **block)
CustomData_bmesh_free_block(data, block);
if (data->totsize > 0)
- *block = BLI_mempool_calloc(data->pool);
+ *block = BLI_mempool_alloc(data->pool);
else
*block = NULL;
}
@@ -2113,6 +2490,82 @@ void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int
return (char *)block + data->layers[layer_index+n].offset;
}
+/*gets from the layer at physical index n, note: doesn't check type.*/
+void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n)
+{
+ if(n < 0 || n >= data->totlayer) return NULL;
+
+ return (char *)block + data->layers[n].offset;
+}
+
+int CustomData_layer_has_math(struct CustomData *data, int layern)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layern].type);
+
+ if (typeInfo->equal && typeInfo->add && typeInfo->multiply &&
+ typeInfo->initminmax && typeInfo->dominmax) return 1;
+
+ return 0;
+}
+
+/*copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
+ another, while not overwriting anything else (e.g. flags)*/
+void CustomData_data_copy_value(int type, void *source, void *dest)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if(!dest) return;
+
+ if(typeInfo->copyvalue)
+ typeInfo->copyvalue(source, dest);
+ else
+ memcpy(dest, source, typeInfo->size);
+}
+
+int CustomData_data_equals(int type, void *data1, void *data2)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (typeInfo->equal)
+ return typeInfo->equal(data1, data2);
+ else return !memcmp(data1, data2, typeInfo->size);
+}
+
+void CustomData_data_initminmax(int type, void *min, void *max)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (typeInfo->initminmax)
+ typeInfo->initminmax(min, max);
+}
+
+
+void CustomData_data_dominmax(int type, void *data, void *min, void *max)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (typeInfo->dominmax)
+ typeInfo->dominmax(data, min, max);
+}
+
+
+void CustomData_data_multiply(int type, void *data, float fac)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (typeInfo->multiply)
+ typeInfo->multiply(data, fac);
+}
+
+
+void CustomData_data_add(int type, void *data1, void *data2)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if (typeInfo->add)
+ typeInfo->add(data1, data2);
+}
+
void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *source)
{
void *dest = CustomData_bmesh_get(data, block, type);
@@ -2139,6 +2592,19 @@ void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void
memcpy(dest, source, typeInfo->size);
}
+void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, void *source)
+{
+ void *dest = CustomData_bmesh_get_layer_n(data, block, n);
+ const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
+
+ if(!dest) return;
+
+ if(typeInfo->copy)
+ typeInfo->copy(source, dest, 1);
+ else
+ memcpy(dest, source, typeInfo->size);
+}
+
void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights,
float *sub_weights, int count, void *dest_block)
{
@@ -2184,6 +2650,7 @@ void CustomData_bmesh_set_default(CustomData *data, void **block)
if(typeInfo->set_default)
typeInfo->set_default((char*)*block + offset, 1);
+ else memset((char*)*block + offset, 0, typeInfo->size);
}
}
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 0f6828cc358..5cae270d4cc 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -42,6 +42,7 @@
#include "BKE_deform.h"
#include "BLI_blenlib.h"
+#include "BLI_cellalloc.h"
void defgroup_copy_list (ListBase *outbase, ListBase *inbase)
@@ -82,10 +83,10 @@ void defvert_copy (MDeformVert *dvert_r, const MDeformVert *dvert)
}
else {
if(dvert_r->dw)
- MEM_freeN(dvert_r->dw);
+ BLI_cellalloc_free(dvert_r->dw);
if(dvert->totweight)
- dvert_r->dw= MEM_dupallocN(dvert->dw);
+ dvert_r->dw= BLI_cellalloc_dupalloc(dvert->dw);
else
dvert_r->dw= NULL;
@@ -489,10 +490,10 @@ MDeformWeight *defvert_verify_index(MDeformVert *dv, const int defgroup)
if(newdw)
return newdw;
- newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
+ newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
if(dv->dw) {
memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
- MEM_freeN(dv->dw);
+ BLI_cellalloc_free(dv->dw);
}
dv->dw=newdw;
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 6ae556874bb..6603e67a306 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -432,6 +432,8 @@ void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal)
totvert= 0;
nextcol= 0;
+ BLI_begin_edgefill();
+
dl= dispbase->first;
while(dl) {
@@ -884,7 +886,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
if (dm) {
if (vertCos) {
- DerivedMesh *tdm = CDDM_copy(dm);
+ DerivedMesh *tdm = CDDM_copy(dm, 0);
dm->release(dm);
dm = tdm;
@@ -925,7 +927,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
if (vertCos) {
if (dm) {
- DerivedMesh *tdm = CDDM_copy(dm);
+ DerivedMesh *tdm = CDDM_copy(dm, 0);
dm->release(dm);
dm = tdm;
diff --git a/source/blender/blenkernel/intern/editderivedbmesh.c b/source/blender/blenkernel/intern/editderivedbmesh.c
new file mode 100644
index 00000000000..acc58b1899e
--- /dev/null
+++ b/source/blender/blenkernel/intern/editderivedbmesh.c
@@ -0,0 +1,1639 @@
+/**
+ * $Id: editderivedbmesh.c 18571 2009-01-19 06:04:57Z joeedh $
+ *
+ * ***** 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., 59 Tbmple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "PIL_time.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_effect_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_key_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_object_fluidsim.h" // N_T
+#include "DNA_scene_types.h" // N_T
+#include "DNA_texture_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_particle_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_edgehash.h"
+#include "BLI_linklist.h"
+#include "BLI_memarena.h"
+#include "BLI_scanfill.h"
+#include "BLI_ghash.h"
+#include "BLI_array.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_deform.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+#include "BKE_modifier.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+#include "BKE_particle.h"
+#include "BKE_tessmesh.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#include "GL/glew.h"
+
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
+#include "bmesh.h"
+
+extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
+
+
+BMEditMesh *BMEdit_Create(BMesh *bm)
+{
+ BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), __func__);
+
+ tm->bm = bm;
+
+ BMEdit_RecalcTesselation(tm);
+
+ return tm;
+}
+
+BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
+{
+ BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), __func__);
+ *tm2 = *tm;
+
+ tm2->derivedCage = tm2->derivedFinal = NULL;
+
+ tm2->bm = BM_Copy_Mesh(tm->bm);
+
+ /*The tesselation is NOT calculated on the copy here,
+ because currently all the callers of this function use
+ it to make a backup copy of the BMEditMesh to restore
+ it in the case of errors in an operation. For perf
+ reasons, in that case it makes more sense to do the
+ tesselation only when/if that copy ends up getting
+ used.*/
+ tm2->looptris = NULL;
+
+ tm2->vert_index = NULL;
+ tm2->edge_index = NULL;
+ tm2->face_index = NULL;
+
+ return tm2;
+}
+
+static void BMEdit_RecalcTesselation_intern(BMEditMesh *tm)
+{
+ BMesh *bm = tm->bm;
+ BMLoop **looptris = NULL;
+ BLI_array_declare(looptris);
+ BMIter iter, liter;
+ BMFace *f;
+ BMLoop *l;
+ int i = 0, j;
+
+ if (tm->looptris) MEM_freeN(tm->looptris);
+
+ f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
+ for ( ; f; f=BMIter_Step(&iter)) {
+ EditVert *v, *lastv=NULL, *firstv=NULL;
+ EditEdge *e;
+ EditFace *efa;
+
+ /*don't consider two-edged faces*/
+ if (f->len < 3) continue;
+
+ BLI_begin_edgefill();
+ /*scanfill time*/
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ for (j=0; l; l=BMIter_Step(&liter), j++) {
+ /*mark order*/
+ l->_index = j;
+
+ v = BLI_addfillvert(l->v->co);
+ v->tmp.p = l;
+
+ if (lastv) {
+ e = BLI_addfilledge(lastv, v);
+ }
+
+ lastv = v;
+ if (firstv==NULL) firstv = v;
+ }
+
+ /*complete the loop*/
+ BLI_addfilledge(firstv, v);
+
+ BLI_edgefill(2);
+
+ for (efa = fillfacebase.first; efa; efa=efa->next) {
+ BMLoop *l1, *l2, *l3;
+
+ BLI_array_growone(looptris);
+ BLI_array_growone(looptris);
+ BLI_array_growone(looptris);
+
+ looptris[i*3] = l1 = efa->v1->tmp.p;
+ looptris[i*3+1] = l2 = efa->v2->tmp.p;
+ looptris[i*3+2] = l3 = efa->v3->tmp.p;
+
+ if (l1->_index > l2->_index) {
+ SWAP(BMLoop*, l1, l2);
+ }
+ if (l2->_index > l3->_index) {
+ SWAP(BMLoop*, l2, l3);
+ }
+ if (l1->_index > l2->_index) {
+ SWAP(BMLoop*, l1, l2);
+ }
+
+ looptris[i*3] = l1;
+ looptris[i*3+1] = l2;
+ looptris[i*3+2] = l3;
+
+ i += 1;
+ }
+
+ BLI_end_edgefill();
+ }
+
+ tm->tottri = i;
+ tm->looptris = (BMLoop *(*)[3])looptris;
+}
+
+void BMEdit_RecalcTesselation(BMEditMesh *em)
+{
+ BMEdit_RecalcTesselation_intern(em);
+
+ if (em->derivedFinal && em->derivedFinal == em->derivedCage) {
+ if (em->derivedFinal->recalcTesselation)
+ em->derivedFinal->recalcTesselation(em->derivedFinal);
+ } else if (em->derivedFinal) {
+ if (em->derivedCage->recalcTesselation)
+ em->derivedCage->recalcTesselation(em->derivedCage);
+ if (em->derivedFinal->recalcTesselation)
+ em->derivedFinal->recalcTesselation(em->derivedFinal);
+ }
+}
+
+void BMEdit_UpdateLinkedCustomData(BMEditMesh *em)
+{
+ BMesh *bm = em->bm;
+ int act;
+
+ if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) {
+ act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act);
+
+ act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act);
+
+ act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act);
+
+ act = CustomData_get_stencil_layer(&bm->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act);
+ }
+}
+
+/*does not free the BMEditMesh struct itself*/
+void BMEdit_Free(BMEditMesh *em)
+{
+ if(em->derivedFinal) {
+ if (em->derivedFinal!=em->derivedCage) {
+ em->derivedFinal->needsFree= 1;
+ em->derivedFinal->release(em->derivedFinal);
+ }
+ em->derivedFinal= NULL;
+ }
+ if(em->derivedCage) {
+ em->derivedCage->needsFree= 1;
+ em->derivedCage->release(em->derivedCage);
+ em->derivedCage= NULL;
+ }
+
+ em->retopo_paint_data= NULL;
+
+ if (em->looptris) MEM_freeN(em->looptris);
+
+ if (em->vert_index) MEM_freeN(em->vert_index);
+ if (em->edge_index) MEM_freeN(em->edge_index);
+ if (em->face_index) MEM_freeN(em->face_index);
+
+ if (em->bm)
+ BM_Free_Mesh(em->bm);
+}
+
+/*
+ok, basic design:
+
+the bmesh derivedmesh exposes the mesh as triangles. it stores pointers
+to three loops per triangle. the derivedmesh stores a cache of tesselations
+for each face. this cache will smartly update as needed (though at first
+it'll simply be more brute force). keeping track of face/edge counts may
+be a small problbm.
+
+this won't be the most efficient thing, considering that internal edges and
+faces of tesselations are exposed. looking up an edge by index in particular
+is likely to be a little slow.
+*/
+
+typedef struct EditDerivedBMesh {
+ DerivedMesh dm;
+
+ Object *ob;
+ BMEditMesh *tc;
+
+ float (*vertexCos)[3];
+ float (*vertexNos)[3];
+ float (*faceNos)[3];
+
+ /*lookup caches; these are rebuilt on dm->RecalcTesselation()
+ (or when the derivedmesh is created, of course)*/
+ GHash *vhash, *ehash, *fhash;
+ BMVert **vtable;
+ BMEdge **etable;
+ BMFace **ftable;
+
+ /*private variables, for number of verts/edges/faces
+ within the above hash/table members*/
+ int tv, te, tf;
+} EditDerivedBMesh;
+
+static void bmdm_recalc_lookups(EditDerivedBMesh *bmdm)
+{
+ BMIter iter;
+ BMHeader *h;
+ int a, i, iters[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+
+ bmdm->tv = bmdm->tc->bm->totvert;
+ bmdm->te = bmdm->tc->bm->totedge;
+ bmdm->tf = bmdm->tc->bm->totface;
+
+ if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL);
+ if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
+ if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
+
+ bmdm->vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived");
+ bmdm->ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived");
+ bmdm->fhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived");
+
+ if (bmdm->vtable) MEM_freeN(bmdm->vtable);
+ if (bmdm->etable) MEM_freeN(bmdm->etable);
+ if (bmdm->ftable) MEM_freeN(bmdm->ftable);
+
+ if (bmdm->tc->bm->totvert)
+ bmdm->vtable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totvert, "bmdm->vtable");
+ else bmdm->vtable = NULL;
+
+ if (bmdm->tc->bm->totedge)
+ bmdm->etable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totedge, "bmdm->etable");
+ else bmdm->etable = NULL;
+
+ if (bmdm->tc->bm->totface)
+ bmdm->ftable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totface, "bmdm->ftable");
+ else bmdm->ftable = NULL;
+
+ for (a=0; a<3; a++) {
+ h = BMIter_New(&iter, bmdm->tc->bm, iters[a], NULL);
+ for (i=0; h; h=BMIter_Step(&iter), i++) {
+ switch (a) {
+ case 0:
+ bmdm->vtable[i] = (BMVert*) h;
+ BLI_ghash_insert(bmdm->vhash, h, SET_INT_IN_POINTER(i));
+ break;
+ case 1:
+ bmdm->etable[i] = (BMEdge*) h;
+ BLI_ghash_insert(bmdm->ehash, h, SET_INT_IN_POINTER(i));
+ break;
+ case 2:
+ bmdm->ftable[i] = (BMFace*) h;
+ BLI_ghash_insert(bmdm->fhash, h, SET_INT_IN_POINTER(i));
+ break;
+
+ }
+ }
+ }
+}
+
+static void bmDM_recalcTesselation(DerivedMesh *UNUSED(dm))
+{
+ //EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+
+ //bmdm_recalc_lookups(bmdm);
+}
+
+static void bmDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMVert *eve;
+ BMIter iter;
+ int i;
+
+ eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; i++, eve=BMIter_Step(&iter)) {
+ if (bmdm->vertexCos) {
+ func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL);
+ } else {
+ func(userData, i, eve->co, eve->no, NULL);
+ }
+ }
+}
+static void bmDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMEdge *eed;
+ BMIter iter;
+ int i;
+
+ if (bmdm->vertexCos) {
+ BMVert *eve;
+ BMIter viter;
+
+ eve = BMIter_New(&viter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&viter), i++) {
+ BM_SetIndex(eve, i);
+ }
+
+ eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+ for(i=0; eed; i++,eed=BMIter_Step(&iter))
+ func(userData, i,
+ bmdm->vertexCos[BM_GetIndex(eed->v1)],
+ bmdm->vertexCos[BM_GetIndex(eed->v2)]);
+ } else {
+ eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+ for(i=0; eed; i++,eed=BMIter_Step(&iter))
+ func(userData, i, eed->v1->co, eed->v2->co);
+ }
+
+}
+
+static void bmDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMEdge *eed;
+ BMIter iter;
+ int i;
+
+ if (bmdm->vertexCos) {
+ BMVert *eve;
+ BMIter viter;
+
+ eve = BMIter_New(&viter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&viter), i++) {
+ BM_SetIndex(eve, i);
+ }
+
+ glBegin(GL_LINES);
+ eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+ for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
+ if(!setDrawOptions || setDrawOptions(userData, i)) {
+ glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v1)]);
+ glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v2)]);
+ }
+ }
+ glEnd();
+
+ } else {
+ glBegin(GL_LINES);
+ eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+ for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
+ if(!setDrawOptions || setDrawOptions(userData, i)) {
+ glVertex3fv(eed->v1->co);
+ glVertex3fv(eed->v2->co);
+ }
+ }
+ glEnd();
+ }
+}
+
+static void bmDM_drawEdges(DerivedMesh *dm, int UNUSED(drawLooseEdges), int UNUSED(drawAllEdges))
+{
+ bmDM_drawMappedEdges(dm, NULL, NULL);
+}
+
+static void bmDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMEdge *eed;
+ BMIter iter;
+ int i;
+
+ if (bmdm->vertexCos) {
+ BMVert *eve;
+
+ eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++)
+ BM_SetIndex(eve, i);
+
+ glBegin(GL_LINES);
+ eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+ for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
+ if(!setDrawOptions || setDrawOptions(userData, i)) {
+ setDrawInterpOptions(userData, i, 0.0);
+ glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(eed->v1)]);
+ setDrawInterpOptions(userData, i, 1.0);
+ glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(eed->v2)]);
+ }
+ }
+ glEnd();
+ } else {
+ glBegin(GL_LINES);
+ eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+ for(i=0; eed; i++,eed=BMIter_Step(&iter)) {
+ if(!setDrawOptions || setDrawOptions(userData, i)) {
+ setDrawInterpOptions(userData, i, 0.0);
+ glVertex3fv(eed->v1->co);
+ setDrawInterpOptions(userData, i, 1.0);
+ glVertex3fv(eed->v2->co);
+ }
+ }
+ glEnd();
+ }
+}
+
+static void bmDM_drawUVEdges(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMEditMesh *em = bmdm->tc;
+ BMFace *efa;
+ BMIter iter;
+
+ glBegin(GL_LINES);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BMIter liter;
+ BMLoop *l;
+ MLoopUV *lastluv = NULL, *firstluv = NULL;
+
+ if (BM_TestHFlag(efa, BM_HIDDEN))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (luv) {
+ if (lastluv)
+ glVertex2fv(luv->uv);
+ glVertex2fv(luv->uv);
+
+ lastluv = luv;
+ if (!firstluv)
+ firstluv = luv;
+ }
+ }
+
+ if (lastluv) {
+ glVertex2fv(lastluv->uv);
+ glVertex2fv(firstluv->uv);
+ }
+ }
+ glEnd();
+}
+
+static void bmDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3],
+ float (*vertexCos)[3])
+{
+ BMIter iter;
+ BMLoop *l;
+ int tot = 0;
+
+ cent[0] = cent[1] = cent[2] = 0.0f;
+
+ /*simple (and stupid) median (average) based method :/ */
+
+ if (vertexCos) {
+ l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
+ for (; l; l=BMIter_Step(&iter)) {
+ VECADD(cent, cent, vertexCos[BM_GetIndex(l->v)]);
+ tot++;
+ }
+ } else {
+ l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
+ for (; l; l=BMIter_Step(&iter)) {
+ VECADD(cent, cent, l->v->co);
+ tot++;
+ }
+ }
+
+ if (tot==0) return;
+ mul_v3_fl(cent, 1.0f/(float)tot);
+}
+
+static void bmDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMVert *eve;
+ BMFace *efa;
+ BMIter iter;
+ float cent[3];
+ int i;
+
+ if (bmdm->vertexCos) {
+ eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++)
+ BM_SetIndex(eve, i);
+ }
+
+ efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
+ for (i=0; efa; efa=BMIter_Step(&iter), i++) {
+ bmDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos);
+ func(userData, i, cent, bmdm->vertexCos?bmdm->faceNos[i]:efa->no);
+ }
+}
+
+static void bmDM_drawMappedFaces(DerivedMesh *dm,
+ int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
+ void *userData, int useColors,
+ int (*setMaterial)(int, void *attribs),
+ int (*compareDrawOptions)(void *userData, int cur_index, int next_index))
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMFace *efa;
+ BMIter iter;
+ int i, draw;
+
+ const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
+
+ /* GL_ZERO is used to detect if drawing has started or not */
+ GLenum poly_prev= GL_ZERO;
+ GLenum shade_prev= GL_ZERO;
+
+ /*BMESH_TODO*/
+ (void)useColors;
+
+ (void)setMaterial; /* UNUSED */
+
+ /* currently unused -- each original face is handled separately */
+ (void)compareDrawOptions;
+
+ if (bmdm->vertexCos) {
+ /* add direct access */
+ float (*vertexCos)[3]= bmdm->vertexCos;
+ float (*vertexNos)[3]= bmdm->vertexNos;
+ float (*faceNos)[3]= bmdm->faceNos;
+ BMVert *eve;
+
+ eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++)
+ BM_SetIndex(eve, i);
+
+ efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
+ for (i=0; efa; efa=BMIter_Step(&iter), i++)
+ BM_SetIndex(efa, i);
+
+ for (i=0; i<bmdm->tc->tottri; i++) {
+ BMLoop **l = bmdm->tc->looptris[i];
+ int drawSmooth;
+
+ efa = l[0]->f;
+ drawSmooth = (efa->head.flag & BM_SMOOTH);
+
+ draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth);
+ if(draw) {
+ const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
+ if (draw==2) { /* enabled with stipple */
+
+ if(poly_prev != GL_ZERO) glEnd();
+ poly_prev= GL_ZERO; /* force glBegin */
+
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(stipple_quarttone);
+ }
+
+ if(skip_normals) {
+ if(poly_type != poly_prev) {
+ if(poly_prev != GL_ZERO) glEnd();
+ glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
+ }
+ glVertex3fv(vertexCos[(int) BM_GetIndex(l[0]->v)]);
+ glVertex3fv(vertexCos[(int) BM_GetIndex(l[1]->v)]);
+ glVertex3fv(vertexCos[(int) BM_GetIndex(l[2]->v)]);
+ }
+ else {
+ const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
+ if (shade_type != shade_prev) {
+ if(poly_prev != GL_ZERO) glEnd();
+ glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
+ glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
+ }
+ if(poly_type != poly_prev) {
+ if(poly_prev != GL_ZERO) glEnd();
+ glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
+ }
+
+ if (!drawSmooth) {
+ glNormal3fv(faceNos[i]);
+ glVertex3fv(vertexCos[(int) BM_GetIndex(l[0]->v)]);
+ glVertex3fv(vertexCos[(int) BM_GetIndex(l[1]->v)]);
+ glVertex3fv(vertexCos[(int) BM_GetIndex(l[2]->v)]);
+ } else {
+ glNormal3fv(vertexNos[(int) BM_GetIndex(l[0]->v)]);
+ glVertex3fv(vertexCos[(int) BM_GetIndex(l[0]->v)]);
+ glNormal3fv(vertexNos[(int) BM_GetIndex(l[1]->v)]);
+ glVertex3fv(vertexCos[(int) BM_GetIndex(l[1]->v)]);
+ glNormal3fv(vertexNos[(int) BM_GetIndex(l[2]->v)]);
+ glVertex3fv(vertexCos[(int) BM_GetIndex(l[2]->v)]);
+ }
+ }
+
+ if (draw==2) {
+ glEnd();
+ poly_prev= GL_ZERO; /* force glBegin */
+
+ glDisable(GL_POLYGON_STIPPLE);
+ }
+ }
+ }
+ } else {
+ efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
+ for (i=0; efa; efa=BMIter_Step(&iter), i++)
+ BM_SetIndex(efa, i);
+
+ for (i=0; i<bmdm->tc->tottri; i++) {
+ BMLoop **l = bmdm->tc->looptris[i];
+ int drawSmooth;
+
+ efa = l[0]->f;
+ drawSmooth = (efa->head.flag & BM_SMOOTH);
+
+ draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth);
+ if(draw) {
+ const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
+ if (draw==2) { /* enabled with stipple */
+
+ if(poly_prev != GL_ZERO) glEnd();
+ poly_prev= GL_ZERO; /* force glBegin */
+
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(stipple_quarttone);
+ }
+
+ if(skip_normals) {
+ if(poly_type != poly_prev) {
+ if(poly_prev != GL_ZERO) glEnd();
+ glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
+ }
+ glVertex3fv(l[0]->v->co);
+ glVertex3fv(l[1]->v->co);
+ glVertex3fv(l[2]->v->co);
+ }
+ else {
+ const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
+ if (shade_type != shade_prev) {
+ if(poly_prev != GL_ZERO) glEnd();
+ glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
+ glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
+ }
+ if(poly_type != poly_prev) {
+ if(poly_prev != GL_ZERO) glEnd();
+ glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
+ }
+
+ if (!drawSmooth) {
+ glNormal3fv(efa->no);
+ glVertex3fv(l[0]->v->co);
+ glVertex3fv(l[1]->v->co);
+ glVertex3fv(l[2]->v->co);
+ } else {
+ glNormal3fv(l[0]->v->no);
+ glVertex3fv(l[0]->v->co);
+ glNormal3fv(l[1]->v->no);
+ glVertex3fv(l[1]->v->co);
+ glNormal3fv(l[2]->v->no);
+ glVertex3fv(l[2]->v->co);
+ }
+ }
+ if (draw==2) {
+ glEnd();
+ poly_prev= GL_ZERO; /* force glBegin */
+
+ glDisable(GL_POLYGON_STIPPLE);
+ }
+ }
+ }
+ }
+
+ /* if non zero we know a face was rendered */
+ if(poly_prev != GL_ZERO) glEnd();
+}
+
+static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3],
+ int has_uv, int has_col)
+{
+ if (has_uv) {
+ luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
+ luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
+ luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
+ }
+
+ if (has_col) {
+ lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
+ lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
+ lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
+ }
+
+
+}
+
+static void bmDM_drawFacesTex_common(DerivedMesh *dm,
+ int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
+ int (*drawParamsMapped)(void *userData, int index),
+ void *userData)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMEditMesh *em = bmdm->tc;
+ BMesh *bm= bmdm->tc->bm;
+ float (*vertexCos)[3]= bmdm->vertexCos;
+ float (*vertexNos)[3]= bmdm->vertexNos;
+ BMFace *efa;
+ BMVert *eve;
+ BMIter iter;
+ MLoopUV *luv[3], dummyluv = {{0}};
+ MLoopCol *lcol[3], dummylcol = {0};
+ int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
+ int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
+
+ luv[0] = luv[1] = luv[2] = &dummyluv;
+ lcol[0] = lcol[1] = lcol[2] = &dummylcol;
+
+ dummylcol.a = dummylcol.r = dummylcol.g = dummylcol.b = 255;
+
+ /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
+ glShadeModel(GL_SMOOTH);
+
+ i = 0;
+ BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL)
+ BM_SetIndex(efa, i++);
+
+ if (vertexCos) {
+ i = 0;
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
+ BM_SetIndex(eve, i++);
+
+ glBegin(GL_TRIANGLES);
+ for (i=0; i<em->tottri; i++) {
+ BMLoop **ls = em->looptris[i];
+ MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
+ MTFace mtf = {{{0}}};
+ /*unsigned char *cp= NULL;*/ /*UNUSED*/
+ int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
+ int flag;
+
+ efa = ls[0]->f;
+
+ if (has_uv) {
+ mtf.flag = tp->flag;
+ mtf.tpage = tp->tpage;
+ mtf.transp = tp->transp;
+ mtf.mode = tp->mode;
+ mtf.tile = tp->tile;
+ mtf.unwrap = tp->unwrap;
+ }
+
+ if(drawParams)
+ flag= drawParams(&mtf, has_vcol, efa->mat_nr);
+ else if(drawParamsMapped)
+ flag= drawParamsMapped(userData, BM_GetIndex(efa));
+ else
+ flag= 1;
+
+ if(flag != 0) { /* flag 0 == the face is hidden or invisible */
+
+ /* we always want smooth here since otherwise vertex colors dont interpolate */
+ if (!has_vcol) {
+ glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
+ }
+
+ if (!drawSmooth) {
+ glNormal3fv(bmdm->faceNos[i]);
+
+ bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+
+ glTexCoord2fv(luv[0]->uv);
+ glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
+ glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]);
+
+ glTexCoord2fv(luv[1]->uv);
+ glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
+ glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]);
+
+ glTexCoord2fv(luv[2]->uv);
+ glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
+ glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]);
+ } else {
+ bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+
+ glTexCoord2fv(luv[0]->uv);
+ glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
+ glNormal3fv(vertexNos[BM_GetIndex(ls[0]->v)]);
+ glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]);
+
+ glTexCoord2fv(luv[1]->uv);
+ glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
+ glNormal3fv(vertexNos[BM_GetIndex(ls[1]->v)]);
+ glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]);
+
+ glTexCoord2fv(luv[2]->uv);
+ glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
+ glNormal3fv(vertexNos[BM_GetIndex(ls[2]->v)]);
+ glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]);
+ }
+ }
+ }
+ glEnd();
+ } else {
+ i = 0;
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
+ BM_SetIndex(eve, i++);
+
+ for (i=0; i<em->tottri; i++) {
+ BMLoop **ls = em->looptris[i];
+ MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
+ MTFace mtf = {{{0}}};
+ /*unsigned char *cp= NULL;*/ /*UNUSED*/
+ int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
+ int flag;
+
+ efa = ls[0]->f;
+
+ if (has_uv) {
+ mtf.flag = tp->flag;
+ mtf.tpage = tp->tpage;
+ mtf.transp = tp->transp;
+ mtf.mode = tp->mode;
+ mtf.tile = tp->tile;
+ mtf.unwrap = tp->unwrap;
+ }
+
+ if(drawParams)
+ flag= drawParams(&mtf, has_vcol, efa->mat_nr);
+ else if(drawParamsMapped)
+ flag= drawParamsMapped(userData, BM_GetIndex(efa));
+ else
+ flag= 1;
+
+ if(flag != 0) { /* flag 0 == the face is hidden or invisible */
+
+ /* we always want smooth here since otherwise vertex colors dont interpolate */
+ if (!has_vcol) {
+ glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
+ }
+
+ glBegin(GL_TRIANGLES);
+ if (!drawSmooth) {
+ glNormal3fv(efa->no);
+
+ bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+
+ if (luv[0])
+ glTexCoord2fv(luv[0]->uv);
+ if (lcol[0])
+ glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
+ else glColor3ub(0, 0, 0);
+ glVertex3fv(ls[0]->v->co);
+
+ if (luv[1])
+ glTexCoord2fv(luv[1]->uv);
+ if (lcol[1])
+ glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
+ else glColor3ub(0, 0, 0);
+ glVertex3fv(ls[1]->v->co);
+
+ if (luv[2])
+ glTexCoord2fv(luv[2]->uv);
+ if (lcol[2])
+ glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
+ else glColor3ub(0, 0, 0);
+ glVertex3fv(ls[2]->v->co);
+ } else {
+ bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+
+ if (luv[0])
+ glTexCoord2fv(luv[0]->uv);
+ if (lcol[0])
+ glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
+ else glColor3ub(0, 0, 0);
+ glNormal3fv(ls[0]->v->no);
+ glVertex3fv(ls[0]->v->co);
+
+ if (luv[1])
+ glTexCoord2fv(luv[1]->uv);
+ if (lcol[1])
+ glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
+ else glColor3ub(0, 0, 0);
+ glNormal3fv(ls[1]->v->no);
+ glVertex3fv(ls[1]->v->co);
+
+ if (luv[2])
+ glTexCoord2fv(luv[2]->uv);
+ if (lcol[2])
+ glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
+ else glColor3ub(0, 0, 0);
+ glNormal3fv(ls[2]->v->no);
+ glVertex3fv(ls[2]->v->co);
+ }
+ glEnd();
+ }
+ }
+ }
+}
+
+static void bmDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr))
+{
+ bmDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
+}
+
+static void bmDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
+{
+ bmDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
+}
+
+static void bmDM_drawMappedFacesGLSL(DerivedMesh *dm,
+ int (*setMaterial)(int, void *attribs),
+ int (*setDrawOptions)(void *userData, int index), void *userData)
+{
+#if 0
+ (void)dm;
+ (void)setMaterial;
+ (void)setDrawOptions;
+ (void)userData;
+#else /*BMESH_TODO*/
+
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMesh *bm= bmdm->tc->bm;
+ BMEditMesh *em = bmdm->tc;
+ float (*vertexCos)[3]= bmdm->vertexCos;
+ float (*vertexNos)[3]= bmdm->vertexNos;
+ BMVert *eve;
+ BMFace *efa;
+ BMIter iter;
+ BMLoop **ltri;
+ DMVertexAttribs attribs;
+ GPUVertexAttribs gattribs;
+
+ int i, b, matnr, new_matnr, dodraw;
+
+ dodraw = 0;
+ matnr = -1;
+
+ memset(&attribs, 0, sizeof(attribs));
+
+ /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
+ glShadeModel(GL_SMOOTH);
+ BM_ITER_INDEX(eve, &iter, bm, BM_VERTS_OF_MESH, NULL, i) {
+ BM_SetIndex(eve, i);
+ }
+
+#define PASSATTRIB(loop, eve, vert) { \
+ if(attribs.totorco) { \
+ float *orco = attribs.orco.array[BM_GetIndex(eve)]; \
+ glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \
+ } \
+ for(b = 0; b < attribs.tottface; b++) { \
+ MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
+ glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv); \
+ } \
+ for(b = 0; b < attribs.totmcol; b++) { \
+ MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
+ GLubyte _col[4]; \
+ _col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a; \
+ glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col); \
+ } \
+ if(attribs.tottang) { \
+ float *tang = attribs.tang.array[i*4 + vert]; \
+ glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \
+ } \
+ }
+
+ BM_ITER_INDEX(efa, &iter, bm, BM_FACES_OF_MESH, NULL, i) {
+ BM_SetIndex(efa, i);
+ }
+
+ for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
+ int drawSmooth;
+
+ efa = ltri[0]->f;
+ drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
+
+ if(setDrawOptions && !setDrawOptions(userData, BM_GetIndex(efa)))
+ continue;
+
+ new_matnr = efa->mat_nr + 1;
+ if(new_matnr != matnr) {
+ dodraw = setMaterial(matnr = new_matnr, &gattribs);
+ if(dodraw)
+ DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+ }
+
+ if(dodraw) {
+ glBegin(GL_TRIANGLES);
+ if (!drawSmooth) {
+ if(vertexCos) glNormal3fv(bmdm->faceNos[i]);
+ else glNormal3fv(efa->no);
+
+ PASSATTRIB(ltri[0], ltri[0]->v, 0);
+ if(vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
+ else glVertex3fv(ltri[0]->v->co);
+
+ PASSATTRIB(ltri[1], ltri[1]->v, 1);
+ if(vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
+ else glVertex3fv(ltri[1]->v->co);
+
+ PASSATTRIB(ltri[2], ltri[2]->v, 2);
+ if(vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
+ else glVertex3fv(ltri[2]->v->co);
+ } else {
+ PASSATTRIB(ltri[0], ltri[0]->v, 0);
+ if(vertexCos) {
+ glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]);
+ glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
+ }
+ else {
+ glNormal3fv(ltri[0]->v->no);
+ glVertex3fv(ltri[0]->v->co);
+ }
+
+ PASSATTRIB(ltri[1], ltri[1]->v, 1);
+ if(vertexCos) {
+ glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]);
+ glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
+ }
+ else {
+ glNormal3fv(ltri[1]->v->no);
+ glVertex3fv(ltri[1]->v->co);
+ }
+
+ PASSATTRIB(ltri[2], ltri[2]->v, 2);
+ if(vertexCos) {
+ glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]);
+ glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
+ }
+ else {
+ glNormal3fv(ltri[2]->v->no);
+ glVertex3fv(ltri[2]->v->co);
+ }
+ }
+ glEnd();
+ }
+ }
+#endif
+}
+
+static void bmDM_drawFacesGLSL(DerivedMesh *dm,
+ int (*setMaterial)(int, void *attribs))
+{
+ dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+}
+
+static void bmDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMVert *eve;
+ BMIter iter;
+ int i;
+
+ if (bmdm->tc->bm->totvert) {
+ eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++) {
+ if (bmdm->vertexCos) {
+ DO_MINMAX(bmdm->vertexCos[i], min_r, max_r);
+ } else {
+ DO_MINMAX(eve->co, min_r, max_r);
+ }
+ }
+ } else {
+ min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
+ }
+}
+static int bmDM_getNumVerts(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+
+ return bmdm->tc->bm->totvert;
+}
+
+static int bmDM_getNumEdges(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+
+ return bmdm->tc->bm->totedge;
+}
+
+static int bmDM_getNumTessFaces(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+
+ return bmdm->tc->tottri;
+}
+
+static int bmDM_getNumFaces(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+
+ return bmdm->tc->bm->totface;
+}
+
+static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r)
+{
+ copy_v3_v3(vert_r->co, ev->co);
+
+ vert_r->no[0] = (short)(ev->no[0] * 32767.0f);
+ vert_r->no[1] = (short)(ev->no[1] * 32767.0f);
+ vert_r->no[2] = (short)(ev->no[2] * 32767.0f);
+
+ vert_r->flag = BMFlags_To_MEFlags(ev);
+
+ if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
+ vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
+ }
+
+ return 1;
+}
+
+static void bmDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
+{
+ BMVert *ev;
+
+ if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tv) {
+ printf("error in bmDM_getVert.\n");
+ return;
+ }
+
+ ev = ((EditDerivedBMesh *)dm)->vtable[index];
+ bmvert_to_mvert(((EditDerivedBMesh *)dm)->tc->bm, ev, vert_r);
+}
+
+static void bmDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+ BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
+ BMEdge *e;
+
+ if (index < 0 || index >= ((EditDerivedBMesh *)dm)->te) {
+ printf("error in bmDM_getEdge.\n");
+ return;
+ }
+
+ e = bmdm->etable[index];
+
+ if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
+ edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_BWEIGHT)*255.0f);
+ }
+
+ if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
+ edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_CREASE)*255.0f);
+ }
+
+ edge_r->flag = BMFlags_To_MEFlags(e);
+
+ edge_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v1));
+ edge_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v2));
+}
+
+static void bmDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+ BMFace *ef;
+ BMLoop **l;
+
+ if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tf) {
+ printf("error in bmDM_getTessFace.\n");
+ return;
+ }
+
+ l = ((EditDerivedBMesh *)dm)->tc->looptris[index];
+
+ ef = l[0]->f;
+
+ face_r->mat_nr = (unsigned char) ef->mat_nr;
+ face_r->flag = BMFlags_To_MEFlags(ef);
+
+ face_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[0]->v));
+ face_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[1]->v));
+ face_r->v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[2]->v));
+ face_r->v4 = 0;
+
+ test_index_face(face_r, NULL, 0, 3);
+}
+
+static void bmDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
+{
+ BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
+ BMVert *ev;
+ BMIter iter;
+
+ ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for( ; ev; ev = BMIter_Step(&iter), ++vert_r) {
+ copy_v3_v3(vert_r->co, ev->co);
+
+ vert_r->no[0] = (short) (ev->no[0] * 32767.0);
+ vert_r->no[1] = (short) (ev->no[1] * 32767.0);
+ vert_r->no[2] = (short) (ev->no[2] * 32767.0);
+
+ vert_r->flag = BMFlags_To_MEFlags(ev);
+
+ if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
+ vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
+ }
+ }
+}
+
+static void bmDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
+{
+ BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
+ BMEdge *ee;
+ BMIter iter;
+ BMVert *ev;
+ int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT);
+ int i, has_crease = CustomData_has_layer(&bm->edata, CD_CREASE);
+
+ /* store vertex indices in tmp union */
+ ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; ev; ev=BMIter_Step(&iter), i++)
+ BM_SetIndex(ev, i);
+
+ ee = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
+ for( ; ee; ee=BMIter_Step(&iter), edge_r++) {
+ if (has_bweight) {
+ edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_BWEIGHT)*255.0f);
+ }
+
+ if (has_crease) {
+ edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_CREASE)*255.0f);
+ }
+
+ edge_r->flag = BMFlags_To_MEFlags(ee);
+
+ edge_r->v1 = (int)BM_GetIndex(ee->v1);
+ edge_r->v2 = (int)BM_GetIndex(ee->v2);
+ }
+}
+
+static void bmDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+ BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
+ BMFace *ef;
+ BMVert *ev;
+ BMIter iter;
+ BMLoop **l;
+ int i;
+
+ /* store vertexes indices in tmp union */
+ i = 0;
+ BM_ITER(ev, &iter, bm, BM_VERTS_OF_MESH, NULL)
+ BM_SetIndex(ev, i++);
+
+ for (i=0; i<bmdm->tc->tottri; i++, face_r++) {
+ l = bmdm->tc->looptris[i];
+ ef = l[0]->f;
+
+ face_r->mat_nr = (unsigned char) ef->mat_nr;
+
+ face_r->flag = BMFlags_To_MEFlags(ef);
+
+ face_r->v1 = BM_GetIndex(l[0]->v);
+ face_r->v2 = BM_GetIndex(l[1]->v);
+ face_r->v3 = BM_GetIndex(l[2]->v);
+ face_r->v4 = 0;
+
+ test_index_face(face_r, NULL, 0, 3);
+ }
+}
+
+
+static void bmDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
+{
+ /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
+ BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
+ BMIter iter, liter;
+ BMVert *v;
+ BMFace *f;
+ BMLoop *l;
+ BMEdge *e;
+ int i;
+
+ i = 0;
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(v, i++);
+ }
+
+ i = 0;
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ BM_SetIndex(e, i++);
+ }
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ loop_r->v = BM_GetIndex(l->v);
+ loop_r->e = BM_GetIndex(l->e);
+ loop_r++;
+ }
+ }
+}
+
+static void bmDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
+{
+ /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
+ BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
+ BMIter iter;
+ BMFace *f;
+ int i;
+
+ i = 0;
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ poly_r->flag = BMFlags_To_MEFlags(f);
+ poly_r->loopstart = i;
+ poly_r->totloop = f->len;
+ poly_r->mat_nr = f->mat_nr;
+
+ poly_r++;
+ i += f->len;
+ }
+}
+
+static void *bmDM_getFaceDataArray(DerivedMesh *dm, int type)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+ BMesh *bm= bmdm->tc->bm;
+ BMFace *efa;
+ char *data, *bmdata;
+ void *datalayer;
+ int index /*, offset*/ /*UNUSED */, size, i;
+
+ datalayer = DM_get_tessface_data_layer(dm, type);
+ if(datalayer)
+ return datalayer;
+
+ /* layers are store per face for editmesh, we convert to a tbmporary
+ * data layer array in the derivedmesh when these are requested */
+ if(type == CD_MTFACE || type == CD_MCOL) {
+ index = CustomData_get_layer_index(&bm->pdata, type);
+
+ if(index != -1) {
+ /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
+ size = CustomData_sizeof(type);
+
+ DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
+ index = CustomData_get_layer_index(&dm->faceData, type);
+ dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
+
+ data = datalayer = DM_get_tessface_data_layer(dm, type);
+ for (i=0; i<bmdm->tc->tottri; i++, data+=size) {
+ efa = bmdm->tc->looptris[i][0]->f;
+ /*BMESH_TODO: need to still add tface data,
+ derived from the loops.*/
+ bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type);
+ memcpy(data, bmdata, size);
+ }
+ }
+ }
+
+ return datalayer;
+}
+
+static void bmDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
+{
+ EditDerivedBMesh *emdm= (EditDerivedBMesh*) dm;
+ BMVert *eve;
+ BMIter iter;
+ int i;
+
+ i= 0;
+ BM_ITER(eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH, NULL) {
+ if (emdm->vertexCos) {
+ copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
+ } else {
+ copy_v3_v3(cos_r[i], eve->co);
+ }
+
+ i++;
+ }
+}
+
+static void bmDM_release(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm= (EditDerivedBMesh *)dm;
+
+ if (DM_release(dm)) {
+ if (bmdm->vertexCos) {
+ MEM_freeN(bmdm->vertexCos);
+ MEM_freeN(bmdm->vertexNos);
+ MEM_freeN(bmdm->faceNos);
+ }
+
+ if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
+ if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
+ if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL);
+
+ if (bmdm->vtable) MEM_freeN(bmdm->vtable);
+ if (bmdm->etable) MEM_freeN(bmdm->etable);
+ if (bmdm->ftable) MEM_freeN(bmdm->ftable);
+
+ MEM_freeN(bmdm);
+ }
+}
+
+static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+ return &bmdm->tc->bm->vdata;
+}
+
+static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+ return &bmdm->tc->bm->edata;
+}
+
+static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+ return &bmdm->dm.faceData;
+}
+
+static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+ return &bmdm->tc->bm->ldata;
+}
+
+static CustomData *bmDm_getFaceDataLayout(DerivedMesh *dm)
+{
+ EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+ return &bmdm->tc->bm->pdata;
+}
+
+
+DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, Object *UNUSED(ob),
+ float (*vertexCos)[3])
+{
+ EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
+ BMesh *bm = em->bm;
+
+ bmdm->tc = em;
+
+ DM_init((DerivedMesh*)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert,
+ em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface);
+
+ CustomData_from_bmeshpoly(&bmdm->dm.faceData, &em->bm->pdata, &em->bm->ldata, 0);
+
+ bmdm->dm.numVertData = bm->totvert;
+ bmdm->dm.numEdgeData = bm->totedge;
+ bmdm->dm.numFaceData = em->tottri;
+ bmdm->dm.numLoopData = bm->totloop;
+ bmdm->dm.numPolyData = bm->totface;
+
+ bmdm->dm.getVertCos = bmDM_getVertCos;
+ bmdm->dm.getMinMax = bmDM_getMinMax;
+
+ bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
+ bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
+ bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
+ bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
+ bmdm->dm.getFaceDataLayout = bmDm_getFaceDataLayout;
+
+ bmdm->dm.getNumVerts = bmDM_getNumVerts;
+ bmdm->dm.getNumEdges = bmDM_getNumEdges;
+ bmdm->dm.getNumTessFaces = bmDM_getNumTessFaces;
+ bmdm->dm.getNumFaces = bmDM_getNumFaces;
+
+ bmdm->dm.getVert = bmDM_getVert;
+ bmdm->dm.getEdge = bmDM_getEdge;
+ bmdm->dm.getTessFace = bmDM_getTessFace;
+ bmdm->dm.copyVertArray = bmDM_copyVertArray;
+ bmdm->dm.copyEdgeArray = bmDM_copyEdgeArray;
+ bmdm->dm.copyTessFaceArray = bmDM_copyFaceArray;
+ bmdm->dm.copyLoopArray = bmDM_copyLoopArray;
+ bmdm->dm.copyPolyArray = bmDM_copyPolyArray;
+
+ bmdm->dm.getTessFaceDataArray = bmDM_getFaceDataArray;
+
+ bmdm->dm.recalcTesselation = bmDM_recalcTesselation;
+
+ bmdm->dm.foreachMappedVert = bmDM_foreachMappedVert;
+ bmdm->dm.foreachMappedEdge = bmDM_foreachMappedEdge;
+ bmdm->dm.foreachMappedFaceCenter = bmDM_foreachMappedFaceCenter;
+
+ bmdm->dm.drawEdges = bmDM_drawEdges;
+ bmdm->dm.drawMappedEdges = bmDM_drawMappedEdges;
+ bmdm->dm.drawMappedEdgesInterp = bmDM_drawMappedEdgesInterp;
+ bmdm->dm.drawMappedFaces = bmDM_drawMappedFaces;
+ bmdm->dm.drawMappedFacesTex = bmDM_drawMappedFacesTex;
+ bmdm->dm.drawMappedFacesGLSL = bmDM_drawMappedFacesGLSL;
+ bmdm->dm.drawFacesTex = bmDM_drawFacesTex;
+ bmdm->dm.drawFacesGLSL = bmDM_drawFacesGLSL;
+ bmdm->dm.drawUVEdges = bmDM_drawUVEdges;
+
+ bmdm->dm.release = bmDM_release;
+
+ bmdm->vertexCos = vertexCos;
+
+ if(CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
+ BMIter iter;
+ BMVert *eve;
+ int i;
+
+ DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
+
+ eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++)
+ DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
+ CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
+ }
+
+ if(vertexCos) {
+ BMVert *eve;
+ BMIter iter;
+ int totface = bmdm->tc->tottri;
+ int i;
+
+ eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++)
+ BM_SetIndex(eve, i);
+
+ bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos)*i, "bmdm_vno");
+ bmdm->faceNos = MEM_mallocN(sizeof(*bmdm->faceNos)*totface, "bmdm_vno");
+
+ for (i=0; i<bmdm->tc->tottri; i++) {
+ BMLoop **l = bmdm->tc->looptris[i];
+ float *v1 = vertexCos[(int) BM_GetIndex(l[0]->v)];
+ float *v2 = vertexCos[(int) BM_GetIndex(l[1]->v)];
+ float *v3 = vertexCos[(int) BM_GetIndex(l[2]->v)];
+ float *no = bmdm->faceNos[i];
+
+ normal_tri_v3( no,v1, v2, v3);
+ add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[0]->v)], bmdm->vertexNos[BM_GetIndex(l[0]->v)], no);
+ add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[1]->v)], bmdm->vertexNos[BM_GetIndex(l[1]->v)], no);
+ add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[2]->v)], bmdm->vertexNos[BM_GetIndex(l[2]->v)], no);
+ }
+
+ eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++) {
+ float *no = bmdm->vertexNos[i];
+ /* following Mesh convention; we use vertex coordinate itself
+ * for normal in this case */
+ if (normalize_v3(no)==0.0) {
+ copy_v3_v3(no, vertexCos[i]);
+ normalize_v3(no);
+ }
+ }
+ }
+
+ //bmdm_recalc_lookups(bmdm);
+
+ return (DerivedMesh*) bmdm;
+}
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index c4543df0d16..37ad2346f17 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -590,7 +590,7 @@ int closest_point_on_surface(SurfaceModifierData *surmd, float *co, float *surfa
}
if(surface_vel) {
- MFace *mface = CDDM_get_face(surmd->dm, nearest.index);
+ MFace *mface = CDDM_get_tessface(surmd->dm, nearest.index);
copy_v3_v3(surface_vel, surmd->v[mface->v1].co);
add_v3_v3(surface_vel, surmd->v[mface->v2].co);
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 3529b7b9e6d..737baa1ddc4 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -433,8 +433,7 @@ int binarysearch_bezt_index (BezTriple array[], float frame, int arraylen, short
/* ...................................... */
/* helper for calc_fcurve_* functions -> find first and last BezTriple to be used */
-static void get_fcurve_end_keyframes (FCurve *fcu, BezTriple **first, BezTriple **last,
- const short do_sel_only)
+static void get_fcurve_end_keyframes (FCurve *fcu, BezTriple **first, BezTriple **last, const short selOnly)
{
/* init outputs */
*first = NULL;
@@ -445,7 +444,7 @@ static void get_fcurve_end_keyframes (FCurve *fcu, BezTriple **first, BezTriple
return;
/* only include selected items? */
- if (do_sel_only) {
+ if (selOnly) {
BezTriple *bezt;
unsigned int i;
@@ -476,12 +475,11 @@ static void get_fcurve_end_keyframes (FCurve *fcu, BezTriple **first, BezTriple
/* Calculate the extents of F-Curve's data */
-void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax,
- const short do_sel_only)
+void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax, const short selOnly)
{
float xminv=999999999.0f, xmaxv=-999999999.0f;
float yminv=999999999.0f, ymaxv=-999999999.0f;
- short foundvert= FALSE;
+ short foundvert=0;
unsigned int i;
if (fcu->totvert) {
@@ -490,7 +488,7 @@ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
if (xmin || xmax) {
/* get endpoint keyframes */
- get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, do_sel_only);
+ get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, selOnly);
if (bezt_first) {
BLI_assert(bezt_last != NULL);
@@ -505,12 +503,11 @@ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
BezTriple *bezt;
for (bezt=fcu->bezt, i=0; i < fcu->totvert; bezt++, i++) {
- if ((do_sel_only == 0) || BEZSELECTED(bezt)) {
+ if ((selOnly == 0) || BEZSELECTED(bezt)) {
if (bezt->vec[1][1] < yminv)
yminv= bezt->vec[1][1];
if (bezt->vec[1][1] > ymaxv)
ymaxv= bezt->vec[1][1];
- foundvert= TRUE;
}
}
}
@@ -531,11 +528,11 @@ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
yminv= fpt->vec[1];
if (fpt->vec[1] > ymaxv)
ymaxv= fpt->vec[1];
-
- foundvert= TRUE;
}
}
}
+
+ foundvert=1;
}
if (foundvert) {
@@ -558,50 +555,43 @@ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
}
/* Calculate the extents of F-Curve's keyframes */
-void calc_fcurve_range (FCurve *fcu, float *start, float *end,
- const short do_sel_only, const short do_min_length)
+void calc_fcurve_range (FCurve *fcu, float *start, float *end, const short selOnly)
{
float min=999999999.0f, max=-999999999.0f;
- short foundvert= FALSE;
+ short foundvert=0;
if (fcu->totvert) {
if (fcu->bezt) {
BezTriple *bezt_first= NULL, *bezt_last= NULL;
/* get endpoint keyframes */
- get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, do_sel_only);
-
+ get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, selOnly);
+
if (bezt_first) {
BLI_assert(bezt_last != NULL);
-
+
min= MIN2(min, bezt_first->vec[1][0]);
max= MAX2(max, bezt_last->vec[1][0]);
-
- foundvert= TRUE;
}
}
else if (fcu->fpt) {
min= MIN2(min, fcu->fpt[0].vec[0]);
max= MAX2(max, fcu->fpt[fcu->totvert-1].vec[0]);
-
- foundvert= TRUE;
}
+ foundvert=1;
}
- if (foundvert == FALSE) {
- min= max= 0.0f;
+ /* minimum length is 1 frame */
+ if (foundvert) {
+ if (min == max) max += 1.0f;
+ *start= min;
+ *end= max;
}
-
- if (do_min_length) {
- /* minimum length is 1 frame */
- if (min == max) {
- max += 1.0f;
- }
+ else {
+ *start= 0.0f;
+ *end= 1.0f;
}
-
- *start= min;
- *end= max;
}
/* ----------------- Status Checks -------------------------- */
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
index bf432785064..42ddd63f072 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -85,9 +85,9 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob,
//dm = mesh_create_derived_no_deform(ob,NULL);
mvert = dm->getVertArray(dm);
- mface = dm->getFaceArray(dm);
+ mface = dm->getTessFaceArray(dm);
totvert = dm->getNumVerts(dm);
- totface = dm->getNumFaces(dm);
+ totface = dm->getNumTessFaces(dm);
*numVertices = totvert;
verts = MEM_callocN( totvert*3*sizeof(float), "elbeemmesh_vertices");
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 5f7d2d40acc..f16b1e6b4ec 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -60,14 +60,10 @@
#include "DNA_camera_types.h"
#include "DNA_sequence_types.h"
#include "DNA_userdef_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "BLI_blenlib.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
#include "BKE_bmfont.h"
#include "BKE_global.h"
@@ -317,132 +313,6 @@ Image *copy_image(Image *ima)
return nima;
}
-static void extern_local_image(Image *UNUSED(ima))
-{
- /* Nothing to do: images don't link to other IDs. This function exists to
- match id_make_local pattern. */
-}
-
-void make_local_image(struct Image *ima) {
- Main *bmain= G.main;
- Tex *tex;
- Brush *brush;
- Mesh *me;
- int local=0, lib=0;
-
- /* - only lib users: do nothing
- * - only local users: set flag
- * - mixed: make copy
- */
-
- if(ima->id.lib==NULL) return;
-
- /* Can't take short cut here: must check meshes at least because of bogus
- texface ID refs. - z0r */
-#if(0)
- if(ima->id.us==1) {
- id_clear_lib_data(&bmain->image, (ID *)ima);
- extern_local_image(ima);
- return;
- }
-#endif
-
- for(tex= bmain->tex.first; tex; tex= tex->id.next) {
- if(tex->ima == ima) {
- if(tex->id.lib) lib= 1;
- else local= 1;
- }
- }
- for(brush= bmain->brush.first; brush; brush= brush->id.next) {
- if(brush->clone.image == ima) {
- if(brush->id.lib) lib= 1;
- else local= 1;
- }
- }
- for(me= bmain->mesh.first; me; me= me->id.next) {
- if(me->mtface) {
- MTFace *tface;
- int a, i;
-
- for(i=0; i<me->fdata.totlayer; i++) {
- if(me->fdata.layers[i].type == CD_MTFACE) {
- tface= (MTFace*)me->fdata.layers[i].data;
-
- for(a=0; a<me->totface; a++, tface++) {
- if(tface->tpage == ima) {
- if(me->id.lib) lib=1;
- else local= 1;
- }
- }
- }
- }
- }
- }
-
- if(local && lib==0) {
- id_clear_lib_data(&bmain->image, (ID *)ima);
- extern_local_image(ima);
- }
- else if(local && lib) {
- Image *iman= copy_image(ima);
- iman->id.us= 0;
-
- /* Remap paths of new ID using old library as base. */
- bpath_traverse_id((ID *)iman, bpath_relocate_visitor,
- ((ID *)ima)->lib->filepath);
-
- tex= bmain->tex.first;
- while(tex) {
- if(tex->id.lib==NULL) {
- if(tex->ima==ima) {
- tex->ima = iman;
- iman->id.us++;
- ima->id.us--;
- }
- }
- tex= tex->id.next;
- }
- brush= bmain->brush.first;
- while(brush) {
- if(brush->id.lib==NULL) {
- if(brush->clone.image==ima) {
- brush->clone.image = iman;
- iman->id.us++;
- ima->id.us--;
- }
- }
- brush= brush->id.next;
- }
- /* Transfer references in texfaces. Texfaces don't add to image ID
- user count *unless* there are no other users. See
- readfile.c:lib_link_mtface. */
- me= bmain->mesh.first;
- while(me) {
- if(me->mtface) {
- MTFace *tface;
- int a, i;
-
- for(i=0; i<me->fdata.totlayer; i++) {
- if(me->fdata.layers[i].type == CD_MTFACE) {
- tface= (MTFace*)me->fdata.layers[i].data;
-
- for(a=0; a<me->totface; a++, tface++) {
- if(tface->tpage == ima) {
- tface->tpage = iman;
- if(iman->id.us == 0) {
- tface->tpage->id.us= 1;
- }
- id_lib_extern((ID*)iman);
- }
- }
- }
- }
- }
- me= me->id.next;
- }
- }
-}
-
void BKE_image_merge(Image *dest, Image *source)
{
ImBuf *ibuf;
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 5ac8780e4a2..349b91ad867 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -56,6 +56,7 @@
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
+#include "BKE_tessmesh.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_deform.h"
@@ -91,6 +92,20 @@ void free_key(Key *key)
}
+void free_key_nolib(Key *key)
+{
+ KeyBlock *kb;
+
+ while( (kb= key->block.first) ) {
+
+ if(kb->data) MEM_freeN(kb->data);
+
+ BLI_remlink(&key->block, kb);
+ MEM_freeN(kb);
+ }
+
+}
+
/* GS reads the memory pointed at in a specific ordering. There are,
* however two definitions for it. I have jotted them down here, both,
* but I think the first one is actually used. The thing is that
@@ -113,6 +128,8 @@ Key *add_key(ID *id) /* common function */
key->type= KEY_NORMAL;
key->from= id;
+
+ key->uidgen = 1;
// XXX the code here uses some defines which will soon be depreceated...
if( GS(id->name)==ID_ME) {
@@ -171,6 +188,32 @@ Key *copy_key(Key *key)
return keyn;
}
+
+Key *copy_key_nolib(Key *key)
+{
+ Key *keyn;
+ KeyBlock *kbn, *kb;
+
+ if(key==0) return 0;
+
+ keyn= MEM_dupallocN(key);
+
+ BLI_duplicatelist(&keyn->block, &key->block);
+
+ kb= key->block.first;
+ kbn= keyn->block.first;
+ while(kbn) {
+
+ if(kbn->data) kbn->data= MEM_dupallocN(kbn->data);
+ if(kb==key->refkey) keyn->refkey= kbn;
+
+ kbn= kbn->next;
+ kb= kb->next;
+ }
+
+ return keyn;
+}
+
void make_local_key(Key *key)
{
@@ -494,18 +537,21 @@ static char *key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char **
edit mode with shape keys blending applied */
if(GS(key->from->name) == ID_ME) {
Mesh *me;
- EditVert *eve;
+ BMVert *eve;
+ BMIter iter;
float (*co)[3];
int a;
me= (Mesh*)key->from;
- if(me->edit_mesh && me->edit_mesh->totvert == kb->totelem) {
+ if(me->edit_btmesh && me->edit_btmesh->bm->totvert == kb->totelem) {
a= 0;
- co= MEM_callocN(sizeof(float)*3*me->edit_mesh->totvert, "key_block_get_data");
+ co= MEM_callocN(sizeof(float)*3*me->edit_btmesh->bm->totvert, "key_block_get_data");
- for(eve=me->edit_mesh->verts.first; eve; eve=eve->next, a++)
+ BM_ITER(eve, &iter, me->edit_btmesh->bm, BM_VERTS_OF_MESH, NULL) {
VECCOPY(co[a], eve->co);
+ a++;
+ }
*freedata= (char*)co;
return (char*)co;
@@ -999,8 +1045,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
static float *get_weights_array(Object *ob, char *vgroup)
{
MDeformVert *dvert= NULL;
- EditMesh *em= NULL;
- EditVert *eve;
+ BMEditMesh *em= NULL;
+ BMIter iter;
+ BMVert *eve;
int totvert= 0, defgrp_index= 0;
/* no vgroup string set? */
@@ -1012,8 +1059,8 @@ static float *get_weights_array(Object *ob, char *vgroup)
dvert= me->dvert;
totvert= me->totvert;
- if(me->edit_mesh && me->edit_mesh->totvert == totvert)
- em= me->edit_mesh;
+ if(me->edit_btmesh && me->edit_btmesh->bm->totvert == totvert)
+ em= me->edit_btmesh;
}
else if(ob->type==OB_LATTICE) {
Lattice *lt= ob->data;
@@ -1032,8 +1079,9 @@ static float *get_weights_array(Object *ob, char *vgroup)
weights= MEM_callocN(totvert*sizeof(float), "weights");
if(em) {
- for(i=0, eve=em->verts.first; eve; eve=eve->next, i++) {
- dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++) {
+ dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
if(dvert) {
weights[i]= defvert_find_weight(dvert, defgrp_index);
@@ -1450,7 +1498,8 @@ KeyBlock *add_keyblock(Key *key, const char *name)
// XXX this is old anim system stuff? (i.e. the 'index' of the shapekey)
kb->adrcode= tot-1;
-
+ kb->uid = key->uidgen++;
+
key->totkey++;
if(key->totkey==1) key->refkey= kb;
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index ebf5492625b..84f9829a639 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -255,7 +255,9 @@ void make_local_lattice(Lattice *lt)
if(lt->id.lib==NULL) return;
if(lt->id.us==1) {
- id_clear_lib_data(&bmain->latt, (ID *)lt);
+ lt->id.lib= NULL;
+ lt->id.flag= LIB_LOCAL;
+ new_id(&bmain->latt, (ID *)lt, NULL);
return;
}
@@ -267,7 +269,9 @@ void make_local_lattice(Lattice *lt)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->latt, (ID *)lt);
+ lt->id.lib= NULL;
+ lt->id.flag= LIB_LOCAL;
+ new_id(&bmain->latt, (ID *)lt, NULL);
}
else if(local && lib) {
Lattice *ltn= copy_lattice(lt);
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 0c2ca4c68b3..d77ef10f76b 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -74,7 +74,7 @@
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
+
#include "BKE_animsys.h"
#include "BKE_context.h"
@@ -108,7 +108,6 @@
#include "BKE_gpencil.h"
#include "BKE_fcurve.h"
#include "BKE_speaker.h"
-#include "BKE_utildefines.h"
#include "RNA_access.h"
@@ -195,8 +194,7 @@ int id_make_local(ID *id, int test)
if(!test) make_local_texture((Tex*)id);
return 1;
case ID_IM:
- if(!test) make_local_image((Image*)id);
- return 1;
+ return 0; /* not implemented */
case ID_LT:
if(!test) {
make_local_lattice((Lattice*)id);
@@ -785,7 +783,7 @@ void free_libblock(ListBase *lb, void *idv)
free_object((Object *)id);
break;
case ID_ME:
- free_mesh((Mesh *)id);
+ free_mesh((Mesh *)id, 1);
break;
case ID_CU:
free_curve((Curve *)id);
@@ -1248,16 +1246,6 @@ int new_id(ListBase *lb, ID *id, const char *tname)
return result;
}
-/* Pull an ID out of a library (make it local). Only call this for IDs that
- don't have other library users. */
-void id_clear_lib_data(ListBase *lb, ID *id)
-{
- bpath_traverse_id(id, bpath_relocate_visitor, id->lib->filepath);
- id->lib= NULL;
- id->flag= LIB_LOCAL;
- new_id(lb, id, NULL);
-}
-
/* next to indirect usage in read/writefile also in editobject.c scene.c */
void clear_id_newpoins(void)
{
@@ -1473,21 +1461,3 @@ void name_uiprefix_id(char *name, ID *id)
strcpy(name+3, id->name+2);
}
-
-void BKE_library_filepath_set(Library *lib, const char *filepath)
-{
- BLI_strncpy(lib->name, filepath, sizeof(lib->name));
- BLI_strncpy(lib->filepath, filepath, sizeof(lib->filepath));
-
- /* not essential but set filepath is an absolute copy of value which
- * is more useful if its kept in sync */
- if (strncmp(lib->filepath, "//", 2) == 0) {
- /* note that the file may be unsaved, in this case, setting the
- * filepath on an indirectly linked path is not allowed from the
- * outliner, and its not really supported but allow from here for now
- * since making local could cause this to be directly linked - campbell
- */
- const char *basepath= lib->parent ? lib->parent->filepath : G.main->name;
- BLI_path_abs(lib->filepath, basepath);
- }
-}
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 12d92d57e86..190df040bf4 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -294,16 +294,15 @@ void make_local_material(Material *ma)
*/
if(ma->id.lib==NULL) return;
-
- /* One local user; set flag and return. */
if(ma->id.us==1) {
- id_clear_lib_data(&bmain->mat, (ID *)ma);
+ ma->id.lib= NULL;
+ ma->id.flag= LIB_LOCAL;
+
+ new_id(&bmain->mat, (ID *)ma, NULL);
extern_local_material(ma);
return;
}
-
- /* Check which other IDs reference this one to determine if it's used by
- lib or local */
+
/* test objects */
ob= bmain->object.first;
while(ob) {
@@ -356,13 +355,14 @@ void make_local_material(Material *ma)
}
mb= mb->id.next;
}
-
- /* Only local users. */
+
if(local && lib==0) {
- id_clear_lib_data(&bmain->mat, (ID *)ma);
+ ma->id.lib= NULL;
+ ma->id.flag= LIB_LOCAL;
+
+ new_id(&bmain->mat, (ID *)ma, NULL);
extern_local_material(ma);
}
- /* Both user and local, so copy. */
else if(local && lib) {
man= copy_material(ma);
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 2c6a3b80d94..b9ca6dda4cf 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -156,7 +156,9 @@ void make_local_mball(MetaBall *mb)
if(mb->id.lib==NULL) return;
if(mb->id.us==1) {
- id_clear_lib_data(&bmain->mball, (ID *)mb);
+ mb->id.lib= NULL;
+ mb->id.flag= LIB_LOCAL;
+ new_id(&bmain->mball, (ID *)mb, NULL);
extern_local_mball(mb);
return;
@@ -170,7 +172,10 @@ void make_local_mball(MetaBall *mb)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->mball, (ID *)mb);
+ mb->id.lib= NULL;
+ mb->id.flag= LIB_LOCAL;
+
+ new_id(&bmain->mball, (ID *)mb, NULL);
extern_local_mball(mb);
}
else if(local && lib) {
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index a5bf39d895c..074860c1076 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -41,15 +41,18 @@
#include "DNA_key_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_ipo_types.h"
+#include "DNA_customdata_types.h"
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
-#include "BLI_utildefines.h"
+#include "BLI_scanfill.h"
#include "BKE_animsys.h"
#include "BKE_main.h"
+#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
@@ -63,20 +66,316 @@
#include "BKE_curve.h"
/* -- */
#include "BKE_object.h"
+#include "BKE_tessmesh.h"
+#include "BLI_edgehash.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_math.h"
+#include "BLI_cellalloc.h"
+#include "BLI_array.h"
+#include "BLI_edgehash.h"
+#include "bmesh.h"
+
+enum {
+ MESHCMP_DVERT_WEIGHTMISMATCH = 1,
+ MESHCMP_DVERT_GROUPMISMATCH,
+ MESHCMP_DVERT_TOTGROUPMISMATCH,
+ MESHCMP_LOOPCOLMISMATCH,
+ MESHCMP_LOOPUVMISMATCH,
+ MESHCMP_LOOPMISMATCH,
+ MESHCMP_POLYVERTMISMATCH,
+ MESHCMP_POLYMISMATCH,
+ MESHCMP_EDGEUNKNOWN,
+ MESHCMP_VERTCOMISMATCH,
+ MESHCMP_CDLAYERS_MISMATCH,
+};
-EditMesh *BKE_mesh_get_editmesh(Mesh *me)
+static const char *cmpcode_to_str(int code)
{
- return me->edit_mesh;
+ switch (code) {
+ case MESHCMP_DVERT_WEIGHTMISMATCH:
+ return "Vertex Weight Mismatch";
+ case MESHCMP_DVERT_GROUPMISMATCH:
+ return "Vertex Group Mismatch";
+ case MESHCMP_DVERT_TOTGROUPMISMATCH:
+ return "Vertex Doesn't Belong To Same Number Of Groups";
+ case MESHCMP_LOOPCOLMISMATCH:
+ return "Vertex Color Mismatch";
+ case MESHCMP_LOOPUVMISMATCH:
+ return "UV Mismatch";
+ case MESHCMP_LOOPMISMATCH:
+ return "Loop Mismatch";
+ case MESHCMP_POLYVERTMISMATCH:
+ return "Loop Vert Mismatch In Poly Test";
+ case MESHCMP_POLYMISMATCH:
+ return "Loop Vert Mismatch";
+ case MESHCMP_EDGEUNKNOWN:
+ return "Edge Mismatch";
+ case MESHCMP_VERTCOMISMATCH:
+ return "Vertex Coordinate Mismatch";
+ case MESHCMP_CDLAYERS_MISMATCH:
+ "CustomData Layer Count Mismatch";
+ default:
+ return "Mesh Comparison Code Unknown";
+ }
}
-void BKE_mesh_end_editmesh(Mesh *UNUSED(me), EditMesh *UNUSED(em))
+/*thresh is threshold for comparing vertices, uvs, vertex colors,
+ weights, etc.*/
+static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2, float thresh)
{
+ CustomDataLayer *l1, *l2;
+ int i, i1=0, i2=0, tot, j;
+
+ for (i=0; i<c1->totlayer; i++) {
+ if (ELEM7(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ i1++;
+ }
+
+ for (i=0; i<c2->totlayer; i++) {
+ if (ELEM7(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ i2++;
+ }
+
+ if (i1 != i2)
+ return MESHCMP_CDLAYERS_MISMATCH;
+
+ l1 = c1->layers; l2 = c2->layers;
+ tot = i1;
+ i1 = 0; i2 = 0;
+ for (i=0; i < tot; i++) {
+ while (i1 < c1->totlayer && !ELEM7(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ i1++, l1++;
+
+ while (i2 < c2->totlayer && !ELEM7(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ i2++, l2++;
+
+ if (l1->type == CD_MVERT) {
+ MVert *v1 = l1->data;
+ MVert *v2 = l2->data;
+ int vtot = m1->totvert;
+
+ for (j=0; j<vtot; j++, v1++, v2++) {
+ if (len_v3v3(v1->co, v2->co) > thresh)
+ return MESHCMP_VERTCOMISMATCH;
+ /*I don't care about normals, let's just do coodinates*/
+ }
+ }
+
+ /*we're order-agnostic for edges here*/
+ if (l1->type == CD_MEDGE) {
+ MEdge *e1 = l1->data;
+ MEdge *e2 = l2->data;
+ EdgeHash *eh = BLI_edgehash_new();
+ int etot = m1->totedge;
+
+ for (j=0; j<etot; j++, e1++) {
+ BLI_edgehash_insert(eh, e1->v1, e1->v2, e1);
+ }
+
+ for (j=0; j<etot; j++, e2++) {
+ if (!BLI_edgehash_lookup(eh, e2->v1, e2->v2))
+ return MESHCMP_EDGEUNKNOWN;
+ }
+ BLI_edgehash_free(eh, NULL);
+ }
+
+ if (l1->type == CD_MPOLY) {
+ MPoly *p1 = l1->data;
+ MPoly *p2 = l2->data;
+ int ptot = m1->totpoly;
+
+ for (j=0; j<ptot; j++, p1++, p2++) {
+ MLoop *lp1, *lp2;
+ int k;
+
+ if (p1->totloop != p2->totloop)
+ return MESHCMP_POLYMISMATCH;
+
+ lp1 = m1->mloop + p1->loopstart;
+ lp2 = m2->mloop + p2->loopstart;
+
+ for (k=0; k<p1->totloop; k++, lp1++, lp2++) {
+ if (lp1->v != lp2->v)
+ return MESHCMP_POLYVERTMISMATCH;
+ }
+ }
+ }
+ if (l1->type == CD_MLOOP) {
+ MLoop *lp1 = l1->data;
+ MLoop *lp2 = l2->data;
+ int ltot = m1->totloop;
+
+ for (j=0; j<ltot; j++, lp1++, lp2++) {
+ if (lp1->v != lp2->v)
+ return MESHCMP_LOOPMISMATCH;
+ }
+ }
+ if (l1->type == CD_MLOOPUV) {
+ MLoopUV *lp1 = l1->data;
+ MLoopUV *lp2 = l2->data;
+ int ltot = m1->totloop;
+
+ for (j=0; j<ltot; j++, lp1++, lp2++) {
+ if (len_v2v2(lp1->uv, lp2->uv) > thresh)
+ return MESHCMP_LOOPUVMISMATCH;
+ }
+ }
+
+ if (l1->type == CD_MLOOPCOL) {
+ MLoopCol *lp1 = l1->data;
+ MLoopCol *lp2 = l2->data;
+ int ltot = m1->totloop;
+
+ for (j=0; j<ltot; j++, lp1++, lp2++) {
+ if (ABS(lp1->r - lp2->r) > thresh ||
+ ABS(lp1->g - lp2->g) > thresh ||
+ ABS(lp1->b - lp2->b) > thresh ||
+ ABS(lp1->a - lp2->a) > thresh)
+ {
+ return MESHCMP_LOOPCOLMISMATCH;
+ }
+ }
+ }
+
+ if (l1->type == CD_MDEFORMVERT) {
+ MDeformVert *dv1 = l1->data;
+ MDeformVert *dv2 = l2->data;
+ int dvtot = m1->totvert;
+
+ for (j=0; j<dvtot; j++, dv1++, dv2++) {
+ int k;
+ MDeformWeight *dw1 = dv1->dw, *dw2=dv2->dw;
+
+ if (dv1->totweight != dv2->totweight)
+ return MESHCMP_DVERT_TOTGROUPMISMATCH;
+
+ for (k=0; k<dv1->totweight; k++, dw1++, dw2++) {
+ if (dw1->def_nr != dw2->def_nr)
+ return MESHCMP_DVERT_GROUPMISMATCH;
+ if (ABS(dw1->weight - dw2->weight) > thresh)
+ return MESHCMP_DVERT_WEIGHTMISMATCH;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*used for testing. returns an error string the two meshes don't match*/
+const char *mesh_cmp(Mesh *me1, Mesh *me2, float thresh)
+{
+ int c;
+
+ if (!me1 || !me2)
+ return "Requires two input meshes";
+
+ if (me1->totvert != me2->totvert)
+ return "Number of verts don't match";
+
+ if (me1->totedge != me2->totedge)
+ return "Number of edges don't match";
+
+ if (me1->totpoly != me2->totpoly)
+ return "Number of faces don't match";
+
+ if (me1->totloop !=me2->totloop)
+ return "Number of loops don't match";
+
+ if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1, me2, thresh)))
+ return cmpcode_to_str(c);
+
+ if ((c = customdata_compare(&me1->edata, &me2->edata, me1, me2, thresh)))
+ return cmpcode_to_str(c);
+
+ if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1, me2, thresh)))
+ return cmpcode_to_str(c);
+
+ if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1, me2, thresh)))
+ return cmpcode_to_str(c);
+
+ return NULL;
}
+static void mesh_ensure_tesselation_customdata(Mesh *me)
+{
+ int tottex, totcol;
+
+ tottex = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ totcol = CustomData_number_of_layers(&me->fdata, CD_MCOL);
+
+ if (tottex != CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY) ||
+ totcol != CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL))
+ {
+ CustomData_free(&me->fdata, me->totface);
+
+ me->mface = NULL;
+ me->mtface = NULL;
+ me->mcol = NULL;
+ me->totface = 0;
+
+ memset(&me->fdata, 0, sizeof(&me->fdata));
+
+ CustomData_from_bmeshpoly(&me->fdata, &me->pdata, &me->ldata, me->totface);
+ printf("Warning! Tesselation uvs or vcol data got out of sync, had to reset!\n");
+ }
+}
+
+/*this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or
+ mloopcol and mcol) have the same relative active/render/clone/mask indices.*/
+static void mesh_update_linked_customdata(Mesh *me)
+{
+ int act;
+
+ if (me->edit_btmesh)
+ BMEdit_UpdateLinkedCustomData(me->edit_btmesh);
+
+ mesh_ensure_tesselation_customdata(me);
+
+ if (CustomData_has_layer(&me->pdata, CD_MTEXPOLY)) {
+ act = CustomData_get_active_layer(&me->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, act);
+ CustomData_set_layer_active(&me->fdata, CD_MTFACE, act);
+
+ act = CustomData_get_render_layer(&me->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_render(&me->ldata, CD_MLOOPUV, act);
+ CustomData_set_layer_render(&me->fdata, CD_MTFACE, act);
+
+ act = CustomData_get_clone_layer(&me->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_clone(&me->ldata, CD_MLOOPUV, act);
+ CustomData_set_layer_clone(&me->fdata, CD_MTFACE, act);
+
+ act = CustomData_get_stencil_layer(&me->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_stencil(&me->ldata, CD_MLOOPUV, act);
+ CustomData_set_layer_stencil(&me->fdata, CD_MTFACE, act);
+ }
+
+ if (CustomData_has_layer(&me->ldata, CD_MLOOPCOL)) {
+ act = CustomData_get_active_layer(&me->ldata, CD_MLOOPCOL);
+ CustomData_set_layer_active(&me->fdata, CD_MCOL, act);
+
+ act = CustomData_get_render_layer(&me->ldata, CD_MLOOPCOL);
+ CustomData_set_layer_render(&me->fdata, CD_MCOL, act);
+
+ act = CustomData_get_clone_layer(&me->ldata, CD_MLOOPCOL);
+ CustomData_set_layer_clone(&me->fdata, CD_MCOL, act);
+
+ act = CustomData_get_stencil_layer(&me->ldata, CD_MLOOPCOL);
+ CustomData_set_layer_stencil(&me->fdata, CD_MCOL, act);
+ }
+}
void mesh_update_customdata_pointers(Mesh *me)
{
+ mesh_update_linked_customdata(me);
+
me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
me->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT);
me->msticky = CustomData_get_layer(&me->vdata, CD_MSTICKY);
@@ -86,6 +385,13 @@ void mesh_update_customdata_pointers(Mesh *me)
me->mface = CustomData_get_layer(&me->fdata, CD_MFACE);
me->mcol = CustomData_get_layer(&me->fdata, CD_MCOL);
me->mtface = CustomData_get_layer(&me->fdata, CD_MTFACE);
+
+ me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY);
+ me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP);
+
+ me->mtpoly = CustomData_get_layer(&me->pdata, CD_MTEXPOLY);
+ me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
+ me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
}
/* Note: unlinking is called when me->id.us is 0, question remains how
@@ -116,9 +422,10 @@ void unlink_mesh(Mesh *me)
/* do not free mesh itself */
-void free_mesh(Mesh *me)
+void free_mesh(Mesh *me, int unlink)
{
- unlink_mesh(me);
+ if (unlink)
+ unlink_mesh(me);
if(me->pv) {
if(me->pv->vert_map) MEM_freeN(me->pv->vert_map);
@@ -134,7 +441,9 @@ void free_mesh(Mesh *me)
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
-
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
+
if(me->adt) {
BKE_free_animdata(&me->id);
me->adt= NULL;
@@ -144,7 +453,7 @@ void free_mesh(Mesh *me)
if(me->bb) MEM_freeN(me->bb);
if(me->mselect) MEM_freeN(me->mselect);
- if(me->edit_mesh) MEM_freeN(me->edit_mesh);
+ if(me->edit_btmesh) MEM_freeN(me->edit_btmesh);
}
void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount)
@@ -159,7 +468,7 @@ void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount)
for (i=0; i<copycount; i++){
if (src[i].dw){
- dst[i].dw = MEM_callocN (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight");
+ dst[i].dw = BLI_cellalloc_calloc (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight");
memcpy (dst[i].dw, src[i].dw, sizeof (MDeformWeight)*src[i].totweight);
}
}
@@ -178,7 +487,7 @@ void free_dverts(MDeformVert *dvert, int totvert)
/* Free any special data from the verts */
for (i=0; i<totvert; i++){
- if (dvert[i].dw) MEM_freeN (dvert[i].dw);
+ if (dvert[i].dw) BLI_cellalloc_free (dvert[i].dw);
}
MEM_freeN (dvert);
}
@@ -203,6 +512,7 @@ Mesh *copy_mesh(Mesh *me)
{
Mesh *men;
MTFace *tface;
+ MTexPoly *txface;
int a, i;
men= copy_libblock(me);
@@ -216,6 +526,8 @@ Mesh *copy_mesh(Mesh *me)
CustomData_copy(&me->vdata, &men->vdata, CD_MASK_MESH, CD_DUPLICATE, men->totvert);
CustomData_copy(&me->edata, &men->edata, CD_MASK_MESH, CD_DUPLICATE, men->totedge);
CustomData_copy(&me->fdata, &men->fdata, CD_MASK_MESH, CD_DUPLICATE, men->totface);
+ CustomData_copy(&me->ldata, &men->ldata, CD_MASK_MESH, CD_DUPLICATE, men->totloop);
+ CustomData_copy(&me->pdata, &men->pdata, CD_MASK_MESH, CD_DUPLICATE, men->totpoly);
mesh_update_customdata_pointers(men);
/* ensure indirect linked data becomes lib-extern */
@@ -228,9 +540,19 @@ Mesh *copy_mesh(Mesh *me)
id_lib_extern((ID*)tface->tpage);
}
}
-
+
+ for(i=0; i<me->pdata.totlayer; i++) {
+ if(me->pdata.layers[i].type == CD_MTEXPOLY) {
+ txface= (MTexPoly*)me->pdata.layers[i].data;
+
+ for(a=0; a<me->totpoly; a++, txface++)
+ if(txface->tpage)
+ id_lib_extern((ID*)txface->tpage);
+ }
+ }
+
men->mselect= NULL;
- men->edit_mesh= NULL;
+ men->edit_btmesh= NULL;
men->pv= NULL; /* looks like this is no-longer supported but NULL just incase */
men->bb= MEM_dupallocN(men->bb);
@@ -241,27 +563,71 @@ Mesh *copy_mesh(Mesh *me)
return men;
}
-static void expand_local_mesh(Mesh *me)
+BMesh *BKE_mesh_to_bmesh(Mesh *me, Object *ob)
{
- id_lib_extern((ID *)me->texcomesh);
+ BMesh *bm;
+ int allocsize[4] = {512,512,2048,512};
- if(me->mtface) {
- MTFace *tface;
- int a, i;
+ bm = BM_Make_Mesh(ob, allocsize);
- for(i=0; i<me->fdata.totlayer; i++) {
- if(me->fdata.layers[i].type == CD_MTFACE) {
- tface= (MTFace*)me->fdata.layers[i].data;
+ BMO_CallOpf(bm, "mesh_to_bmesh mesh=%p object=%p set_shapekey=%i", me, ob, 1);
- for(a=0; a<me->totface; a++, tface++) {
- if(tface->tpage) {
- id_lib_extern((ID *)tface->tpage);
+ return bm;
+}
+
+static void make_local_tface(Main *bmain, Mesh *me)
+{
+ MTFace *tface;
+ MTexPoly *txface;
+ Image *ima;
+ int a, i;
+
+ for(i=0; i<me->pdata.totlayer; i++) {
+ if(me->pdata.layers[i].type == CD_MTEXPOLY) {
+ txface= (MTexPoly*)me->fdata.layers[i].data;
+
+ for(a=0; a<me->totpoly; a++, txface++) {
+ /* special case: ima always local immediately */
+ if(txface->tpage) {
+ ima= txface->tpage;
+ if(ima->id.lib) {
+ ima->id.lib= 0;
+ ima->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)ima, 0);
}
}
}
}
}
+ for(i=0; i<me->fdata.totlayer; i++) {
+ if(me->fdata.layers[i].type == CD_MTFACE) {
+ tface= (MTFace*)me->fdata.layers[i].data;
+
+ for(a=0; a<me->totface; a++, tface++) {
+ /* special case: ima always local immediately */
+ if(tface->tpage) {
+ ima= tface->tpage;
+ if(ima->id.lib) {
+ ima->id.lib= NULL;
+ ima->id.flag= LIB_LOCAL;
+ new_id(&bmain->image, (ID *)ima, NULL);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void expand_local_mesh(Main *bmain, Mesh *me)
+{
+ id_lib_extern((ID *)me->texcomesh);
+
+ if(me->mtface) {
+ /* why is this an exception? - should not really make local when extern'ing - campbell */
+ make_local_tface(bmain, me);
+ }
+
if(me->mat) {
extern_local_matarar(me->mat, me->totcol);
}
@@ -280,8 +646,11 @@ void make_local_mesh(Mesh *me)
if(me->id.lib==NULL) return;
if(me->id.us==1) {
- id_clear_lib_data(&bmain->mesh, (ID *)me);
- expand_local_mesh(me);
+ me->id.lib= NULL;
+ me->id.flag= LIB_LOCAL;
+
+ new_id(&bmain->mesh, (ID *)me, NULL);
+ expand_local_mesh(bmain, me);
return;
}
@@ -293,8 +662,11 @@ void make_local_mesh(Mesh *me)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->mesh, (ID *)me);
- expand_local_mesh(me);
+ me->id.lib= NULL;
+ me->id.flag= LIB_LOCAL;
+
+ new_id(&bmain->mesh, (ID *)me, NULL);
+ expand_local_mesh(bmain, me);
}
else if(local && lib) {
Mesh *men= copy_mesh(me);
@@ -576,13 +948,17 @@ static void mfaces_strip_loose(MFace *mface, int *totface)
}
/* Create edges based on known verts and faces */
-static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, int UNUSED(totvert), int totface,
+static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, MLoop *allloop,
+ MPoly *allpoly, int UNUSED(totvert), int totface, int UNUSED(totloop), int totpoly,
int old, MEdge **alledge, int *_totedge)
{
+ MPoly *mpoly;
+ MLoop *mloop;
MFace *mface;
MEdge *medge;
+ EdgeHash *hash = BLI_edgehash_new();
struct edgesort *edsort, *ed;
- int a, totedge=0, final=0;
+ int a, b, totedge=0, final=0;
/* we put all edges in array, sort them, and detect doubles that way */
@@ -654,6 +1030,26 @@ static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, int UNUSED(
medge->flag |= ME_EDGERENDER;
MEM_freeN(edsort);
+
+ /*set edge members of mloops*/
+ medge= *alledge;
+ for (a=0; a<*_totedge; a++, medge++) {
+ BLI_edgehash_insert(hash, medge->v1, medge->v2, SET_INT_IN_POINTER(a));
+ }
+
+ mpoly = allpoly;
+ for (a=0; a<totpoly; a++, mpoly++) {
+ mloop = allloop + mpoly->loopstart;
+ for (b=0; b<mpoly->totloop; b++) {
+ int v1, v2;
+
+ v1 = mloop[b].v;
+ v2 = mloop[(b+1)%mpoly->totloop].v;
+ mloop[b].e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(hash, v1, v2));
+ }
+ }
+
+ BLI_edgehash_free(hash, NULL);
}
void make_edges(Mesh *me, int old)
@@ -661,7 +1057,7 @@ void make_edges(Mesh *me, int old)
MEdge *medge;
int totedge=0;
- make_edges_mdata(me->mvert, me->mface, me->totvert, me->totface, old, &medge, &totedge);
+ make_edges_mdata(me->mvert, me->mface, me->mloop, me->mpoly, me->totvert, me->totface, me->totloop, me->totpoly, old, &medge, &totedge);
if(totedge==0) {
/* flag that mesh has edges */
me->medge = medge;
@@ -757,31 +1153,37 @@ void mball_to_mesh(ListBase *lb, Mesh *me)
}
make_edges(me, 0); // all edges
- }
+ convert_mfaces_to_mpolys(me);
+ }
}
/* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
/* return non-zero on error */
int nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert,
- MEdge **alledge, int *totedge, MFace **allface, int *totface)
+ MEdge **alledge, int *totedge, MFace **allface, MLoop **allloop, MPoly **allpoly,
+ int *totface, int *totloop, int *totpoly)
{
return nurbs_to_mdata_customdb(ob, &ob->disp,
- allvert, totvert, alledge, totedge, allface, totface);
+ allvert, totvert, alledge, totedge, allface, allloop, allpoly, totface, totloop, totpoly);
}
/* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
/* use specified dispbase */
int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int *_totvert,
- MEdge **alledge, int *_totedge, MFace **allface, int *_totface)
+ MEdge **alledge, int *_totedge, MFace **allface, MLoop **allloop, MPoly **allpoly,
+ int *_totface, int *_totloop, int *_totpoly)
{
DispList *dl;
Curve *cu;
MVert *mvert;
MFace *mface;
+ MPoly *mpoly;
+ MLoop *mloop;
float *data;
int a, b, ofs, vertcount, startvert, totvert=0, totvlak=0;
int p1, p2, p3, p4, *index;
int conv_polys= 0;
+ int i, j;
cu= ob->data;
@@ -820,7 +1222,9 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int
*allvert= mvert= MEM_callocN(sizeof (MVert) * totvert, "nurbs_init mvert");
*allface= mface= MEM_callocN(sizeof (MFace) * totvlak, "nurbs_init mface");
-
+ *allloop = mloop = MEM_callocN(sizeof(MLoop) * totvlak * 4, "nurbs_init mloop");
+ *allpoly = mpoly = MEM_callocN(sizeof(MPoly) * totvlak * 4, "nurbs_init mloop");
+
/* verts and faces */
vertcount= 0;
@@ -958,11 +1362,35 @@ int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int
dl= dl->next;
}
-
+
+ mface= *allface;
+ j = 0;
+ for (i=0; i<totvert; i++, mpoly++, mface++) {
+ int k;
+
+ if (!mface->v3) {
+ mpoly--;
+ i--;
+ continue;
+ }
+
+ if (mface >= *allface + totvlak)
+ break;
+
+ mpoly->flag |= mface->flag & ME_SMOOTH;
+ mpoly->loopstart= j;
+ mpoly->totloop= mface->v4 ? 4 : 3;
+ for (k=0; k<mpoly->totloop; k++, mloop++, j++) {
+ mloop->v = (&mface->v1)[k];
+ }
+ }
+
+ *_totpoly= i;
+ *_totloop= j;
*_totvert= totvert;
*_totface= totvlak;
- make_edges_mdata(*allvert, *allface, totvert, totvlak, 0, alledge, _totedge);
+ make_edges_mdata(*allvert, *allface, *allloop, *allpoly, totvert, totvlak, *_totloop, *_totpoly, 0, alledge, _totedge);
mfaces_strip_loose(*allface, _totface);
return 0;
@@ -979,12 +1407,14 @@ void nurbs_to_mesh(Object *ob)
MVert *allvert= NULL;
MEdge *alledge= NULL;
MFace *allface= NULL;
- int totvert, totedge, totface;
+ MLoop *allloop = NULL;
+ MPoly *allpoly = NULL;
+ int totvert, totedge, totface, totloop, totpoly;
cu= ob->data;
if (dm == NULL) {
- if (nurbs_to_mdata (ob, &allvert, &totvert, &alledge, &totedge, &allface, &totface) != 0) {
+ if (nurbs_to_mdata (ob, &allvert, &totvert, &alledge, &totedge, &allface, &allloop, &allpoly, &totface, &totloop, &totpoly) != 0) {
/* Error initializing */
return;
}
@@ -994,15 +1424,19 @@ void nurbs_to_mesh(Object *ob)
me->totvert= totvert;
me->totface= totface;
me->totedge= totedge;
+ me->totloop = totloop;
+ me->totpoly = totpoly;
me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, allvert, me->totvert);
- me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, allface, me->totface);
me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, alledge, me->totedge);
+ me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, allface, me->totface);
+ me->mloop= CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, allloop, me->totloop);
+ me->mpoly= CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, allpoly, me->totpoly);
- mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+ mesh_calc_normals(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL, NULL, 0, NULL, NULL);
} else {
me= add_mesh("Mesh");
- DM_to_mesh(dm, me);
+ DM_to_mesh(dm, me, ob);
}
me->totcol= cu->totcol;
@@ -1063,10 +1497,10 @@ void mesh_to_curve(Scene *scene, Object *ob)
MVert *mverts= dm->getVertArray(dm);
MEdge *med, *medge= dm->getEdgeArray(dm);
- MFace *mf, *mface= dm->getFaceArray(dm);
+ MFace *mf, *mface= dm->getTessFaceArray(dm);
int totedge = dm->getNumEdges(dm);
- int totface = dm->getNumFaces(dm);
+ int totface = dm->getNumTessFaces(dm);
int totedges = 0;
int i, needsFree = 0;
@@ -1229,10 +1663,16 @@ void mesh_to_curve(Scene *scene, Object *ob)
void mesh_delete_material_index(Mesh *me, short index)
{
- MFace *mf;
int i;
- for (i=0, mf=me->mface; i<me->totface; i++, mf++) {
+ for (i=0; i<me->totpoly; i++) {
+ MPoly *mp = &((MPoly*) me->mpoly)[i];
+ if (mp->mat_nr && mp->mat_nr>=index)
+ mp->mat_nr--;
+ }
+
+ for (i=0; i<me->totface; i++) {
+ MFace *mf = &((MFace*) me->mface)[i];
if (mf->mat_nr && mf->mat_nr>=index)
mf->mat_nr--;
}
@@ -1243,6 +1683,16 @@ void mesh_set_smooth_flag(Object *meshOb, int enableSmooth)
Mesh *me = meshOb->data;
int i;
+ for (i=0; i<me->totpoly; i++) {
+ MPoly *mp = &((MPoly*) me->mpoly)[i];
+
+ if (enableSmooth) {
+ mp->flag |= ME_SMOOTH;
+ } else {
+ mp->flag &= ~ME_SMOOTH;
+ }
+ }
+
for (i=0; i<me->totface; i++) {
MFace *mf = &((MFace*) me->mface)[i];
@@ -1253,10 +1703,98 @@ void mesh_set_smooth_flag(Object *meshOb, int enableSmooth)
}
}
- mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+ mesh_calc_normals(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop,
+ me->totpoly, NULL, NULL, 0, NULL, NULL);
}
-void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*faceNors_r)[3])
+void mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys,
+ int UNUSED(numLoops), int numPolys, float (*polyNors_r)[3], MFace *mfaces, int numFaces,
+ int *origIndexFace, float (*faceNors_r)[3])
+{
+ float (*pnors)[3] = polyNors_r, (*fnors)[3] = faceNors_r;
+ float (*tnorms)[3], (*edgevecbuf)[3];
+ float **vertcos = NULL, **vertnos = NULL;
+ BLI_array_declare(vertcos);
+ BLI_array_declare(vertnos);
+ int i, j, maxPolyVerts = 0;
+ MFace *mf;
+ MPoly *mp;
+ MLoop *ml;
+
+ if (numPolys == 0) {
+ return;
+ }
+
+ mp = mpolys;
+ for (i=0; i<numPolys; i++, mp++) {
+ maxPolyVerts = MAX2(mp->totloop, maxPolyVerts);
+ }
+
+ if (maxPolyVerts == 0) {
+ return;
+ }
+
+ /*first go through and calculate normals for all the polys*/
+ edgevecbuf = MEM_callocN(sizeof(float)*3*maxPolyVerts, "edgevecbuf mesh.c");
+ tnorms = MEM_callocN(sizeof(float)*3*numVerts, "tnorms mesh.c");
+ if (!pnors)
+ pnors = MEM_callocN(sizeof(float)*3*numPolys, "poly_nors mesh.c");
+ if (!fnors)
+ fnors = MEM_callocN(sizeof(float)*3*numFaces, "face nors mesh.c");
+
+ mp = mpolys;
+ for (i=0; i<numPolys; i++, mp++) {
+ mesh_calc_poly_normal(mp, mloop+mp->loopstart, mverts, pnors[i]);
+ ml = mloop + mp->loopstart;
+
+ BLI_array_empty(vertcos);
+ BLI_array_empty(vertnos);
+ for (j=0; j<mp->totloop; j++) {
+ int vindex = ml[j].v;
+ BLI_array_append(vertcos, mverts[vindex].co);
+ BLI_array_append(vertnos, tnorms[vindex]);
+ }
+
+ accumulate_vertex_normals_poly(vertnos, pnors[i], vertcos, edgevecbuf, mp->totloop);
+ }
+
+ /* following Mesh convention; we use vertex coordinate itself for normal in this case */
+ for(i=0; i<numVerts; i++) {
+ MVert *mv= &mverts[i];
+ float *no= tnorms[i];
+
+ if(normalize_v3(no) == 0.0f)
+ normalize_v3_v3(no, mv->co);
+
+ normal_float_to_short_v3(mv->no, no);
+ }
+
+ if (origIndexFace && fnors==faceNors_r && numFaces) {
+ mf = mfaces;
+ for (i=0; i<numFaces; i++, mf++, origIndexFace++) {
+ if (*origIndexFace < numPolys) {
+ VECCOPY(fnors[i], pnors[*origIndexFace]);
+ } else {
+ /*eek, we're not corrusponding to polys*/
+ printf("error in mesh_calc_normals; tesselation face indices are incorrect. normals may look bad.\n");
+ }
+ }
+ }
+
+ BLI_array_free(vertcos);
+ BLI_array_free(vertnos);
+ MEM_freeN(edgevecbuf);
+ MEM_freeN(tnorms);
+ if (fnors != faceNors_r)
+ MEM_freeN(fnors);
+ if (pnors != polyNors_r)
+ MEM_freeN(pnors);
+
+ fnors = pnors = NULL;
+
+}
+
+void mesh_calc_tessface_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*faceNors_r)[3])
{
float (*tnorms)[3]= MEM_callocN(numVerts*sizeof(*tnorms), "tnorms");
float (*fnors)[3]= (faceNors_r)? faceNors_r: MEM_callocN(sizeof(*fnors)*numFaces, "meshnormals");
@@ -1294,6 +1832,157 @@ void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces,
MEM_freeN(fnors);
}
+
+static void bmesh_corners_to_loops(Mesh *me, int findex, int loopstart, int numTex, int numCol)
+{
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ MFace *mf;
+ int i;
+
+ mf = me->mface + findex;
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_n(&me->fdata, CD_MTFACE, findex, i);
+ texpoly = CustomData_get_n(&me->pdata, CD_MTEXPOLY, findex, i);
+
+ texpoly->tpage = texface->tpage;
+ texpoly->flag = texface->flag;
+ texpoly->transp = texface->transp;
+ texpoly->mode = texface->mode;
+ texpoly->tile = texface->tile;
+ texpoly->unwrap = texface->unwrap;
+
+ mloopuv = CustomData_get_n(&me->ldata, CD_MLOOPUV, loopstart, i);
+ mloopuv->uv[0] = texface->uv[0][0]; mloopuv->uv[1] = texface->uv[0][1]; mloopuv++;
+ mloopuv->uv[0] = texface->uv[1][0]; mloopuv->uv[1] = texface->uv[1][1]; mloopuv++;
+ mloopuv->uv[0] = texface->uv[2][0]; mloopuv->uv[1] = texface->uv[2][1]; mloopuv++;
+
+ if (mf->v4) {
+ mloopuv->uv[0] = texface->uv[3][0]; mloopuv->uv[1] = texface->uv[3][1]; mloopuv++;
+ }
+ }
+
+ for(i=0; i < numCol; i++){
+ mloopcol = CustomData_get_n(&me->ldata, CD_MLOOPCOL, loopstart, i);
+ mcol = CustomData_get_n(&me->fdata, CD_MCOL, findex, i);
+
+ mloopcol->r = mcol[0].r; mloopcol->g = mcol[0].g; mloopcol->b = mcol[0].b; mloopcol->a = mcol[0].a; mloopcol++;
+ mloopcol->r = mcol[1].r; mloopcol->g = mcol[1].g; mloopcol->b = mcol[1].b; mloopcol->a = mcol[1].a; mloopcol++;
+ mloopcol->r = mcol[2].r; mloopcol->g = mcol[2].g; mloopcol->b = mcol[2].b; mloopcol->a = mcol[2].a; mloopcol++;
+ if (mf->v4) {
+ mloopcol->r = mcol[3].r; mloopcol->g = mcol[3].g; mloopcol->b = mcol[3].b; mloopcol->a = mcol[3].a; mloopcol++;
+ }
+ }
+
+ if (CustomData_has_layer(&me->fdata, CD_MDISPS)) {
+ MDisps *ld = CustomData_get(&me->ldata, loopstart, CD_MDISPS);
+ MDisps *fd = CustomData_get(&me->fdata, findex, CD_MDISPS);
+ float (*disps)[3] = fd->disps;
+ int i, tot = mf->v4 ? 4 : 3;
+ int side, corners;
+
+ corners = multires_mdisp_corners(fd);
+
+ if (corners == 0) {
+ /* Empty MDisp layers appear in at least one of the sintel.blend files.
+ Not sure why this happens, but it seems fine to just ignore them here.
+ If corners==0 for a non-empty layer though, something went wrong. */
+ BLI_assert(fd->totdisp == 0);
+ }
+ else {
+ side = sqrt(fd->totdisp / corners);
+
+ for (i=0; i<tot; i++, disps += side*side, ld++) {
+ ld->totdisp = side*side;
+
+ if (ld->disps)
+ BLI_cellalloc_free(ld->disps);
+
+ ld->disps = BLI_cellalloc_calloc(sizeof(float)*3*side*side, "converted loop mdisps");
+ if (fd->disps) {
+ memcpy(ld->disps, disps, sizeof(float)*3*side*side);
+ }
+ }
+ }
+ }
+}
+
+void convert_mfaces_to_mpolys(Mesh *mesh)
+{
+ MFace *mf;
+ MLoop *ml;
+ MPoly *mp;
+ MEdge *me;
+ EdgeHash *eh;
+ int numTex, numCol;
+ int i, j, totloop;
+
+ mesh->totpoly = mesh->totface;
+ mesh->mpoly = MEM_callocN(sizeof(MPoly)*mesh->totpoly, "mpoly converted");
+ CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_ASSIGN, mesh->mpoly, mesh->totpoly);
+
+ numTex = CustomData_number_of_layers(&mesh->fdata, CD_MTFACE);
+ numCol = CustomData_number_of_layers(&mesh->fdata, CD_MCOL);
+
+ totloop = 0;
+ mf = mesh->mface;
+ for (i=0; i<mesh->totface; i++, mf++) {
+ totloop += mf->v4 ? 4 : 3;
+ }
+
+ mesh->totloop = totloop;
+ mesh->mloop = MEM_callocN(sizeof(MLoop)*mesh->totloop, "mloop converted");
+
+ CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_ASSIGN, mesh->mloop, totloop);
+ CustomData_to_bmeshpoly(&mesh->fdata, &mesh->pdata, &mesh->ldata,
+ mesh->totloop, mesh->totpoly);
+
+ eh = BLI_edgehash_new();
+
+ /*build edge hash*/
+ me = mesh->medge;
+ for (i=0; i<mesh->totedge; i++, me++) {
+ BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i));
+ }
+
+ j = 0; /*current loop index*/
+ ml = mesh->mloop;
+ mf = mesh->mface;
+ mp = mesh->mpoly;
+ for (i=0; i<mesh->totface; i++, mf++, mp++) {
+ mp->loopstart = j;
+
+ mp->totloop = mf->v4 ? 4 : 3;
+
+ mp->mat_nr = mf->mat_nr;
+ mp->flag = mf->flag;
+
+ #define ML(v1, v2) {ml->v = mf->v1; ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2)); ml++; j++;}
+
+ ML(v1, v2);
+ ML(v2, v3);
+ if (mf->v4) {
+ ML(v3, v4);
+ ML(v4, v1);
+ } else {
+ ML(v3, v1);
+ }
+
+ #undef ML
+
+ bmesh_corners_to_loops(mesh, i, mp->loopstart, numTex, numCol);
+ }
+
+ /* note, we dont convert FGons at all, these are not even real ngons,
+ * they have their own UV's, colors etc - its more an editing feature. */
+
+ BLI_edgehash_free(eh, NULL);
+}
+
float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3]
{
int i, numVerts = me->totvert;
@@ -1523,6 +2212,288 @@ void mesh_pmv_off(Mesh *me)
}
}
+void mesh_loops_to_tri_corners(CustomData *fdata, CustomData *ldata,
+ CustomData *pdata, int lindex[3], int findex,
+ int polyindex)
+{
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ int i, j, hasWCol = CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL);
+ int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+ int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
+ texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i);
+
+ texface->tpage = texpoly->tpage;
+ texface->flag = texpoly->flag;
+ texface->transp = texpoly->transp;
+ texface->mode = texpoly->mode;
+ texface->tile = texpoly->tile;
+ texface->unwrap = texpoly->unwrap;
+
+ for (j=0; j<3; j++) {
+ mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, lindex[j], i);
+ texface->uv[j][0] = mloopuv->uv[0];
+ texface->uv[j][1] = mloopuv->uv[1];
+ }
+ }
+
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_get_n(fdata, CD_MCOL, findex, i);
+
+ for (j=0; j<3; j++) {
+ mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, lindex[j], i);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
+ }
+
+ if (hasWCol) {
+ mcol = CustomData_get(fdata, findex, CD_WEIGHT_MCOL);
+
+ for (j=0; j<3; j++) {
+ mloopcol = CustomData_get(ldata, lindex[j], CD_WEIGHT_MLOOPCOL);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
+ }
+}
+
+/*
+ this function recreates a tesselation.
+ returns number of tesselation faces.
+
+ use_poly_origindex sets whether or not the tesselation faces' origindex
+ layer should point to original poly indices or real poly indices.
+
+ use_face_origindex sets the tesselation faces' origindex layer
+ to point to the tesselation faces themselves, not the polys.
+
+ if both of the above are 0, it'll use the indices of the mpolys of the MPoly
+ data in pdata, and ignore the origindex layer altogether.
+ */
+int mesh_recalcTesselation(CustomData *fdata,
+ CustomData *ldata, CustomData *pdata,
+ MVert *mvert, int totface, int UNUSED(totloop),
+ int totpoly, int use_poly_origindex,
+ int use_face_origindex)
+{
+ MPoly *mp, *mpoly;
+ MLoop *ml, *mloop;
+ MFace *mf = NULL, *mface;
+ BLI_array_declare(mf);
+ EditVert *v, *lastv, *firstv;
+ EditFace *f;
+ BLI_array_declare(origIndex);
+ int i, j, k, lindex[4], *origIndex = NULL, *polyorigIndex;
+ int numTex, numCol;
+
+ mpoly = CustomData_get_layer(pdata, CD_MPOLY);
+ mloop = CustomData_get_layer(ldata, CD_MLOOP);
+
+ numTex = CustomData_number_of_layers(ldata, CD_MLOOPUV);
+ numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+
+ k = 0;
+ mp = mpoly;
+ polyorigIndex = use_poly_origindex? CustomData_get_layer(pdata, CD_ORIGINDEX) : NULL;
+ for (i=0; i<totpoly; i++, mp++) {
+ if (mp->totloop > 2) {
+ ml = mloop + mp->loopstart;
+
+ BLI_begin_edgefill();
+ firstv = NULL;
+ lastv = NULL;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ v = BLI_addfillvert(mvert[ml->v].co);
+ if (polyorigIndex && use_poly_origindex)
+ v->hash = polyorigIndex[i];
+ else
+ v->hash = i;
+
+ v->keyindex = mp->loopstart + j;
+
+ if (lastv)
+ BLI_addfilledge(lastv, v);
+
+ if (!firstv)
+ firstv = v;
+ lastv = v;
+ }
+ BLI_addfilledge(lastv, firstv);
+
+ BLI_edgefill(2);
+ for (f=fillfacebase.first; f; f=f->next) {
+ BLI_array_growone(mf);
+ BLI_array_growone(origIndex);
+
+ /*these are loop indices, they'll be transformed
+ into vert indices later.*/
+ mf[k].v1 = f->v1->keyindex;
+ mf[k].v2 = f->v2->keyindex;
+ mf[k].v3 = f->v3->keyindex;
+
+ /*put poly index in mf->v4*/
+ mf[k].v4 = f->v1->hash;
+
+ mf[k].mat_nr = mp->mat_nr;
+ mf[k].flag = mp->flag;
+ origIndex[k] = use_face_origindex ? k : f->v1->hash;
+
+ k++;
+ }
+
+ BLI_end_edgefill();
+ }
+ }
+
+ CustomData_free(fdata, totface);
+ memset(fdata, 0, sizeof(CustomData));
+ totface = k;
+
+ CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mf, totface);
+ CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, origIndex, totface);
+ CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
+
+ mface = mf;
+ for (i=0; i<totface; i++, mf++) {
+ /*sort loop indices to ensure winding is correct*/
+ if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2);
+ if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3);
+ if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2);
+
+ if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2);
+ if (mf->v2 > mf->v3) SWAP(int, mf->v2, mf->v3);
+ if (mf->v1 > mf->v2) SWAP(int, mf->v1, mf->v2);
+
+ lindex[0] = mf->v1;
+ lindex[1] = mf->v2;
+ lindex[2] = mf->v3;
+
+ /*transform loop indices to vert indices*/
+ mf->v1 = mloop[mf->v1].v;
+ mf->v2 = mloop[mf->v2].v;
+ mf->v3 = mloop[mf->v3].v;
+
+ mesh_loops_to_tri_corners(fdata, ldata, pdata,
+ lindex, i, mf->v4);
+
+ mf->v4 = 0;
+ }
+
+ return totface;
+}
+
+/*
+ * COMPUTE POLY NORMAL
+ *
+ * Computes the normal of a planar
+ * polygon See Graphics Gems for
+ * computing newell normal.
+ *
+*/
+static void mesh_calc_ngon_normal(MPoly *mpoly, MLoop *loopstart,
+ MVert *mvert, float *normal)
+{
+
+ MVert *v1, *v2, *v3;
+ double u[3], v[3], w[3];
+ double n[3] = {0.0, 0.0, 0.0}, l;
+ int i;
+
+ for(i = 0; i < mpoly->totloop; i++){
+ v1 = mvert + loopstart[i].v;
+ v2 = mvert + loopstart[(i+1)%mpoly->totloop].v;
+ v3 = mvert + loopstart[(i+2)%mpoly->totloop].v;
+
+ VECCOPY(u, v1->co);
+ VECCOPY(v, v2->co);
+ VECCOPY(w, v3->co);
+
+ /*this fixes some weird numerical error*/
+ if (i==0) {
+ u[0] += 0.0001f;
+ u[1] += 0.0001f;
+ u[2] += 0.0001f;
+ }
+
+ /* newell's method
+
+ so thats?:
+ (a[1] - b[1]) * (a[2] + b[2]);
+ a[1]*b[2] - b[1]*a[2] - b[1]*b[2] + a[1]*a[2]
+
+ odd. half of that is the cross product. . .what's the
+ other half?
+
+ also could be like a[1]*(b[2] + a[2]) - b[1]*(a[2] - b[2])
+ */
+
+ n[0] += (u[1] - v[1]) * (u[2] + v[2]);
+ n[1] += (u[2] - v[2]) * (u[0] + v[0]);
+ n[2] += (u[0] - v[0]) * (u[1] + v[1]);
+ }
+
+ l = n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+ l = sqrt(l);
+
+ if (l == 0.0) {
+ normal[0] = 0.0f;
+ normal[1] = 0.0f;
+ normal[2] = 1.0f;
+
+ return;
+ } else l = 1.0f / l;
+
+ n[0] *= l;
+ n[1] *= l;
+ n[2] *= l;
+
+ normal[0] = (float) n[0];
+ normal[1] = (float) n[1];
+ normal[2] = (float) n[2];
+
+}
+
+void mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart,
+ MVert *mvarray, float *no)
+{
+ if(mpoly->totloop > 4) {
+ mesh_calc_ngon_normal(mpoly, loopstart, mvarray, no);
+ }
+ else if(mpoly->totloop == 3){
+ MVert *v1, *v2, *v3;
+
+ v1 = mvarray + (loopstart++)->v;
+ v2 = mvarray + (loopstart++)->v;
+ v3 = mvarray + loopstart->v;
+ normal_tri_v3( no,v1->co, v2->co, v3->co);
+ }
+ else if(mpoly->totloop == 4){
+ MVert *v1, *v2, *v3, *v4;
+
+ v1 = mvarray + (loopstart++)->v;
+ v2 = mvarray + (loopstart++)->v;
+ v3 = mvarray + (loopstart++)->v;
+ v4 = mvarray + loopstart->v;
+ normal_quad_v3( no,v1->co, v2->co, v3->co, v4->co);
+ }
+ else{ /*horrible, two sided face!*/
+ no[0] = 0.0;
+ no[1] = 0.0;
+ no[2] = 1.0;
+ }
+}
+
/* basic vertex data functions */
int minmax_mesh(Mesh *me, float min[3], float max[3])
{
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index 0dac4b8cd80..b3a9bf98d37 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -115,10 +115,9 @@ static int search_face_cmp(const void *v1, const void *v2)
}
-#define PRINT if(do_verbose) printf
-
int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), unsigned int totvert, MEdge *medges, unsigned int totedge, MFace *mfaces, unsigned int totface, const short do_verbose, const short do_fixes)
{
+# define PRINT if(do_verbose) printf
# define REMOVE_EDGE_TAG(_med) { _med->v2= _med->v1; do_edge_free= 1; }
# define REMOVE_FACE_TAG(_mf) { _mf->v3=0; do_face_free= 1; }
@@ -283,6 +282,7 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), unsigned int totve
PRINT("BKE_mesh_validate: finished\n\n");
+# undef PRINT
# undef REMOVE_EDGE_TAG
# undef REMOVE_FACE_TAG
@@ -303,62 +303,17 @@ int BKE_mesh_validate_arrays(Mesh *me, MVert *UNUSED(mverts), unsigned int totve
return (do_face_free || do_edge_free || do_edge_recalc);
}
-static int mesh_validate_customdata(CustomData *data, short do_verbose, const short do_fixes)
-{
- int i= 0, has_fixes= 0;
-
- while(i<data->totlayer) {
- CustomDataLayer *layer= &data->layers[i];
- int mask= 1 << layer->type;
- int ok= 1;
-
- if((mask&CD_MASK_MESH)==0) {
- PRINT("CustomDataLayer type %d which isn't in CD_MASK_MESH is stored in Mehs structure\n", layer->type);
-
- if(do_fixes) {
- CustomData_free_layer(data, layer->type, 0, i);
- ok= 0;
- has_fixes= 1;
- }
- }
-
- if(ok)
- i++;
- }
-
- return has_fixes;
-}
-
-#undef PRINT
-
-int BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata, CustomData *fdata, short do_verbose, const short do_fixes)
-{
- int vfixed= 0, efixed= 0, ffixed= 0;
-
- vfixed= mesh_validate_customdata(vdata, do_verbose, do_fixes);
- efixed= mesh_validate_customdata(edata, do_verbose, do_fixes);
- ffixed= mesh_validate_customdata(fdata, do_verbose, do_fixes);
-
- return vfixed || efixed || ffixed;
-}
-
int BKE_mesh_validate(Mesh *me, int do_verbose)
{
- int layers_fixed= 0, arrays_fixed= 0;
-
if(do_verbose) {
printf("MESH: %s\n", me->id.name+2);
}
-
- layers_fixed= BKE_mesh_validate_all_customdata(&me->vdata, &me->edata, &me->fdata, do_verbose, TRUE);
- arrays_fixed= BKE_mesh_validate_arrays(me, me->mvert, me->totvert, me->medge, me->totedge, me->mface, me->totface, do_verbose, TRUE);
-
- return layers_fixed || arrays_fixed;
+ return BKE_mesh_validate_arrays(me, me->mvert, me->totvert, me->medge, me->totedge, me->mface, me->totface, do_verbose, TRUE);
}
int BKE_mesh_validate_dm(DerivedMesh *dm)
{
- return BKE_mesh_validate_arrays(NULL, dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getFaceArray(dm), dm->getNumFaces(dm), TRUE, FALSE);
+ return BKE_mesh_validate_arrays(NULL, dm->getVertArray(dm), dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), TRUE, FALSE);
}
void BKE_mesh_calc_edges(Mesh *mesh, int update)
@@ -369,6 +324,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update)
MEdge *med, *med_orig;
EdgeHash *eh = BLI_edgehash_new();
int i, totedge, totface = mesh->totface;
+ int med_index;
if(mesh->totedge==0)
update= 0;
@@ -381,20 +337,37 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update)
BLI_edgehash_insert(eh, med->v1, med->v2, med);
}
- for (i = 0; i < totface; i++, mf++) {
- if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
- BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
- if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
- BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
-
- if (mf->v4) {
- if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
- BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
- if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
- BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
- } else {
- if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
- BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
+ if(mesh->totpoly) {
+ /* mesh loops (bmesh only) */
+ MPoly *mp= mesh->mpoly;
+ for(i=0; i < mesh->totpoly; i++, mp++) {
+ MLoop *l= &mesh->mloop[mp->loopstart];
+ int j, l_prev= (l + (mp->totloop-1))->v;
+ for (j=0; j < mp->totloop; j++, l++) {
+ if (!BLI_edgehash_haskey(eh, l_prev, l->v)) {
+ BLI_edgehash_insert(eh, l_prev, l->v, NULL);
+ }
+ l_prev= l->v;
+ }
+ }
+ }
+ else {
+ /* regular faces (note, we could remove this for bmesh - campbell) */
+ for (i = 0; i < totface; i++, mf++) {
+ if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
+ BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
+ if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
+ BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
+
+ if (mf->v4) {
+ if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
+ BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
+ if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
+ BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
+ } else {
+ if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
+ BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
+ }
}
}
@@ -415,9 +388,29 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update)
BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
med->flag = ME_EDGEDRAW|ME_EDGERENDER|SELECT; /* select for newly created meshes which are selected [#25595] */
}
+
+ /* store the new edge index in the hash value */
+ BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i));
}
BLI_edgehashIterator_free(ehi);
+ if (mesh->totpoly) {
+ /* second pass, iterate through all loops again and assign
+ the newly created edges to them. */
+ MPoly *mp= mesh->mpoly;
+ for(i=0; i < mesh->totpoly; i++, mp++) {
+ MLoop *l= &mesh->mloop[mp->loopstart];
+ MLoop *l_prev= (l + (mp->totloop-1));
+ int j;
+ for (j=0; j < mp->totloop; j++, l++) {
+ /* lookup hashed edge index */
+ med_index = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, l_prev->v, l->v));
+ l_prev->e = med_index;
+ l_prev= l;
+ }
+ }
+ }
+
/* free old CustomData and assign new one */
CustomData_free(&mesh->edata, mesh->totedge);
mesh->edata = edata;
diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c
new file mode 100644
index 00000000000..46e922a35cc
--- /dev/null
+++ b/source/blender/blenkernel/intern/modifiers_bmesh.c
@@ -0,0 +1,220 @@
+/*
+* $Id: modifier_bmesh.c 20831 2009-06-12 14:02:37Z joeedh $
+*
+* ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Joseph Eagar
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+* Modifier stack implementation.
+*
+* BKE_modifier.h contains the function prototypes for this file.
+*
+*/
+
+#include "string.h"
+#include "stdarg.h"
+#include "math.h"
+#include "float.h"
+#include "ctype.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_kdopbvh.h"
+#include "BLI_kdtree.h"
+#include "BLI_linklist.h"
+#include "BLI_rand.h"
+#include "BLI_edgehash.h"
+#include "BLI_ghash.h"
+#include "BLI_memarena.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_cloth_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+
+#include "BLI_editVert.h"
+#include "BLI_array.h"
+
+#include "BKE_main.h"
+#include "BKE_anim.h"
+#include "BKE_bmesh.h"
+// XXX #include "BKE_booleanops.h"
+#include "BKE_cloth.h"
+#include "BKE_collision.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_curve.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_displist.h"
+#include "BKE_fluidsim.h"
+#include "BKE_global.h"
+#include "BKE_multires.h"
+#include "BKE_lattice.h"
+#include "BKE_library.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_softbody.h"
+#include "BKE_subsurf.h"
+#include "BKE_texture.h"
+#include "BKE_tessmesh.h"
+
+#include "depsgraph_private.h"
+#include "BKE_deform.h"
+#include "BKE_shrinkwrap.h"
+
+#include "CCGSubSurf.h"
+#include "RE_shader_ext.h"
+#include "LOD_decimation.h"
+
+/*converts a cddm to a BMEditMesh. if existing is non-NULL, the
+ new geometry will be put in there.*/
+BMEditMesh *CDDM_To_BMesh(Object *ob, DerivedMesh *dm, BMEditMesh *existing)
+{
+ int allocsize[4] = {512, 512, 2048, 512};
+ BMesh *bm, bmold; /*bmold is for storing old customdata layout*/
+ BMEditMesh *em = existing;
+ MVert *mv, *mvert;
+ MEdge *me, *medge;
+ MPoly *mpoly, *mp;
+ MLoop *mloop, *ml;
+ BMVert *v, **vtable, **verts=NULL;
+ BMEdge *e, **etable, **edges=NULL;
+ BMFace *f;
+ BMIter liter;
+ BLI_array_declare(verts);
+ BLI_array_declare(edges);
+ int numTex, numCol;
+ int i, j, k, totvert, totedge, totface;
+
+ if (em) bm = em->bm;
+ else bm = BM_Make_Mesh(ob, allocsize);
+
+ bmold = *bm;
+
+ /*merge custom data layout*/
+ CustomData_bmesh_merge(&dm->vertData, &bm->vdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_VERT);
+ CustomData_bmesh_merge(&dm->edgeData, &bm->edata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_EDGE);
+ CustomData_bmesh_merge(&dm->loopData, &bm->ldata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_LOOP);
+ CustomData_bmesh_merge(&dm->polyData, &bm->pdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_FACE);
+
+ /*needed later*/
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ totvert = dm->getNumVerts(dm);
+ totedge = dm->getNumEdges(dm);
+ totface = dm->getNumFaces(dm);
+
+ vtable = MEM_callocN(sizeof(void**)*totvert, "vert table in BMDM_Copy");
+ etable = MEM_callocN(sizeof(void**)*totedge, "edge table in BMDM_Copy");
+
+ /*do verts*/
+ mv = mvert = dm->dupVertArray(dm);
+ for (i=0; i<totvert; i++, mv++) {
+ v = BM_Make_Vert(bm, mv->co, NULL);
+ normal_short_to_float_v3(v->no, mv->no);
+ v->head.flag = MEFlags_To_BMFlags(mv->flag, BM_VERT);
+
+ CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data);
+ vtable[i] = v;
+ }
+ MEM_freeN(mvert);
+
+ /*do edges*/
+ me = medge = dm->dupEdgeArray(dm);
+ for (i=0; i<totedge; i++, me++) {
+ e = BM_Make_Edge(bm, vtable[me->v1], vtable[me->v2], NULL, 0);
+
+ e->head.flag = MEFlags_To_BMFlags(me->flag, BM_EDGE);
+
+ CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data);
+ etable[i] = e;
+ }
+ MEM_freeN(medge);
+
+ /*do faces*/
+ mpoly = mp = dm->getPolyArray(dm);
+ mloop = dm->getLoopArray(dm);
+ for (i=0; i<dm->numPolyData; i++, mp++) {
+ BMLoop *l;
+
+ BLI_array_empty(verts);
+ BLI_array_empty(edges);
+
+ ml = mloop + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ BLI_array_growone(verts);
+ BLI_array_growone(edges);
+
+ verts[j] = vtable[ml->v];
+ edges[j] = etable[ml->e];
+ }
+
+ f = BM_Make_Ngon(bm, verts[0], verts[1], edges, mp->totloop, 0);
+
+ if (!f)
+ continue;
+
+ f->head.flag = MEFlags_To_BMFlags(mp->flag, BM_FACE);
+ f->mat_nr = mp->mat_nr;
+
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ k = mp->loopstart;
+
+ for (j=0; l; l=BMIter_Step(&liter), k++) {
+ CustomData_to_bmesh_block(&dm->loopData, &bm->ldata, k, &l->head.data);
+ }
+
+ CustomData_to_bmesh_block(&dm->polyData, &bm->pdata,
+ i, &f->head.data);
+ }
+
+ MEM_freeN(vtable);
+ MEM_freeN(etable);
+
+ BLI_array_free(verts);
+ BLI_array_free(edges);
+
+ if (!em) em = BMEdit_Create(bm);
+ else BMEdit_RecalcTesselation(em);
+
+ return em;
+}
+
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 6579d7a01f4..94e8f4863a0 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -42,6 +42,7 @@
#include "BLI_pbvh.h"
#include "BLI_editVert.h"
#include "BLI_utildefines.h"
+#include "BLI_cellalloc.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_mesh.h"
@@ -50,6 +51,7 @@
#include "BKE_paint.h"
#include "BKE_scene.h"
#include "BKE_subsurf.h"
+#include "BKE_tessmesh.h"
#include "BKE_object.h"
@@ -64,7 +66,7 @@ static const int multires_grid_tot[] = {0, 4, 9, 25, 81, 289, 1089, 4225, 16641,
static const int multires_side_tot[] = {0, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097};
static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert);
-static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl);
+static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm2, int invert, int add, DMGridData **oldGridData, int totlvl);
DerivedMesh *get_multires_dm(Scene *scene, MultiresModifierData *mmd, Object *ob)
{
@@ -75,7 +77,7 @@ DerivedMesh *get_multires_dm(Scene *scene, MultiresModifierData *mmd, Object *ob
dm = mti->applyModifier(md, ob, tdm, 0, 1);
if (dm == tdm) {
- dm = CDDM_copy(tdm);
+ dm = CDDM_copy(tdm, 0);
}
return dm;
@@ -127,6 +129,9 @@ MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob, int use_fi
static int multires_get_level(Object *ob, MultiresModifierData *mmd, int render)
{
+ if (!ob || !mmd)
+ return 0;
+
if(render)
return (mmd->modifier.scene)? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->renderlvl): mmd->renderlvl;
else if(ob->mode == OB_MODE_SCULPT)
@@ -177,7 +182,7 @@ void multires_force_external_reload(Object *ob)
{
Mesh *me = get_mesh(ob);
- CustomData_external_reload(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
+ CustomData_external_reload(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
multires_force_update(ob);
}
@@ -234,7 +239,7 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm
dm->getVertCos(dm, deformedVerts);
mti->deformVerts(md, ob, dm, deformedVerts, numVerts, 0, 0);
- ndm= CDDM_copy(dm);
+ ndm= CDDM_copy(dm, 0);
CDDM_apply_vert_coords(ndm, deformedVerts);
MEM_freeN(deformedVerts);
@@ -253,26 +258,31 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm
static int get_levels_from_disps(Object *ob)
{
Mesh *me = ob->data;
- MDisps *mdisp;
- int i, totlvl= 0;
-
- mdisp = CustomData_get_layer(&me->fdata, CD_MDISPS);
+ MDisps *mdisp, *md;
+ int i, j, totlvl= 0;
- for(i = 0; i < me->totface; ++i, ++mdisp) {
- int S = me->mface[i].v4 ? 4 : 3;
-
- if(mdisp->totdisp == 0) continue;
-
- while(1) {
- int side = (1 << (totlvl-1)) + 1;
- int lvl_totdisp = side*side*S;
- if(mdisp->totdisp == lvl_totdisp)
- break;
- else if(mdisp->totdisp < lvl_totdisp)
- --totlvl;
- else
- ++totlvl;
+ mdisp = CustomData_get_layer(&me->ldata, CD_MDISPS);
+ for(i = 0; i < me->totpoly; ++i) {
+ int S = me->mpoly[i].totloop;
+
+ md = mdisp + me->mpoly[i].loopstart;
+ for (j=0; j<me->mpoly[i].totloop; j++, md++) {
+ if(md->totdisp == 0) continue;
+
+ while(1) {
+ int side = (1 << (totlvl-1)) + 1;
+ int lvl_totdisp = side*side*S;
+ if(md->totdisp == lvl_totdisp)
+ break;
+ else if(md->totdisp < lvl_totdisp)
+ --totlvl;
+ else
+ ++totlvl;
+
+ }
+
+ break;
}
}
@@ -285,10 +295,10 @@ void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *o
Mesh *me = ob->data;
MDisps *mdisp;
- if(me->edit_mesh)
- mdisp = CustomData_get_layer(&me->edit_mesh->fdata, CD_MDISPS);
+ if(me->edit_btmesh)
+ mdisp = CustomData_get_layer(&me->edit_btmesh->bm->ldata, CD_MDISPS);
else
- mdisp = CustomData_get_layer(&me->fdata, CD_MDISPS);
+ mdisp = CustomData_get_layer(&me->ldata, CD_MDISPS);
if(mdisp) {
mmd->totlvl = get_levels_from_disps(ob);
@@ -300,31 +310,27 @@ void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *o
static void multires_set_tot_mdisps(Mesh *me, int lvl)
{
- MDisps *mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
+ MDisps *mdisps= CustomData_get_layer(&me->ldata, CD_MDISPS);
int i;
if(mdisps) {
- for(i = 0; i < me->totface; i++) {
- if(mdisps[i].totdisp == 0) {
- int nvert = (me->mface[i].v4)? 4: 3;
- mdisps[i].totdisp = multires_grid_tot[lvl]*nvert;
- }
+ for(i = 0; i < me->totloop; i++, mdisps++) {
+ mdisps->totdisp = multires_grid_tot[lvl];
}
}
}
-static void multires_reallocate_mdisps(Mesh *me, MDisps *mdisps, int lvl)
+static void multires_reallocate_mdisps(int totloop, MDisps *mdisps, int lvl)
{
int i;
/* reallocate displacements to be filled in */
- for(i = 0; i < me->totface; ++i) {
- int nvert = (me->mface[i].v4)? 4: 3;
- int totdisp = multires_grid_tot[lvl]*nvert;
- float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps");
+ for(i = 0; i < totloop; ++i) {
+ int totdisp = multires_grid_tot[lvl];
+ float (*disps)[3] = BLI_cellalloc_calloc(sizeof(float) * 3 * totdisp, "multires disps");
if(mdisps[i].disps)
- MEM_freeN(mdisps[i].disps);
+ BLI_cellalloc_free(mdisps[i].disps);
mdisps[i].disps = disps;
mdisps[i].totdisp = totdisp;
@@ -385,44 +391,43 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
MDisps *mdisps;
multires_set_tot_mdisps(me, mmd->totlvl);
- CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
- mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
+ CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
+ mdisps= CustomData_get_layer(&me->ldata, CD_MDISPS);
multires_force_update(ob);
if(mdisps && levels > 0) {
if(lvl > 0) {
+ /* MLoop *ml = me->mloop; */ /*UNUSED*/
int nsize = multires_side_tot[lvl];
int hsize = multires_side_tot[mmd->totlvl];
- int i;
+ int i, j;
- for(i = 0; i < me->totface; ++i) {
- MDisps *mdisp= &mdisps[i];
- float (*disps)[3], (*ndisps)[3], (*hdisps)[3];
- int nvert = (me->mface[i].v4)? 4: 3;
- int totdisp = multires_grid_tot[lvl]*nvert;
- int S;
+ for(i = 0; i < me->totpoly; ++i) {
+ for (j=0; j<me->mpoly[i].totloop; j++) {
+ MDisps *mdisp= &mdisps[me->mpoly[i].loopstart+j];
+ float (*disps)[3], (*ndisps)[3], (*hdisps)[3];
+ int totdisp = multires_grid_tot[lvl];
- disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps");
+ disps = BLI_cellalloc_calloc(sizeof(float) * 3 * totdisp, "multires disps");
- ndisps = disps;
- hdisps = mdisp->disps;
+ ndisps = disps;
+ hdisps = mdisp->disps;
- for(S = 0; S < nvert; S++) {
multires_copy_grid(ndisps, hdisps, nsize, hsize);
ndisps += nsize*nsize;
hdisps += hsize*hsize;
- }
- MEM_freeN(mdisp->disps);
- mdisp->disps = disps;
- mdisp->totdisp = totdisp;
+ BLI_cellalloc_free(mdisp->disps);
+ mdisp->disps = disps;
+ mdisp->totdisp = totdisp;
+ }
}
}
else {
- CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
- CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
+ CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
+ CustomData_free_layer_active(&me->ldata, CD_MDISPS, me->totloop);
}
}
@@ -438,8 +443,8 @@ void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int dire
MDisps *mdisps;
multires_set_tot_mdisps(me, mmd->totlvl);
- CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
- mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
+ CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
+ mdisps= CustomData_get_layer(&me->ldata, CD_MDISPS);
multires_force_update(ob);
@@ -594,7 +599,7 @@ void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob)
cddm->release(cddm);
/* calc disps */
- multiresModifier_disp_run(dispdm, me, 1, 0, origdm->getGridData(origdm), totlvl);
+ multiresModifier_disp_run(dispdm, me, NULL, 1, 0, origdm->getGridData(origdm), totlvl);
origdm->release(origdm);
dispdm->release(dispdm);
@@ -611,9 +616,9 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl
multires_force_update(ob);
- mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
+ mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
if(!mdisps)
- mdisps = CustomData_add_layer(&me->fdata, CD_MDISPS, CD_DEFAULT, NULL, me->totface);
+ mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS, CD_DEFAULT, NULL, me->totloop);
if(mdisps->disps && !updateblock && totlvl > 1) {
/* upsample */
@@ -658,10 +663,10 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl
ccgSubSurf_updateLevels(ss, lvl, NULL, 0);
/* reallocate displacements */
- multires_reallocate_mdisps(me, mdisps, totlvl);
+ multires_reallocate_mdisps(me->totloop, mdisps, totlvl);
/* compute displacements */
- multiresModifier_disp_run(highdm, me, 1, 0, subGridData, totlvl);
+ multiresModifier_disp_run(highdm, me, NULL, 1, 0, subGridData, totlvl);
/* free */
highdm->release(highdm);
@@ -671,7 +676,7 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl
}
else {
/* only reallocate, nothing to upsample */
- multires_reallocate_mdisps(me, mdisps, totlvl);
+ multires_reallocate_mdisps(me->totloop, mdisps, totlvl);
}
multires_set_tot_level(ob, mmd, totlvl);
@@ -682,7 +687,7 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updat
multires_subdivide(mmd, ob, mmd->totlvl+1, updateblock, simple);
}
-static void grid_tangent(int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3])
+void grid_tangent(int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3])
{
if(axis == 0) {
if(x == gridSize - 1) {
@@ -706,18 +711,30 @@ static void grid_tangent(int gridSize, int index, int x, int y, int axis, DMGrid
}
}
-static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl)
+static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm2, int invert, int add, DMGridData **oldGridData, int totlvl)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)dm;
DMGridData **gridData, **subGridData;
- MFace *mface = me->mface;
- MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
+ MPoly *mpoly = me->mpoly;
+ MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
int *gridOffset;
- int i, /*numGrids,*/ gridSize, dGridSize, dSkip;
-
+ int i, k, /*numGrids,*/ gridSize, dGridSize, dSkip;
+ int totloop, totpoly;
+
+ /*this happens in the dm made by bmesh_set_mdisps_space*/
+ if (dm2 && CustomData_has_layer(&dm2->loopData, CD_MDISPS)) {
+ mpoly = CustomData_get_layer(&dm2->polyData, CD_MPOLY);
+ mdisps = CustomData_get_layer(&dm2->loopData, CD_MDISPS);
+ totloop = dm2->numLoopData;
+ totpoly = dm2->numPolyData;
+ } else {
+ totloop = me->totloop;
+ totpoly = me->totpoly;
+ }
+
if(!mdisps) {
if(invert)
- mdisps = CustomData_add_layer(&me->fdata, CD_MDISPS, CD_DEFAULT, NULL, me->totface);
+ mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS, CD_DEFAULT, NULL, me->totloop);
else
return;
}
@@ -731,23 +748,28 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int
dGridSize = multires_side_tot[totlvl];
dSkip = (dGridSize-1)/(gridSize-1);
- #pragma omp parallel for private(i) if(me->totface*gridSize*gridSize*4 >= CCG_OMP_LIMIT)
- for(i = 0; i < me->totface; ++i) {
- const int numVerts = mface[i].v4 ? 4 : 3;
- MDisps *mdisp = &mdisps[i];
- int S, x, y, gIndex = gridOffset[i];
+ k = 0; /*current loop/mdisp index within the mloop array*/
- /* when adding new faces in edit mode, need to allocate disps */
- if(!mdisp->disps)
- #pragma omp critical
- {
- multires_reallocate_mdisps(me, mdisps, totlvl);
- }
+ #pragma omp parallel for private(i) if(totloop*gridSize*gridSize >= CCG_OMP_LIMIT)
- for(S = 0; S < numVerts; ++S, ++gIndex) {
+ for(i = 0; i < totpoly; ++i) {
+ const int numVerts = mpoly[i].totloop;
+ int S, x, y, gIndex = gridOffset[i];
+
+ for(S = 0; S < numVerts; ++S, ++gIndex, ++k) {
+ MDisps *mdisp = &mdisps[mpoly[i].loopstart+S];
DMGridData *grid = gridData[gIndex];
DMGridData *subgrid = subGridData[gIndex];
- float (*dispgrid)[3] = &mdisp->disps[S*dGridSize*dGridSize];
+ float (*dispgrid)[3] = NULL;
+
+ /* when adding new faces in edit mode, need to allocate disps */
+ if(!mdisp->disps)
+ #pragma omp critical
+ {
+ multires_reallocate_mdisps(totloop, mdisps, totlvl);
+ }
+
+ dispgrid = mdisp->disps;
for(y = 0; y < gridSize; y++) {
for(x = 0; x < gridSize; x++) {
@@ -810,8 +832,8 @@ static void multiresModifier_update(DerivedMesh *dm)
me = ccgdm->multires.ob->data;
mmd = ccgdm->multires.mmd;
multires_set_tot_mdisps(me, mmd->totlvl);
- CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
- mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
+ CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
+ mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
if(mdisps) {
int lvl = ccgdm->multires.lvl;
@@ -825,7 +847,7 @@ static void multiresModifier_update(DerivedMesh *dm)
int i, j, numGrids, highGridSize, lowGridSize;
/* create subsurf DM from original mesh at high level */
- if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform);
+ if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform, 0);
else cddm = CDDM_from_mesh(me, NULL);
DM_set_only_copy(cddm, CD_MASK_BAREMESH);
@@ -868,7 +890,7 @@ static void multiresModifier_update(DerivedMesh *dm)
ccgSubSurf_updateLevels(ss, lvl, NULL, 0);
/* add to displacements */
- multiresModifier_disp_run(highdm, me, 1, 1, subGridData, mmd->totlvl);
+ multiresModifier_disp_run(highdm, me, NULL, 1, 1, subGridData, mmd->totlvl);
/* free */
highdm->release(highdm);
@@ -879,20 +901,141 @@ static void multiresModifier_update(DerivedMesh *dm)
else {
DerivedMesh *cddm, *subdm;
- if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform);
+ if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform, 0);
else cddm = CDDM_from_mesh(me, NULL);
DM_set_only_copy(cddm, CD_MASK_BAREMESH);
subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv);
cddm->release(cddm);
- multiresModifier_disp_run(dm, me, 1, 0, subdm->getGridData(subdm), mmd->totlvl);
+ multiresModifier_disp_run(dm, me, NULL, 1, 0, subdm->getGridData(subdm), mmd->totlvl);
subdm->release(subdm);
}
}
}
+
+void multires_set_space(DerivedMesh *dm, Object *ob, int from, int to)
+{
+ DerivedMesh *ccgdm, *subsurf=NULL;
+ DMGridData **gridData, **subGridData=NULL;
+ MPoly *mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
+ MDisps *mdisps;
+ MultiresModifierData *mmd = get_multires_modifier(NULL, ob, 1);
+ int *gridOffset, totlvl;
+ int i, k, numGrids, gridSize, dGridSize, dSkip;
+
+ if (!mmd)
+ return;
+
+ mdisps = CustomData_get_layer(&dm->loopData, CD_MDISPS);
+
+ if(!mdisps) {
+ goto cleanup;
+ }
+
+ totlvl = mmd->totlvl;
+ ccgdm = multires_dm_create_local(ob, dm, totlvl, totlvl, mmd->simple);
+
+ subsurf = subsurf_dm_create_local(ob, dm, totlvl,
+ mmd->simple, mmd->flags & eMultiresModifierFlag_ControlEdges, mmd->flags & eMultiresModifierFlag_PlainUv);
+
+ numGrids = subsurf->getNumGrids(subsurf);
+ gridSize = subsurf->getGridSize(subsurf);
+ gridData = subsurf->getGridData(subsurf);
+
+ subGridData = MEM_callocN(sizeof(DMGridData*)*numGrids, "subGridData*");
+
+ for(i = 0; i < numGrids; i++) {
+ subGridData[i] = MEM_callocN(sizeof(DMGridData)*gridSize*gridSize, "subGridData");
+ memcpy(subGridData[i], gridData[i], sizeof(DMGridData)*gridSize*gridSize);
+ }
+
+ /*numGrids = ccgdm->dm->getNumGrids((DerivedMesh*)ccgdm);*/ /*UNUSED*/
+ gridSize = ccgdm->getGridSize((DerivedMesh*)ccgdm);
+ gridData = ccgdm->getGridData((DerivedMesh*)ccgdm);
+ gridOffset = ccgdm->getGridOffset((DerivedMesh*)ccgdm);
+
+ dGridSize = multires_side_tot[totlvl];
+ dSkip = (dGridSize-1)/(gridSize-1);
+
+ k = 0; /*current loop/mdisp index within the mloop array*/
+
+ //#pragma omp parallel for private(i) if(dm->numLoopData*gridSize*gridSize >= CCG_OMP_LIMIT)
+
+ for(i = 0; i < dm->numPolyData; ++i) {
+ const int numVerts = mpoly[i].totloop;
+ int S, x, y, gIndex = gridOffset[i];
+
+ for(S = 0; S < numVerts; ++S, ++gIndex, ++k) {
+ MDisps *mdisp = &mdisps[mpoly[i].loopstart+S];
+ /* DMGridData *grid = gridData[gIndex]; */ /* UNUSED */
+ DMGridData *subgrid = subGridData[gIndex];
+ float (*dispgrid)[3] = NULL;
+
+ /* when adding new faces in edit mode, need to allocate disps */
+ if(!mdisp->disps) {
+ mdisp->totdisp = gridSize*gridSize;
+ mdisp->disps = BLI_cellalloc_calloc(sizeof(float)*3*mdisp->totdisp, "disp in multires_set_space");
+ }
+
+ dispgrid = mdisp->disps;
+
+ for(y = 0; y < gridSize; y++) {
+ for(x = 0; x < gridSize; x++) {
+ float *data = dispgrid[dGridSize*y*dSkip + x*dSkip];
+ float *no = subgrid[x + y*gridSize].no;
+ float *co = subgrid[x + y*gridSize].co;
+ float mat[3][3], tx[3], ty[3], dco[3];
+
+ /* construct tangent space matrix */
+ grid_tangent(gridSize, gIndex, x, y, 0, subGridData, tx);
+ normalize_v3(tx);
+
+ grid_tangent(gridSize, gIndex, x, y, 1, subGridData, ty);
+ normalize_v3(ty);
+ column_vectors_to_mat3(mat, tx, ty, no);
+
+ /* convert to absolute coordinates in space */
+ if (from == MULTIRES_SPACE_TANGENT) {
+ mul_v3_m3v3(dco, mat, data);
+ add_v3_v3(dco, co);
+ } else if (from == MULTIRES_SPACE_OBJECT) {
+ add_v3_v3v3(dco, co, data);
+ } else if (from == MULTIRES_SPACE_ABSOLUTE) {
+ copy_v3_v3(dco, data);
+ }
+
+ column_vectors_to_mat3(mat, tx, ty, no);
+
+ /*now, convert to desired displacement type*/
+ if (to == MULTIRES_SPACE_TANGENT) {
+ invert_m3(mat);
+
+ sub_v3_v3(dco, co);
+ mul_v3_m3v3(data, mat, dco);
+ } else if (to == MULTIRES_SPACE_OBJECT) {
+ sub_v3_v3(dco, co);
+ mul_v3_m3v3(data, mat, dco);
+ } else if (to == MULTIRES_SPACE_ABSOLUTE) {
+ copy_v3_v3(data, dco);
+ }
+ }
+ }
+ }
+ }
+
+cleanup:
+ if (subsurf) {
+ subsurf->needsFree = 1;
+ subsurf->release(subsurf);
+ }
+
+ ccgdm->needsFree = 1;
+ ccgdm->release(ccgdm);
+}
+
void multires_stitch_grids(Object *ob)
{
/* utility for smooth brush */
@@ -953,8 +1096,10 @@ DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int loca
}
multires_set_tot_mdisps(me, mmd->totlvl);
- CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
- multiresModifier_disp_run(result, ob->data, 0, 0, subGridData, mmd->totlvl);
+ CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
+
+ /*run displacement*/
+ multiresModifier_disp_run(result, ob->data, dm, 0, 0, subGridData, mmd->totlvl);
for(i = 0; i < numGrids; i++)
MEM_freeN(subGridData[i]);
@@ -973,7 +1118,10 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u,
const int st_max = st - 1;
float urat, vrat, uopp;
float d[4][3], d2[2][3];
-
+
+ if (!disps || isnan(u) || isnan(v))
+ return;
+
if(u < 0)
u = 0;
else if(u >= st)
@@ -1029,7 +1177,7 @@ static void old_mdisps_convert(MFace *mface, MDisps *mdisp)
int x, y, S;
float (*disps)[3], (*out)[3], u = 0.0f, v = 0.0f; /* Quite gcc barking. */
- disps = MEM_callocN(sizeof(float) * 3 * newtotdisp, "multires disps");
+ disps = BLI_cellalloc_calloc(sizeof(float) * 3 * newtotdisp, "multires disps");
out = disps;
for(S = 0; S < nvert; S++) {
@@ -1046,7 +1194,7 @@ static void old_mdisps_convert(MFace *mface, MDisps *mdisp)
}
}
- MEM_freeN(mdisp->disps);
+ BLI_cellalloc_free(mdisp->disps);
mdisp->totdisp= newtotdisp;
mdisp->disps= disps;
@@ -1054,15 +1202,33 @@ static void old_mdisps_convert(MFace *mface, MDisps *mdisp)
void multires_load_old_250(Mesh *me)
{
- MDisps *mdisps;
- int a;
+ MDisps *mdisps, *mdisps2;
+ MFace *mf;
+ int i, j, k;
mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
if(mdisps) {
- for(a=0; a<me->totface; a++)
- if(mdisps[a].totdisp)
- old_mdisps_convert(&me->mface[a], &mdisps[a]);
+ for(i=0; i<me->totface; i++)
+ if(mdisps[i].totdisp)
+ old_mdisps_convert(&me->mface[i], &mdisps[i]);
+
+ CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop);
+ mdisps2 = CustomData_get_layer(&me->ldata, CD_MDISPS);
+
+ k = 0;
+ mf = me->mface;
+ for (i=0; i<me->totface; i++, mf++) {
+ int nvert = mf->v4 ? 4 : 3;
+ int totdisp = mdisps[i].totdisp / nvert;
+
+ for (j=0; j < mf->v4 ? 4 : 3; j++, k++) {
+ mdisps2[k].disps = BLI_cellalloc_calloc(sizeof(float)*3*totdisp, "multires disp in conversion");
+ mdisps2[k].totdisp = totdisp;
+ memcpy(mdisps2[k].disps, mdisps[i].disps + totdisp*j, totdisp);
+ }
+
+ }
}
}
@@ -1587,8 +1753,8 @@ static void multires_sync_levels(Scene *scene, Object *ob, Object *to_ob)
Mesh *me= (Mesh*)ob->data;
- CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
- CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
+ CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
+ CustomData_free_layer_active(&me->ldata, CD_MDISPS, me->totloop);
}
if(!mmd || !to_mmd) return;
@@ -1602,7 +1768,8 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3])
DerivedMesh *dm= NULL, *cddm= NULL, *subdm= NULL;
DMGridData **gridData, **subGridData;
Mesh *me= (Mesh*)ob->data;
- MFace *mface= me->mface;
+ MPoly *mpoly= me->mpoly;
+ /* MLoop *mloop = me->mloop; */ /* UNUSED */
MDisps *mdisps;
int *gridOffset;
int i, /*numGrids,*/ gridSize, dGridSize, dSkip, totvert;
@@ -1610,8 +1777,8 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3])
MultiresModifierData *mmd= get_multires_modifier(scene, ob, 1);
MultiresModifierData high_mmd;
- CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
- mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
+ CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
+ mdisps= CustomData_get_layer(&me->ldata, CD_MDISPS);
if(!mdisps || !mmd) return;
@@ -1647,15 +1814,15 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3])
dSkip= (dGridSize-1)/(gridSize-1);
#pragma omp parallel for private(i) if(me->totface*gridSize*gridSize*4 >= CCG_OMP_LIMIT)
- for(i = 0; i < me->totface; ++i) {
- const int numVerts= mface[i].v4 ? 4 : 3;
- MDisps *mdisp= &mdisps[i];
+ for(i = 0; i < me->totpoly; ++i) {
+ const int numVerts= mpoly[i].totloop;
+ MDisps *mdisp= &mdisps[mpoly[i].loopstart];
int S, x, y, gIndex = gridOffset[i];
- for(S = 0; S < numVerts; ++S, ++gIndex) {
+ for(S = 0; S < numVerts; ++S, ++gIndex, mdisp++) {
DMGridData *grid= gridData[gIndex];
DMGridData *subgrid= subGridData[gIndex];
- float (*dispgrid)[3]= &mdisp->disps[S*dGridSize*dGridSize];
+ float (*dispgrid)[3]= mdisp->disps;
for(y = 0; y < gridSize; y++) {
for(x = 0; x < gridSize; x++) {
@@ -1728,6 +1895,7 @@ void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob)
}
/* update multires data after topology changing */
+#if 0 // BMESH_TODO
void multires_topology_changed(Scene *scene, Object *ob)
{
Mesh *me= (Mesh*)ob->data;
@@ -1778,6 +1946,7 @@ void multires_topology_changed(Scene *scene, Object *ob)
}
}
}
+#endif // BMESH_TODO
/* makes displacement along grid boundary symmetrical */
void multires_mdisp_smooth_bounds(MDisps *disps)
@@ -2185,13 +2354,13 @@ void mdisp_join_tris(MDisps *dst, MDisps *tri1, MDisps *tri2)
MDisps *src;
if(dst->disps)
- MEM_freeN(dst->disps);
+ BLI_cellalloc_free(dst->disps);
side = sqrt(tri1->totdisp / 3);
st = (side<<1)-1;
dst->totdisp = 4 * side * side;
- out = dst->disps = MEM_callocN(3*dst->totdisp*sizeof(float), "join disps");
+ out = dst->disps = BLI_cellalloc_calloc(3*dst->totdisp*sizeof(float), "join disps");
for(S = 0; S < 4; S++)
for(y = 0; y < side; ++y)
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 6a3e0353a07..c450b4624d0 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1039,7 +1039,6 @@ static void ntreeMakeLocal_LinkNew(void *calldata, ID *owner_id, bNodeTree *ntre
void ntreeMakeLocal(bNodeTree *ntree)
{
- Main *bmain= G.main;
bNodeTreeType *treetype= ntreeGetType(ntree->type);
MakeLocalCallData cd;
@@ -1050,7 +1049,9 @@ void ntreeMakeLocal(bNodeTree *ntree)
if(ntree->id.lib==NULL) return;
if(ntree->id.us==1) {
- id_clear_lib_data(&bmain->nodetree, (ID *)ntree);
+ ntree->id.lib= NULL;
+ ntree->id.flag= LIB_LOCAL;
+ new_id(NULL, (ID *)ntree, NULL);
return;
}
@@ -1064,7 +1065,9 @@ void ntreeMakeLocal(bNodeTree *ntree)
/* if all users are local, we simply make tree local */
if(cd.local && cd.lib==0) {
- id_clear_lib_data(&bmain->nodetree, (ID *)ntree);
+ ntree->id.lib= NULL;
+ ntree->id.flag= LIB_LOCAL;
+ new_id(NULL, (ID *)ntree, NULL);
}
else if(cd.local && cd.lib) {
/* this is the mixed case, we copy the tree and assign it to local users */
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 6e09aefeea2..fcdb39ce3db 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -83,6 +83,7 @@
#include "BKE_lattice.h"
#include "BKE_library.h"
#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
#include "BKE_mball.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@@ -756,7 +757,9 @@ void make_local_camera(Camera *cam)
if(cam->id.lib==NULL) return;
if(cam->id.us==1) {
- id_clear_lib_data(&bmain->camera, (ID *)cam);
+ cam->id.lib= NULL;
+ cam->id.flag= LIB_LOCAL;
+ new_id(&bmain->camera, (ID *)cam, NULL);
return;
}
@@ -768,7 +771,9 @@ void make_local_camera(Camera *cam)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->camera, (ID *)cam);
+ cam->id.lib= NULL;
+ cam->id.flag= LIB_LOCAL;
+ new_id(&bmain->camera, (ID *)cam, NULL);
}
else if(local && lib) {
Camera *camn= copy_camera(cam);
@@ -917,7 +922,9 @@ void make_local_lamp(Lamp *la)
if(la->id.lib==NULL) return;
if(la->id.us==1) {
- id_clear_lib_data(&bmain->lamp, (ID *)la);
+ la->id.lib= NULL;
+ la->id.flag= LIB_LOCAL;
+ new_id(&bmain->lamp, (ID *)la, NULL);
return;
}
@@ -931,7 +938,9 @@ void make_local_lamp(Lamp *la)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->lamp, (ID *)la);
+ la->id.lib= NULL;
+ la->id.flag= LIB_LOCAL;
+ new_id(&bmain->lamp, (ID *)la, NULL);
}
else if(local && lib) {
lan= copy_lamp(la);
@@ -1083,7 +1092,6 @@ Object *add_only_object(int type, const char *name)
/* ob->pad3 == Contact Processing Threshold */
ob->m_contactProcessingThreshold = 1.;
ob->obstacleRad = 1.;
- ob->col_group = ob->col_mask = 1;
/* NT fluid sim defaults */
ob->fluidsimFlag = 0;
@@ -1461,8 +1469,9 @@ void make_local_object(Object *ob)
ob->proxy= ob->proxy_from= NULL;
if(ob->id.us==1) {
- id_clear_lib_data(&bmain->object, (ID *)ob);
- extern_local_object(ob);
+ ob->id.lib= NULL;
+ ob->id.flag= LIB_LOCAL;
+ new_id(&bmain->object, (ID *)ob, NULL);
}
else {
for(sce= bmain->scene.first; sce && ELEM(0, lib, local); sce= sce->id.next) {
@@ -1473,8 +1482,9 @@ void make_local_object(Object *ob)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->object, (ID *)ob);
- extern_local_object(ob);
+ ob->id.lib= NULL;
+ ob->id.flag= LIB_LOCAL;
+ new_id(&bmain->object, (ID *)ob, NULL);
}
else if(local && lib) {
Object *obn= copy_object(ob);
@@ -1497,6 +1507,8 @@ void make_local_object(Object *ob)
}
}
}
+
+ extern_local_object(ob);
}
/*
@@ -1958,7 +1970,7 @@ static void ob_parbone(Object *ob, Object *par, float mat[][4])
static void give_parvert(Object *par, int nr, float *vec)
{
- EditMesh *em;
+ BMEditMesh *em;
int a, count;
vec[0]=vec[1]=vec[2]= 0.0f;
@@ -1967,7 +1979,22 @@ static void give_parvert(Object *par, int nr, float *vec)
Mesh *me= par->data;
DerivedMesh *dm;
- em = BKE_mesh_get_editmesh(me);
+ em = me->edit_btmesh;
+
+ if(em) {
+ BMVert *eve;
+ BMIter iter;
+
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ int *keyindex = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
+
+ if(keyindex && *keyindex==nr) {
+ memcpy(vec, eve->co, sizeof(float)*3);
+ break;
+ }
+ }
+ }
+
dm = (em)? em->derivedFinal: par->derivedFinal;
if(dm) {
@@ -1995,9 +2022,6 @@ static void give_parvert(Object *par, int nr, float *vec)
dm->getVertCo(dm, 0, vec);
}
}
-
- if(em)
- BKE_mesh_end_editmesh(me, em);
}
else if (ELEM(par->type, OB_CURVE, OB_SURF)) {
Nurb *nu;
@@ -2664,22 +2688,19 @@ void object_handle_update(Scene *scene, Object *ob)
case OB_MESH:
{
#if 0 // XXX, comment for 2.56a release, background wont set 'scene->customdata_mask'
- EditMesh *em = (ob == scene->obedit)? BKE_mesh_get_editmesh(ob->data): NULL;
+ BMEditMesh *em = (ob == scene->obedit)? ((Mesh*)ob->data)->edit_btmesh : NULL;
BLI_assert((scene->customdata_mask & CD_MASK_BAREMESH) == CD_MASK_BAREMESH);
if(em) {
- makeDerivedMesh(scene, ob, em, scene->customdata_mask); /* was CD_MASK_BAREMESH */
- BKE_mesh_end_editmesh(ob->data, em);
+ makeDerivedMesh(scene, ob, em, scene->customdata_mask, 0); /* was CD_MASK_BAREMESH */
} else
- makeDerivedMesh(scene, ob, NULL, scene->customdata_mask);
+ makeDerivedMesh(scene, ob, NULL, scene->customdata_mask, 0);
#else /* ensure CD_MASK_BAREMESH for now */
- EditMesh *em = (ob == scene->obedit)? BKE_mesh_get_editmesh(ob->data): NULL;
- unsigned int data_mask= scene->customdata_mask | ob->customdata_mask | CD_MASK_BAREMESH;
+ BMEditMesh *em = (ob == scene->obedit)? ((Mesh*)ob->data)->edit_btmesh : NULL;
if(em) {
- makeDerivedMesh(scene, ob, em, data_mask); /* was CD_MASK_BAREMESH */
- BKE_mesh_end_editmesh(ob->data, em);
+ makeDerivedMesh(scene, ob, em, scene->customdata_mask | CD_MASK_BAREMESH, 0); /* was CD_MASK_BAREMESH */
} else
- makeDerivedMesh(scene, ob, NULL, data_mask);
+ makeDerivedMesh(scene, ob, NULL, scene->customdata_mask | CD_MASK_BAREMESH, 0);
#endif
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index f478c8faf07..680c7479c16 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -53,6 +53,8 @@
#include "BLI_rand.h"
#include "BLI_threads.h"
#include "BLI_linklist.h"
+#include "BLI_cellalloc.h"
+#include "BLI_math.h"
#include "BKE_anim.h"
#include "BKE_animsys.h"
@@ -692,7 +694,7 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float
data->totchildcache= psys->totchildcache;
if(psmd->dm)
- data->dm= CDDM_copy(psmd->dm);
+ data->dm= CDDM_copy(psmd->dm, 0);
data->totdmvert= psmd->totdmvert;
data->totdmedge= psmd->totdmedge;
data->totdmface= psmd->totdmface;
@@ -795,9 +797,9 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
return tot;
mvert= dm->getVertArray(dm);
- mface= dm->getFaceArray(dm);
- origindex= dm->getFaceDataArray(dm, CD_ORIGINDEX);
- totface= dm->getNumFaces(dm);
+ mface= dm->getTessFaceArray(dm);
+ origindex= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ totface= dm->getNumTessFaces(dm);
totorigface= me->totface;
if(totface == 0 || totorigface == 0)
@@ -1536,7 +1538,7 @@ static float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int
case PART_FROM_FACE:
case PART_FROM_VOLUME:
{
- MFace *mf=dm->getFaceData(dm,index,CD_MFACE);
+ MFace *mf=dm->getTessFaceData(dm,index,CD_MFACE);
return interpolate_particle_value(values[mf->v1],values[mf->v2],values[mf->v3],values[mf->v4],fw,mf->v4);
}
@@ -1584,11 +1586,11 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, float *
int quad, findex, totface;
float uv[2], (*faceuv)[2];
- mface = dm->getFaceDataArray(dm, CD_MFACE);
- origindex = dm->getFaceDataArray(dm, CD_ORIGINDEX);
- osface = dm->getFaceDataArray(dm, CD_ORIGSPACE);
+ mface = dm->getTessFaceDataArray(dm, CD_MFACE);
+ origindex = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ osface = dm->getTessFaceDataArray(dm, CD_ORIGSPACE);
- totface = dm->getNumFaces(dm);
+ totface = dm->getNumTessFaces(dm);
if(osface==NULL || origindex==NULL) {
/* Assume we dont need osface data */
@@ -1657,7 +1659,7 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_
*mapindex = index;
}
else { /* FROM_FACE/FROM_VOLUME */
- if(index >= dm->getNumFaces(dm))
+ if(index >= dm->getNumTessFaces(dm))
return 0;
*mapindex = index;
@@ -1681,15 +1683,15 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_
i = index_dmcache;
- if(i== DMCACHE_NOTFOUND || i >= dm->getNumFaces(dm))
+ if(i== DMCACHE_NOTFOUND || i >= dm->getNumTessFaces(dm))
return 0;
*mapindex = i;
/* modify the original weights to become
* weights for the derived mesh face */
- osface= dm->getFaceDataArray(dm, CD_ORIGSPACE);
- mface= dm->getFaceData(dm, i, CD_MFACE);
+ osface= dm->getTessFaceDataArray(dm, CD_ORIGSPACE);
+ mface= dm->getTessFaceData(dm, i, CD_MFACE);
if(osface == NULL)
mapfw[0]= mapfw[1]= mapfw[2]= mapfw[3]= 0.0f;
@@ -1747,7 +1749,7 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
MTFace *mtface;
MVert *mvert;
- mface=dm->getFaceData(dm,mapindex,CD_MFACE);
+ mface=dm->getTessFaceData(dm,mapindex,CD_MFACE);
mvert=dm->getVertDataArray(dm,CD_MVERT);
mtface=CustomData_get_layer(&dm->faceData,CD_MTFACE);
@@ -3322,10 +3324,10 @@ static void psys_face_mat(Object *ob, DerivedMesh *dm, ParticleData *pa, float m
int i = pa->num_dmcache==DMCACHE_NOTFOUND ? pa->num : pa->num_dmcache;
- if (i==-1 || i >= dm->getNumFaces(dm)) { unit_m4(mat); return; }
+ if (i==-1 || i >= dm->getNumTessFaces(dm)) { unit_m4(mat); return; }
- mface=dm->getFaceData(dm,i,CD_MFACE);
- osface=dm->getFaceData(dm,i,CD_ORIGSPACE);
+ mface=dm->getTessFaceData(dm,i,CD_MFACE);
+ osface=dm->getTessFaceData(dm,i,CD_ORIGSPACE);
if(orco && (orcodata=dm->getVertDataArray(dm, CD_ORCO))) {
VECCOPY(v[0], orcodata[mface->v1]);
@@ -3610,7 +3612,9 @@ void make_local_particlesettings(ParticleSettings *part)
if(part->id.lib==0) return;
if(part->id.us==1) {
- id_clear_lib_data(&bmain->particle, (ID *)part);
+ part->id.lib= 0;
+ part->id.flag= LIB_LOCAL;
+ new_id(&bmain->particle, (ID *)part, 0);
expand_local_particlesettings(part);
return;
}
@@ -3627,7 +3631,9 @@ void make_local_particlesettings(ParticleSettings *part)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->particle, (ID *)part);
+ part->id.lib= 0;
+ part->id.flag= LIB_LOCAL;
+ new_id(&bmain->particle, (ID *)part, 0);
expand_local_particlesettings(part);
}
else if(local && lib) {
@@ -3668,7 +3674,7 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, fl
if(pa) {
i= (pa->num_dmcache==DMCACHE_NOTFOUND)? pa->num: pa->num_dmcache;
- if(i >= dm->getNumFaces(dm))
+ if(i >= dm->getNumTessFaces(dm))
i = -1;
}
else
@@ -3680,7 +3686,7 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, fl
texco[2]= 0.0f;
}
else {
- mf= dm->getFaceData(dm, i, CD_MFACE);
+ mf= dm->getTessFaceData(dm, i, CD_MFACE);
psys_interpolate_uvs(&tf[i], mf->v4, fuv, texco);
@@ -4325,7 +4331,7 @@ void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, Partic
if(part->childtype == PART_CHILD_FACES) {
mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
if(mtface) {
- mface= psmd->dm->getFaceData(psmd->dm, cpa->num, CD_MFACE);
+ mface= psmd->dm->getTessFaceData(psmd->dm, cpa->num, CD_MFACE);
mtface += cpa->num;
psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
}
@@ -4345,14 +4351,14 @@ void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, Partic
if(num == DMCACHE_NOTFOUND)
num= pa->num;
- if (num >= psmd->dm->getNumFaces(psmd->dm)) {
+ if (num >= psmd->dm->getNumTessFaces(psmd->dm)) {
/* happens when simplify is enabled
* gives invalid coords but would crash otherwise */
num= DMCACHE_NOTFOUND;
}
if(mtface && num != DMCACHE_NOTFOUND) {
- mface= psmd->dm->getFaceData(psmd->dm, num, CD_MFACE);
+ mface= psmd->dm->getTessFaceData(psmd->dm, num, CD_MFACE);
mtface += num;
psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
}
@@ -4511,7 +4517,6 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3]
VECADDFAC(center, center, yvec, bb->offset[1]);
}
-
void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys) {
ParticleSimulationData sim= {0};
sim.scene= scene;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index c28bbfa0554..2f4c2806826 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -57,7 +57,6 @@
#include "DNA_ipo_types.h" // XXX old animation system stuff... to be removed!
#include "DNA_listBase.h"
-#include "BLI_edgehash.h"
#include "BLI_rand.h"
#include "BLI_jitter.h"
#include "BLI_math.h"
@@ -67,6 +66,7 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
+#include "BLI_edgehash.h"
#include "BKE_main.h"
#include "BKE_animsys.h"
@@ -347,9 +347,9 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
origindex= dm->getVertDataArray(dm, CD_ORIGINDEX);
}
else { /* FROM_FACE/FROM_VOLUME */
- totdmelem= dm->getNumFaces(dm);
+ totdmelem= dm->getNumTessFaces(dm);
totelem= me->totface;
- origindex= dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ origindex= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
}
nodedmelem= MEM_callocN(sizeof(LinkNode)*totdmelem, "psys node elems");
@@ -518,8 +518,8 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
int a, a1, a2, a0mul, a1mul, a2mul, totface;
int amax= from==PART_FROM_FACE ? 3 : 1;
- totface=dm->getNumFaces(dm);
- mface_array= dm->getFaceDataArray(dm,CD_MFACE);
+ totface=dm->getNumTessFaces(dm);
+ mface=mface_array=dm->getTessFaceDataArray(dm,CD_MFACE);
for(a=0; a<amax; a++){
if(a==0){ a0mul=res*res; a1mul=res; a2mul=1; }
@@ -778,7 +778,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch
MFace *mface;
pa->num = i = ctx->index[p];
- mface = dm->getFaceData(dm,i,CD_MFACE);
+ mface = dm->getTessFaceData(dm,i,CD_MFACE);
switch(distr){
case PART_DISTR_JIT:
@@ -808,7 +808,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch
if(from==PART_FROM_VOLUME){
MVert *mvert=dm->getVertDataArray(dm,CD_MVERT);
- tot=dm->getNumFaces(dm);
+ tot=dm->getNumTessFaces(dm);
psys_interpolate_face(mvert,mface,0,0,pa->fuv,co1,nor,0,0,0,0);
@@ -820,7 +820,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch
min_d=2.0;
intersect=0;
- for(i=0,mface=dm->getFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++){
+ for(i=0,mface=dm->getTessFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++){
if(i==pa->num) continue;
v1=mvert[mface->v1].co;
@@ -868,7 +868,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch
return;
}
- mf= dm->getFaceData(dm, ctx->index[p], CD_MFACE);
+ mf= dm->getTessFaceData(dm, ctx->index[p], CD_MFACE);
randu= rng_getFloat(thread->rng);
randv= rng_getFloat(thread->rng);
@@ -1035,7 +1035,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
if(totpart==0)
return 0;
- if (!finaldm->deformedOnly && !finaldm->getFaceDataArray(finaldm, CD_ORIGINDEX)) {
+ if (!finaldm->deformedOnly && !finaldm->getTessFaceDataArray(finaldm, CD_ORIGINDEX)) {
printf("Can't create particles with the current modifier stack, disable destructive modifiers\n");
// XXX error("Can't paint with the current modifier stack, disable destructive modifiers");
return 0;
@@ -1112,7 +1112,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
}
/* Get total number of emission elements and allocate needed arrays */
- totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumFaces(dm);
+ totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumTessFaces(dm);
if(totelem == 0){
distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0);
@@ -1138,7 +1138,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
orcodata= dm->getVertDataArray(dm, CD_ORCO);
for(i=0; i<totelem; i++){
- MFace *mf=dm->getFaceData(dm,i,CD_MFACE);
+ MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
if(orcodata) {
VECCOPY(co1, orcodata[mf->v1]);
@@ -1196,7 +1196,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
}
else { /* PART_FROM_FACE / PART_FROM_VOLUME */
for(i=0;i<totelem; i++){
- MFace *mf=dm->getFaceData(dm,i,CD_MFACE);
+ MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
if(mf->v4) {
@@ -1271,7 +1271,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
}
else {
if(dm->numFaceData)
- COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ COMPARE_ORIG_INDEX= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
}
if(COMPARE_ORIG_INDEX) {
@@ -3448,7 +3448,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
}
if(!dm) {
- dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0);
+ dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0, 0, 0);
DM_add_vert_layer(dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
}
diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c
index c5761dcc456..be66797bc56 100644
--- a/source/blender/blenkernel/intern/seqcache.c
+++ b/source/blender/blenkernel/intern/seqcache.c
@@ -17,8 +17,6 @@
*
* Peter Schlaile <peter [at] schlaile [dot] de> 2010
*
- * Contributor(s): Sergey Sharybin
- *
* ***** END GPL LICENSE BLOCK *****
*/
@@ -28,15 +26,22 @@
#include <stddef.h>
-
-#include "BLO_sys_types.h" /* for intptr_t */
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
#include "MEM_guardedalloc.h"
+#include "MEM_CacheLimiterC-Api.h"
#include "DNA_sequence_types.h"
#include "BKE_sequencer.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_mempool.h"
+#include <pthread.h>
-#include "IMB_moviecache.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
typedef struct seqCacheKey
{
@@ -46,9 +51,20 @@ typedef struct seqCacheKey
seq_stripelem_ibuf_t type;
} seqCacheKey;
-static struct MovieCache *moviecache = NULL;
-
-static unsigned int seqcache_hashhash(const void *key_)
+typedef struct seqCacheEntry
+{
+ ImBuf * ibuf;
+ MEM_CacheLimiterHandleC * c_handle;
+} seqCacheEntry;
+
+static GHash * hash = NULL;
+static MEM_CacheLimiterC * limitor = NULL;
+static struct BLI_mempool * entrypool = NULL;
+static struct BLI_mempool * keypool = NULL;
+static int ibufs_in = 0;
+static int ibufs_rem = 0;
+
+static unsigned int HashHash(const void *key_)
{
const seqCacheKey *key = (seqCacheKey*) key_;
unsigned int rval = seq_hash_render_data(&key->context);
@@ -60,7 +76,7 @@ static unsigned int seqcache_hashhash(const void *key_)
return rval;
}
-static int seqcache_hashcmp(const void *a_, const void *b_)
+static int HashCmp(const void *a_, const void *b_)
{
const seqCacheKey * a = (seqCacheKey*) a_;
const seqCacheKey * b = (seqCacheKey*) b_;
@@ -89,37 +105,109 @@ static int seqcache_hashcmp(const void *a_, const void *b_)
return seq_cmp_render_data(&a->context, &b->context);
}
+static void HashKeyFree(void *key)
+{
+ BLI_mempool_free(keypool, key);
+}
+
+static void HashValFree(void *val)
+{
+ seqCacheEntry* e = (seqCacheEntry*) val;
+
+ if (e->ibuf) {
+ /* fprintf(stderr, "Removing: %p, cnt: %d\n", e->ibuf,
+ e->ibuf->refcounter); */
+ IMB_freeImBuf(e->ibuf);
+ MEM_CacheLimiter_unmanage(e->c_handle);
+ ibufs_rem++;
+ }
+
+ e->ibuf = NULL;
+ e->c_handle = NULL;
+
+ BLI_mempool_free(entrypool, e);
+}
+
+static void IMB_seq_cache_destructor(void * p)
+{
+ seqCacheEntry* e = (seqCacheEntry*) p;
+
+ if (e && e->ibuf) {
+ /* fprintf(stderr, "Removing: %p, cnt: %d\n", e->ibuf,
+ e->ibuf->refcounter); */
+ IMB_freeImBuf(e->ibuf);
+ ibufs_rem++;
+
+ e->ibuf = NULL;
+ e->c_handle = NULL;
+ }
+}
+
+void seq_stripelem_cache_init(void)
+{
+ hash = BLI_ghash_new(HashHash, HashCmp, "seq stripelem cache hash");
+ limitor = new_MEM_CacheLimiter( IMB_seq_cache_destructor );
+
+ entrypool = BLI_mempool_create(sizeof(seqCacheEntry), 64, 64, 0, 0);
+ keypool = BLI_mempool_create(sizeof(seqCacheKey), 64, 64, 0, 0);
+}
+
void seq_stripelem_cache_destruct(void)
{
- if(moviecache)
- IMB_moviecache_free(moviecache);
+ if (!entrypool) {
+ return;
+ }
+ BLI_ghash_free(hash, HashKeyFree, HashValFree);
+ delete_MEM_CacheLimiter(limitor);
+ BLI_mempool_destroy(entrypool);
+ BLI_mempool_destroy(keypool);
}
void seq_stripelem_cache_cleanup(void)
{
- if(moviecache) {
- IMB_moviecache_free(moviecache);
- moviecache = IMB_moviecache_create(sizeof(seqCacheKey), seqcache_hashhash,
- seqcache_hashcmp, NULL);
+ if (!entrypool) {
+ seq_stripelem_cache_init();
}
+
+ /* fprintf(stderr, "Stats before cleanup: in: %d rem: %d\n",
+ ibufs_in, ibufs_rem); */
+
+ BLI_ghash_free(hash, HashKeyFree, HashValFree);
+ hash = BLI_ghash_new(HashHash, HashCmp, "seq stripelem cache hash");
+
+ /* fprintf(stderr, "Stats after cleanup: in: %d rem: %d\n",
+ ibufs_in, ibufs_rem); */
+
}
struct ImBuf * seq_stripelem_cache_get(
SeqRenderData context, struct Sequence * seq,
float cfra, seq_stripelem_ibuf_t type)
{
+ seqCacheKey key;
+ seqCacheEntry * e;
- if(moviecache && seq) {
- seqCacheKey key;
-
- key.seq = seq;
- key.context = context;
- key.cfra = cfra - seq->start;
- key.type = type;
+ if (!seq) {
+ return NULL;
+ }
- return IMB_moviecache_get(moviecache, &key);
+ if (!entrypool) {
+ seq_stripelem_cache_init();
}
+ key.seq = seq;
+ key.context = context;
+ key.cfra = cfra - seq->start;
+ key.type = type;
+
+ e = (seqCacheEntry*) BLI_ghash_lookup(hash, &key);
+
+ if (e && e->ibuf) {
+ IMB_refImBuf(e->ibuf);
+
+ MEM_CacheLimiter_touch(e->c_handle);
+ return e->ibuf;
+ }
return NULL;
}
@@ -127,21 +215,39 @@ void seq_stripelem_cache_put(
SeqRenderData context, struct Sequence * seq,
float cfra, seq_stripelem_ibuf_t type, struct ImBuf * i)
{
- seqCacheKey key;
+ seqCacheKey * key;
+ seqCacheEntry * e;
if (!i) {
return;
}
- if(!moviecache) {
- moviecache = IMB_moviecache_create(sizeof(seqCacheKey), seqcache_hashhash,
- seqcache_hashcmp, NULL);
+ ibufs_in++;
+
+ if (!entrypool) {
+ seq_stripelem_cache_init();
}
- key.seq = seq;
- key.context = context;
- key.cfra = cfra - seq->start;
- key.type = type;
+ key = (seqCacheKey*) BLI_mempool_alloc(keypool);
+
+ key->seq = seq;
+ key->context = context;
+ key->cfra = cfra - seq->start;
+ key->type = type;
+
+ IMB_refImBuf(i);
+
+ e = (seqCacheEntry*) BLI_mempool_alloc(entrypool);
+
+ e->ibuf = i;
+ e->c_handle = NULL;
+
+ BLI_ghash_remove(hash, key, HashKeyFree, HashValFree);
+ BLI_ghash_insert(hash, key, e);
+
+ e->c_handle = MEM_CacheLimiter_insert(limitor, e);
- IMB_moviecache_put(moviecache, &key, i);
+ MEM_CacheLimiter_ref(e->c_handle);
+ MEM_CacheLimiter_enforce_limits(limitor);
+ MEM_CacheLimiter_unref(e->c_handle);
}
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 6b319e6b5e1..5d52874b3b3 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -1324,10 +1324,6 @@ static void seq_proxy_build_frame(SeqRenderData context,
quality = seq->strip->proxy->quality;
ibuf->ftype= JPG | quality;
- /* unsupported feature only confuses other s/w */
- if(ibuf->depth==32)
- ibuf->depth= 24;
-
BLI_make_existing_file(name);
ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat);
@@ -2505,6 +2501,9 @@ static void *seq_prefetch_thread(void * This_)
for (e = prefetch_done.first; e; e = e->next) {
if (s_last > e->monoton_cfra) {
+ if (e->ibuf) {
+ IMB_cache_limiter_unref(e->ibuf);
+ }
BLI_remlink(&prefetch_done, e);
MEM_freeN(e);
}
@@ -2582,6 +2581,9 @@ static void seq_stop_threads()
}
for (e = prefetch_done.first; e; e = e->next) {
+ if (e->ibuf) {
+ IMB_cache_limiter_unref(e->ibuf);
+ }
BLI_remlink(&prefetch_done, e);
MEM_freeN(e);
}
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index e47dcd68ce1..5d47b127096 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -54,6 +54,8 @@
#include "BKE_deform.h"
#include "BKE_mesh.h"
#include "BKE_subsurf.h"
+#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
/* Util macros */
#define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n"))
@@ -89,11 +91,11 @@ typedef void ( *Shrinkwrap_ForeachVertexCallback) (DerivedMesh *target, float *c
DerivedMesh *object_get_derived_final(Object *ob)
{
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
+ BMEditMesh *em = me->edit_btmesh;
- if(em) {
+ if (em)
+ {
DerivedMesh *dm = em->derivedFinal;
- BKE_mesh_end_editmesh(me, em);
return dm;
}
@@ -589,7 +591,9 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
}
//free memory
- if(ss_mesh)
+ if(ss_mesh) {
+ ss_mesh->needsFree = 1;
ss_mesh->release(ss_mesh);
+ }
}
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index ac2a840c95a..cc51ffac0ba 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -41,6 +41,7 @@
#include <stdio.h>
#include <string.h> /* memset */
+#include "BLI_utildefines.h"
#include "BLI_linklist.h"
#include "BLI_rand.h"
#include "BLI_jitter.h"
@@ -49,7 +50,6 @@
#include "BLI_edgehash.h"
#include "BLI_kdtree.h"
#include "BLI_kdopbvh.h"
-#include "BLI_utildefines.h"
#include "BKE_bvhutils.h"
#include "BKE_cdderivedmesh.h"
@@ -309,7 +309,7 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
if(!smd->coll->bvhtree)
{
- smd->coll->bvhtree = NULL; // bvhtree_build_from_smoke ( ob->obmat, dm->getFaceArray(dm), dm->getNumFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 );
+ smd->coll->bvhtree = NULL; // bvhtree_build_from_smoke ( ob->obmat, dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 );
}
return 1;
}
@@ -320,7 +320,7 @@ static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene,
static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
{
MVert *mvert = dm->getVertArray(dm);
- MFace *mface = dm->getFaceArray(dm);
+ MFace *mface = dm->getTessFaceArray(dm);
int i = 0, divs = 0;
int *tridivs = NULL;
float cell_len = 1.0 / 50.0; // for res = 50
@@ -328,16 +328,16 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
int quads = 0, facecounter = 0;
// count quads
- for(i = 0; i < dm->getNumFaces(dm); i++)
+ for(i = 0; i < dm->getNumTessFaces(dm); i++)
{
if(mface[i].v4)
quads++;
}
- calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface, dm->getNumFaces(dm), dm->getNumFaces(dm) + quads, &tridivs, cell_len);
+ calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface, dm->getNumTessFaces(dm), dm->getNumTessFaces(dm) + quads, &tridivs, cell_len);
// count triangle divisions
- for(i = 0; i < dm->getNumFaces(dm) + quads; i++)
+ for(i = 0; i < dm->getNumTessFaces(dm) + quads; i++)
{
divs += (tridivs[3 * i] + 1) * (tridivs[3 * i + 1] + 1) * (tridivs[3 * i + 2] + 1);
}
@@ -354,7 +354,7 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
VECCOPY(&scs->points[i * 3], tmpvec);
}
- for(i = 0, facecounter = 0; i < dm->getNumFaces(dm); i++)
+ for(i = 0, facecounter = 0; i < dm->getNumTessFaces(dm); i++)
{
int again = 0;
do
@@ -1339,7 +1339,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
if(smd->coll->dm)
smd->coll->dm->release(smd->coll->dm);
- smd->coll->dm = CDDM_copy(dm);
+ smd->coll->dm = CDDM_copy(dm, 1);
// rigid movement support
copy_m4_m4(smd->coll->mat_old, smd->coll->mat);
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index fb6a473f04d..b743f847bb7 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -87,7 +87,9 @@ void make_local_speaker(Speaker *spk)
if(spk->id.lib==NULL) return;
if(spk->id.us==1) {
- id_clear_lib_data(&bmain->speaker, (ID *)spk);
+ spk->id.lib= NULL;
+ spk->id.flag= LIB_LOCAL;
+ new_id(&bmain->speaker, (ID *)spk, NULL);
return;
}
@@ -101,7 +103,9 @@ void make_local_speaker(Speaker *spk)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->speaker, (ID *)spk);
+ spk->id.lib= NULL;
+ spk->id.flag= LIB_LOCAL;
+ new_id(&bmain->speaker, (ID *)spk, NULL);
}
else if(local && lib) {
Speaker *spkn= copy_speaker(spk);
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 115b26452e1..a186efcaff8 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -44,12 +44,12 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_edgehash.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_pbvh.h"
-#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
@@ -58,6 +58,10 @@
#include "BKE_paint.h"
#include "BKE_scene.h"
#include "BKE_subsurf.h"
+#include "BKE_tessmesh.h"
+
+#include "PIL_time.h"
+#include "BLI_array.h"
#include "GL/glew.h"
@@ -69,9 +73,10 @@
extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
-static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v);
-static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e);
-static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f);
+static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
+ int drawInteriorEdges,
+ int useSubsurfUv,
+ DerivedMesh *dm);
static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm);
///
@@ -159,7 +164,8 @@ static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize) {
return edgeBase + x-1;
}
}
-static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) {
+
+BM_INLINE int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) {
int faceBase = *((int*) ccgSubSurf_getFaceUserData(ss, f));
int numVerts = ccgSubSurf_getFaceNumVerts(f);
@@ -214,10 +220,16 @@ static void get_face_uv_map_vert(UvVertMap *vmap, struct MFace *mf, int fi, CCGV
}
static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, MTFace *tface) {
- MFace *mface = dm->getFaceArray(dm);
+#if 1 /*BMESH_TODO*/
+ (void)ss;
+ (void)origss;
+ (void)dm;
+ (void)tface;
+#else
+ MFace *mface = dm->getTessFaceArray(dm);
MVert *mvert = dm->getVertArray(dm);
int totvert = dm->getNumVerts(dm);
- int totface = dm->getNumFaces(dm);
+ int totface = dm->getNumTessFaces(dm);
int i, j, seam;
UvMapVert *v;
UvVertMap *vmap;
@@ -307,6 +319,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
free_uv_vert_map(vmap);
ccgSubSurf_processSync(ss);
+#endif
return 1;
}
@@ -380,65 +393,123 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result,
}
/* face weighting */
-static void calc_ss_weights(int gridFaces,
- FaceVertWeight **qweight, FaceVertWeight **tweight)
+typedef struct FaceVertWeightEntry {
+ FaceVertWeight *weight;
+ float *w;
+ int valid;
+} FaceVertWeightEntry;
+
+typedef struct WeightTable {
+ FaceVertWeightEntry *weight_table;
+ int len;
+} WeightTable;
+
+static float *get_ss_weights(WeightTable *wtable, int gridCuts, int faceLen)
{
- FaceVertWeight *qw, *tw;
- int x, y, j;
- int numWeights = gridFaces * gridFaces;
-
- *tweight = MEM_mallocN(sizeof(**tweight) * numWeights, "ssTriWeight");
- *qweight = MEM_mallocN(sizeof(**qweight) * numWeights, "ssQuadWeight");
-
- qw = *qweight;
- tw = *tweight;
-
- for (y = 0; y < gridFaces; y++) {
- for (x = 0; x < gridFaces; x++) {
- for (j = 0; j < 4; j++) {
- int fx = x + (j == 2 || j == 3);
- int fy = y + (j == 1 || j == 2);
- float x_v = (float) fx / gridFaces;
- float y_v = (float) fy / gridFaces;
- float tx_v = (1.0f - x_v), ty_v = (1.0f - y_v);
- float center = (1.0f / 3.0f) * tx_v * ty_v;
-
- (*tw)[j][0] = center + 0.5f * tx_v * y_v;
- (*tw)[j][2] = center + 0.5f * x_v * ty_v;
- (*tw)[j][1] = 1.0f - (*tw)[j][0] - (*tw)[j][2];
- (*tw)[j][3] = 0.0f;
-
- tx_v *= 0.5f;
- ty_v *= 0.5f;
-
- (*qw)[j][3] = tx_v * ty_v;
- (*qw)[j][0] = (*qw)[j][3] + tx_v * y_v;
- (*qw)[j][2] = (*qw)[j][3] + x_v * ty_v;
- (*qw)[j][1] = 1.0f - (*qw)[j][0] - (*qw)[j][2] - (*qw)[j][3];
+ int x, y, i, j;
+ float *w, w1, w2, w4, fac, fac2, fx, fy;
+
+ if (wtable->len <= faceLen) {
+ void *tmp = MEM_callocN(sizeof(FaceVertWeightEntry)*(faceLen+1), "weight table alloc 2");
+
+ if (wtable->len) {
+ memcpy(tmp, wtable->weight_table, sizeof(FaceVertWeightEntry)*wtable->len);
+ MEM_freeN(wtable->weight_table);
+ }
+
+ wtable->weight_table = tmp;
+ wtable->len = faceLen+1;
+ }
+ if (!wtable->weight_table[faceLen].valid) {
+ wtable->weight_table[faceLen].valid = 1;
+ wtable->weight_table[faceLen].w = w = MEM_callocN(sizeof(float)*faceLen*faceLen*(gridCuts+2)*(gridCuts+2), "weight table alloc");
+ fac = 1.0f / (float)faceLen;
+
+ for (i=0; i<faceLen; i++) {
+ for (x=0; x<gridCuts+2; x++) {
+ for (y=0; y<gridCuts+2; y++) {
+ fx = 0.5f - (float)x / (float)(gridCuts+1) / 2.0f;
+ fy = 0.5f - (float)y / (float)(gridCuts+1) / 2.0f;
+
+ fac2 = faceLen - 4;
+ w1 = (1.0f - fx) * (1.0f - fy) + (-fac2*fx*fy*fac);
+ w2 = (1.0f - fx + fac2*fx*-fac) * (fy);
+ w4 = (fx) * (1.0f - fy + -fac2*fy*fac);
+
+ fac2 = 1.0f - (w1+w2+w4);
+ fac2 = fac2 / (float)(faceLen-3);
+ for (j=0; j<faceLen; j++)
+ w[j] = fac2;
+
+ w[i] = w1;
+ w[(i-1+faceLen)%faceLen] = w2;
+ w[(i+1)%faceLen] = w4;
+
+ w += faceLen;
+ }
}
- tw++;
- qw++;
}
}
+
+ return wtable->weight_table[faceLen].w;
+}
+
+static void free_ss_weights(WeightTable *wtable)
+{
+ int i;
+
+ for (i=0; i<wtable->len; i++) {
+ if (wtable->weight_table[i].valid)
+ MEM_freeN(wtable->weight_table[i].w);
+ }
+
+ if (wtable->weight_table)
+ MEM_freeN(wtable->weight_table);
+}
+
+#if 0
+static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
+ int drawInteriorEdges, int useSubsurfUv,
+ DerivedMesh *dm, struct MultiresSubsurf *ms)
+{
+ DerivedMesh *cgdm, *result;
+ double curt = PIL_check_seconds_timer();
+
+ cgdm = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm);
+ result = CDDM_copy(cgdm, 1);
+
+ printf("subsurf conversion time: %.6lf\n", PIL_check_seconds_timer() - curt);
+
+ cgdm->needsFree = 1;
+ cgdm->release(cgdm);
+
+ CDDM_calc_normals(result);
+
+ return result;
}
+#endif
-static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
+static int ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
float (*vertexCos)[3], int useFlatSubdiv)
{
float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
- CCGVertHDL fVerts[4];
- int totvert = dm->getNumVerts(dm);
- int totedge = dm->getNumEdges(dm);
- int totface = dm->getNumFaces(dm);
- int i;
- int *index;
+ CCGVertHDL *fVerts = NULL;
+ BLI_array_declare(fVerts);
MVert *mvert = dm->getVertArray(dm);
MEdge *medge = dm->getEdgeArray(dm);
- MFace *mface = dm->getFaceArray(dm);
+ /* MFace *mface = dm->getTessFaceArray(dm); */ /* UNUSED */
MVert *mv;
MEdge *me;
- MFace *mf;
+ MLoop *mloop = dm->getLoopArray(dm), *ml;
+ MPoly *mpoly = dm->getPolyArray(dm), *mp;
+ /*MFace *mf;*/ /*UNUSED*/
+ int totvert = dm->getNumVerts(dm);
+ int totedge = dm->getNumEdges(dm);
+ /*int totface = dm->getNumTessFaces(dm);*/ /*UNUSED*/
+ /*int totpoly = dm->getNumFaces(dm);*/ /*UNUSED*/
+ int i, j;
+ int *index;
ccgSubSurf_initFullSync(ss);
@@ -471,38 +542,43 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
((int*)ccgSubSurf_getEdgeUserData(ss, e))[1] = (index)? *index++: i;
}
- mf = mface;
- index = (int *)dm->getFaceDataArray(dm, CD_ORIGINDEX);
- for (i = 0; i < totface; i++, mf++) {
- CCGFace *f;
+ mp = mpoly;
+ index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
+ for (i=0; i<dm->numPolyData; i++, mp++) {
+ CCGFace *f=NULL;
+
+ BLI_array_empty(fVerts);
- fVerts[0] = SET_INT_IN_POINTER(mf->v1);
- fVerts[1] = SET_INT_IN_POINTER(mf->v2);
- fVerts[2] = SET_INT_IN_POINTER(mf->v3);
- fVerts[3] = SET_INT_IN_POINTER(mf->v4);
+ ml = mloop + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ BLI_array_append(fVerts, SET_INT_IN_POINTER(ml->v));
+ }
- // this is very bad, means mesh is internally consistent.
- // it is not really possible to continue without modifying
- // other parts of code significantly to handle missing faces.
- // since this really shouldn't even be possible we just bail.
- if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), fVerts[3] ? 4 : 3,
+ /* this is very bad, means mesh is internally inconsistent.
+ * it is not really possible to continue without modifying
+ * other parts of code significantly to handle missing faces.
+ * since this really shouldn't even be possible we just bail.*/
+ if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), mp->totloop,
fVerts, &f) == eCCGError_InvalidValue) {
static int hasGivenError = 0;
if(!hasGivenError) {
- //XXX error("Unrecoverable error in SubSurf calculation,"
- // " mesh is inconsistent.");
+ printf("Unrecoverable error in SubSurf calculation,"
+ " mesh is inconsistent.\n");
hasGivenError = 1;
}
- return;
+ return 0;
}
- ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = (index)? *index++: i;
+ ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = index ? *index++: i;
}
ccgSubSurf_processSync(ss);
+
+ BLI_array_free(fVerts);
+ return 1;
}
/***/
@@ -519,9 +595,9 @@ static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f) {
return ((int*) ccgSubSurf_getFaceUserData(ss, f))[1];
}
-static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+static void cgdm_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
CCGVertIterator *vi = ccgSubSurf_getVertIterator(ss);
CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
@@ -563,32 +639,32 @@ static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
ccgEdgeIterator_free(ei);
ccgVertIterator_free(vi);
}
-static int ccgDM_getNumVerts(DerivedMesh *dm) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+static int cgdm_getNumVerts(DerivedMesh *dm) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
- return ccgSubSurf_getNumFinalVerts(ccgdm->ss);
+ return ccgSubSurf_getNumFinalVerts(cgdm->ss);
}
-static int ccgDM_getNumEdges(DerivedMesh *dm) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+static int cgdm_getNumEdges(DerivedMesh *dm) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
- return ccgSubSurf_getNumFinalEdges(ccgdm->ss);
+ return ccgSubSurf_getNumFinalEdges(cgdm->ss);
}
-static int ccgDM_getNumFaces(DerivedMesh *dm) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+static int cgdm_getNumTessFaces(DerivedMesh *dm) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
- return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
+ return ccgSubSurf_getNumFinalFaces(cgdm->ss);
}
static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
DMGridData *vd;
int i;
memset(mv, 0, sizeof(*mv));
- if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
+ if((vertNum < cgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
/* this vert comes from face data */
int lastface = ccgSubSurf_getNumFaces(ss) - 1;
CCGFace *f;
@@ -601,10 +677,10 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
int gridInternalEnd;
i = 0;
- while(i < lastface && vertNum >= ccgdm->faceMap[i + 1].startVert)
+ while(i < lastface && vertNum >= cgdm->faceMap[i + 1].startVert)
++i;
- f = ccgdm->faceMap[i].face;
+ f = cgdm->faceMap[i].face;
numVerts = ccgSubSurf_getFaceNumVerts(f);
gridSideVerts = gridSize - 2;
@@ -613,7 +689,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
gridSideEnd = 1 + numVerts * gridSideVerts;
gridInternalEnd = gridSideEnd + numVerts * gridInternalVerts;
- offset = vertNum - ccgdm->faceMap[i].startVert;
+ offset = vertNum - cgdm->faceMap[i].startVert;
if(offset < 1) {
vd = ccgSubSurf_getFaceCenterData(f);
copy_v3_v3(mv->co, vd->co);
@@ -635,28 +711,28 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
copy_v3_v3(mv->co, vd->co);
normal_float_to_short_v3(mv->no, vd->no);
}
- } else if((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
+ } else if((vertNum < cgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
/* this vert comes from edge data */
CCGEdge *e;
int lastedge = ccgSubSurf_getNumEdges(ss) - 1;
int x;
i = 0;
- while(i < lastedge && vertNum >= ccgdm->edgeMap[i + 1].startVert)
+ while(i < lastedge && vertNum >= cgdm->edgeMap[i + 1].startVert)
++i;
- e = ccgdm->edgeMap[i].edge;
+ e = cgdm->edgeMap[i].edge;
- x = vertNum - ccgdm->edgeMap[i].startVert + 1;
+ x = vertNum - cgdm->edgeMap[i].startVert + 1;
vd = ccgSubSurf_getEdgeData(ss, e, x);
copy_v3_v3(mv->co, vd->co);
normal_float_to_short_v3(mv->no, vd->no);
} else {
/* this vert comes from vert data */
CCGVert *v;
- i = vertNum - ccgdm->vertMap[0].startVert;
+ i = vertNum - cgdm->vertMap[0].startVert;
- v = ccgdm->vertMap[i].vert;
+ v = cgdm->vertMap[i].vert;
vd = ccgSubSurf_getVertData(ss, v);
copy_v3_v3(mv->co, vd->co);
normal_float_to_short_v3(mv->no, vd->no);
@@ -681,13 +757,13 @@ static void ccgDM_getFinalVertNo(DerivedMesh *dm, int vertNum, float no_r[3])
static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
int i;
memset(med, 0, sizeof(*med));
- if(edgeNum < ccgdm->edgeMap[0].startEdge) {
+ if(edgeNum < cgdm->edgeMap[0].startEdge) {
/* this edge comes from face data */
int lastface = ccgSubSurf_getNumFaces(ss) - 1;
CCGFace *f;
@@ -697,18 +773,48 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int gridSideEdges;
int gridInternalEdges;
+ int lasti, previ;
+
+ i = lastface;
+ lasti = 0;
+ while (1) {
+ previ = i;
+ if (cgdm->faceMap[i].startEdge >= edgeNum) {
+ i -= fabsf(i-lasti)/2.0f;
+ } else if (cgdm->faceMap[i].startEdge < edgeNum) {
+ i += fabsf(i-lasti)/2.0f;
+ } else {
+ break;
+ }
- i = 0;
- while(i < lastface && edgeNum >= ccgdm->faceMap[i + 1].startEdge)
+ if (i < 0) {
+ i = 0;
+ break;
+ }
+
+ if (i > lastface) {
+ i = lastface;
+ break;
+
+ }
+
+ if (i == lasti)
+ break;
+
+ lasti = previ;
+ }
+
+ i = i > 0 ? i - 1 : i;
+ while(i < lastface && edgeNum >= cgdm->faceMap[i + 1].startEdge)
++i;
- f = ccgdm->faceMap[i].face;
+ f = cgdm->faceMap[i].face;
/* numVerts = ccgSubSurf_getFaceNumVerts(f); */ /*UNUSED*/
gridSideEdges = gridSize - 1;
gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
- offset = edgeNum - ccgdm->faceMap[i].startEdge;
+ offset = edgeNum - cgdm->faceMap[i].startEdge;
grid = offset / (gridSideEdges + gridInternalEdges);
offset %= (gridSideEdges + gridInternalEdges);
@@ -736,18 +842,18 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
short *edgeFlag;
unsigned int flags = 0;
- i = (edgeNum - ccgdm->edgeMap[0].startEdge) / (edgeSize - 1);
+ i = (edgeNum - cgdm->edgeMap[0].startEdge) / (edgeSize - 1);
- e = ccgdm->edgeMap[i].edge;
+ e = cgdm->edgeMap[i].edge;
if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
- x = edgeNum - ccgdm->edgeMap[i].startEdge;
+ x = edgeNum - cgdm->edgeMap[i].startEdge;
med->v1 = getEdgeIndex(ss, e, x, edgeSize);
med->v2 = getEdgeIndex(ss, e, x+1, edgeSize);
- edgeFlag = (ccgdm->edgeFlags)? &ccgdm->edgeFlags[i]: NULL;
+ edgeFlag = (cgdm->edgeFlags)? &cgdm->edgeFlags[i]: NULL;
if(edgeFlag)
flags |= (*edgeFlag & (ME_SEAM | ME_SHARP))
| ME_EDGEDRAW | ME_EDGERENDER;
@@ -760,8 +866,8 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
int gridSize = ccgSubSurf_getGridSize(ss);
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int gridSideEdges = gridSize - 1;
@@ -772,19 +878,19 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
int offset;
int grid;
int x, y;
- int lastface = ccgSubSurf_getNumFaces(ss) - 1;
- char *faceFlags = ccgdm->faceFlags;
+ /*int lastface = ccgSubSurf_getNumFaces(ss) - 1;*/ /*UNUSED*/
+ char *faceFlags = cgdm->faceFlags;
memset(mf, 0, sizeof(*mf));
+ if (faceNum >= cgdm->dm.numFaceData)
+ return;
- i = 0;
- while(i < lastface && faceNum >= ccgdm->faceMap[i + 1].startFace)
- ++i;
+ i = cgdm->reverseFaceMap[faceNum];
- f = ccgdm->faceMap[i].face;
+ f = cgdm->faceMap[i].face;
/*numVerts = ccgSubSurf_getFaceNumVerts(f);*/ /*UNUSED*/
- offset = faceNum - ccgdm->faceMap[i].startFace;
+ offset = faceNum - cgdm->faceMap[i].startFace;
grid = offset / gridFaces;
offset %= gridFaces;
y = offset / gridSideEdges;
@@ -804,8 +910,8 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
DMGridData *vd;
int index;
int totvert, totedge, totface;
@@ -815,7 +921,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
totface = ccgSubSurf_getNumFaces(ss);
for(index = 0; index < totface; index++) {
- CCGFace *f = ccgdm->faceMap[index].face;
+ CCGFace *f = cgdm->faceMap[index].face;
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
vd= ccgSubSurf_getFaceCenterData(f);
@@ -844,7 +950,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
totedge = ccgSubSurf_getNumEdges(ss);
for(index = 0; index < totedge; index++) {
- CCGEdge *e = ccgdm->edgeMap[index].edge;
+ CCGEdge *e = cgdm->edgeMap[index].edge;
int x;
for(x = 1; x < edgeSize - 1; x++, i++) {
@@ -861,7 +967,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
totvert = ccgSubSurf_getNumVerts(ss);
for(index = 0; index < totvert; index++) {
- CCGVert *v = ccgdm->vertMap[index].vert;
+ CCGVert *v = cgdm->vertMap[index].vert;
vd= ccgSubSurf_getVertData(ss, v);
copy_v3_v3(mvert[i].co, vd->co);
@@ -872,25 +978,25 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
int index;
int totedge, totface;
int gridSize = ccgSubSurf_getGridSize(ss);
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int i = 0;
- short *edgeFlags = ccgdm->edgeFlags;
+ short *edgeFlags = cgdm->edgeFlags;
totface = ccgSubSurf_getNumFaces(ss);
for(index = 0; index < totface; index++) {
- CCGFace *f = ccgdm->faceMap[index].face;
+ CCGFace *f = cgdm->faceMap[index].face;
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
for(S = 0; S < numVerts; S++) {
for(x = 0; x < gridSize - 1; x++) {
MEdge *med = &medge[i];
- if(ccgdm->drawInteriorEdges)
+ if(cgdm->drawInteriorEdges)
med->flag = ME_EDGEDRAW | ME_EDGERENDER;
med->v1 = getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize);
med->v2 = getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize);
@@ -902,7 +1008,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
MEdge *med;
med = &medge[i];
- if(ccgdm->drawInteriorEdges)
+ if(cgdm->drawInteriorEdges)
med->flag = ME_EDGEDRAW | ME_EDGERENDER;
med->v1 = getFaceIndex(ss, f, S, x, y,
edgeSize, gridSize);
@@ -911,7 +1017,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
i++;
med = &medge[i];
- if(ccgdm->drawInteriorEdges)
+ if(cgdm->drawInteriorEdges)
med->flag = ME_EDGEDRAW | ME_EDGERENDER;
med->v1 = getFaceIndex(ss, f, S, y, x,
edgeSize, gridSize);
@@ -925,7 +1031,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
totedge = ccgSubSurf_getNumEdges(ss);
for(index = 0; index < totedge; index++) {
- CCGEdge *e = ccgdm->edgeMap[index].edge;
+ CCGEdge *e = cgdm->edgeMap[index].edge;
unsigned int flags = 0;
int x;
int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
@@ -953,18 +1059,18 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
int index;
int totface;
int gridSize = ccgSubSurf_getGridSize(ss);
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int i = 0;
- char *faceFlags = ccgdm->faceFlags;
+ char *faceFlags = cgdm->faceFlags;
totface = ccgSubSurf_getNumFaces(ss);
for(index = 0; index < totface; index++) {
- CCGFace *f = ccgdm->faceMap[index].face;
+ CCGFace *f = cgdm->faceMap[index].face;
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
/* keep types in sync with MFace, avoid many conversions */
char flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH;
@@ -982,6 +1088,11 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
edgeSize, gridSize);
mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
edgeSize, gridSize);
+ if (faceFlags) {
+ mat_nr = faceFlags[index*2+1];
+ mf->flag = faceFlags[index*2];
+ } else mf->flag = flag;
+
mf->mat_nr = mat_nr;
mf->flag = flag;
@@ -992,9 +1103,118 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
}
}
-static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop)
+{
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
+ int index;
+ int totface;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int i = 0;
+ MLoop *mv;
+ /* char *faceFlags = cgdm->faceFlags; */ /* UNUSED */
+
+ if (!cgdm->ehash) {
+ MEdge *medge;
+
+ cgdm->ehash = BLI_edgehash_new();
+ medge = cgdm->dm.getEdgeArray((DerivedMesh*)cgdm);
+
+ for (i=0; i<cgdm->dm.numEdgeData; i++) {
+ BLI_edgehash_insert(cgdm->ehash, medge[i].v1, medge[i].v2, SET_INT_IN_POINTER(i));
+ }
+ }
+
+ totface = ccgSubSurf_getNumFaces(ss);
+ mv = mloop;
+ for(index = 0; index < totface; index++) {
+ CCGFace *f = cgdm->faceMap[index].face;
+ int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ /* int flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH; */ /* UNUSED */
+ /* int mat_nr = (faceFlags)? faceFlags[index*2+1]: 0; */ /* UNUSED */
+
+ for(S = 0; S < numVerts; S++) {
+ for(y = 0; y < gridSize - 1; y++) {
+ for(x = 0; x < gridSize - 1; x++) {
+ int v1, v2, v3, v4;
+
+ v1 = getFaceIndex(ss, f, S, x + 0, y + 0,
+ edgeSize, gridSize);
+
+ v2 = getFaceIndex(ss, f, S, x + 0, y + 1,
+ edgeSize, gridSize);
+ v3 = getFaceIndex(ss, f, S, x + 1, y + 1,
+ edgeSize, gridSize);
+ v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
+ edgeSize, gridSize);
+
+ mv->v = v1;
+ mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v1, v2));
+ mv++, i++;
+
+ mv->v = v2;
+ mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v2, v3));
+ mv++, i++;
+
+ mv->v = v3;
+ mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v3, v4));
+ mv++, i++;
+
+ mv->v = v4;
+ mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v4, v1));
+ mv++, i++;
+ }
+ }
+ }
+ }
+}
+
+
+static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *mface)
+{
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
+ int index;
+ int totface;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ /* int edgeSize = ccgSubSurf_getEdgeSize(ss); */ /* UNUSED */
+ int i = 0, k = 0;
+ char *faceFlags = cgdm->faceFlags;
+
+ totface = ccgSubSurf_getNumFaces(ss);
+ for(index = 0; index < totface; index++) {
+ CCGFace *f = cgdm->faceMap[index].face;
+ int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ int flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH;
+ int mat_nr = (faceFlags)? faceFlags[index*2+1]: 0;
+
+ for(S = 0; S < numVerts; S++) {
+ for(y = 0; y < gridSize - 1; y++) {
+ for(x = 0; x < gridSize - 1; x++) {
+ MPoly *mf = &mface[i];
+
+ if (faceFlags) {
+ mat_nr = faceFlags[index*2+1];
+ mf->flag = faceFlags[index*2];
+ } else mf->flag = flag;
+
+ mf->mat_nr = mat_nr;
+ mf->flag = flag;
+ mf->loopstart = k;
+ mf->totloop = 4;
+
+ k += 4;
+ i++;
+ }
+ }
+ }
+ }
+}
+
+static void cgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int gridSize = ccgSubSurf_getGridSize(ss);
int i;
@@ -1075,14 +1295,14 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
MEM_freeN(edgeMap2);
MEM_freeN(faceMap2);
}
-static void ccgDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGVertIterator *vi = ccgSubSurf_getVertIterator(ccgdm->ss);
+static void cgdm_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGVertIterator *vi = ccgSubSurf_getVertIterator(cgdm->ss);
for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
CCGVert *v = ccgVertIterator_getCurrent(vi);
- DMGridData *vd = ccgSubSurf_getVertData(ccgdm->ss, v);
- int index = ccgDM_getVertMapIndex(ccgdm->ss, v);
+ DMGridData *vd = ccgSubSurf_getVertData(cgdm->ss, v);
+ int index = ccgDM_getVertMapIndex(cgdm->ss, v);
if (index!=-1)
func(userData, index, vd->co, vd->no, NULL);
@@ -1090,9 +1310,9 @@ static void ccgDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData
ccgVertIterator_free(vi);
}
-static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+static void cgdm_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
@@ -1111,8 +1331,8 @@ static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData
}
static void ccgDM_drawVerts(DerivedMesh *dm) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int gridSize = ccgSubSurf_getGridSize(ss);
CCGVertIterator *vi;
@@ -1243,8 +1463,8 @@ static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int UNUSED(draw
ccgEdgeIterator_free(ei);
}
static void ccgDM_drawLooseEdges(DerivedMesh *dm) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
@@ -1367,20 +1587,20 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
}
/* Only used by non-editmesh types */
-static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
GPUVertexAttribs gattribs;
DMVertexAttribs attribs= {{{NULL}}};
- /* MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
+ /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
int gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
int edgeSize = ccgSubSurf_getEdgeSize(ss);
- char *faceFlags = ccgdm->faceFlags;
+ char *faceFlags = cgdm->faceFlags;
int a, b, i, doDraw, numVerts, matnr, new_matnr, totface;
- ccgdm_pbvh_update(ccgdm);
+ ccgdm_pbvh_update(cgdm);
doDraw = 0;
matnr = -1;
@@ -1408,7 +1628,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v
totface = ccgSubSurf_getNumFaces(ss);
for(a = 0, i = 0; i < totface; i++) {
- CCGFace *f = ccgdm->faceMap[i].face;
+ CCGFace *f = cgdm->faceMap[i].face;
int S, x, y, drawSmooth;
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
int origIndex = ccgDM_getFaceMapIndex(ss, f);
@@ -1507,19 +1727,19 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v
ccgFaceIterator_free(fi);
}
-static void ccgDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
+static void cgdm_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
}
-static void ccgDM_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), unsigned char *col1, unsigned char *col2) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+static void cgdm_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), unsigned char *col1, unsigned char *col2) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
int gridSize = ccgSubSurf_getGridSize(ss);
unsigned char *cp1, *cp2;
int useTwoSide=1;
- ccgdm_pbvh_update(ccgdm);
+ ccgdm_pbvh_update(cgdm);
cp1= col1;
if(col2) {
@@ -1580,27 +1800,27 @@ static void ccgDM_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), uns
ccgFaceIterator_free(fi);
}
-static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
+static void cgdm_drawFacesTex_common(DerivedMesh *dm,
int (*drawParams)(MTFace *tface, int has_mcol, int matnr),
int (*drawParamsMapped)(void *userData, int index),
void *userData)
{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
- MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
- MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
- char *faceFlags = ccgdm->faceFlags;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
+ MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
+ MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ char *faceFlags = cgdm->faceFlags;
int i, totface, flag, gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
- ccgdm_pbvh_update(ccgdm);
+ ccgdm_pbvh_update(cgdm);
if(!mcol)
- mcol = dm->getFaceDataArray(dm, CD_MCOL);
+ mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
totface = ccgSubSurf_getNumFaces(ss);
for(i = 0; i < totface; i++) {
- CCGFace *f = ccgdm->faceMap[i].face;
+ CCGFace *f = cgdm->faceMap[i].face;
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
@@ -1720,21 +1940,21 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
}
}
-static void ccgDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr))
+static void cgdm_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr))
{
- ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
+ cgdm_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
}
-static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
+static void cgdm_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
{
- ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
+ cgdm_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
}
-static void ccgDM_drawUVEdges(DerivedMesh *dm)
+static void cgdm_drawUVEdges(DerivedMesh *dm)
{
- MFace *mf = dm->getFaceArray(dm);
- MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
+ MFace *mf = dm->getTessFaceArray(dm);
+ MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
int i;
if (tf) {
@@ -1765,25 +1985,25 @@ static void ccgDM_drawUVEdges(DerivedMesh *dm)
static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs),
int (*compareDrawOptions)(void *userData, int cur_index, int next_index)) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
MCol *mcol= NULL;
int i, gridSize = ccgSubSurf_getGridSize(ss);
- char *faceFlags = ccgdm->faceFlags;
+ char *faceFlags = cgdm->faceFlags;
int gridFaces = gridSize - 1, totface;
/* currently unused -- each original face is handled separately */
(void)compareDrawOptions;
if(useColors) {
- mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
+ mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
if(!mcol)
- mcol = dm->getFaceDataArray(dm, CD_MCOL);
+ mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
}
totface = ccgSubSurf_getNumFaces(ss);
for(i = 0; i < totface; i++) {
- CCGFace *f = ccgdm->faceMap[i].face;
+ CCGFace *f = cgdm->faceMap[i].face;
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
int origIndex;
@@ -1883,9 +2103,9 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u
}
}
}
-static void ccgDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+static void cgdm_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
@@ -1913,9 +2133,9 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *u
ccgEdgeIterator_free(ei);
}
-static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+static void cgdm_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
@@ -1944,9 +2164,9 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(v
ccgEdgeIterator_free(ei);
}
-static void ccgDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
- CCGSubSurf *ss = ccgdm->ss;
+static void cgdm_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) {
+ CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = cgdm->ss;
CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
@@ -1964,7 +2184,7 @@ static void ccgDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *us
ccgFaceIterator_free(fi);
}
-static void ccgDM_release(DerivedMesh *dm) {
+static void cgdm_release(DerivedMesh *dm) {
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
if (DM_release(dm)) {
@@ -1977,6 +2197,10 @@ static void ccgDM_release(DerivedMesh *dm) {
ccgdm->multires.update(dm);
}
+ if (ccgdm->ehash)
+ BLI_edgehash_free(ccgdm->ehash, NULL);
+
+ if(ccgdm->reverseFaceMap) MEM_freeN(ccgdm->reverseFaceMap);
if(ccgdm->gridFaces) MEM_freeN(ccgdm->gridFaces);
if(ccgdm->gridData) MEM_freeN(ccgdm->gridData);
if(ccgdm->gridAdjacency) MEM_freeN(ccgdm->gridAdjacency);
@@ -1993,12 +2217,66 @@ static void ccgDM_release(DerivedMesh *dm) {
}
}
+static void ccg_loops_to_corners(CustomData *fdata, CustomData *ldata,
+ CustomData *pdata, int loopstart, int findex,
+ int polyindex, int numTex, int numCol)
+{
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ int i, j, hasWCol = CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL);
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
+ texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i);
+
+ texface->tpage = texpoly->tpage;
+ texface->flag = texpoly->flag;
+ texface->transp = texpoly->transp;
+ texface->mode = texpoly->mode;
+ texface->tile = texpoly->tile;
+ texface->unwrap = texpoly->unwrap;
+
+ mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i);
+ for (j=0; j<4; j++, mloopuv++) {
+ texface->uv[j][0] = mloopuv->uv[0];
+ texface->uv[j][1] = mloopuv->uv[1];
+ }
+ }
+
+ for(i=0; i < numCol; i++){
+ mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i);
+ mcol = CustomData_get_n(fdata, CD_MCOL, findex, i);
+
+ for (j=0; j<4; j++, mloopcol++) {
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
+ }
+
+ if (hasWCol) {
+ mloopcol = CustomData_get(ldata, loopstart, CD_WEIGHT_MLOOPCOL);
+ mcol = CustomData_get(fdata, findex, CD_WEIGHT_MCOL);
+
+ for (j=0; j<4; j++, mloopcol++) {
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
+ }
+}
+
static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type)
{
if(type == CD_ORIGINDEX) {
/* create origindex on demand to save memory */
- CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
- CCGSubSurf *ss= ccgdm->ss;
+ CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
+ CCGSubSurf *ss= cgdm->ss;
int *origindex;
int a, index, totnone, totorig;
@@ -2013,8 +2291,8 @@ static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type)
origindex[a]= ORIGINDEX_NONE;
for(index=0; index<totorig; index++, a++) {
- CCGVert *v = ccgdm->vertMap[index].vert;
- origindex[a] = ccgDM_getVertMapIndex(ccgdm->ss, v);
+ CCGVert *v = cgdm->vertMap[index].vert;
+ origindex[a] = ccgDM_getVertMapIndex(cgdm->ss, v);
}
return origindex;
@@ -2027,8 +2305,8 @@ static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type)
{
if(type == CD_ORIGINDEX) {
/* create origindex on demand to save memory */
- CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
- CCGSubSurf *ss= ccgdm->ss;
+ CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
+ CCGSubSurf *ss= cgdm->ss;
int *origindex;
int a, i, index, totnone, totorig, totedge;
int edgeSize= ccgSubSurf_getEdgeSize(ss);
@@ -2045,7 +2323,7 @@ static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type)
origindex[a]= ORIGINDEX_NONE;
for(index=0; index<totedge; index++) {
- CCGEdge *e= ccgdm->edgeMap[index].edge;
+ CCGEdge *e= cgdm->edgeMap[index].edge;
int mapIndex= ccgDM_getEdgeMapIndex(ss, e);
for(i = 0; i < edgeSize - 1; i++, a++)
@@ -2062,19 +2340,19 @@ static void *ccgDM_get_face_data_layer(DerivedMesh *dm, int type)
{
if(type == CD_ORIGINDEX) {
/* create origindex on demand to save memory */
- CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
- CCGSubSurf *ss= ccgdm->ss;
+ CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
+ CCGSubSurf *ss= cgdm->ss;
int *origindex;
int a, i, index, totface;
int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
DM_add_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
- origindex= DM_get_face_data_layer(dm, CD_ORIGINDEX);
+ origindex= DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
totface= ccgSubSurf_getNumFaces(ss);
for(a=0, index=0; index<totface; index++) {
- CCGFace *f = ccgdm->faceMap[index].face;
+ CCGFace *f = cgdm->faceMap[index].face;
int numVerts = ccgSubSurf_getFaceNumVerts(f);
int mapIndex = ccgDM_getFaceMapIndex(ss, f);
@@ -2085,19 +2363,19 @@ static void *ccgDM_get_face_data_layer(DerivedMesh *dm, int type)
return origindex;
}
- return DM_get_face_data_layer(dm, type);
+ return DM_get_tessface_data_layer(dm, type);
}
static int ccgDM_getNumGrids(DerivedMesh *dm)
{
- CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
+ CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
int index, numFaces, numGrids;
- numFaces= ccgSubSurf_getNumFaces(ccgdm->ss);
+ numFaces= ccgSubSurf_getNumFaces(cgdm->ss);
numGrids= 0;
for(index=0; index<numFaces; index++) {
- CCGFace *f = ccgdm->faceMap[index].face;
+ CCGFace *f = cgdm->faceMap[index].face;
numGrids += ccgSubSurf_getFaceNumVerts(f);
}
@@ -2106,11 +2384,11 @@ static int ccgDM_getNumGrids(DerivedMesh *dm)
static int ccgDM_getGridSize(DerivedMesh *dm)
{
- CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
- return ccgSubSurf_getGridSize(ccgdm->ss);
+ CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
+ return ccgSubSurf_getGridSize(cgdm->ss);
}
-static int ccgdm_adjacent_grid(CCGSubSurf *ss, int *gridOffset, CCGFace *f, int S, int offset)
+static int cgdm_adjacent_grid(CCGSubSurf *ss, int *gridOffset, CCGFace *f, int S, int offset)
{
CCGFace *adjf;
CCGEdge *e;
@@ -2143,15 +2421,15 @@ static int ccgdm_adjacent_grid(CCGSubSurf *ss, int *gridOffset, CCGFace *f, int
static void ccgdm_create_grids(DerivedMesh *dm)
{
- CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
- CCGSubSurf *ss= ccgdm->ss;
+ CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
+ CCGSubSurf *ss= cgdm->ss;
DMGridData **gridData;
DMGridAdjacency *gridAdjacency, *adj;
CCGFace **gridFaces;
int *gridOffset;
int index, numFaces, numGrids, S, gIndex /*, gridSize*/;
- if(ccgdm->gridData)
+ if(cgdm->gridData)
return;
numGrids = ccgDM_getNumGrids(dm);
@@ -2159,10 +2437,10 @@ static void ccgdm_create_grids(DerivedMesh *dm)
/*gridSize = ccgDM_getGridSize(dm);*/ /*UNUSED*/
/* compute offset into grid array for each face */
- gridOffset = MEM_mallocN(sizeof(int)*numFaces, "ccgdm.gridOffset");
+ gridOffset = MEM_mallocN(sizeof(int)*numFaces, "cgdm.gridOffset");
for(gIndex = 0, index = 0; index < numFaces; index++) {
- CCGFace *f = ccgdm->faceMap[index].face;
+ CCGFace *f = cgdm->faceMap[index].face;
int numVerts = ccgSubSurf_getFaceNumVerts(f);
gridOffset[index] = gIndex;
@@ -2170,12 +2448,12 @@ static void ccgdm_create_grids(DerivedMesh *dm)
}
/* compute grid data */
- gridData = MEM_mallocN(sizeof(DMGridData*)*numGrids, "ccgdm.gridData");
- gridAdjacency = MEM_mallocN(sizeof(DMGridAdjacency)*numGrids, "ccgdm.gridAdjacency");
- gridFaces = MEM_mallocN(sizeof(CCGFace*)*numGrids, "ccgdm.gridFaces");
+ gridData = MEM_mallocN(sizeof(DMGridData*)*numGrids, "cgdm.gridData");
+ gridAdjacency = MEM_mallocN(sizeof(DMGridAdjacency)*numGrids, "cgdm.gridAdjacency");
+ gridFaces = MEM_mallocN(sizeof(CCGFace*)*numGrids, "cgdm.gridFaces");
for(gIndex = 0, index = 0; index < numFaces; index++) {
- CCGFace *f = ccgdm->faceMap[index].face;
+ CCGFace *f = cgdm->faceMap[index].face;
int numVerts = ccgSubSurf_getFaceNumVerts(f);
for(S = 0; S < numVerts; S++, gIndex++) {
@@ -2189,43 +2467,43 @@ static void ccgdm_create_grids(DerivedMesh *dm)
adj->index[0] = gIndex - S + nextS;
adj->rotation[0] = 3;
- adj->index[1] = ccgdm_adjacent_grid(ss, gridOffset, f, prevS, 0);
+ adj->index[1] = cgdm_adjacent_grid(ss, gridOffset, f, prevS, 0);
adj->rotation[1] = 1;
- adj->index[2] = ccgdm_adjacent_grid(ss, gridOffset, f, S, 1);
+ adj->index[2] = cgdm_adjacent_grid(ss, gridOffset, f, S, 1);
adj->rotation[2] = 3;
adj->index[3] = gIndex - S + prevS;
adj->rotation[3] = 1;
}
}
- ccgdm->gridData = gridData;
- ccgdm->gridFaces = gridFaces;
- ccgdm->gridAdjacency = gridAdjacency;
- ccgdm->gridOffset = gridOffset;
+ cgdm->gridData = gridData;
+ cgdm->gridFaces = gridFaces;
+ cgdm->gridAdjacency = gridAdjacency;
+ cgdm->gridOffset = gridOffset;
}
static DMGridData **ccgDM_getGridData(DerivedMesh *dm)
{
- CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
+ CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
ccgdm_create_grids(dm);
- return ccgdm->gridData;
+ return cgdm->gridData;
}
static DMGridAdjacency *ccgDM_getGridAdjacency(DerivedMesh *dm)
{
- CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
+ CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
ccgdm_create_grids(dm);
- return ccgdm->gridAdjacency;
+ return cgdm->gridAdjacency;
}
static int *ccgDM_getGridOffset(DerivedMesh *dm)
{
- CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
+ CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
ccgdm_create_grids(dm);
- return ccgdm->gridOffset;
+ return cgdm->gridOffset;
}
static ListBase *ccgDM_getFaceMap(Object *ob, DerivedMesh *dm)
@@ -2312,50 +2590,74 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
int useSubsurfUv,
DerivedMesh *dm)
{
- CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
+ CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "cgdm");
CCGVertIterator *vi;
CCGEdgeIterator *ei;
CCGFaceIterator *fi;
int index, totvert, totedge, totface;
int i;
int vertNum, edgeNum, faceNum;
+ int *vertOrigIndex, *faceOrigIndex, *polyOrigIndex, *base_polyOrigIndex; /* *edgeOrigIndex - as yet, unused */
short *edgeFlags;
char *faceFlags;
- int edgeSize;
+ int *loopidx = NULL, *vertidx = NULL;
+ BLI_array_declare(loopidx);
+ BLI_array_declare(vertidx);
+ int loopindex, loopindex2;
+ int edgeSize, has_edge_origindex;
int gridSize;
- int gridFaces;
+ int gridFaces, gridCuts;
/*int gridSideVerts;*/
int gridSideEdges;
+ int numTex, numCol;
int gridInternalEdges;
+ float *w = NULL;
+ WeightTable wtable = {0};
+ MCol *mcol;
MEdge *medge = NULL;
- MFace *mface = NULL;
- int *orig_indices;
- FaceVertWeight *qweight, *tweight;
+ /* MFace *mface = NULL; */
+ MPoly *mpoly = NULL;
DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM,
ccgSubSurf_getNumFinalVerts(ss),
ccgSubSurf_getNumFinalEdges(ss),
+ ccgSubSurf_getNumFinalFaces(ss),
+ ccgSubSurf_getNumFinalFaces(ss)*4,
ccgSubSurf_getNumFinalFaces(ss));
+
+ numTex = CustomData_number_of_layers(&ccgdm->dm.loopData, CD_MLOOPUV);
+ numCol = CustomData_number_of_layers(&ccgdm->dm.loopData, CD_MLOOPCOL);
+
+ if (numTex && CustomData_number_of_layers(&ccgdm->dm.faceData, CD_MTFACE) != numTex)
+ CustomData_from_bmeshpoly(&ccgdm->dm.faceData, &ccgdm->dm.polyData, &ccgdm->dm.loopData, ccgSubSurf_getNumFinalFaces(ss));
+ else if (numCol && CustomData_number_of_layers(&ccgdm->dm.faceData, CD_MCOL) != numCol)
+ CustomData_from_bmeshpoly(&ccgdm->dm.faceData, &ccgdm->dm.polyData, &ccgdm->dm.loopData, ccgSubSurf_getNumFinalFaces(ss));
+
+ ccgdm->dm.getMinMax = cgdm_getMinMax;
+ ccgdm->dm.getNumVerts = cgdm_getNumVerts;
+ ccgdm->dm.getNumEdges = cgdm_getNumEdges;
+ ccgdm->dm.getNumTessFaces = cgdm_getNumTessFaces;
+ ccgdm->dm.getNumFaces = cgdm_getNumTessFaces;
- ccgdm->dm.getMinMax = ccgDM_getMinMax;
- ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
- ccgdm->dm.getNumFaces = ccgDM_getNumFaces;
+ ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
+ ccgdm->dm.getPBVH = ccgDM_getPBVH;
- ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
ccgdm->dm.getVert = ccgDM_getFinalVert;
ccgdm->dm.getEdge = ccgDM_getFinalEdge;
- ccgdm->dm.getFace = ccgDM_getFinalFace;
+ ccgdm->dm.getTessFace = ccgDM_getFinalFace;
ccgdm->dm.getVertCo = ccgDM_getFinalVertCo;
ccgdm->dm.getVertNo = ccgDM_getFinalVertNo;
ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
- ccgdm->dm.copyFaceArray = ccgDM_copyFinalFaceArray;
+ ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray;
+ ccgdm->dm.copyLoopArray = ccgDM_copyFinalLoopArray;
+ ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray;
ccgdm->dm.getVertData = DM_get_vert_data;
ccgdm->dm.getEdgeData = DM_get_edge_data;
- ccgdm->dm.getFaceData = DM_get_face_data;
+ ccgdm->dm.getTessFaceData = DM_get_face_data;
ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer;
ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer;
- ccgdm->dm.getFaceDataArray = ccgDM_get_face_data_layer;
+ ccgdm->dm.getTessFaceDataArray = ccgDM_get_face_data_layer;
ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
ccgdm->dm.getGridSize = ccgDM_getGridSize;
ccgdm->dm.getGridData = ccgDM_getGridData;
@@ -2364,34 +2666,45 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->dm.getFaceMap = ccgDM_getFaceMap;
ccgdm->dm.getPBVH = ccgDM_getPBVH;
- ccgdm->dm.getVertCos = ccgdm_getVertCos;
- ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
- ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge;
- ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter;
+ ccgdm->dm.getTessFace = ccgDM_getFinalFace;
+ ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
+ ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
+ ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray;
+ ccgdm->dm.getVertData = DM_get_vert_data;
+ ccgdm->dm.getEdgeData = DM_get_edge_data;
+ ccgdm->dm.getTessFaceData = DM_get_face_data;
+ ccgdm->dm.getVertDataArray = DM_get_vert_data_layer;
+ ccgdm->dm.getEdgeDataArray = DM_get_edge_data_layer;
+ ccgdm->dm.getTessFaceDataArray = DM_get_tessface_data_layer;
+
+ ccgdm->dm.getVertCos = cgdm_getVertCos;
+ ccgdm->dm.foreachMappedVert = cgdm_foreachMappedVert;
+ ccgdm->dm.foreachMappedEdge = cgdm_foreachMappedEdge;
+ ccgdm->dm.foreachMappedFaceCenter = cgdm_foreachMappedFaceCenter;
ccgdm->dm.drawVerts = ccgDM_drawVerts;
ccgdm->dm.drawEdges = ccgDM_drawEdges;
ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges;
ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
- ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
- ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
- ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
+ ccgdm->dm.drawFacesColored = cgdm_drawFacesColored;
+ ccgdm->dm.drawFacesTex = cgdm_drawFacesTex;
+ ccgdm->dm.drawFacesGLSL = cgdm_drawFacesGLSL;
ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
- ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
- ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
- ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
+ ccgdm->dm.drawMappedFacesTex = cgdm_drawMappedFacesTex;
+ ccgdm->dm.drawMappedFacesGLSL = cgdm_drawMappedFacesGLSL;
+ ccgdm->dm.drawUVEdges = cgdm_drawUVEdges;
- ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
- ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
+ ccgdm->dm.drawMappedEdgesInterp = cgdm_drawMappedEdgesInterp;
+ ccgdm->dm.drawMappedEdges = cgdm_drawMappedEdges;
- ccgdm->dm.release = ccgDM_release;
+ ccgdm->dm.release = cgdm_release;
ccgdm->ss = ss;
ccgdm->drawInteriorEdges = drawInteriorEdges;
ccgdm->useSubsurfUv = useSubsurfUv;
totvert = ccgSubSurf_getNumVerts(ss);
- ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
+ ccgdm->vertMap = MEM_callocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
vi = ccgSubSurf_getVertIterator(ss);
for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
CCGVert *v = ccgVertIterator_getCurrent(vi);
@@ -2401,7 +2714,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgVertIterator_free(vi);
totedge = ccgSubSurf_getNumEdges(ss);
- ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
+ ccgdm->edgeMap = MEM_callocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
ei = ccgSubSurf_getEdgeIterator(ss);
for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
@@ -2410,7 +2723,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
}
totface = ccgSubSurf_getNumFaces(ss);
- ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
+ ccgdm->faceMap = MEM_callocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
fi = ccgSubSurf_getFaceIterator(ss);
for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
CCGFace *f = ccgFaceIterator_getCurrent(fi);
@@ -2419,139 +2732,190 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
}
ccgFaceIterator_free(fi);
+ ccgdm->reverseFaceMap = MEM_callocN(sizeof(int)*ccgSubSurf_getNumFinalFaces(ss), "reverseFaceMap");
+
edgeSize = ccgSubSurf_getEdgeSize(ss);
gridSize = ccgSubSurf_getGridSize(ss);
gridFaces = gridSize - 1;
- /*gridSideVerts = gridSize - 2;*/ /*UNUSED*/
- /*gridInternalVerts = gridSideVerts * gridSideVerts; */ /*UNUSED*/
+ gridCuts = gridSize - 2;
+ /*gridInternalVerts = gridSideVerts * gridSideVerts; - as yet, unused */
gridSideEdges = gridSize - 1;
gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
- calc_ss_weights(gridFaces, &qweight, &tweight);
-
vertNum = 0;
edgeNum = 0;
faceNum = 0;
- /* mvert = dm->getVertArray(dm); - as yet unused */
+ /* mvert = dm->getVertArray(dm); */ /* UNUSED */
medge = dm->getEdgeArray(dm);
- mface = dm->getFaceArray(dm);
+ /* mface = dm->getTessFaceArray(dm); */ /* UNUSED */
+ mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
+ base_polyOrigIndex = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
+
+ /*CDDM hack*/
+ edgeFlags = ccgdm->edgeFlags = MEM_callocN(sizeof(short)*totedge, "faceFlags");
faceFlags = ccgdm->faceFlags = MEM_callocN(sizeof(char)*2*totface, "faceFlags");
- orig_indices = (int*)ccgdm->dm.getFaceDataArray(&ccgdm->dm, CD_ORIGINDEX);
- for(index = 0; index < totface; ++index) {
+ vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX);
+ /*edgeOrigIndex = DM_get_edge_data_layer(&cgdm->dm, CD_ORIGINDEX);*/
+ faceOrigIndex = DM_get_tessface_data_layer(&ccgdm->dm, CD_ORIGINDEX);
+
+ polyOrigIndex = DM_get_face_data_layer(&ccgdm->dm, CD_ORIGINDEX);
+
+ if (!CustomData_has_layer(&ccgdm->dm.faceData, CD_MCOL))
+ DM_add_tessface_layer(&ccgdm->dm, CD_MCOL, CD_CALLOC, NULL);
+
+ mcol = DM_get_tessface_data_layer(&ccgdm->dm, CD_MCOL);
+ has_edge_origindex = CustomData_has_layer(&ccgdm->dm.edgeData, CD_ORIGINDEX);
+
+ faceNum = 0;
+ loopindex = loopindex2 = 0; //current loop index
+ for (index = 0; index < totface; index++) {
CCGFace *f = ccgdm->faceMap[index].face;
int numVerts = ccgSubSurf_getFaceNumVerts(f);
int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges);
int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
- FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
- int S, x, y;
- int vertIdx[4];
+ int g2_wid = gridCuts+2;
+ float *w2;
+ int s, x, y;
+
+ origIndex = base_polyOrigIndex ? base_polyOrigIndex[origIndex] : origIndex;
+
+ w = get_ss_weights(&wtable, gridCuts, numVerts);
ccgdm->faceMap[index].startVert = vertNum;
ccgdm->faceMap[index].startEdge = edgeNum;
ccgdm->faceMap[index].startFace = faceNum;
-
- if(orig_indices)
- orig_indices[faceNum] = origIndex;
+
+ faceFlags[0] = mpoly ? mpoly[origIndex].flag : 0;
+ faceFlags[1] = mpoly ? mpoly[origIndex].mat_nr : 0;
+ faceFlags += 2;
/* set the face base vert */
*((int*)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
- for(S = 0; S < numVerts; S++) {
- CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
+ BLI_array_empty(loopidx);
+ for (s=0; s<numVerts; s++) {
+ BLI_array_growone(loopidx);
+ loopidx[s] = loopindex++;
+ }
+
+ BLI_array_empty(vertidx);
+ for(s = 0; s < numVerts; s++) {
+ CCGVert *v = ccgSubSurf_getFaceVert(ss, f, s);
+
+ BLI_array_growone(vertidx);
+ vertidx[s] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
+ }
+
- vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
+ /*I think this is for interpolating the center vert?*/
+ w2 = w; // + numVerts*(g2_wid-1)*(g2_wid-1); //numVerts*((g2_wid-1)*g2_wid+g2_wid-1);
+ DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2,
+ numVerts, vertNum);
+ if (vertOrigIndex) {
+ *vertOrigIndex = ORIGINDEX_NONE;
+ ++vertOrigIndex;
}
- DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, weight[0][0],
- numVerts, vertNum);
++vertNum;
- for(S = 0; S < numVerts; S++) {
- int prevS = (S - 1 + numVerts) % numVerts;
- int nextS = (S + 1) % numVerts;
- int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
+ /*interpolate per-vert data*/
+ for(s = 0; s < numVerts; s++) {
for(x = 1; x < gridFaces; x++) {
- float w[4];
- w[prevS] = weight[x][0][0];
- w[S] = weight[x][0][1];
- w[nextS] = weight[x][0][2];
- w[otherS] = weight[x][0][3];
- DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
- numVerts, vertNum);
+ w2 = w + s*numVerts*g2_wid*g2_wid + x*numVerts;
+ DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2,
+ numVerts, vertNum);
+
+ if (vertOrigIndex) {
+ *vertOrigIndex = ORIGINDEX_NONE;
+ ++vertOrigIndex;
+ }
+
++vertNum;
}
}
- for(S = 0; S < numVerts; S++) {
- int prevS = (S - 1 + numVerts) % numVerts;
- int nextS = (S + 1) % numVerts;
- int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
+ /*interpolate per-vert data*/
+ for(s = 0; s < numVerts; s++) {
for(y = 1; y < gridFaces; y++) {
for(x = 1; x < gridFaces; x++) {
- float w[4];
- w[prevS] = weight[y * gridFaces + x][0][0];
- w[S] = weight[y * gridFaces + x][0][1];
- w[nextS] = weight[y * gridFaces + x][0][2];
- w[otherS] = weight[y * gridFaces + x][0][3];
- DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
- numVerts, vertNum);
+ w2 = w + s*numVerts*g2_wid*g2_wid + (y*g2_wid+x)*numVerts;
+ DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2,
+ numVerts, vertNum);
+
+ if (vertOrigIndex) {
+ *vertOrigIndex = ORIGINDEX_NONE;
+ ++vertOrigIndex;
+ }
+
++vertNum;
}
}
}
- for(S = 0; S < numVerts; S++) {
- int prevS = (S - 1 + numVerts) % numVerts;
- int nextS = (S + 1) % numVerts;
- int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
-
- weight = (numVerts == 4) ? qweight : tweight;
-
- for(y = 0; y < gridFaces; y++) {
- for(x = 0; x < gridFaces; x++) {
- FaceVertWeight w;
- int j;
-
- for(j = 0; j < 4; ++j) {
- w[j][prevS] = (*weight)[j][0];
- w[j][S] = (*weight)[j][1];
- w[j][nextS] = (*weight)[j][2];
- w[j][otherS] = (*weight)[j][3];
+ if (has_edge_origindex) {
+ for(i = 0; i < numFinalEdges; ++i)
+ *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i,
+ CD_ORIGINDEX) = ORIGINDEX_NONE;
+ }
+
+ for (s=0; s<numVerts; s++) {
+ /*interpolate per-face data*/
+ for (y=0; y<gridFaces; y++) {
+ for (x=0; x<gridFaces; x++) {
+ w2 = w + s*numVerts*g2_wid*g2_wid + (y*g2_wid+x)*numVerts;
+ CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
+ loopidx, w2, NULL, numVerts, loopindex2);
+ loopindex2++;
+
+ w2 = w + s*numVerts*g2_wid*g2_wid + ((y+1)*g2_wid+(x))*numVerts;
+ CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
+ loopidx, w2, NULL, numVerts, loopindex2);
+ loopindex2++;
+
+ w2 = w + s*numVerts*g2_wid*g2_wid + ((y+1)*g2_wid+(x+1))*numVerts;
+ CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
+ loopidx, w2, NULL, numVerts, loopindex2);
+ loopindex2++;
+
+ w2 = w + s*numVerts*g2_wid*g2_wid + ((y)*g2_wid+(x+1))*numVerts;
+ CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
+ loopidx, w2, NULL, numVerts, loopindex2);
+ loopindex2++;
+
+ /*copy over poly data, e.g. mtexpoly*/
+ CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1);
+
+ /*generate tesselated face data used for drawing*/
+ ccg_loops_to_corners(&ccgdm->dm.faceData, &ccgdm->dm.loopData,
+ &ccgdm->dm.polyData, loopindex2-4, faceNum, faceNum, numTex, numCol);
+
+ /*set original index data*/
+ if (faceOrigIndex) {
+ *faceOrigIndex = origIndex;
+ faceOrigIndex++;
+ }
+ if (polyOrigIndex) {
+ *polyOrigIndex = origIndex;
+ polyOrigIndex++;
}
- DM_interp_face_data(dm, &ccgdm->dm, &origIndex, NULL,
- &w, 1, faceNum);
- weight++;
+ ccgdm->reverseFaceMap[faceNum] = index;
- ++faceNum;
+ faceNum++;
}
}
}
- faceFlags[index*2] = mface[origIndex].flag;
- faceFlags[index*2 + 1] = mface[origIndex].mat_nr;
-
edgeNum += numFinalEdges;
}
- if(useSubsurfUv) {
- CustomData *fdata = &ccgdm->dm.faceData;
- CustomData *dmfdata = &dm->faceData;
- int numlayer = CustomData_number_of_layers(fdata, CD_MTFACE);
- int dmnumlayer = CustomData_number_of_layers(dmfdata, CD_MTFACE);
-
- for (i=0; i<numlayer && i<dmnumlayer; i++)
- set_subsurf_uv(ss, dm, &ccgdm->dm, i);
- }
-
- edgeFlags = ccgdm->edgeFlags = MEM_callocN(sizeof(short)*totedge, "edgeFlags");
-
for(index = 0; index < totedge; ++index) {
CCGEdge *e = ccgdm->edgeMap[index].edge;
int numFinalEdges = edgeSize - 1;
+ int mapIndex = ccgDM_getEdgeMapIndex(ss, e);
int x;
int vertIdx[2];
int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
@@ -2565,6 +2929,9 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->edgeMap[index].startVert = vertNum;
ccgdm->edgeMap[index].startEdge = edgeNum;
+ if(edgeIdx >= 0 && edgeFlags)
+ edgeFlags[edgeIdx] = medge[edgeIdx].flag;
+
/* set the edge base vert */
*((int*)ccgSubSurf_getEdgeUserData(ss, e)) = vertNum;
@@ -2573,32 +2940,53 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
w[1] = (float) x / (edgeSize - 1);
w[0] = 1 - w[1];
DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, 2, vertNum);
+ if (vertOrigIndex) {
+ *vertOrigIndex = ORIGINDEX_NONE;
+ ++vertOrigIndex;
+ }
++vertNum;
}
- edgeFlags[index]= medge[edgeIdx].flag;
+ for(i = 0; i < numFinalEdges; ++i) {
+ if (has_edge_origindex) {
+ *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i,
+ CD_ORIGINDEX) = mapIndex;
+ }
+ }
edgeNum += numFinalEdges;
}
for(index = 0; index < totvert; ++index) {
CCGVert *v = ccgdm->vertMap[index].vert;
- int vertIdx;
+ int mapIndex = ccgDM_getVertMapIndex(ccgdm->ss, v);
+ int vidx;
- vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
+ vidx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
ccgdm->vertMap[index].startVert = vertNum;
/* set the vert base vert */
*((int*) ccgSubSurf_getVertUserData(ss, v)) = vertNum;
- DM_copy_vert_data(dm, &ccgdm->dm, vertIdx, vertNum, 1);
+ DM_copy_vert_data(dm, &ccgdm->dm, vidx, vertNum, 1);
+ if (vertOrigIndex) {
+ *vertOrigIndex = mapIndex;
+ ++vertOrigIndex;
+ }
++vertNum;
}
- MEM_freeN(qweight);
- MEM_freeN(tweight);
+ ccgdm->dm.numVertData = vertNum;
+ ccgdm->dm.numEdgeData = edgeNum;
+ ccgdm->dm.numFaceData = faceNum;
+ ccgdm->dm.numLoopData = loopindex2;
+ ccgdm->dm.numPolyData = faceNum;
+
+ BLI_array_free(vertidx);
+ BLI_array_free(loopidx);
+ free_ss_weights(&wtable);
return ccgdm;
}
@@ -2615,7 +3003,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr;
int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv;
int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
- CCGDerivedMesh *result;
+ CCGDerivedMesh *result = NULL;
if(forEditMode) {
int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels;
@@ -2644,7 +3032,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
result->freeSS = 1;
} else {
- int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental);
+ int useIncremental = 1; //(smd->flags & eSubsurfModifierFlag_Incremental);
int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr;
int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels;
CCGSubSurf *ss;
@@ -2669,7 +3057,14 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
smd->mCache = ss = _getSubSurf(smd->mCache, levels,
useAging, 0, useSimple);
- ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
+ if (!ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple)) {
+ //ccgSubSurf_free(smd->mCache);
+ smd->mCache = ss = _getSubSurf(NULL, levels,
+ useAging, 0, useSimple);
+
+ ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
+
+ }
result = getCCGDerivedMesh(smd->mCache,
drawInteriorEdges,
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index b7fc2835f63..42415248bdc 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -814,10 +814,6 @@ Tex *localize_texture(Tex *tex)
/* ------------------------------------------------------------------------- */
-static void extern_local_texture(Tex *tex) {
- id_lib_extern((ID *)tex->ima);
-}
-
void make_local_texture(Tex *tex)
{
Main *bmain= G.main;
@@ -836,9 +832,18 @@ void make_local_texture(Tex *tex)
if(tex->id.lib==NULL) return;
+ /* special case: ima always local immediately */
+ if(tex->ima) {
+ tex->ima->id.lib= NULL;
+ tex->ima->id.flag= LIB_LOCAL;
+ new_id(&bmain->image, (ID *)tex->ima, NULL);
+ }
+
if(tex->id.us==1) {
- id_clear_lib_data(&bmain->tex, (ID *)tex);
- extern_local_texture(tex);
+ tex->id.lib= NULL;
+ tex->id.flag= LIB_LOCAL;
+ new_id(&bmain->tex, (ID *)tex, NULL);
+
return;
}
@@ -892,8 +897,9 @@ void make_local_texture(Tex *tex)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->tex, (ID *)tex);
- extern_local_texture(tex);
+ tex->id.lib= NULL;
+ tex->id.flag= LIB_LOCAL;
+ new_id(&bmain->tex, (ID *)tex, NULL);
}
else if(local && lib) {
texn= copy_texture(tex);
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 150bf7157d9..5c705c5fe94 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -160,7 +160,9 @@ void make_local_world(World *wrld)
if(wrld->id.lib==NULL) return;
if(wrld->id.us==1) {
- id_clear_lib_data(&bmain->world, (ID *)wrld);
+ wrld->id.lib= NULL;
+ wrld->id.flag= LIB_LOCAL;
+ new_id(NULL, (ID *)wrld, NULL);
return;
}
@@ -172,7 +174,9 @@ void make_local_world(World *wrld)
}
if(local && lib==0) {
- id_clear_lib_data(&bmain->world, (ID *)wrld);
+ wrld->id.lib= NULL;
+ wrld->id.flag= LIB_LOCAL;
+ new_id(NULL, (ID *)wrld, NULL);
}
else if(local && lib) {
World *wrldn= copy_world(wrld);
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index da1412dac0d..ed0a351716c 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -396,20 +396,6 @@ static void set_ffmpeg_property_option(AVCodecContext* c, IDProperty * prop)
}
}
-static int ffmpeg_proprty_valid(AVCodecContext *c, const char *prop_name, IDProperty *curr)
-{
- int valid= 1;
-
- if(strcmp(prop_name, "video")==0) {
- if(strcmp(curr->name, "bf")==0) {
- /* flash codec doesn't support b frames */
- valid&= c->codec_id!=CODEC_ID_FLV1;
- }
- }
-
- return valid;
-}
-
static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char * prop_name)
{
IDProperty * prop;
@@ -428,8 +414,7 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char
iter = IDP_GetGroupIterator(prop);
while ((curr = IDP_GroupIterNext(iter)) != NULL) {
- if(ffmpeg_proprty_valid(c, prop_name, curr))
- set_ffmpeg_property_option(c, curr);
+ set_ffmpeg_property_option(c, curr);
}
}
@@ -1102,7 +1087,7 @@ IDProperty *ffmpeg_property_add(RenderData *rd, char * type, int opt_index, int
idp_type = IDP_FLOAT;
break;
case FF_OPT_TYPE_STRING:
- val.str = (char *)" ";
+ val.str = " ";
idp_type = IDP_STRING;
break;
case FF_OPT_TYPE_CONST:
@@ -1202,9 +1187,6 @@ void ffmpeg_set_preset(RenderData *rd, int preset)
{
int isntsc = (rd->frs_sec != 25);
- if(rd->ffcodecdata.properties)
- IDP_FreeProperty(rd->ffcodecdata.properties);
-
switch (preset) {
case FFMPEG_PRESET_VCD:
rd->ffcodecdata.type = FFMPEG_MPEG1;
@@ -1235,11 +1217,8 @@ void ffmpeg_set_preset(RenderData *rd, int preset)
case FFMPEG_PRESET_DVD:
rd->ffcodecdata.type = FFMPEG_MPEG2;
rd->ffcodecdata.video_bitrate = 6000;
-
- /* Don't set resolution, see [#21351]
- * rd->xsch = 720;
- * rd->ysch = isntsc ? 480 : 576; */
-
+ rd->xsch = 720;
+ rd->ysch = isntsc ? 480 : 576;
rd->ffcodecdata.gop_size = isntsc ? 18 : 15;
rd->ffcodecdata.rc_max_rate = 9000;
rd->ffcodecdata.rc_min_rate = 0;
@@ -1342,8 +1321,8 @@ void ffmpeg_verify_image_type(RenderData *rd)
rd->ffcodecdata.video_bitrate <= 1) {
rd->ffcodecdata.codec = CODEC_ID_MPEG2VIDEO;
-
- ffmpeg_set_preset(rd, FFMPEG_PRESET_DVD);
+ /* Don't set preset, disturbs render resolution.
+ * ffmpeg_set_preset(rd, FFMPEG_PRESET_DVD); */
}
if(rd->ffcodecdata.type == FFMPEG_OGG) {
rd->ffcodecdata.type = FFMPEG_MPEG2;
@@ -1377,3 +1356,4 @@ void ffmpeg_verify_image_type(RenderData *rd)
}
#endif
+
diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h
new file mode 100644
index 00000000000..b9bc3d456d6
--- /dev/null
+++ b/source/blender/blenlib/BLI_array.h
@@ -0,0 +1,162 @@
+/**
+ * Array Library
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Eagar.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+this library needs to be changed to not use macros quite so heavily,
+and to be more of a complete array API. The way arrays are
+exposed to client code as normal C arrays is very useful though, imho.
+it does require some use of macros, however.
+
+anyway, it's used a bit too heavily to simply rewrite as a
+more "correct" solution without macros entirely. I originally wrote this
+to be very easy to use, without the normal pain of most array libraries.
+This was especially helpful when it came to the massive refactors necessary for
+bmesh, and really helped to speed the process up. - joeedh
+
+little array macro library. example of usage:
+
+int *arr = NULL;
+BLI_array_declare(arr);
+int i;
+
+for (i=0; i<10; i++) {
+ BLI_array_growone(arr);
+ arr[i] = something;
+}
+BLI_array_free(arr);
+
+arrays are buffered, using double-buffering (so on each reallocation,
+the array size is doubled). supposedly this should give good Big Oh
+behaviour, though it may not be the best in practice.
+*/
+
+#define BLI_array_declare(arr) \
+ int _##arr##_count=0; \
+ void *_##arr##_tmp; \
+ void *_##arr##_static = NULL
+
+/* this will use stack space, up to maxstatic array elements, befoe
+ * switching to dynamic heap allocation */
+#define BLI_array_staticdeclare(arr, maxstatic) \
+ int _##arr##_count=0; \
+ void *_##arr##_tmp; \
+ char _##arr##_static[maxstatic*sizeof(arr)]
+
+
+/* this returns the entire size of the array, including any buffering. */
+#define BLI_array_totalsize_dyn(arr) ( \
+ ((arr)==NULL) ? \
+ 0 : \
+ MEM_allocN_len(arr) / sizeof(*arr) \
+)
+
+
+#define BLI_array_totalsize(arr) ( \
+ (signed int) \
+ (((void *)(arr) == (void *)_##arr##_static && (void *)(arr) != NULL) ? \
+ (sizeof(_##arr##_static) / sizeof(*arr)) : \
+ BLI_array_totalsize_dyn(arr)) \
+)
+
+
+/* this returns the logical size of the array, not including buffering. */
+#define BLI_array_count(arr) _##arr##_count
+
+/* grow the array by one. zeroes the new elements. */
+#define _BLI_array_growone(arr) ( \
+ (BLI_array_totalsize(arr) > _##arr##_count) ? \
+ ++_##arr##_count : \
+ ((_##arr##_tmp = MEM_callocN( \
+ sizeof(*arr)*(_##arr##_count*2+2), \
+ #arr " " __FILE__ ":" STRINGIFY(__LINE__) \
+ ) \
+ ), \
+ (arr && memcpy(_##arr##_tmp, arr, sizeof(*arr) * _##arr##_count)), \
+ (arr && ((void *)(arr) != (void*)_##arr##_static ? \
+ (MEM_freeN(arr), arr) : \
+ arr)), \
+ (arr = _##arr##_tmp), \
+ _##arr##_count++) \
+)
+
+
+/* returns length of array */
+#define BLI_array_growone(arr) ( \
+ ((void *)(arr)==NULL && (void *)(_##arr##_static) != NULL) ? \
+ ((arr=(void*)_##arr##_static), ++_##arr##_count) : \
+ _BLI_array_growone(arr) \
+)
+
+
+/* appends an item to the array and returns a pointer to the item in the array.
+ * item is not a pointer, but actual data value.*/
+#define BLI_array_append(arr, item) ( \
+ BLI_array_growone(arr), \
+ (arr[_##arr##_count-1] = item), \
+ (arr+(_##arr##_count-1)) \
+)
+
+
+/* grow an array by a specified number of items. */
+/* TODO, this could be done in a less crappy way by not looping - campbell */
+#define BLI_array_growitems(arr, num) \
+ { \
+ int _i; \
+ for (_i = 0; _i < (num); _i++) { \
+ BLI_array_growone(arr); \
+ } \
+ }
+
+#define BLI_array_free(arr) \
+ if (arr && (char *)arr != _##arr##_static) { \
+ BLI_array_fake_user(arr); \
+ MEM_freeN(arr); \
+ }
+
+#define BLI_array_pop(arr) ( \
+ (arr&&_##arr##_count) ? \
+ arr[--_##arr##_count] : \
+ 0 \
+)
+
+/* resets the logical size of an array to zero, but doesn't
+ * free the memory. */
+#define BLI_array_empty(arr) \
+ _##arr##_count=0
+
+/* set the count of the array, doesn't actually increase the allocated array
+ * size. don't use this unless you know what you're doing. */
+#define BLI_array_set_length(arr, count) \
+ _##arr##_count = (count)
+
+/* only to prevent unused warnings */
+#define BLI_array_fake_user(arr) \
+ (void)_##arr##_count, \
+ (void)_##arr##_tmp, \
+ (void)_##arr##_static
diff --git a/source/blender/blenlib/BLI_bpath.h b/source/blender/blenlib/BLI_bpath.h
index 5774d90912e..6101c94e26f 100644
--- a/source/blender/blenlib/BLI_bpath.h
+++ b/source/blender/blenlib/BLI_bpath.h
@@ -37,7 +37,6 @@
struct BPathIterator;
struct ReportList;
struct Main;
-struct ID;
void BLI_bpathIterator_init (struct BPathIterator **bpi, struct Main *bmain, const char *basedir, const int flag);
void BLI_bpathIterator_free (struct BPathIterator *bpi);
@@ -52,13 +51,6 @@ void BLI_bpathIterator_getPath (struct BPathIterator *bpi, char *path);
void BLI_bpathIterator_getPathExpanded (struct BPathIterator *bpi, char *path_expanded);
void BLI_bpathIterator_setPath (struct BPathIterator *bpi, const char *path);
-/* Function that does something with an ID's file path. Should return 1 if the
- path has changed, and in that case, should write the result to pathOut. */
-typedef int (*bpath_visitor)(void *userdata, char *pathIn, char *pathOut);
-/* Executes 'visit' for each path associated with 'id'. */
-void bpath_traverse_id(struct ID *id, bpath_visitor visit, void *userdata);
-int bpath_relocate_visitor(void *oldbasepath, char *pathIn, char *pathOut);
-
/* high level funcs */
/* creates a text file with missing files if there are any */
diff --git a/source/blender/blenlib/BLI_cellalloc.h b/source/blender/blenlib/BLI_cellalloc.h
new file mode 100644
index 00000000000..a6e779d5990
--- /dev/null
+++ b/source/blender/blenlib/BLI_cellalloc.h
@@ -0,0 +1,57 @@
+/**
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+ this evil bit of code is necassary for vgroups and multires to run fast
+ enough. it is surprisingly tricky allocate MDeformWeights and MDisps in
+ a way that doesn't cause severe performance problems. once a better solution
+ is found we can get rid of this code, but until then this is necassary
+ (though, disabling it if jedmalloc is in use might be feasible).
+
+ ideas for replacement:
+ ok, mdisps could store a mempool in CustomDataLayer. there might be
+ one there already? vgroups, uh. . .not sure what to do with vgroups,
+ they do cause a significant performance problem.
+
+ it's tempting to split vgroups into lots of little customdata layers,
+ but that would waste a LOT of memory. ugh. can we plug in jemalloc
+ to guardedalloc, on all platforms? that would work.
+
+ I really hate this little library; it really should be replaced before trunk
+ reintegration.
+
+ - joeedh
+*/
+
+void *BLI_cellalloc_malloc(long size, const char *tag);
+void *BLI_cellalloc_calloc(long size, const char *tag);
+void BLI_cellalloc_free(void *mem);
+void BLI_cellalloc_printleaks(void);
+int BLI_cellalloc_get_totblock(void);
+void BLI_cellalloc_destroy(void);
+void *BLI_cellalloc_dupalloc(void *mem);
diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h
index 283b52e06b9..58b63d3d2f9 100644
--- a/source/blender/blenlib/BLI_edgehash.h
+++ b/source/blender/blenlib/BLI_edgehash.h
@@ -34,6 +34,10 @@
* \brief A general unordered 2-int pair hash table ADT.
*/
+#include "MEM_guardedalloc.h"
+#include "BKE_utildefines.h"
+#include "BLI_mempool.h"
+
struct EdgeHash;
struct EdgeHashIterator;
typedef struct EdgeHash EdgeHash;
@@ -47,22 +51,22 @@ void BLI_edgehash_free (EdgeHash *eh, EdgeHashFreeFP valfreefp);
/* Insert edge (v0,v1) into hash with given value, does
* not check for duplicates.
*/
-void BLI_edgehash_insert (EdgeHash *eh, int v0, int v1, void *val);
+//void BLI_edgehash_insert (EdgeHash *eh, int v0, int v1, void *val);
/* Return value for given edge (v0,v1), or NULL if
* if key does not exist in hash. (If need exists
* to differentiate between key-value being NULL and
* lack of key then see BLI_edgehash_lookup_p().
*/
-void* BLI_edgehash_lookup (EdgeHash *eh, int v0, int v1);
+//void* BLI_edgehash_lookup (EdgeHash *eh, int v0, int v1);
/* Return pointer to value for given edge (v0,v1),
* or NULL if key does not exist in hash.
*/
-void** BLI_edgehash_lookup_p (EdgeHash *eh, int v0, int v1);
+//void** BLI_edgehash_lookup_p (EdgeHash *eh, int v0, int v1);
/* Return boolean true/false if edge (v0,v1) in hash. */
-int BLI_edgehash_haskey (EdgeHash *eh, int v0, int v1);
+//int BLI_edgehash_haskey (EdgeHash *eh, int v0, int v1);
/* Return number of keys in hash. */
int BLI_edgehash_size (EdgeHash *eh);
@@ -97,5 +101,99 @@ void BLI_edgehashIterator_step (EdgeHashIterator *ehi);
/* Determine if an iterator is done. */
int BLI_edgehashIterator_isDone (EdgeHashIterator *ehi);
+/**************inlined code************/
+static unsigned int _ehash_hashsizes[]= {
+ 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
+ 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
+ 4194319, 8388617, 16777259, 33554467, 67108879, 134217757,
+ 268435459
+};
+
+#define EDGEHASH(v0,v1) ((v0*39)^(v1*31))
+
+/***/
+
+typedef struct EdgeEntry EdgeEntry;
+struct EdgeEntry {
+ EdgeEntry *next;
+ int v0, v1;
+ void *val;
+};
+
+struct EdgeHash {
+ EdgeEntry **buckets;
+ BLI_mempool *epool;
+ int nbuckets, nentries, cursize;
+};
+
+
+BM_INLINE void BLI_edgehash_insert(EdgeHash *eh, int v0, int v1, void *val) {
+ unsigned int hash;
+ EdgeEntry *e= BLI_mempool_alloc(eh->epool);
+
+ if (v1<v0) {
+ v0 ^= v1;
+ v1 ^= v0;
+ v0 ^= v1;
+ }
+ hash = EDGEHASH(v0,v1)%eh->nbuckets;
+
+ e->v0 = v0;
+ e->v1 = v1;
+ e->val = val;
+ e->next= eh->buckets[hash];
+ eh->buckets[hash]= e;
+
+ if (++eh->nentries>eh->nbuckets*3) {
+ EdgeEntry *e, **old= eh->buckets;
+ int i, nold= eh->nbuckets;
+
+ eh->nbuckets= _ehash_hashsizes[++eh->cursize];
+ eh->buckets= MEM_mallocN(eh->nbuckets*sizeof(*eh->buckets), "eh buckets");
+ BMEMSET(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets));
+
+ for (i=0; i<nold; i++) {
+ for (e= old[i]; e;) {
+ EdgeEntry *n= e->next;
+
+ hash= EDGEHASH(e->v0,e->v1)%eh->nbuckets;
+ e->next= eh->buckets[hash];
+ eh->buckets[hash]= e;
+
+ e= n;
+ }
+ }
+
+ MEM_freeN(old);
+ }
+}
+
+BM_INLINE void** BLI_edgehash_lookup_p(EdgeHash *eh, int v0, int v1) {
+ unsigned int hash;
+ EdgeEntry *e;
+
+ if (v1<v0) {
+ v0 ^= v1;
+ v1 ^= v0;
+ v0 ^= v1;
+ }
+ hash = EDGEHASH(v0,v1)%eh->nbuckets;
+ for (e= eh->buckets[hash]; e; e= e->next)
+ if (v0==e->v0 && v1==e->v1)
+ return &e->val;
+
+ return NULL;
+}
+
+BM_INLINE void* BLI_edgehash_lookup(EdgeHash *eh, int v0, int v1) {
+ void **value_p = BLI_edgehash_lookup_p(eh,v0,v1);
+
+ return value_p?*value_p:NULL;
+}
+
+BM_INLINE int BLI_edgehash_haskey(EdgeHash *eh, int v0, int v1) {
+ return BLI_edgehash_lookup_p(eh, v0, v1)!=NULL;
+}
+
#endif
diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h
index ad36f86ea0f..3f20187dee1 100644
--- a/source/blender/blenlib/BLI_editVert.h
+++ b/source/blender/blenlib/BLI_editVert.h
@@ -43,6 +43,7 @@
struct DerivedMesh;
struct RetopoPaintData;
+struct BLI_mempool;
/* note; changing this also might affect the undo copy in editmesh.c */
typedef struct EditVert
@@ -156,6 +157,8 @@ typedef struct EditMesh
HashEdge *hashedgetab;
/* this is for the editmesh_fastmalloc */
+ struct BLI_mempool *vertpool, *edgepool, *facepool;
+
EditVert *allverts, *curvert;
EditEdge *alledges, *curedge;
EditFace *allfaces, *curface;
diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h
index 0e33ee2be3f..1463ff90e5a 100644
--- a/source/blender/blenlib/BLI_math_color.h
+++ b/source/blender/blenlib/BLI_math_color.h
@@ -86,6 +86,12 @@ void linearrgb_to_srgb_rgba_buf(float *col, int tot);
void srgb_to_linearrgb_rgba_rgba_buf(float *col_to, float *col_from, int tot);
void linearrgb_to_srgb_rgba_rgba_buf(float *col_to, float *col_from, int tot);
+/* rgba buffer convenience functions */
+void srgb_to_linearrgb_rgba_buf(float *col, int tot);
+void linearrgb_to_srgb_rgba_buf(float *col, int tot);
+void srgb_to_linearrgb_rgba_rgba_buf(float *col_to, float *col_from, int tot);
+void linearrgb_to_srgb_rgba_rgba_buf(float *col_to, float *col_from, int tot);
+
/************************** Other *************************/
int constrain_rgb(float *r, float *g, float *b);
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 713466f13f8..bc2d501645d 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -54,6 +54,8 @@ float area_tri_v3(const float a[3], const float b[3], const float c[3]);
float area_quad_v3(const float a[3], const float b[3], const float c[3], const float d[3]);
float area_poly_v3(int nr, float verts[][3], const float normal[3]);
+int is_quad_convex_v3(const float *v1, const float *v2, const float *v3, const float *v4);
+
/********************************* Distance **********************************/
float dist_to_line_v2(const float p[2], const float l1[2], const float l2[2]);
@@ -198,6 +200,9 @@ void accumulate_vertex_normals(float n1[3], float n2[3], float n3[3],
float n4[3], const float f_no[3], const float co1[3], const float co2[3],
const float co3[3], const float co4[3]);
+void accumulate_vertex_normals_poly(float **vertnos, float polyno[3],
+ float **vertcos, float vdiffs[][3], int nverts);
+
/********************************* Tangents **********************************/
typedef struct VertexTangent {
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index e259071a27a..9930960d745 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -38,6 +38,8 @@ extern "C" {
#ifdef BLI_MATH_INLINE_H
#include "intern/math_vector_inline.c"
+#else
+#define MINLINE
#endif
/************************************* Init ***********************************/
@@ -92,8 +94,6 @@ MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], floa
MINLINE void madd_v3_v3v3v3(float r[3], const float a[3], const float b[3], const float c[3]);
MINLINE void madd_v4_v4fl(float r[4], const float a[4], float f);
-MINLINE void negate_v2(float r[2]);
-MINLINE void negate_v2_v2(float r[2], const float a[2]);
MINLINE void negate_v3(float r[3]);
MINLINE void negate_v3_v3(float r[3], const float a[3]);
MINLINE void negate_v4(float r[4]);
@@ -163,6 +163,7 @@ float angle_v3v3v3(const float a[3], const float b[3], const float c[3]);
float angle_normalized_v3v3(const float v1[3], const float v2[3]);
void angle_tri_v3(float angles[3], const float v1[3], const float v2[3], const float v3[3]);
void angle_quad_v3(float angles[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
+void angle_poly_v3(float* angles, const float* verts[3], int len);
/********************************* Geometry **********************************/
diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h
index 2a81966986f..54b4e5584eb 100644
--- a/source/blender/blenlib/BLI_mempool.h
+++ b/source/blender/blenlib/BLI_mempool.h
@@ -34,12 +34,122 @@
* \brief Simple fast memory allocator.
*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
struct BLI_mempool;
-struct BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk, int use_sysmalloc);
-void *BLI_mempool_alloc(struct BLI_mempool *pool);
-void *BLI_mempool_calloc(struct BLI_mempool *pool);
-void BLI_mempool_free(struct BLI_mempool *pool, void *addr);
-void BLI_mempool_destroy(struct BLI_mempool *pool);
+#include "BLI_listbase.h"
+#include "BLI_blenlib.h"
+#include <string.h>
+
+typedef struct BLI_freenode{
+ struct BLI_freenode *next;
+ int freeword; /*used to identify this as a freed node*/
+}BLI_freenode;
+
+typedef struct BLI_mempool_chunk{
+ struct BLI_mempool_chunk *next, *prev;
+ void *data;
+}BLI_mempool_chunk;
+
+typedef struct BLI_mempool{
+ struct ListBase chunks;
+ int esize, csize, pchunk; /*size of elements and chunks in bytes and number of elements per chunk*/
+ BLI_freenode *free; /*free element list. Interleaved into chunk datas.*/
+ int totalloc, totused; /*total number of elements allocated in total, and currently in use*/
+ int use_sysmalloc, allow_iter;
+}BLI_mempool;
+
+/*allow_iter allows iteration on this mempool. note: this requires that the
+ first four bytes of the elements never contain the character string
+ 'free'. use with care.*/
+
+BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk,
+ int use_sysmalloc, int allow_iter);
+//void *BLI_mempool_alloc(BLI_mempool *pool);
+void *BLI_mempool_calloc(BLI_mempool *pool);
+void BLI_mempool_free(BLI_mempool *pool, void *addr);
+void BLI_mempool_destroy(BLI_mempool *pool);
+int BLI_mempool_count(BLI_mempool *pool);
+
+/** iteration stuff. note: this may easy to produce bugs with **/
+/*private structure*/
+typedef struct BLI_mempool_iter {
+ BLI_mempool *pool;
+ struct BLI_mempool_chunk *curchunk;
+ int curindex;
+} BLI_mempool_iter;
+
+/*allow iteration on this mempool. note: this requires that the
+ first four bytes of the elements never contain the character string
+ 'free'. use with care.*/
+void BLI_mempool_allow_iter(BLI_mempool *pool);
+void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter);
+void *BLI_mempool_iterstep(BLI_mempool_iter *iter);
+
+/* XXX - copied from BKE_utildefines.h, dont use here because we're in BLI */
+#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__hppa__) || defined (__BIG_ENDIAN__)
+ /* Big Endian */
+#define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
+#else
+ /* Little Endian */
+#define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
+#endif
+
+/************ inlined stuff ***********/
+#define FREEWORD MAKE_ID('f', 'r', 'e', 'e')
+#include "MEM_guardedalloc.h"
+
+BM_INLINE void *BLI_mempool_alloc(BLI_mempool *pool) {
+ void *retval=NULL;
+ BLI_freenode *curnode=NULL;
+ char *addr=NULL;
+
+ if (!pool) return NULL;
+
+ pool->totused++;
+
+ if (!(pool->free)) {
+ int j;
+ /*need to allocate a new chunk*/
+ BLI_mempool_chunk *mpchunk = pool->use_sysmalloc ? (BLI_mempool_chunk*)malloc(sizeof(BLI_mempool_chunk)) : (BLI_mempool_chunk*)MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
+ mpchunk->next = mpchunk->prev = NULL;
+ mpchunk->data = pool->use_sysmalloc ? malloc(pool->csize) : MEM_mallocN(pool->csize, "BLI_Mempool Chunk Data");
+ BLI_addtail(&(pool->chunks), mpchunk);
+
+ pool->free = (BLI_freenode*)mpchunk->data; /*start of the list*/
+ if (pool->allow_iter)
+ pool->free->freeword = FREEWORD;
+ for(addr = (char*)mpchunk->data, j=0; j < pool->pchunk; j++){
+ curnode = ((BLI_freenode*)addr);
+ addr += pool->esize;
+ curnode->next = (BLI_freenode*)addr;
+
+ if (pool->allow_iter) {
+ curnode->freeword = FREEWORD;
+ if (j != pool->pchunk-1)
+ curnode->next->freeword = FREEWORD;
+ }
+ }
+ curnode->next = NULL; /*terminate the list*/
+
+ pool->totalloc += pool->pchunk;
+ }
+
+ retval = pool->free;
+ if (pool->allow_iter)
+ pool->free->freeword = 0x7FFFFFFF;
+
+ pool->free = pool->free->next;
+ //memset(retval, 0, pool->esize);
+ return retval;
+}
+
+#ifdef __cplusplus
+}
+#endif
#endif
diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h
index 8af98b2d348..fb8ad4780fd 100644
--- a/source/blender/blenlib/BLI_scanfill.h
+++ b/source/blender/blenlib/BLI_scanfill.h
@@ -51,6 +51,8 @@ extern "C" {
/* scanfill.c: used in displist only... */
struct EditVert *BLI_addfillvert(float *vec);
struct EditEdge *BLI_addfilledge(struct EditVert *v1, struct EditVert *v2);
+
+int BLI_begin_edgefill(void);
int BLI_edgefill(short mat_nr);
void BLI_end_edgefill(void);
diff --git a/source/blender/blenlib/BLI_smallhash.h b/source/blender/blenlib/BLI_smallhash.h
new file mode 100755
index 00000000000..c956b8c63ea
--- /dev/null
+++ b/source/blender/blenlib/BLI_smallhash.h
@@ -0,0 +1,73 @@
+/**
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Eagar.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_SMALLHASH_H
+#define BLI_SMALLHASH_H
+
+/** \file BLI_smallhash.h
+ * \ingroup bli
+ */
+
+/* a light stack-friendly hash library,
+ * (it uses stack space for smallish hash tables) */
+
+/* based on a doubling non-chaining approach */
+
+typedef struct {
+ uintptr_t key;
+ void *val;
+} SmallHashEntry;
+
+/*how much stack space to use before dynamically allocating memory*/
+#define SMSTACKSIZE 521
+typedef struct SmallHash {
+ SmallHashEntry *table;
+ SmallHashEntry _stacktable[SMSTACKSIZE];
+ SmallHashEntry _copytable[SMSTACKSIZE];
+ SmallHashEntry *stacktable, *copytable;
+ int used;
+ int curhash;
+ int size;
+} SmallHash;
+
+typedef struct {
+ SmallHash *hash;
+ int i;
+} SmallHashIter;
+
+void BLI_smallhash_init(SmallHash *hash);
+void BLI_smallhash_release(SmallHash *hash);
+void BLI_smallhash_insert(SmallHash *hash, uintptr_t key, void *item);
+void BLI_smallhash_remove(SmallHash *hash, uintptr_t key);
+void * BLI_smallhash_lookup(SmallHash *hash, uintptr_t key);
+int BLI_smallhash_haskey(SmallHash *hash, uintptr_t key);
+int BLI_smallhash_count(SmallHash *hash);
+void * BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key);
+void * BLI_smallhash_iternew(SmallHash *hash, SmallHashIter *iter, uintptr_t *key);
+/* void BLI_smallhash_print(SmallHash *hash); */ /* UNUSED */
+
+#endif // BLI_SMALLHASH_H
diff --git a/source/blender/blenlib/BLI_sparsemap.h b/source/blender/blenlib/BLI_sparsemap.h
new file mode 100755
index 00000000000..0c892997dd4
--- /dev/null
+++ b/source/blender/blenlib/BLI_sparsemap.h
@@ -0,0 +1,73 @@
+#if 0
+/**
+ * $Id:
+ *
+ * ***** 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) 2009 Blender Foundation, Joshua Leung
+ * All rights reserved.
+ *
+ * Contributor(s): Joseph Eagar (original author)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "BLI_math_inline.h"
+
+typedef struct SparseMap {
+ int max;
+ int blocksize;
+ void **blocks;
+ int totblock;
+} SparseMap;
+
+MALWAYS_INLINE SparseMap *BLI_sparsemap_new(int blocksize, char *name)
+{
+ SparseMap *sm = MEM_callocN(sizeof(SparseMap), name);
+
+ sm->blocksize = blocksize;
+ return sm;
+}
+
+MALWAYS_INLINE void BLI_sparsemap_free(SparseMap *sm)
+{
+ if (sm->blocks)
+ MEM_freeN(sm->blocks);
+
+ MEM_freeN(sm);
+}
+
+MALWAYS_INLINE void BLI_sparsemap_set(SparseMap *sm, int index, void *ptr)
+{
+ if (index >= sm->max || (sm->blocks && !sm->blocks[index/sm->blocksize])) {
+ int totblock = MAX2((index+1)/sm->blocksize, 2);
+ void *blocks = MEM_callocN(sizeof(void*)*totblock);
+
+ if (sm->blocks)
+ memcpy(blocks, sm->blocks, sizeof(void*)*sm->totblock);
+ sm->totblock = totblock;
+ MEM_freeN(sm->blocks);
+ sm->blocks = blocks;
+ }
+
+ if (!sm->blocks[index/sm->blocksize]) {
+ sm->blocks[index/sm->blocksize] = MEM_mallocN(sizeof(void*)*sm->blocksize);
+ }
+
+ sm->blocks[index/sm->blocksize] = ptr;
+}
+#endif
diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h
index 00d8131d813..973bb57bb42 100644
--- a/source/blender/blenlib/BLI_threads.h
+++ b/source/blender/blenlib/BLI_threads.h
@@ -70,6 +70,7 @@ int BLI_system_thread_count(void); /* gets the number of threads the system can
#define LOCK_CUSTOM1 3
#define LOCK_RCACHE 4
#define LOCK_OPENGL 5
+#define LOCK_SCANFILL 6
void BLI_lock_thread(int type);
void BLI_unlock_thread(int type);
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index a6b4f2c9b92..9ca57493acb 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -302,4 +302,6 @@ do { \
# define BLI_assert(a) (void)0
#endif
+#define BMEMSET(mem, val, size) {unsigned int _i, _size = (size); char *_c = (char*) mem; for (_i=0; _i<_size; _i++) *_c++ = val;}
+
#endif // BLI_UTILDEFINES_H
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 4711acbb600..2f6b6f7cb26 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -48,6 +48,7 @@ set(SRC
intern/BLI_linklist.c
intern/BLI_memarena.c
intern/BLI_mempool.c
+ intern/BLI_cellalloc.c
intern/DLRB_tree.c
intern/boxpack2d.c
intern/bpath.c
@@ -77,6 +78,7 @@ set(SRC
intern/rand.c
intern/rct.c
intern/scanfill.c
+ intern/smallhash.c
intern/storage.c
intern/string.c
intern/string_utf8.c
@@ -86,6 +88,10 @@ set(SRC
intern/voxel.c
intern/winstuff.c
+ BLI_array.h
+ BLI_cellalloc.h
+ BLI_smallhash.h
+ BLI_sparsemap.h
BLI_args.h
BLI_blenlib.h
BLI_boxpack2d.h
diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript
index 00caf8cd01d..c8172439167 100644
--- a/source/blender/blenlib/SConscript
+++ b/source/blender/blenlib/SConscript
@@ -5,6 +5,8 @@ sources = env.Glob('intern/*.c')
cflags=''
incs = '. ../makesdna ../blenkernel #/intern/guardedalloc #/intern/ghost ../editors/include ../gpu ../blenloader'
+incs += ' ../windowmanager ../bmesh #/extern/glew/include'
+
incs += ' ' + env['BF_FREETYPE_INC']
incs += ' ' + env['BF_ZLIB_INC']
defs = []
diff --git a/source/blender/blenlib/intern/BLI_cellalloc.c b/source/blender/blenlib/intern/BLI_cellalloc.c
new file mode 100644
index 00000000000..47013535ce3
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_cellalloc.c
@@ -0,0 +1,203 @@
+/**
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+ Simple, fast memory allocator that uses many BLI_mempools for allocation.
+ this is meant to be used by lots of relatively small objects.
+
+ this is a temporary and imperfect fix for performance issues caused
+ by vgroups. it needs to be replaced with something better, preferably
+ integrated into guardedalloc.
+
+ Basically, it's a quick fix for vgroups and MDisps (both of which
+ are major performance hitters).
+*/
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+
+#include "DNA_listBase.h"
+#include "BLI_mempool.h"
+
+#include "BLI_cellalloc.h" /* own include */
+
+#include <string.h>
+
+static BLI_mempool **pools;
+static int totpool = 0;
+static ListBase active_mem = {NULL, NULL};
+static int celltotblock = 0;
+
+#define MEMIDCHECK ('a' | ('b' << 4) | ('c' << 8) | ('d' << 12))
+
+typedef struct MemHeader {
+ struct MemHeader *next, *prev;
+
+ int size;
+ const char *tag;
+ int idcheck;
+} MemHeader;
+
+//#define USE_GUARDEDALLOC
+
+void *BLI_cellalloc_malloc(long size, const char *tag)
+{
+ MemHeader *memh;
+ int slot = size + sizeof(MemHeader);
+
+#ifdef USE_GUARDEDALLOC
+ return MEM_mallocN(size, tag);
+#endif
+ if (!slot)
+ return NULL;
+
+ /*stupid optimization trick.
+ round up to nearest 16 bytes boundary.
+ this is to reduce the number of potential
+ pools. hopefully it'll help.*/
+ slot += 16 - (slot & 15);
+
+ if (slot >= totpool) {
+ void *tmp;
+
+ tmp = calloc(1, sizeof(void*)*(slot+1));
+ if (pools) {
+ memcpy(tmp, pools, totpool*sizeof(void*));
+ }
+
+ pools = tmp;
+ totpool = slot+1;
+ }
+
+ if (!pools[slot]) {
+ pools[slot] = BLI_mempool_create(slot, 1, 128, 1, 0);
+ }
+
+ memh = BLI_mempool_alloc(pools[slot]);
+ memh->size = size;
+ memh->idcheck = MEMIDCHECK;
+ memh->tag = tag;
+ BLI_addtail(&active_mem, memh);
+ celltotblock++;
+
+ return memh + 1;
+}
+
+void *BLI_cellalloc_calloc(long size, const char *tag)
+{
+ void *mem = BLI_cellalloc_malloc(size, tag);
+ BMEMSET(mem, 0, size);
+
+ return mem;
+}
+
+void BLI_cellalloc_free(void *mem)
+{
+ MemHeader *memh = mem;
+ int slot;
+
+#ifdef USE_GUARDEDALLOC
+ MEM_freeN(mem);
+ return;
+#endif
+ if (!memh)
+ return;
+
+ memh--;
+ if (memh->idcheck != MEMIDCHECK) {
+ printf("Error in BLI_cellalloc: attempt to free invalid block.\n");
+ return;
+ }
+
+ slot = memh->size + sizeof(MemHeader);
+ slot += 16 - (slot & 15);
+
+ if (memh->size > 0 && slot < totpool) {
+ BLI_remlink(&active_mem, memh);
+ BLI_mempool_free(pools[slot], memh);
+ celltotblock--;
+ } else {
+ printf("Error in BLI_cellalloc: attempt to free corrupted block.\n");
+ }
+}
+
+void *BLI_cellalloc_dupalloc(void *mem)
+{
+ MemHeader *memh = mem;
+ void *tmp;
+
+#ifdef USE_GUARDEDALLOC
+ MEM_freeN(mem);
+ return NULL;
+#endif
+ if (!memh)
+ return NULL;
+
+ memh--;
+ if (memh->idcheck != MEMIDCHECK) {
+ printf("Error in BLI_cellalloc: attempt to free invalid block.\n");
+ return NULL;
+ }
+
+ tmp = BLI_cellalloc_malloc(memh->size, memh->tag);
+ memcpy(tmp, mem, memh->size);
+
+ return tmp;
+}
+
+void BLI_cellalloc_printleaks(void)
+{
+ MemHeader *memh;
+
+ if (!active_mem.first) return;
+
+ for (memh=active_mem.first; memh; memh=memh->next) {
+ printf("%s %d %p\n", memh->tag, memh->size, memh+1);
+ }
+}
+
+int BLI_cellalloc_get_totblock(void)
+{
+ return celltotblock;
+}
+
+void BLI_cellalloc_destroy(void)
+{
+ int i;
+
+ for (i=0; i<totpool; i++) {
+ if (pools[i]) {
+ BLI_mempool_destroy(pools[i]);
+ pools[i] = NULL;
+ }
+ }
+}
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 080dc77fc06..45edf6052d3 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -40,14 +40,14 @@
// #include "BLI_blenlib.h"
-#include "BLI_mempool.h"
#include "BLI_utildefines.h"
+#include "BLI_mempool.h"
#include "BLI_ghash.h"
#include "BLO_sys_types.h" // for intptr_t support
/***/
-static unsigned int hashsizes[]= {
+unsigned int hashsizes[]= {
5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
4194319, 8388617, 16777259, 33554467, 67108879, 134217757,
@@ -60,7 +60,7 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) {
GHash *gh= MEM_mallocN(sizeof(*gh), info);
gh->hashfp= hashfp;
gh->cmpfp= cmpfp;
- gh->entrypool = BLI_mempool_create(sizeof(Entry), 64, 64, 0);
+ gh->entrypool = BLI_mempool_create(sizeof(Entry), 64, 64, 1, 0);
gh->cursize= 0;
gh->nentries= 0;
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index b4dc5b73a65..eb219a37a8d 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -20,7 +20,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Geoffery Bantle
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -35,47 +35,48 @@
*/
#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
#include "BLI_mempool.h"
-#include <string.h>
+#include "BLI_utildefines.h"
-typedef struct BLI_freenode{
- struct BLI_freenode *next;
-}BLI_freenode;
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
-typedef struct BLI_mempool_chunk{
- struct BLI_mempool_chunk *next, *prev;
- void *data;
-}BLI_mempool_chunk;
+#include <string.h>
-typedef struct BLI_mempool{
- struct ListBase chunks;
- int esize, csize, pchunk; /*size of elements and chunks in bytes and number of elements per chunk*/
- struct BLI_freenode *free; /*free element list. Interleaved into chunk datas.*/
- int totalloc, totused; /*total number of elements allocated in total, and currently in use*/
- int use_sysmalloc;
-}BLI_mempool;
+#define BLI_MEMPOOL_INTERN
+#include "BLI_mempool.h"
-BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk, int use_sysmalloc)
+BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk,
+ int use_sysmalloc, int allow_iter)
{ BLI_mempool *pool = NULL;
BLI_freenode *lasttail = NULL, *curnode = NULL;
int i,j, maxchunks;
char *addr;
- if (esize < sizeof(void*))
- esize = sizeof(void*);
+ if (esize < sizeof(void*)*2)
+ esize = sizeof(void*)*2;
+ if (esize < sizeof(void*)*2)
+ esize = sizeof(void*)*2;
+
/*allocate the pool structure*/
pool = use_sysmalloc ? malloc(sizeof(BLI_mempool)) : MEM_mallocN(sizeof(BLI_mempool), "memory pool");
- pool->esize = esize;
+ pool->esize = allow_iter ? MAX2(esize, sizeof(BLI_freenode)) : esize;
pool->use_sysmalloc = use_sysmalloc;
pool->pchunk = pchunk;
pool->csize = esize * pchunk;
pool->chunks.first = pool->chunks.last = NULL;
pool->totused= 0;
+ pool->allow_iter= allow_iter;
maxchunks = tote / pchunk + 1;
-
+ if (maxchunks==0) maxchunks = 1;
+
/*allocate the actual chunks*/
for(i=0; i < maxchunks; i++){
BLI_mempool_chunk *mpchunk = use_sysmalloc ? malloc(sizeof(BLI_mempool_chunk)) : MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
@@ -83,30 +84,49 @@ BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk, int use_sysmall
mpchunk->data = use_sysmalloc ? malloc(pool->csize) : MEM_mallocN(pool->csize, "BLI Mempool Chunk Data");
BLI_addtail(&(pool->chunks), mpchunk);
- if(i==0) pool->free = mpchunk->data; /*start of the list*/
+ if(i==0) {
+ pool->free = mpchunk->data; /*start of the list*/
+ if (pool->allow_iter)
+ pool->free->freeword = FREEWORD;
+ }
+
/*loop through the allocated data, building the pointer structures*/
for(addr = mpchunk->data, j=0; j < pool->pchunk; j++){
curnode = ((BLI_freenode*)addr);
addr += pool->esize;
curnode->next = (BLI_freenode*)addr;
+ if (pool->allow_iter) {
+ if (j != pool->pchunk-1)
+ curnode->next->freeword = FREEWORD;
+ curnode->freeword = FREEWORD;
+ }
}
/*final pointer in the previously allocated chunk is wrong.*/
- if(lasttail) lasttail->next = mpchunk->data;
+ if(lasttail) {
+ lasttail->next = mpchunk->data;
+ if (pool->allow_iter)
+ lasttail->freeword = FREEWORD;
+ }
+
/*set the end of this chunks memoryy to the new tail for next iteration*/
lasttail = curnode;
pool->totalloc += pool->pchunk;
}
+
/*terminate the list*/
curnode->next = NULL;
return pool;
}
+#if 0
void *BLI_mempool_alloc(BLI_mempool *pool){
void *retval=NULL;
BLI_freenode *curnode=NULL;
char *addr=NULL;
int j;
-
+
+ if (!pool) return NULL;
+
pool->totused++;
if(!(pool->free)){
@@ -117,10 +137,18 @@ void *BLI_mempool_alloc(BLI_mempool *pool){
BLI_addtail(&(pool->chunks), mpchunk);
pool->free = mpchunk->data; /*start of the list*/
+ if (pool->allow_iter)
+ pool->free->freeword = FREEWORD;
for(addr = mpchunk->data, j=0; j < pool->pchunk; j++){
curnode = ((BLI_freenode*)addr);
addr += pool->esize;
curnode->next = (BLI_freenode*)addr;
+
+ if (pool->allow_iter) {
+ curnode->freeword = FREEWORD;
+ if (j != pool->pchunk-1)
+ curnode->next->freeword = FREEWORD;
+ }
}
curnode->next = NULL; /*terminate the list*/
@@ -128,15 +156,19 @@ void *BLI_mempool_alloc(BLI_mempool *pool){
}
retval = pool->free;
+ if (pool->allow_iter)
+ pool->free->freeword = 0x7FFFFFFF;
+
pool->free = pool->free->next;
//memset(retval, 0, pool->esize);
return retval;
}
+#endif
void *BLI_mempool_calloc(BLI_mempool *pool){
void *retval=NULL;
retval = BLI_mempool_alloc(pool);
- memset(retval, 0, pool->esize);
+ BMEMSET(retval, 0, pool->esize);
return retval;
}
@@ -146,7 +178,9 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr){ //doesnt protect against d
BLI_freenode *curnode=NULL;
char *tmpaddr=NULL;
int i;
-
+
+ if (pool->allow_iter)
+ newhead->freeword = FREEWORD;
newhead->next = pool->free;
pool->free = newhead;
@@ -179,6 +213,50 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr){ //doesnt protect against d
}
}
+void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter)
+{
+ if (!pool->allow_iter) {
+ fprintf(stderr, "evil! you can't iterate over this mempool!\n");
+ iter->curchunk = NULL;
+ iter->curindex = 0;
+
+ return;
+ }
+
+ iter->pool = pool;
+ iter->curchunk = pool->chunks.first;
+ iter->curindex = 0;
+}
+
+static void *bli_mempool_iternext(BLI_mempool_iter *iter)
+{
+ void *ret = NULL;
+
+ if (!iter->curchunk || !iter->pool->totused) return NULL;
+
+ ret = ((char*)iter->curchunk->data) + iter->pool->esize*iter->curindex;
+
+ iter->curindex++;
+
+ if (iter->curindex >= iter->pool->pchunk) {
+ iter->curchunk = iter->curchunk->next;
+ iter->curindex = 0;
+ }
+
+ return ret;
+}
+
+void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
+{
+ BLI_freenode *ret;
+
+ do {
+ ret = bli_mempool_iternext(iter);
+ } while (ret && ret->freeword == FREEWORD);
+
+ return ret;
+}
+
void BLI_mempool_destroy(BLI_mempool *pool)
{
BLI_mempool_chunk *mpchunk=NULL;
diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c
index 2884ea2743a..455b3b91467 100644
--- a/source/blender/blenlib/intern/bpath.c
+++ b/source/blender/blenlib/intern/bpath.c
@@ -951,60 +951,3 @@ void findMissingFiles(Main *bmain, const char *str)
//XXX waitcursor( 0 );
}
-
-/* Run a visitor on a string, replacing the contents of the string as needed. */
-static void rewrite_path(char *path, bpath_visitor visit, void *userdata) {
- char pathOut[FILE_MAX];
- if (visit(userdata, path, pathOut))
- BLI_strncpy(path, pathOut, FILE_MAX);
-}
-
-/* Run visitor function 'visit' on all paths contained in 'id'. */
-void bpath_traverse_id(ID *id, bpath_visitor visit, void *userdata) {
- Image *ima;
-
- switch(GS(id->name)) {
- case ID_IM:
- ima = (Image*)id;
- if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
- rewrite_path(ima->name, visit, userdata);
- break;
- case ID_OB:
- case ID_SO:
- case ID_TXT:
- /* TODO: add other ID types e.g. object (modifiers) */
- default:
- /* Nothing to do for other IDs that don't contain file paths. */
- break;
- }
-}
-
-/* Rewrites a relative path to be relative to the main file - unless the path is
- absolute, in which case it is not altered. */
-int bpath_relocate_visitor(void *oldbasepath_v, char *pathIn, char *pathOut) {
- /* be sure there is low chance of the path being too short */
- char filepath[(FILE_MAXDIR * 2) + FILE_MAXFILE];
- char *oldbasepath = oldbasepath_v;
-
- if (strncmp(oldbasepath, "//", 2) == 0) {
- printf("Error: old base path '%s' is not absolute.\n", oldbasepath);
- return 0;
- }
-
- /* Make referenced file absolute. This would be a side-effect of
- BLI_cleanup_file, but we do it explicitely so we know if it changed. */
- BLI_strncpy(filepath, pathIn, FILE_MAX);
- if (BLI_path_abs(filepath, oldbasepath)) {
- /* Path was relative and is now absolute. Remap.
- * Important BLI_cleanup_dir runs before the path is made relative
- * because it wont work for paths that start with "//../" */
- BLI_cleanup_file(G.main->name, filepath);
- BLI_path_rel(filepath, G.main->name);
- BLI_strncpy(pathOut, filepath, FILE_MAX);
- return 1;
- }
- else {
- /* Path was not relative to begin with. */
- return 0;
- }
-}
diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c
index 65c5dffa33c..8a8c9054673 100644
--- a/source/blender/blenlib/intern/edgehash.c
+++ b/source/blender/blenlib/intern/edgehash.c
@@ -20,7 +20,7 @@
*
* The Original Code is: none of this file.
*
- * Contributor(s): Daniel Dunbar
+ * Contributor(s): Daniel Dunbar, Joseph Eagar
*
* ***** END GPL LICENSE BLOCK *****
* A general (pointer -> pointer) hash table ADT
@@ -35,113 +35,23 @@
#include <string.h>
#include "MEM_guardedalloc.h"
-#include "BLI_edgehash.h"
-
-/***/
-
-static unsigned int hashsizes[]= {
- 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
- 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
- 4194319, 8388617, 16777259, 33554467, 67108879, 134217757,
- 268435459
-};
-
-#define EDGEHASH(v0,v1) ((v0*39)^(v1*31))
-
-/***/
-
-typedef struct Entry Entry;
-struct Entry {
- Entry *next;
- int v0, v1;
- void *val;
-};
-struct EdgeHash {
- Entry **buckets;
- int nbuckets, nentries, cursize;
-};
+#include "BLI_utildefines.h"
+#include "BLI_edgehash.h"
+#include "BLI_mempool.h"
/***/
EdgeHash *BLI_edgehash_new(void) {
- EdgeHash *eh= MEM_mallocN(sizeof(*eh), "EdgeHash");
+ EdgeHash *eh= MEM_callocN(sizeof(*eh), "EdgeHash");
eh->cursize= 0;
eh->nentries= 0;
- eh->nbuckets= hashsizes[eh->cursize];
-
- eh->buckets= malloc(eh->nbuckets*sizeof(*eh->buckets));
- memset(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets));
-
- return eh;
-}
-
-void BLI_edgehash_insert(EdgeHash *eh, int v0, int v1, void *val) {
- unsigned int hash;
- Entry *e= malloc(sizeof(*e));
-
- if (v1<v0) {
- v0 ^= v1;
- v1 ^= v0;
- v0 ^= v1;
- }
- hash = EDGEHASH(v0,v1)%eh->nbuckets;
-
- e->v0 = v0;
- e->v1 = v1;
- e->val = val;
- e->next= eh->buckets[hash];
- eh->buckets[hash]= e;
+ eh->nbuckets= _ehash_hashsizes[eh->cursize];
- if (++eh->nentries>eh->nbuckets*3) {
- Entry **old= eh->buckets;
- int i, nold= eh->nbuckets;
-
- eh->nbuckets= hashsizes[++eh->cursize];
- eh->buckets= malloc(eh->nbuckets*sizeof(*eh->buckets));
- memset(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets));
-
- for (i=0; i<nold; i++) {
- for (e= old[i]; e;) {
- Entry *n= e->next;
-
- hash= EDGEHASH(e->v0,e->v1)%eh->nbuckets;
- e->next= eh->buckets[hash];
- eh->buckets[hash]= e;
-
- e= n;
- }
- }
-
- free(old);
- }
-}
-
-void** BLI_edgehash_lookup_p(EdgeHash *eh, int v0, int v1) {
- unsigned int hash;
- Entry *e;
+ eh->buckets= MEM_callocN(eh->nbuckets*sizeof(*eh->buckets), "eh buckets 2");
+ eh->epool = BLI_mempool_create(sizeof(EdgeEntry), 512, 512, 1, 0);
- if (v1<v0) {
- v0 ^= v1;
- v1 ^= v0;
- v0 ^= v1;
- }
- hash = EDGEHASH(v0,v1)%eh->nbuckets;
- for (e= eh->buckets[hash]; e; e= e->next)
- if (v0==e->v0 && v1==e->v1)
- return &e->val;
-
- return NULL;
-}
-
-void* BLI_edgehash_lookup(EdgeHash *eh, int v0, int v1) {
- void **value_p = BLI_edgehash_lookup_p(eh,v0,v1);
-
- return value_p?*value_p:NULL;
-}
-
-int BLI_edgehash_haskey(EdgeHash *eh, int v0, int v1) {
- return BLI_edgehash_lookup_p(eh, v0, v1)!=NULL;
+ return eh;
}
int BLI_edgehash_size(EdgeHash *eh) {
@@ -152,13 +62,13 @@ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) {
int i;
for (i=0; i<eh->nbuckets; i++) {
- Entry *e;
+ EdgeEntry *e;
for (e= eh->buckets[i]; e; ) {
- Entry *n= e->next;
+ EdgeEntry *n= e->next;
if (valfreefp) valfreefp(e->val);
- free(e);
+ BLI_mempool_free(eh->epool, e);
e= n;
}
@@ -170,8 +80,10 @@ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) {
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp) {
BLI_edgehash_clear(eh, valfreefp);
-
- free(eh->buckets);
+
+ BLI_mempool_destroy(eh->epool);
+
+ MEM_freeN(eh->buckets);
MEM_freeN(eh);
}
@@ -181,11 +93,11 @@ void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp) {
struct EdgeHashIterator {
EdgeHash *eh;
int curBucket;
- Entry *curEntry;
+ EdgeEntry *curEntry;
};
EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) {
- EdgeHashIterator *ehi= malloc(sizeof(*ehi));
+ EdgeHashIterator *ehi= MEM_mallocN(sizeof(*ehi), "eh iter");
ehi->eh= eh;
ehi->curEntry= NULL;
ehi->curBucket= -1;
@@ -198,7 +110,7 @@ EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) {
return ehi;
}
void BLI_edgehashIterator_free(EdgeHashIterator *ehi) {
- free(ehi);
+ MEM_freeN(ehi);
}
void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, int *v0_r, int *v1_r) {
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index ae3cba7e94f..c1cb3c9d588 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -39,7 +39,7 @@
#define BLI_MATH_BASE_INLINE_H
/* A few small defines. Keep'em local! */
-#define SMALL_NUMBER 1.e-8
+#define SMALL_NUMBER 1.e-8f
MINLINE float sqrt3f(float f)
{
@@ -106,7 +106,7 @@ MINLINE float interpf(float target, float origin, float fac)
* the distance gets very high, 180d would be inf, but this case isn't valid */
MINLINE float shell_angle_to_dist(const float angle)
{
- return (angle < (float)SMALL_NUMBER) ? 1.0f : fabsf(1.0f / cosf(angle));
+ return (1.0f + SMALL_NUMBER) / (fabs(cosf(angle)) + SMALL_NUMBER);
}
/* used for zoom values*/
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index b79ae9f0042..21f82353ac2 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -2295,6 +2295,39 @@ void accumulate_vertex_normals(float n1[3], float n2[3], float n3[3],
}
}
+/* Add weighted face normal component into normals of the face vertices.
+ Caller must pass pre-allocated vdiffs of nverts length. */
+#define VERT_BUF_SIZE 100
+void accumulate_vertex_normals_poly(float **vertnos, float polyno[3],
+ float **vertcos, float vdiffs[][3], int nverts)
+{
+ int i;
+
+ /* calculate normalized edge directions for each edge in the poly */
+ for (i = 0; i < nverts; i++) {
+ sub_v3_v3v3(vdiffs[i], vertcos[(i+1) % nverts], vertcos[i]);
+ normalize_v3(vdiffs[i]);
+ }
+
+ /* accumulate angle weighted face normal */
+ {
+ const float *prev_edge = vdiffs[nverts-1];
+ int i;
+
+ for(i=0; i<nverts; i++) {
+ const float *cur_edge = vdiffs[i];
+
+ /* calculate angle between the two poly edges incident on
+ this vertex */
+ const float fac= saacos(-dot_v3v3(cur_edge, prev_edge));
+
+ /* accumulate */
+ madd_v3_v3fl(vertnos[i], polyno, fac);
+ prev_edge = cur_edge;
+ }
+ }
+}
+
/********************************* Tangents **********************************/
/* For normal map tangents we need to detect uv boundaries, and only average
@@ -2951,3 +2984,39 @@ float form_factor_hemi_poly(float p[3], float n[3], float v1[3], float v2[3], fl
return contrib;
}
+
+/* evaluate if entire quad is a proper convex quad */
+ int is_quad_convex_v3(const float *v1, const float *v2, const float *v3, const float *v4)
+ {
+ float nor[3], nor1[3], nor2[3], vec[4][2];
+
+ /* define projection, do both trias apart, quad is undefined! */
+ normal_tri_v3( nor1,v1, v2, v3);
+ normal_tri_v3( nor2,v1, v3, v4);
+ nor[0]= ABS(nor1[0]) + ABS(nor2[0]);
+ nor[1]= ABS(nor1[1]) + ABS(nor2[1]);
+ nor[2]= ABS(nor1[2]) + ABS(nor2[2]);
+
+ if(nor[2] >= nor[0] && nor[2] >= nor[1]) {
+ vec[0][0]= v1[0]; vec[0][1]= v1[1];
+ vec[1][0]= v2[0]; vec[1][1]= v2[1];
+ vec[2][0]= v3[0]; vec[2][1]= v3[1];
+ vec[3][0]= v4[0]; vec[3][1]= v4[1];
+ }
+ else if(nor[1] >= nor[0] && nor[1]>= nor[2]) {
+ vec[0][0]= v1[0]; vec[0][1]= v1[2];
+ vec[1][0]= v2[0]; vec[1][1]= v2[2];
+ vec[2][0]= v3[0]; vec[2][1]= v3[2];
+ vec[3][0]= v4[0]; vec[3][1]= v4[2];
+ }
+ else {
+ vec[0][0]= v1[1]; vec[0][1]= v1[2];
+ vec[1][0]= v2[1]; vec[1][1]= v2[2];
+ vec[2][0]= v3[1]; vec[2][1]= v3[2];
+ vec[3][0]= v4[1]; vec[3][1]= v4[2];
+ }
+
+ /* linetests, the 2 diagonals have to instersect to be convex */
+ if( isect_line_line_v2(vec[0], vec[2], vec[1], vec[3]) > 0 ) return 1;
+ return 0;
+}
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 01c3e112cd8..b4b9bf03803 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -239,6 +239,20 @@ void angle_quad_v3(float angles[4], const float v1[3], const float v2[3], const
angles[3]= (float)M_PI - angle_normalized_v3v3(ed4, ed1);
}
+void angle_poly_v3(float *angles, const float *verts[3], int len)
+{
+ int i;
+ float vec[3][3];
+
+ sub_v3_v3v3(vec[2], verts[len-1], verts[0]);
+ normalize_v3(vec[2]);
+ for (i = 0; i < len; i++) {
+ sub_v3_v3v3(vec[i%3], verts[i%len], verts[(i+1)%len]);
+ normalize_v3(vec[i%3]);
+ angles[i] = (float)M_PI - angle_normalized_v3v3(vec[(i+2)%3], vec[i%3]);
+ }
+}
+
/********************************* Geometry **********************************/
/* Project v1 on v2 */
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index c460b69679b..bf896f6348d 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -308,18 +308,6 @@ MINLINE void mul_v3_v3v3(float r[3], const float v1[3], const float v2[3])
r[2] = v1[2] * v2[2];
}
-MINLINE void negate_v2(float r[3])
-{
- r[0]= -r[0];
- r[1]= -r[1];
-}
-
-MINLINE void negate_v2_v2(float r[2], const float a[2])
-{
- r[0]= -a[0];
- r[1]= -a[1];
-}
-
MINLINE void negate_v3(float r[3])
{
r[0]= -r[0];
@@ -466,6 +454,29 @@ MINLINE float normalize_v3_v3(float r[3], const float a[3])
return d;
}
+MINLINE double normalize_dv3(double n[3])
+{
+ double d= n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+
+ /* a larger value causes normalize errors in a
+ scaled down models with camera xtreme close */
+ if(d > 1.0e-35) {
+ double mul;
+
+ d= sqrt(d);
+ mul = 1.0 / d;
+
+ n[0] *= mul;
+ n[1] *= mul;
+ n[2] *= mul;
+ } else {
+ n[0] = n[1] = n[2] = 0;
+ d= 0.0;
+ }
+
+ return d;
+}
+
MINLINE float normalize_v3(float n[3])
{
return normalize_v3_v3(n, n);
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index bc24415fd3f..4fa2bcd2cb8 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -35,6 +35,7 @@
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
+#include <stddef.h>
#include <assert.h>
#include "MEM_guardedalloc.h"
@@ -308,7 +309,7 @@ void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char deli
void BLI_cleanup_path(const char *relabase, char *dir)
{
- short a;
+ ptrdiff_t a;
char *start, *eind;
if (relabase) {
BLI_path_abs(dir, relabase);
diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c
index 9471f096682..6cba79849c2 100644
--- a/source/blender/blenlib/intern/pbvh.c
+++ b/source/blender/blenlib/intern/pbvh.c
@@ -1577,7 +1577,7 @@ void BLI_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
}
/* coordinates are new -- normals should also be updated */
- mesh_calc_normals(pbvh->verts, pbvh->totvert, pbvh->faces, pbvh->totprim, NULL);
+ mesh_calc_tessface_normals(pbvh->verts, pbvh->totvert, pbvh->faces, pbvh->totprim, NULL);
for (a= 0; a < pbvh->totnode; ++a)
BLI_pbvh_node_mark_update(&pbvh->nodes[a]);
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index 4bd17fcf0b9..71ae8df7ba6 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -30,6 +30,10 @@
* \ingroup bli
*/
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
@@ -38,6 +42,8 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_scanfill.h"
+#include "BLI_utildefines.h"
+#include "BLI_threads.h"
/* callbacks for errors and interrupts and some goo */
static void (*BLI_localErrorCallBack)(const char*) = NULL;
@@ -137,54 +143,64 @@ struct mem_elements {
only to be used within loops, and not by one function at a time
free in the end, with argument '-1'
*/
+#define MEM_ELEM_BLOCKSIZE 16384
+static struct mem_elements * melem__cur= 0;
+static int melem__offs= 0; /* the current free address */
+static ListBase melem__lb= {NULL, NULL};
-static void *new_mem_element(int size)
+static void *mem_element_new(int size)
{
- int blocksize= 16384;
- static int offs= 0; /* the current free address */
- static struct mem_elements *cur= 0;
- static ListBase lb= {0, 0};
- void *adr;
+ BLI_assert(!(size>10000 || size==0)); /* this is invalid use! */
+
+ size = (size + 3 ) & ~3; /* allocate in units of 4 */
- if(size>10000 || size==0) {
- printf("incorrect use of new_mem_element\n");
+ if(melem__cur && (size + melem__offs < MEM_ELEM_BLOCKSIZE)) {
+ void *adr= (void *) (melem__cur->data+melem__offs);
+ melem__offs+= size;
+ return adr;
}
- else if(size== -1) {
- cur= lb.first;
- while(cur) {
- MEM_freeN(cur->data);
- cur= cur->next;
- }
- BLI_freelistN(&lb);
-
- return NULL;
+ else {
+ melem__cur= MEM_callocN( sizeof(struct mem_elements), "newmem");
+ melem__cur->data= MEM_callocN(MEM_ELEM_BLOCKSIZE, "newmem");
+ BLI_addtail(&melem__lb, melem__cur);
+
+ melem__offs= size;
+ return melem__cur->data;
}
-
- size= 4*( (size+3)/4 );
-
- if(cur) {
- if(size+offs < blocksize) {
- adr= (void *) (cur->data+offs);
- offs+= size;
- return adr;
+}
+static void mem_element_reset(void)
+{
+ struct mem_elements *first;
+ /*BMESH_TODO: keep the first block, gives memory leak on exit with 'newmem' */
+
+ if((first= melem__lb.first)) { /* can be false if first fill fails */
+ BLI_remlink(&melem__lb, first);
+
+ melem__cur= melem__lb.first;
+ while(melem__cur) {
+ MEM_freeN(melem__cur->data);
+ melem__cur= melem__cur->next;
}
+ BLI_freelistN(&melem__lb);
+
+ /*reset the block we're keeping*/
+ BLI_addtail(&melem__lb, first);
+ memset(first->data, 0, MEM_ELEM_BLOCKSIZE);
}
-
- cur= MEM_callocN( sizeof(struct mem_elements), "newmem");
- cur->data= MEM_callocN(blocksize, "newmem");
- BLI_addtail(&lb, cur);
-
- offs= size;
- return cur->data;
+
+ melem__cur= first;
+ melem__offs= 0;
}
void BLI_end_edgefill(void)
{
- new_mem_element(-1);
+ mem_element_reset();
fillvertbase.first= fillvertbase.last= 0;
filledgebase.first= filledgebase.last= 0;
fillfacebase.first= fillfacebase.last= 0;
+
+ BLI_unlock_thread(LOCK_SCANFILL);
}
/* **** FILL ROUTINES *************************** */
@@ -193,7 +209,7 @@ EditVert *BLI_addfillvert(float *vec)
{
EditVert *eve;
- eve= new_mem_element(sizeof(EditVert));
+ eve= mem_element_new(sizeof(EditVert));
BLI_addtail(&fillvertbase, eve);
eve->co[0] = vec[0];
@@ -207,7 +223,7 @@ EditEdge *BLI_addfilledge(EditVert *v1, EditVert *v2)
{
EditEdge *newed;
- newed= new_mem_element(sizeof(EditEdge));
+ newed= mem_element_new(sizeof(EditEdge));
BLI_addtail(&filledgebase, newed);
newed->v1= v1;
@@ -221,7 +237,7 @@ static void addfillface(EditVert *v1, EditVert *v2, EditVert *v3, short mat_nr)
/* does not make edges */
EditFace *evl;
- evl= new_mem_element(sizeof(EditFace));
+ evl= mem_element_new(sizeof(EditFace));
BLI_addtail(&fillfacebase, evl);
evl->v1= v1;
@@ -498,7 +514,7 @@ static int scanfill(PolyFill *pf, short mat_nr)
EditVert *eve,*v1,*v2,*v3;
EditEdge *eed,*nexted,*ed1,*ed2,*ed3;
float miny = 0.0;
- int a,b,verts, maxface, totface;
+ int a,b,verts, maxface, totface;
short nr, test, twoconnected=0;
nr= pf->nr;
@@ -750,6 +766,12 @@ static int scanfill(PolyFill *pf, short mat_nr)
}
+int BLI_begin_edgefill(void)
+{
+ BLI_lock_thread(LOCK_SCANFILL);
+
+ return 1;
+}
int BLI_edgefill(short mat_nr)
{
@@ -765,17 +787,48 @@ int BLI_edgefill(short mat_nr)
EditVert *eve;
EditEdge *eed,*nexted;
PolyFill *pflist,*pf;
- float *minp, *maxp, *v1, *v2, norm[3], len;
+ float limit, *minp, *maxp, *v1, *v2, norm[3], len;
short a,c,poly=0,ok=0,toggle=0;
int totfaces= 0; /* total faces added */
/* reset variables */
eve= fillvertbase.first;
+ a = 0;
while(eve) {
eve->f= 0;
eve->xs= 0;
eve->h= 0;
eve= eve->next;
+ a += 1;
+ }
+
+ if (a == 3 && (mat_nr & 2)) {
+ eve = fillvertbase.first;
+
+ addfillface(eve, eve->next, eve->next->next, 0);
+ return 1;
+ } else if (a == 4 && (mat_nr & 2)) {
+ float vec1[3], vec2[3];
+
+ eve = fillvertbase.first;
+ /* no need to check 'eve->next->next->next' is valid, already counted */
+ if (1) { //BMESH_TODO) {
+ /*use shortest diagonal for quad*/
+ sub_v3_v3v3(vec1, eve->co, eve->next->next->co);
+ sub_v3_v3v3(vec2, eve->next->co, eve->next->next->next->co);
+
+ if (INPR(vec1, vec1) < INPR(vec2, vec2)) {
+ addfillface(eve, eve->next, eve->next->next, 0);
+ addfillface(eve->next->next, eve->next->next->next, eve, 0);
+ } else{
+ addfillface(eve->next, eve->next->next, eve->next->next->next, 0);
+ addfillface(eve->next->next->next, eve, eve->next, 0);
+ }
+ } else {
+ addfillface(eve, eve->next, eve->next->next, 0);
+ addfillface(eve->next->next, eve->next->next->next, eve, 0);
+ }
+ return 2;
}
/* first test vertices if they are in edges */
@@ -810,9 +863,17 @@ int BLI_edgefill(short mat_nr)
v1= eve->co;
v2= 0;
eve= fillvertbase.first;
+ limit = a < 5 ? FLT_EPSILON*200 : M_PI/24.0;
while(eve) {
if(v2) {
if( compare_v3v3(v2, eve->co, COMPLIMIT)==0) {
+ float inner = angle_v3v3v3(v1, v2, eve->co);
+
+ if (fabs(inner-M_PI) < limit || fabs(inner) < limit) {
+ eve = eve->next;
+ continue;
+ }
+
len= normal_tri_v3( norm,v1, v2, eve->co);
if(len != 0.0f) break;
}
diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c
new file mode 100644
index 00000000000..c78dcd415cc
--- /dev/null
+++ b/source/blender/blenlib/intern/smallhash.c
@@ -0,0 +1,280 @@
+/**
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Eagar.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
+#include <string.h>
+
+#include "BLI_smallhash.h"
+
+/* SMHASH_CELL_UNUSED means this cell is inside a key series,
+ * while SMHASH_CELL_FREE means this cell terminates a key series.
+ *
+ * no chance of anyone shoving INT32_MAX-2 into a *val pointer, I
+ * imagine. hopefully.
+ *
+ * note: these have the SMHASH suffix because we may want to make them public.
+ */
+#define SMHASH_CELL_UNUSED ((void *)0x7FFFFFFF)
+#define SMHASH_CELL_FREE ((void *)0x7FFFFFFD)
+
+#define SMHASH_NONZERO(n) ((n) + !(n))
+#define SMHASH_NEXT(h, hoff) ABS(((h) + ((hoff=SMHASH_NONZERO(hoff*2)+1), hoff)))
+
+extern unsigned int hashsizes[];
+
+void BLI_smallhash_init(SmallHash *hash)
+{
+ int i;
+
+ memset(hash, 0, sizeof(*hash));
+
+ hash->table = hash->_stacktable;
+ hash->curhash = 2;
+ hash->size = hashsizes[hash->curhash];
+
+ hash->copytable = hash->_copytable;
+ hash->stacktable = hash->_stacktable;
+
+ for (i=0; i<hash->size; i++) {
+ hash->table[i].val = SMHASH_CELL_FREE;
+ }
+}
+
+/*NOTE: does *not* free *hash itself! only the direct data!*/
+void BLI_smallhash_release(SmallHash *hash)
+{
+ if (hash == NULL) {
+ return;
+ }
+
+ if (hash->table != hash->stacktable) {
+ MEM_freeN(hash->table);
+ }
+}
+
+void BLI_smallhash_insert(SmallHash *hash, uintptr_t key, void *item)
+{
+ int h, hoff=1;
+
+ if (hash->size < hash->used * 3) {
+ int newsize = hashsizes[++hash->curhash];
+ SmallHashEntry *tmp;
+ int i = 0;
+
+ if (hash->table != hash->stacktable || newsize > SMSTACKSIZE) {
+ tmp = MEM_callocN(sizeof(*hash->table) * newsize, "new hashkeys");
+ }
+ else {
+ SWAP(SmallHashEntry *, hash->stacktable, hash->copytable);
+ tmp = hash->stacktable;
+ }
+
+ SWAP(SmallHashEntry *, tmp, hash->table);
+
+ hash->size = newsize;
+
+ for (i=0; i<hash->size; i++) {
+ hash->table[i].val = SMHASH_CELL_FREE;
+ }
+
+ for (i=0; i<hashsizes[hash->curhash-1]; i++) {
+ if (ELEM(tmp[i].val, SMHASH_CELL_UNUSED, SMHASH_CELL_FREE)) {
+ continue;
+ }
+
+ h = ABS((int)(tmp[i].key));
+ hoff = 1;
+ while (!ELEM(hash->table[h % newsize].val, SMHASH_CELL_UNUSED, SMHASH_CELL_FREE)) {
+ h = SMHASH_NEXT(h, hoff);
+ }
+
+ h %= newsize;
+
+ hash->table[h].key = tmp[i].key;
+ hash->table[h].val = tmp[i].val;
+ }
+
+ if (tmp != hash->stacktable && tmp != hash->copytable) {
+ MEM_freeN(tmp);
+ }
+ }
+
+ h = ABS((int)key);
+ hoff = 1;
+
+ while (!ELEM(hash->table[h % hash->size].val, SMHASH_CELL_UNUSED, SMHASH_CELL_FREE)) {
+ h = SMHASH_NEXT(h, hoff);
+ }
+
+ h %= hash->size;
+ hash->table[h].key = key;
+ hash->table[h].val = item;
+
+ hash->used++;
+}
+
+void BLI_smallhash_remove(SmallHash *hash, uintptr_t key)
+{
+ int h, hoff=1;
+
+ h = ABS((int)key);
+
+ while ((hash->table[h % hash->size].key != key) ||
+ (hash->table[h % hash->size].val == SMHASH_CELL_UNUSED))
+ {
+ if (hash->table[h % hash->size].val == SMHASH_CELL_FREE) {
+ return;
+ }
+
+ h = SMHASH_NEXT(h, hoff);
+ }
+
+ h %= hash->size;
+ hash->table[h].key = 0;
+ hash->table[h].val = SMHASH_CELL_UNUSED;
+}
+
+void *BLI_smallhash_lookup(SmallHash *hash, uintptr_t key)
+{
+ int h, hoff=1;
+ void *v;
+
+ h = ABS((int)key);
+
+ if (hash->table == NULL) {
+ return NULL;
+ }
+
+ while ((hash->table[h % hash->size].key != key) ||
+ (hash->table[h % hash->size].val == SMHASH_CELL_UNUSED))
+ {
+ if (hash->table[h % hash->size].val == SMHASH_CELL_FREE) {
+ return NULL;
+ }
+
+ h = SMHASH_NEXT(h, hoff);
+ }
+
+ v = hash->table[h % hash->size].val;
+ if (ELEM(v, SMHASH_CELL_UNUSED, SMHASH_CELL_FREE)) {
+ return NULL;
+ }
+
+ return v;
+}
+
+
+int BLI_smallhash_haskey(SmallHash *hash, uintptr_t key)
+{
+ int h = ABS((int)key);
+ int hoff =1;
+
+ if (hash->table == NULL) {
+ return 0;
+ }
+
+ while ((hash->table[h % hash->size].key != key) ||
+ (hash->table[h % hash->size].val == SMHASH_CELL_UNUSED))
+ {
+ if (hash->table[h % hash->size].val == SMHASH_CELL_FREE) {
+ return 0;
+ }
+
+ h = SMHASH_NEXT(h, hoff);
+ }
+
+ return !ELEM(hash->table[h % hash->size].val, SMHASH_CELL_UNUSED, SMHASH_CELL_FREE);
+}
+
+int BLI_smallhash_count(SmallHash *hash)
+{
+ return hash->used;
+}
+
+void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
+{
+ while (iter->i < iter->hash->size) {
+ if ( (iter->hash->table[iter->i].val != SMHASH_CELL_UNUSED) &&
+ (iter->hash->table[iter->i].val != SMHASH_CELL_FREE))
+ {
+ if (key) {
+ *key = iter->hash->table[iter->i].key;
+ }
+
+ iter->i++;
+
+ return iter->hash->table[iter->i-1].val;
+ }
+
+ iter->i++;
+ }
+
+ return NULL;
+}
+
+void *BLI_smallhash_iternew(SmallHash *hash, SmallHashIter *iter, uintptr_t *key)
+{
+ iter->hash = hash;
+ iter->i = 0;
+
+ return BLI_smallhash_iternext(iter, key);
+}
+
+/* note, this was called _print_smhash in knifetool.c
+ * it may not be intended for general use - campbell */
+#if 0
+void BLI_smallhash_print(SmallHash *hash)
+{
+ int i, linecol=79, c=0;
+
+ printf("{");
+ for (i=0; i<hash->size; i++) {
+ if (hash->table[i].val == SMHASH_CELL_UNUSED) {
+ printf("--u-");
+ }
+ else if (hash->table[i].val == SMHASH_CELL_FREE) {
+ printf("--f-");
+ }
+ else {
+ printf("%2x", (unsigned int)hash->table[i].key);
+ }
+
+ if (i != hash->size-1)
+ printf(", ");
+
+ c += 6;
+
+ if (c >= linecol) {
+ printf("\n ");
+ c = 0;
+ }
+ }
+
+ fflush(stdout);
+}
+#endif
diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c
index f8cdc3ec873..a9c28be6663 100644
--- a/source/blender/blenlib/intern/string_utf8.c
+++ b/source/blender/blenlib/intern/string_utf8.c
@@ -319,8 +319,6 @@ int BLI_str_utf8_size(const char *p)
UTF8_COMPUTE (c, mask, len);
- (void)mask; /* quiet warning */
-
return len;
}
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index c049ab85546..37f37887688 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -113,6 +113,7 @@ static pthread_mutex_t _viewer_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _custom1_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _rcache_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _opengl_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t _scanfill_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_t mainid;
static int thread_levels= 0; /* threads can be invoked inside threads */
@@ -347,6 +348,8 @@ void BLI_lock_thread(int type)
pthread_mutex_lock(&_rcache_lock);
else if (type==LOCK_OPENGL)
pthread_mutex_lock(&_opengl_lock);
+ else if (type == LOCK_SCANFILL)
+ pthread_mutex_lock(&_scanfill_lock);
}
void BLI_unlock_thread(int type)
@@ -363,6 +366,8 @@ void BLI_unlock_thread(int type)
pthread_mutex_unlock(&_rcache_lock);
else if(type==LOCK_OPENGL)
pthread_mutex_unlock(&_opengl_lock);
+ else if(type == LOCK_SCANFILL)
+ pthread_mutex_unlock(&_scanfill_lock);
}
/* Mutex Locks */
diff --git a/source/blender/blenloader/SConscript b/source/blender/blenloader/SConscript
index d5d2df3ea35..57075ac3bcf 100644
--- a/source/blender/blenloader/SConscript
+++ b/source/blender/blenloader/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('intern/*.c')
incs = '. #/intern/guardedalloc ../blenlib ../blenkernel'
incs += ' ../makesdna ../editors/include'
-incs += ' ../render/extern/include ../makesrna ../nodes'
+incs += ' ../render/extern/include ../makesrna ../nodes ../bmesh'
incs += ' ' + env['BF_ZLIB_INC']
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 45ab4a5cdaf..ce58582d2ca 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -91,9 +91,11 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
+#include "BLI_cellalloc.h"
+#include "BLI_edgehash.h"
#include "BKE_anim.h"
#include "BKE_action.h"
@@ -2538,6 +2540,16 @@ static void lib_link_key(FileData *fd, Main *main)
key= main->key.first;
while(key) {
+ /*check if we need to generate unique ids for the shapekeys*/
+ if (!key->uidgen) {
+ KeyBlock *block;
+
+ key->uidgen = 1;
+ for (block=key->block.first; block; block=block->next) {
+ block->uid = key->uidgen++;
+ }
+ }
+
if(key->id.flag & LIB_NEEDLINK) {
if(key->adt) lib_link_animdata(fd, &key->id, key->adt);
@@ -3426,9 +3438,6 @@ static void lib_link_mtface(FileData *fd, Mesh *me, MTFace *mtface, int totface)
MTFace *tf= mtface;
int i;
- /* Add pseudo-references (not fake users!) to images used by texface. A
- little bogus; it would be better if each mesh consistently added one ref
- to each image it used. - z0r */
for (i=0; i<totface; i++, tf++) {
tf->tpage= newlibadr(fd, me->id.lib, tf->tpage);
if(tf->tpage && tf->tpage->id.us==0)
@@ -3448,6 +3457,26 @@ static void lib_link_customdata_mtface(FileData *fd, Mesh *me, CustomData *fdata
}
+static void lib_link_customdata_mtpoly(FileData *fd, Mesh *me, CustomData *pdata, int totface)
+{
+ int i;
+
+ for(i=0; i<pdata->totlayer; i++) {
+ CustomDataLayer *layer = &pdata->layers[i];
+
+ if(layer->type == CD_MTEXPOLY) {
+ MTexPoly *tf= layer->data;
+ int i;
+
+ for (i=0; i<totface; i++, tf++) {
+ tf->tpage= newlibadr(fd, me->id.lib, tf->tpage);
+ if(tf->tpage && tf->tpage->id.us==0)
+ tf->tpage->id.us= 1;
+ }
+ }
+ }
+}
+
static void lib_link_mesh(FileData *fd, Main *main)
{
Mesh *me;
@@ -3475,10 +3504,16 @@ static void lib_link_mesh(FileData *fd, Main *main)
me->texcomesh= newlibadr_us(fd, me->id.lib, me->texcomesh);
lib_link_customdata_mtface(fd, me, &me->fdata, me->totface);
+ lib_link_customdata_mtpoly(fd, me, &me->pdata, me->totpoly);
if(me->mr && me->mr->levels.first)
lib_link_customdata_mtface(fd, me, &me->mr->fdata,
((MultiresLevel*)me->mr->levels.first)->totface);
+ /*check if we need to convert mfaces to mpolys*/
+ if (me->totface && !me->totpoly) {
+ convert_mfaces_to_mpolys(me);
+ }
+
me->id.flag -= LIB_NEEDLINK;
}
me= me->id.next;
@@ -3497,10 +3532,17 @@ static void direct_link_dverts(FileData *fd, int count, MDeformVert *mdverts)
}
for (i= count; i > 0; i--, mdverts++) {
- if(mdverts->dw) {
- mdverts->dw= newdataadr(fd, mdverts->dw);
+ /*convert to vgroup allocation system*/
+ MDeformWeight *dw;
+ if(mdverts->dw && (dw= newdataadr(fd, mdverts->dw))) {
+ const ssize_t dw_len= mdverts->totweight * sizeof(MDeformWeight);
+ void *dw_tmp= BLI_cellalloc_malloc(dw_len, "direct_link_dverts");
+ memcpy(dw_tmp, dw, dw_len);
+ mdverts->dw= dw_tmp;
+ MEM_freeN(dw);
}
- if (mdverts->dw == NULL) {
+ else {
+ mdverts->dw= NULL;
mdverts->totweight= 0;
}
}
@@ -3513,7 +3555,18 @@ static void direct_link_mdisps(FileData *fd, int count, MDisps *mdisps, int exte
for(i = 0; i < count; ++i) {
mdisps[i].disps = newdataadr(fd, mdisps[i].disps);
-
+
+ /*put .disps into cellalloc system*/
+ if (mdisps[i].disps) {
+ float *disp2;
+
+ disp2 = BLI_cellalloc_malloc(MEM_allocN_len(mdisps[i].disps), "cellalloc .disps copy");
+ memcpy(disp2, mdisps[i].disps, MEM_allocN_len(mdisps[i].disps));
+
+ MEM_freeN(mdisps[i].disps);
+ mdisps[i].disps = (float (*)[3])disp2;
+ }
+
if( (fd->flags & FD_FLAGS_SWITCH_ENDIAN) && (mdisps[i].disps) ) {
/* DNA_struct_switch_endian doesn't do endian swap for (*disps)[] */
/* this does swap for data written at write_mdisps() - readfile.c */
@@ -3530,6 +3583,7 @@ static void direct_link_mdisps(FileData *fd, int count, MDisps *mdisps, int exte
}
}
+/*this isn't really a public api function, so prototyped here*/
static void direct_link_customdata(FileData *fd, CustomData *data, int count)
{
int i = 0;
@@ -3550,6 +3604,8 @@ static void direct_link_customdata(FileData *fd, CustomData *data, int count)
i++;
}
}
+
+ CustomData_update_typemap(data);
}
static void direct_link_mesh(FileData *fd, Mesh *mesh)
@@ -3560,12 +3616,17 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
mesh->mvert= newdataadr(fd, mesh->mvert);
mesh->medge= newdataadr(fd, mesh->medge);
mesh->mface= newdataadr(fd, mesh->mface);
+ mesh->mloop= newdataadr(fd, mesh->mloop);
+ mesh->mpoly= newdataadr(fd, mesh->mpoly);
mesh->tface= newdataadr(fd, mesh->tface);
mesh->mtface= newdataadr(fd, mesh->mtface);
mesh->mcol= newdataadr(fd, mesh->mcol);
mesh->msticky= newdataadr(fd, mesh->msticky);
mesh->dvert= newdataadr(fd, mesh->dvert);
-
+ mesh->mloopcol= newdataadr(fd, mesh->mloopcol);
+ mesh->mloopuv= newdataadr(fd, mesh->mloopuv);
+ mesh->mtpoly= newdataadr(fd, mesh->mtpoly);
+
/* animdata */
mesh->adt= newdataadr(fd, mesh->adt);
direct_link_animdata(fd, mesh->adt);
@@ -3586,10 +3647,12 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
direct_link_customdata(fd, &mesh->vdata, mesh->pv ? mesh->pv->totvert : mesh->totvert);
direct_link_customdata(fd, &mesh->edata, mesh->pv ? mesh->pv->totedge : mesh->totedge);
direct_link_customdata(fd, &mesh->fdata, mesh->pv ? mesh->pv->totface : mesh->totface);
-
+ direct_link_customdata(fd, &mesh->ldata, mesh->totloop);
+ direct_link_customdata(fd, &mesh->pdata, mesh->totpoly);
+
mesh->bb= NULL;
mesh->mselect = NULL;
- mesh->edit_mesh= NULL;
+ mesh->edit_btmesh= NULL;
/* Multires data */
mesh->mr= newdataadr(fd, mesh->mr);
@@ -10464,6 +10527,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
sce->gm.dome.warptext = sce->r.dometext;
//Stand Alone
+ sce->gm.fullscreen = sce->r.fullscreen;
sce->gm.xplay = sce->r.xplay;
sce->gm.yplay = sce->r.yplay;
sce->gm.freqplay = sce->r.freqplay;
@@ -11818,7 +11882,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
Mesh *me;
for(me= main->mesh.first; me; me= me->id.next)
- mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+ mesh_calc_tessface_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
}
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 2)){
@@ -12190,22 +12254,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
-
- {
- /* Initialize BGE exit key to esc key */
- Scene *scene;
- for(scene= main->scene.first; scene; scene= scene->id.next) {
- if (!scene->gm.exitkey)
- scene->gm.exitkey = 218; //218 is the Blender key code for ESC
- }
- }
-
- {
- /* Initialize default values for collision masks */
- Object *ob;
- for(ob=main->object.first; ob; ob=ob->id.next)
- ob->col_group = ob->col_mask = 1;
- }
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index df5ed5a050c..04c324bd28e 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1665,6 +1665,7 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
write_customdata(wd, &mesh->id, mesh->pv->totvert, &mesh->vdata, -1, 0);
write_customdata(wd, &mesh->id, mesh->pv->totedge, &mesh->edata,
CD_MEDGE, mesh->totedge);
+ /* BMESH_TODO: probably need to deal with polys here */
write_customdata(wd, &mesh->id, mesh->pv->totface, &mesh->fdata,
CD_MFACE, mesh->totface);
}
@@ -1672,6 +1673,8 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, -1, 0);
write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, -1, 0);
write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0);
}
/* PMV data */
diff --git a/source/blender/blenpluginapi/SConscript b/source/blender/blenpluginapi/SConscript
index 7c7c1318a6e..a5e7f479cfb 100644
--- a/source/blender/blenpluginapi/SConscript
+++ b/source/blender/blenpluginapi/SConscript
@@ -7,6 +7,8 @@ incs = '. .. #/intern/guardedalloc ../blenlib ../imbuf ../makesdna ../blenloader
defs = []
+incs += ' ' + env["BF_PTHREADS_INC"]
+
if env['WITH_BF_QUICKTIME']:
defs.append('WITH_QUICKTIME')
incs += ' ' + env['BF_QUICKTIME_INC']
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
new file mode 100644
index 00000000000..d21f24637b0
--- /dev/null
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -0,0 +1,137 @@
+# $Id: CMakeLists.txt 31746 2010-09-04 05:31:25Z joeedh $
+# ***** 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 *****
+
+set(INC
+ .
+ intern
+ operators
+ ../avi
+ ../blenfont
+ ../blenkernel
+ ../blenlib
+ ../blenloader
+ ../editors/include
+ ../editors/mesh
+ ../gpu
+ ../ikplugin
+ ../imbuf
+ ../makesdna
+ ../makesrna
+ ../modifiers
+ ../nodes
+ ../render/extern/include
+ ../../../extern/glew/include
+ ../../../intern/audaspace/intern
+ ../../../intern/bsp/extern
+ ../../../intern/decimation/extern
+ ../../../intern/elbeem/extern
+ ../../../intern/guardedalloc
+ ../../../intern/iksolver/extern
+ ../../../intern/memutil
+ ../../../intern/mikktspace
+ ../../../intern/opennl/extern
+ ../../../intern/smoke/extern
+ # XXX - BAD LEVEL CALL WM_api.h
+ ../../../source/blender/windowmanager
+)
+
+set(INC_SYS
+ ${ZLIB_INCLUDE_DIRS}
+)
+
+set(SRC
+ operators/bevel.c
+ operators/bmesh_dupeops.c
+ operators/utils.c
+ operators/subdivideop.c
+ operators/connectops.c
+ operators/removedoubles.c
+ operators/mirror.c
+ operators/primitiveops.c
+ operators/join_triangles.c
+ operators/edgesplitop.c
+ operators/createops.c
+ operators/dissolveops.c
+ operators/subdivideop.h
+ operators/triangulateop.c
+ operators/mesh_conv.c
+ operators/extrudeops.c
+ bmesh_operators.h
+ bmesh_iterators.h
+ intern/bmesh_newcore.c
+ intern/bmesh_interp.c
+ intern/bmesh_iterators.c
+ intern/bmesh_marking.c
+ intern/bmesh_mesh.c
+ intern/bmesh_mods.c
+ intern/bmesh_structure.h
+ intern/bmesh_construct.c
+ intern/bmesh_to_editmesh.c
+ intern/bmesh_operators_private.h
+ intern/editmesh_to_bmesh.c
+ intern/bmesh_structure.c
+ intern/bmesh_polygon.c
+ intern/bmesh_queries.c
+ intern/bmesh_opdefines.c
+ intern/bmesh_filters.c
+ intern/bmesh_eulers.c
+ intern/bmesh_operators.c
+ intern/bmesh_private.h
+ intern/bmesh_walkers.c
+ intern/bmesh_walkers_impl.c
+ intern/bmesh_walkers_private.h
+ intern/bmesh_inline.c
+ bmesh_error.h
+ bmesh_queries.h
+ bmesh.h
+ bmesh_marking.h
+ bmesh_operator_api.h
+ bmesh_filters.h
+ bmesh_class.h
+ bmesh_walkers.h
+)
+
+add_definitions(-DGLEW_STATIC)
+
+if(WITH_LZO)
+ add_definitions(-DWITH_LZO)
+ list(APPEND INC_SYS
+ ../../../extern/lzo/minilzo
+ )
+endif()
+
+if(WITH_LZMA)
+ add_definitions(-DWITH_LZMA)
+ list(APPEND INC_SYS
+ ../../../extern/lzma
+ )
+endif()
+
+if(MSVC)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
+endif()
+
+blender_add_lib(bf_bmesh "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/bmesh/SConscript b/source/blender/bmesh/SConscript
new file mode 100644
index 00000000000..91b7a72bb1f
--- /dev/null
+++ b/source/blender/bmesh/SConscript
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+Import ('env')
+
+cflags=''
+"""
+sources = ['intern/bmesh_eulers.c']
+sources.append('intern/bmesh_mesh.c')
+sources.append('intern/bmesh_polygon.c')
+sources.append('intern/bmesh_structure.c')
+sources.append('intern/bmesh_marking.c')
+
+sources.append('intern/bmesh_construct.c')
+sources.append('intern/bmesh_interp.c')
+sources.append('intern/bmesh_filters.c')
+sources.append('intern/bmesh_iterators.c')
+sources.append('intern/bmesh_mods.c')
+sources.append('intern/bmesh_queries.c')
+sources.append('intern/bmesh_operators.c')
+"""
+#sources.append('api/BME_walkers.c')
+
+
+sources = env.Glob('intern/*.c')
+sources += env.Glob('operators/*.c')
+
+#sources += env.Glob('tools/*.c')
+
+incs = ['#/intern/guardedalloc']
+incs.append('../blenlib')
+incs.append('../blenloader')
+incs.append('../makesdna')
+incs.append('../makesrna')
+incs.append('../blenkernel')
+incs.append('./')
+incs.append('./intern')
+incs.append('../editors/mesh')
+incs.append('../editors/include')
+
+defs = []
+env.BlenderLib ( libname = 'bf_bmesh', sources = sources, includes = Split(incs), libtype = 'core', defines=defs, priority=100, compileflags=cflags )
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
new file mode 100644
index 00000000000..052bd616a86
--- /dev/null
+++ b/source/blender/bmesh/bmesh.h
@@ -0,0 +1,327 @@
+/**
+ * bmesh.h jan 2007
+ *
+ * BMesh API.
+ *
+ * $Id: bmesh.h,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Geoffrey Bantle, Levi Schooley.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BMESH_H
+#define BMESH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
+#include "DNA_customdata_types.h"
+
+#include "BKE_customdata.h"
+
+#include "BLI_utildefines.h"
+
+/*
+short introduction:
+
+the bmesh structure is a boundary representation, supporting non-manifold
+locally modifiable topology. the API is designed to allow clean, maintainable
+code, that never (or almost never) directly inspects the underlying structure.
+
+The API includes iterators, including many useful topological iterators;
+walkers, which walk over a mesh, without the risk of hitting the recursion
+limit; operators, which are logical, reusable mesh modules; topological
+modification functions (like split face, join faces, etc), which are used for
+topological manipulations; and some (not yet finished) geometric utility
+functions.
+
+some definitions:
+
+tool flags: private flags for tools. each operator has it's own private
+ tool flag "layer", which it can use to flag elements.
+ tool flags are also used by various other parts of the api.
+header flags: stores persistent flags, such as selection state, hide state,
+ etc. be careful of touching these.
+*/
+
+/*forward declarations*/
+struct BMesh;
+struct BMVert;
+struct BMEdge;
+struct BMFace;
+struct BMLoop;
+struct BMOperator;
+struct Mesh;
+struct EditMesh;
+
+/*
+ * BMHeader
+ *
+ * All mesh elements begin with a BMHeader. This structure
+ * hold several types of data
+ *
+ * 1: The type of the element (vert, edge, loop or face)
+ * 2: Persistant "header" flags/markings (sharp, seam, select, hidden, ect)
+ note that this is different from the "tool" flags.
+ * 3: Unique ID in the bmesh.
+ * 4: some elements for internal record keeping.
+ *
+*/
+
+/*BMHeader->type*/
+#define BM_VERT 1
+#define BM_EDGE 2
+#define BM_LOOP 4
+#define BM_FACE 8
+#define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE)
+
+/*BMHeader->flag*/
+#define BM_SELECT (1<<0)
+
+#define BM_SEAM (1<<1)
+#define BM_FGON (1<<2)
+#define BM_HIDDEN (1<<3)
+#define BM_SHARP (1<<4)
+#define BM_SMOOTH (1<<5)
+#define BM_ACTIVE (1<<6)
+#define BM_NONORMCALC (1<<7)
+#define BM_FLIPPED (1<<8) /*internal flag, used for ensuring correct normals during multires interpolation*/
+
+#include "bmesh_class.h"
+
+/*stub */
+void bmesh_error ( void );
+
+/*Mesh Level Ops */
+
+/*ob is needed by multires*/
+struct BMesh *BM_Make_Mesh (struct Object *ob, int allocsize[4] );
+BMesh *BM_Copy_Mesh ( BMesh *bmold );
+void BM_Free_Mesh ( struct BMesh *bm );
+
+/*frees mesh, but not actual BMesh struct*/
+void BM_Free_Mesh_Data ( BMesh *bm );
+void BM_Compute_Normals ( struct BMesh *bm );
+
+/*Construction*/
+struct BMVert *BM_Make_Vert ( struct BMesh *bm, float co[3], const struct BMVert *example );
+struct BMEdge *BM_Make_Edge ( struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, const struct BMEdge *example, int nodouble );
+struct BMFace *BM_Make_Quadtriangle ( struct BMesh *bm, struct BMVert **verts, BMEdge **edges, int len, const struct BMFace *example, int nodouble );
+
+BMFace *BM_Make_Face(BMesh *bm, BMVert **verts, BMEdge **edges, int len, int nodouble);
+
+/*more easier to use version of BM_Make_Quadtriangle.
+ creates edges if necassary.*/
+BMFace *BM_Make_QuadTri ( BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3,
+ BMVert *v4, const BMFace *example, int nodouble );
+
+/*makes an ngon from an unordered list of edges. v1 and v2 must be the verts
+defining edges[0], and define the winding of the new face.*/
+struct BMFace *BM_Make_Ngon ( struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMEdge **edges, int len, int nodouble );
+
+/*stuff for dealing with header flags*/
+BM_INLINE int BM_TestHFlag(const void *element, const int flag);
+
+/*stuff for dealing with header flags*/
+BM_INLINE void BM_SetHFlag(void *element, const int flag);
+
+/*stuff for dealing with header flags*/
+BM_INLINE void BM_ClearHFlag(void *element, const int flag);
+
+/*stuff for dealing BM_ToggleHFlag header flags*/
+BM_INLINE void BM_ToggleHFlag(void *element, const int flag);
+BM_INLINE void BM_MergeHFlag(void *element_a, void *element_b);
+BM_INLINE void BM_SetIndex(void *element, const int index);
+BM_INLINE int BM_GetIndex(const void *element);
+
+/*copies loop data from adjacent faces*/
+void BM_Face_CopyShared ( BMesh *bm, BMFace *f );
+
+/*copies attributes, e.g. customdata, header flags, etc, from one element
+ to another of the same type.*/
+void BM_Copy_Attributes ( struct BMesh *source_mesh, struct BMesh *target_mesh, const void *source, void *target );
+
+/*Modification*/
+/*join two adjacent faces together along an edge. note that
+ the faces must only be joined by on edge. e is the edge you
+ wish to dissolve.*/
+BMFace *BM_Join_TwoFaces(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
+
+/*generic, flexible join faces function; note that most everything uses
+ this, including BM_Join_TwoFaces*/
+BMFace *BM_Join_Faces(BMesh *bm, BMFace **faces, int totface);
+
+/*split a face along two vertices. returns the newly made face, and sets
+ the nl member to a loop in the newly created edge.*/
+struct BMFace *BM_Split_Face ( struct BMesh *bm, struct BMFace *f,
+ struct BMVert *v1, struct BMVert *v2,
+ struct BMLoop **nl, struct BMEdge *example );
+
+/*dissolves a vert shared only by two edges*/
+BMEdge* BM_Collapse_Vert ( struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv,
+ float fac );
+
+/*splits an edge. ne is set to the new edge created.*/
+struct BMVert *BM_Split_Edge ( struct BMesh *bm, struct BMVert *v,
+ struct BMEdge *e, struct BMEdge **ne,
+ float percent );
+
+/*split an edge multiple times evenly*/
+struct BMVert *BM_Split_Edge_Multi ( struct BMesh *bm, struct BMEdge *e,
+ int numcuts );
+
+/*connect two verts together, through a face they share. this function may
+ be removed in the future.*/
+BMEdge *BM_Connect_Verts ( BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf );
+
+/*rotates an edge topologically, either clockwise (if ccw=0) or counterclockwise
+ (if ccw is 1).*/
+BMEdge *BM_Rotate_Edge ( BMesh *bm, BMEdge *e, int ccw );
+
+/* Rip a single face from a vertex fan */
+BMVert *BM_Rip_Vertex ( BMesh *bm, BMFace *sf, BMVert *sv);
+
+/*updates a face normal*/
+void BM_Face_UpdateNormal ( BMesh *bm, BMFace *f );
+
+/*updates face and vertex normals incident on an edge*/
+void BM_Edge_UpdateNormals ( BMesh *bm, BMEdge *e );
+
+/*update a vert normal (but not the faces incident on it)*/
+void BM_Vert_UpdateNormal ( BMesh *bm, BMVert *v );
+void BM_Vert_UpdateAllNormals ( BMesh *bm, BMVert *v );
+
+void BM_flip_normal ( BMesh *bm, BMFace *f );
+
+/*dissolves all faces around a vert, and removes it.*/
+int BM_Dissolve_Disk ( BMesh *bm, BMVert *v );
+
+/*dissolves vert, in more situations then BM_Dissolve_Disk
+ (e.g. if the vert is part of a wire edge, etc).*/
+int BM_Dissolve_Vert ( BMesh *bm, BMVert *v );
+
+/*Projects co onto face f, and returns true if it is inside
+ the face bounds. Note that this uses a best-axis projection
+ test, instead of projecting co directly into f's orientation
+ space, so there might be accuracy issues.*/
+int BM_Point_In_Face(BMesh *bm, BMFace *f, float co[3]);
+
+/*Interpolation*/
+
+/*projects target onto source for customdata interpolation. note: only
+ does loop customdata. multires is handled. */
+void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source);
+
+/*projects a single loop, target, onto source for customdata interpolation. multires is handled.
+ if do_vertex is true, target's vert data will also get interpolated.*/
+void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
+ int do_vertex, int do_multires);
+
+/*smoothes boundaries between multires grids, including some borders in adjacent faces*/
+void BM_multires_smooth_bounds(BMesh *bm, BMFace *f);
+
+/*project the multires grid in target onto source's set of multires grids*/
+void BM_loop_interp_multires(BMesh *bm, BMLoop *target, BMFace *source);
+void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source);
+
+void BM_Data_Interp_From_Verts (struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, float fac );
+void BM_Data_Facevert_Edgeinterp (struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, struct BMEdge *e1, float fac );
+void BM_add_data_layer (BMesh *em, CustomData *data, int type );
+void BM_add_data_layer_named (BMesh *bm, CustomData *data, int type, char *name );
+void BM_free_data_layer (BMesh *em, CustomData *data, int type );
+void BM_free_data_layer_n(BMesh *bm, CustomData *data, int type, int n);
+float BM_GetCDf(struct CustomData *cd, void *element, int type);
+void BM_SetCDf(struct CustomData *cd, void *element, int type, float val);
+
+/*computes the centroid of a face, using the center of the bounding box*/
+int BM_Compute_Face_Center ( BMesh *bm, BMFace *f, float center[3] );
+
+void BM_SelectMode_Flush ( BMesh *bm );
+
+/*convert an editmesh to a bmesh*/
+BMesh *editmesh_to_bmesh ( struct EditMesh *em );
+
+/*initializes editmesh to bmesh operator, but doesn't execute.
+ this is used in situations where you need to get access to the
+ conversion operator's editmesh->bmesh mapping slot (e.g. if you
+ need to find the bmesh edge that corrusponds to a specific editmesh
+ edge).*/
+BMesh *init_editmesh_to_bmesh ( struct EditMesh *em, struct BMOperator *op );
+
+/*converts a bmesh to an editmesh*/
+struct EditMesh *bmesh_to_editmesh ( BMesh *bm );
+
+/*convert between bmesh and Mesh flags*/
+int BMFlags_To_MEFlags ( void *element );
+
+/*convert between Mesh and bmesh flags
+ type must be BM_VERT/BM_EDGE/BM_FACE,
+ and represents the type of the element
+ parameter (the three defines map to
+ MVert, MEdge, and MPoly, respectively).*/
+int MEFlags_To_BMFlags ( int flag, int type );
+
+/*convert MLoop*** in a bmface to mtface and mcol in
+ an MFace*/
+void BM_loops_to_corners ( BMesh *bm, struct Mesh *me, int findex,
+ BMFace *f, int numTex, int numCol );
+
+void BM_Kill_Loop(BMesh *bm, BMLoop *l);
+void BM_Kill_Face(BMesh *bm, BMFace *f);
+void BM_Kill_Edge(BMesh *bm, BMEdge *e);
+void BM_Kill_Vert(BMesh *bm, BMVert *v);
+
+/*kills all edges associated with f, along with any other faces containing
+ those edges*/
+void BM_Kill_Face_Edges(BMesh *bm, BMFace *f);
+
+/*kills all verts associated with f, along with any other faces containing
+ those vertices*/
+void BM_Kill_Face_Verts(BMesh *bm, BMFace *f) ;
+
+/*start/stop edit*/
+void bmesh_begin_edit(struct BMesh *bm, int flag);
+void bmesh_end_edit(struct BMesh *bm, int flag);
+
+
+#define bm_firstfaceloop(p) ((BMLoopList*)(p->loops.first))->first
+
+/*include the rest of the API*/
+#include "bmesh_filters.h"
+#include "bmesh_iterators.h"
+#include "bmesh_marking.h"
+#include "bmesh_operator_api.h"
+#include "bmesh_operators.h"
+#include "bmesh_error.h"
+#include "bmesh_queries.h"
+#include "bmesh_walkers.h"
+#include "intern/bmesh_inline.c"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BMESH_H */
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
new file mode 100644
index 00000000000..30c3b627628
--- /dev/null
+++ b/source/blender/bmesh/bmesh_class.h
@@ -0,0 +1,166 @@
+/**
+ * bmesh_class.h september 2010
+ *
+ * BMesh API.
+ *
+ * $Id: $
+ *
+ * ***** 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Geoffrey Bantle, Levi Schooley, Joseph Eagar.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef _BMESH_CLASS_H
+#define _BMESH_CLASS_H
+
+/*bmesh data structures*/
+
+#include "DNA_listBase.h"
+
+#include "BKE_utildefines.h"
+#include "BLI_utildefines.h"
+
+struct BMesh;
+struct BMVert;
+struct BMEdge;
+struct BMLoop;
+struct BMFace;
+struct BMVert;
+struct BMEdge;
+struct BMLoop;
+struct BMFace;
+struct BMLayerType;
+struct BMSubClassLayer;
+struct BMFlagLayer;
+struct BLI_mempool;
+struct Object;
+
+/*note: it is very important for BMHeader to start with two
+ pointers. this is a requirement of mempool's method of
+ iteration.
+*/
+typedef struct BMHeader {
+ void *data; /*customdata layers*/
+ struct BMFlagLayer *flags;
+ short type; /*element geometric type (verts/edges/loops/faces)*/
+ short flag; /*this would be a CD layer, see below*/
+ int index; /*note: use BM_GetIndex/SetIndex macros for index*/
+} BMHeader;
+
+/*note: need some way to specify custom locations for custom data layers. so we can
+make them point directly into structs. and some way to make it only happen to the
+active layer, and properly update when switching active layers.*/
+
+typedef struct BMVert {
+ BMHeader head;
+ float co[3];
+ float no[3];
+ struct BMEdge *e;
+} BMVert;
+
+typedef struct BMEdge {
+ BMHeader head;
+ struct BMVert *v1, *v2;
+ struct BMLoop *l;
+
+ /*disk cycle pointers*/
+ struct {
+ struct BMEdge *next, *prev;
+ } dlink1;
+ struct {
+ struct BMEdge *next, *prev;
+ } dlink2;
+} BMEdge;
+
+typedef struct BMLoop {
+ BMHeader head;
+ struct BMVert *v;
+ struct BMEdge *e;
+ struct BMFace *f;
+
+ struct BMLoop *radial_next, *radial_prev;
+
+ /*private variables*/
+ struct BMLoop *next, *prev; /*won't be able to use listbase API, ger, due to head*/\
+ int _index; /*used for sorting during tesselation*/
+} BMLoop;
+
+typedef struct BMLoopList {
+ struct BMLoopList *next, *prev;
+ struct BMLoop *first, *last;
+} BMLoopList;
+
+typedef struct BMFace {
+ BMHeader head;
+ int len; /*includes all boundary loops*/\
+ int totbounds; /*total boundaries, is one plus the number of holes in the face*/\
+ ListBase loops;
+ float no[3]; /*yes, we do store this here*/\
+ short mat_nr;
+} BMFace;
+
+typedef struct BMFlagLayer {
+ short f, pflag; /*flags*/
+ int index; /*generic index*/
+} BMFlagLayer;
+
+typedef struct BMesh {
+ int totvert, totedge, totloop, totface;
+ int totvertsel, totedgesel, totfacesel;
+
+ /*element pools*/
+ struct BLI_mempool *vpool, *epool, *lpool, *fpool;
+
+ /*operator api stuff*/
+ struct BLI_mempool *toolflagpool;
+ int stackdepth;
+ struct BMOperator *currentop;
+
+ CustomData vdata, edata, ldata, pdata;
+
+ struct BLI_mempool *looplistpool;
+
+ /*should be copy of scene select mode*/
+ int selectmode;
+
+ /*ID of the shape key this bmesh came from*/
+ int shapenr;
+
+ int walkers, totflags;
+ ListBase selected, error_stack;
+
+ BMFace *act_face;
+
+ ListBase errorstack;
+ struct Object *ob; /*owner object*/
+
+ int opflag; /*current operator flag*/
+} BMesh;
+
+BMFace *BM_Copy_Face(BMesh *bm, BMFace *f, int copyedges, int copyverts);
+
+#define BM_VERT 1
+#define BM_EDGE 2
+#define BM_LOOP 4
+#define BM_FACE 8
+
+#endif /* _BMESH_CLASS_H */
diff --git a/source/blender/bmesh/bmesh_error.h b/source/blender/bmesh/bmesh_error.h
new file mode 100644
index 00000000000..3482402b45b
--- /dev/null
+++ b/source/blender/bmesh/bmesh_error.h
@@ -0,0 +1,43 @@
+#ifndef _BMESH_ERROR_H
+#define _BMESH_ERROR_H
+
+/*----------- bmop error system ----------*/
+
+/*pushes an error onto the bmesh error stack.
+ if msg is null, then the default message for the errorcode is used.*/
+void BMO_RaiseError(BMesh *bm, BMOperator *owner, int errcode, const char *msg);
+
+/*gets the topmost error from the stack.
+ returns error code or 0 if no error.*/
+int BMO_GetError(BMesh *bm, const char **msg, BMOperator **op);
+int BMO_HasError(BMesh *bm);
+
+/*same as geterror, only pops the error off the stack as well*/
+int BMO_PopError(BMesh *bm, const char **msg, BMOperator **op);
+void BMO_ClearStack(BMesh *bm);
+
+#if 0
+//this is meant for handling errors, like self-intersection test failures.
+//it's dangerous to handle errors in general though, so disabled for now.
+
+/*catches an error raised by the op pointed to by catchop.
+ errorcode is either the errorcode, or BMERR_ALL for any
+ error.*/
+int BMO_CatchOpError(BMesh *bm, BMOperator *catchop, int errorcode, char **msg);
+#endif
+
+/*------ error code defines -------*/
+
+/*error messages*/
+#define BMERR_SELF_INTERSECTING 1
+#define BMERR_DISSOLVEDISK_FAILED 2
+#define BMERR_CONNECTVERT_FAILED 3
+#define BMERR_WALKER_FAILED 4
+#define BMERR_DISSOLVEFACES_FAILED 5
+#define BMERR_DISSOLVEVERTS_FAILED 6
+#define BMERR_TESSELATION 7
+#define BMERR_NONMANIFOLD 8
+#define BMERR_INVALID_SELECTION 9
+#define BMERR_MESH_ERROR 10
+
+#endif /* _BMESH_ERROR_H */
diff --git a/source/blender/bmesh/bmesh_filters.h b/source/blender/bmesh/bmesh_filters.h
new file mode 100644
index 00000000000..9eed4e509fa
--- /dev/null
+++ b/source/blender/bmesh/bmesh_filters.h
@@ -0,0 +1,4 @@
+#ifndef BM_FILTER_H
+#define BM_FILTER_H
+
+#endif
diff --git a/source/blender/bmesh/bmesh_iterators.h b/source/blender/bmesh/bmesh_iterators.h
new file mode 100644
index 00000000000..49920a77074
--- /dev/null
+++ b/source/blender/bmesh/bmesh_iterators.h
@@ -0,0 +1,82 @@
+/*
+ * BMESH ITERATORS
+ *
+ * The functions and structures in this file
+ * provide a unified method for iterating over
+ * the elements of a mesh and answering simple
+ * adjacency queries. Tool authors should use
+ * the iterators provided in this file instead
+ * of inspecting the structure directly.
+ *
+*/
+
+#ifndef BM_ITERATORS_H
+#define BM_ITERATORS_H
+
+#include "BLI_mempool.h"
+
+/*Defines for passing to BMIter_New.
+
+ "OF" can be substituted for "around"
+ so BM_VERTS_OF_FACE means "vertices
+ around a face."
+ */
+
+/*these iterator over all elements of a specific
+ type in the mesh.*/
+#define BM_VERTS_OF_MESH 1
+#define BM_EDGES_OF_MESH 2
+#define BM_FACES_OF_MESH 3
+
+/*these are topological iterators.*/
+#define BM_EDGES_OF_VERT 4
+#define BM_FACES_OF_VERT 5
+#define BM_LOOPS_OF_VERT 6
+#define BM_FACES_OF_EDGE 7
+#define BM_VERTS_OF_FACE 8
+#define BM_EDGES_OF_FACE 9
+#define BM_LOOPS_OF_FACE 10
+/*returns elements from all boundaries, and returns
+the first element at the end to flag that we're entering
+a different face hole boundary*/
+#define BM_ALL_LOOPS_OF_FACE 11
+
+/*iterate through loops around this loop, which are fetched
+ from the other faces in the radial cycle surrounding the
+ input loop's edge.*/
+#define BM_LOOPS_OF_LOOP 12
+#define BM_LOOPS_OF_EDGE 13
+
+#define BM_ITER(ele, iter, bm, type, data) \
+ ele = BMIter_New(iter, bm, type, data); \
+ for ( ; ele; ele=BMIter_Step(iter))
+
+#define BM_ITER_INDEX(ele, iter, bm, type, data, indexvar) \
+ ele = BMIter_New(iter, bm, type, data); \
+ for (indexvar=0; ele; indexvar++, ele=BMIter_Step(iter))
+
+/*Iterator Structure*/
+typedef struct BMIter {
+ BLI_mempool_iter pooliter;
+
+ struct BMVert *firstvert, *nextvert, *vdata;
+ struct BMEdge *firstedge, *nextedge, *edata;
+ struct BMLoop *firstloop, *nextloop, *ldata, *l;
+ struct BMFace *firstpoly, *nextpoly, *pdata;
+ struct BMesh *bm;
+ void (*begin)(struct BMIter *iter);
+ void *(*step)(struct BMIter *iter);
+ union{
+ void *p;
+ int i;
+ long l;
+ float f;
+ }filter;
+ int type, count;
+}BMIter;
+
+void *BMIter_New(struct BMIter *iter, struct BMesh *bm, int type, void *data);
+void *BMIter_Step(struct BMIter *iter);
+void *BMIter_AtIndex(struct BMesh *bm, int type, void *data, int index);
+
+#endif
diff --git a/source/blender/bmesh/bmesh_marking.h b/source/blender/bmesh/bmesh_marking.h
new file mode 100644
index 00000000000..c8e161a37fd
--- /dev/null
+++ b/source/blender/bmesh/bmesh_marking.h
@@ -0,0 +1,54 @@
+#ifndef BM_MARKING_H
+#define BM_MARKING_H
+
+typedef struct BMEditSelection
+{
+ struct BMEditSelection *next, *prev;
+ short type;
+ void *data;
+} BMEditSelection;
+
+/* pinning code */
+void BM_Pin(BMesh *bm, void *element, int pin);
+void BM_Pin_Vert(BMesh *bm, BMVert *v, int pin);
+void BM_Pin_Edge(BMesh *bm, BMEdge *e, int pin);
+void BM_Pin_Face(BMesh *bm, BMFace *f, int pin);
+
+/*geometry hiding code*/
+void BM_Hide(BMesh *bm, void *element, int hide);
+void BM_Hide_Vert(BMesh *bm, BMVert *v, int hide);
+void BM_Hide_Edge(BMesh *bm, BMEdge *e, int hide);
+void BM_Hide_Face(BMesh *bm, BMFace *f, int hide);
+
+/*Selection code*/
+void BM_Select(struct BMesh *bm, void *element, int select);
+/*I don't use this function anywhere, been using BM_TestHFlag instead.
+ Need to decide either to keep it and convert everything over, or
+ chuck it.*/
+int BM_Selected(BMesh *bm, const void *element);
+
+void BM_clear_flag_all(BMesh *bm, int flag);
+
+/*individual element select functions, BM_Select is a shortcut for these
+ that automatically detects which one to use*/
+void BM_Select_Vert(struct BMesh *bm, struct BMVert *v, int select);
+void BM_Select_Edge(struct BMesh *bm, struct BMEdge *e, int select);
+void BM_Select_Face(struct BMesh *bm, struct BMFace *f, int select);
+
+void BM_Selectmode_Set(struct BMesh *bm, int selectmode);
+
+/*counts number of elements with flag set*/
+int BM_CountFlag(struct BMesh *bm, int type, int flag, int respecthide);
+
+/*edit selection stuff*/
+void BM_set_actFace(BMesh *em, BMFace *f);
+BMFace *BM_get_actFace(BMesh *bm, int sloppy);
+void BM_editselection_center(BMesh *bm, float *center, BMEditSelection *ese);
+void BM_editselection_normal(float *normal, BMEditSelection *ese);
+void BM_editselection_plane(BMesh *bm, float *plane, BMEditSelection *ese);
+void BM_remove_selection(BMesh *bm, void *data);
+void BM_store_selection(BMesh *bm, void *data);
+void BM_validate_selections(BMesh *bm);
+void BM_clear_selection_history(BMesh *em);
+
+#endif
diff --git a/source/blender/bmesh/bmesh_operator_api.h b/source/blender/bmesh/bmesh_operator_api.h
new file mode 100644
index 00000000000..c463f6fb5ae
--- /dev/null
+++ b/source/blender/bmesh/bmesh_operator_api.h
@@ -0,0 +1,499 @@
+#ifndef _BMESH_OPERATOR_API_H
+#define _BMESH_OPERATOR_API_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_memarena.h"
+#include "BLI_ghash.h"
+
+#include "BKE_utildefines.h"
+
+#include <stdarg.h>
+
+/*
+operators represent logical, executable mesh modules. all topological
+operations involving a bmesh has to go through them.
+
+operators are nested, as are tool flags, which are private to an operator
+when it's executed. tool flags are allocated in layers, one per operator
+execution, and are used for all internal flagging a tool needs to do.
+
+each operator has a series of "slots," which can be of the following types:
+* simple numerical types
+* arrays of elements (e.g. arrays of faces).
+* hash mappings.
+
+each slot is identified by a slot code, as are each operator.
+operators, and their slots, are defined in bmesh_opdefines.c (with their
+execution functions prototyped in bmesh_operators_private.h), with all their
+operator code and slot codes defined in bmesh_operators.h. see
+bmesh_opdefines.c and the BMOpDefine struct for how to define new operators.
+
+in general, operators are fed arrays of elements, created using either
+BM_HeaderFlag_To_Slot or BM_Flag_To_Slot (or through one of the format
+specifyers in BMO_CallOpf or BMO_InitOpf). Note that multiple element
+types (e.g. faces and edges) can be fed to the same slot array. Operators
+act on this data, and possibly spit out data into output slots.
+
+some notes:
+* operators should never read from header flags (e.g. element->head.flag). for
+ example, if you want an operator to only operate on selected faces, you
+ should use BM_HeaderFlag_To_Slot to put the selected elements into a slot.
+* when you read from an element slot array or mapping, you can either tool-flag
+ all the elements in it, or read them using an iterator APi (which is
+ semantically similar to the iterator api in bmesh_iterators.h).
+*/
+
+struct GHashIterator;
+
+/*slot type arrays are terminated by the last member
+ having a slot type of 0.*/
+#define BMOP_OPSLOT_SENTINEL 0
+#define BMOP_OPSLOT_INT 1
+#define BMOP_OPSLOT_FLT 2
+#define BMOP_OPSLOT_PNT 3
+#define BMOP_OPSLOT_MAT 4
+#define BMOP_OPSLOT_VEC 7
+
+/*after BMOP_OPSLOT_VEC, everything is
+
+ dynamically allocated arrays. we
+ leave a space in the identifiers
+ for future growth.
+
+ */
+//it's very important this remain a power of two
+#define BMOP_OPSLOT_ELEMENT_BUF 8
+#define BMOP_OPSLOT_MAPPING 9
+#define BMOP_OPSLOT_TYPES 10
+
+/*please ignore all these structures, don't touch them in tool code, except
+ for when your defining an operator with BMOpDefine.*/
+
+typedef struct BMOpSlot{
+ int slottype;
+ int len;
+ int flag;
+ int index; /*index within slot array*/
+ union {
+ int i;
+ float f;
+ void *p;
+ float vec[3];
+ void *buf;
+ GHash *ghash;
+ } data;
+} BMOpSlot;
+
+#define BMOP_MAX_SLOTS 16 /*way more than probably needed*/
+
+#ifdef slots
+#undef slots
+#endif
+
+typedef struct BMOperator {
+ int type;
+ int slottype;
+ int needflag;
+ int flag;
+ struct BMOpSlot slots[BMOP_MAX_SLOTS];
+ void (*exec)(struct BMesh *bm, struct BMOperator *op);
+ MemArena *arena;
+} BMOperator;
+
+#define MAX_SLOTNAME 32
+
+typedef struct slottype {
+ int type;
+ char name[MAX_SLOTNAME];
+} slottype;
+
+typedef struct BMOpDefine {
+ const char *name;
+ slottype slottypes[BMOP_MAX_SLOTS];
+ void (*exec)(BMesh *bm, BMOperator *op);
+ int flag;
+} BMOpDefine;
+
+/*BMOpDefine->flag*/
+#define BMOP_UNTAN_MULTIRES 1 /*switch from multires tangent space to absolute coordinates*/
+
+
+/*ensures consistent normals before operator execution,
+ restoring the original ones windings/normals afterwards.
+ keep in mind, this won't work if the input mesh isn't
+ manifold.*/
+#define BMOP_RATIONALIZE_NORMALS 2
+
+/*------------- Operator API --------------*/
+
+/*data types that use pointers (arrays, etc) should never
+ have it set directly. and never use BMO_Set_Pnt to
+ pass in a list of edges or any arrays, really.*/
+
+void BMO_Init_Op(struct BMOperator *op, const char *opname);
+
+/*executes an operator, pushing and popping a new tool flag
+ layer as appropriate.*/
+void BMO_Exec_Op(struct BMesh *bm, struct BMOperator *op);
+
+/*finishes an operator (though note the operator's tool flag is removed
+ after it finishes executing in BMO_Exec_Op).*/
+void BMO_Finish_Op(struct BMesh *bm, struct BMOperator *op);
+
+
+/*tool flag API. never, ever ever should tool code put junk in
+ header flags (element->head.flag), nor should they use
+ element->head.eflag1/eflag2. instead, use this api to set
+ flags.
+
+ if you need to store a value per element, use a
+ ghash or a mapping slot to do it.*/
+/*flags 15 and 16 (1<<14 and 1<<15) are reserved for bmesh api use*/
+#define BMO_TestFlag(bm, element, flag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f & (flag))
+#define BMO_SetFlag(bm, element, flag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f |= (flag))
+#define BMO_ClearFlag(bm, element, flag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f &= ~(flag))
+#define BMO_ToggleFlag(bm, element, flag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f ^= (flag))
+
+/*profiling showed a significant amount of time spent in BMO_TestFlag
+void BMO_SetFlag(struct BMesh *bm, void *element, int flag);
+void BMO_ClearFlag(struct BMesh *bm, void *element, int flag);
+int BMO_TestFlag(struct BMesh *bm, void *element, int flag);*/
+
+/*count the number of elements with a specific flag. type
+ can be a bitmask of BM_FACE, BM_EDGE, or BM_FACE.*/
+int BMO_CountFlag(struct BMesh *bm, int flag, int type);
+
+/*---------formatted operator initialization/execution-----------*/
+/*
+ this system is used to execute or initialize an operator,
+ using a formatted-string system.
+
+ for example, BMO_CallOpf(bm, "del geom=%hf context=%d", BM_SELECT, DEL_FACES);
+ . . .will execute the delete operator, feeding in selected faces, deleting them.
+
+ the basic format for the format string is:
+ [operatorname] [slotname]=%[code] [slotname]=%[code]
+
+ as in printf, you pass in one additional argument to the function
+ for every code.
+
+ the formatting codes are:
+ %d - put int in slot
+ %f - put float in slot
+ %p - put pointer in slot
+ %h[f/e/v] - put elements with a header flag in slot.
+ the letters after %h define which element types to use,
+ so e.g. %hf will do faces, %hfe will do faces and edges,
+ %hv will do verts, etc. must pass in at least one
+ element type letter.
+ %f[f/e/v] - same as %h, except it deals with tool flags instead of
+ header flags.
+ %a[f/e/v] - pass all elements (of types specified by f/e/v) to the
+ slot.
+ %e - pass in a single element.
+ %v - pointer to a float vector of length 3.
+ %m[3/4] - matrix, 3/4 refers to the matrix size, 3 or 4. the
+ corrusponding argument must be a pointer to
+ a float matrix.
+ %s - copy a slot from another op, instead of mapping to one
+ argument, it maps to two, a pointer to an operator and
+ a slot name.
+*/
+void BMO_push(BMesh *bm, BMOperator *op);
+void BMO_pop(BMesh *bm);
+
+/*executes an operator*/
+int BMO_CallOpf(BMesh *bm, const char *fmt, ...);
+
+/*initializes, but doesn't execute an operator. this is so you can
+ gain access to the outputs of the operator. note that you have
+ to execute/finitsh (BMO_Exec_Op and BMO_Finish_Op) yourself.*/
+int BMO_InitOpf(BMesh *bm, BMOperator *op, const char *fmt, ...);
+
+/*va_list version, used to implement the above two functions,
+ plus EDBM_CallOpf in bmeshutils.c.*/
+int BMO_VInitOpf(BMesh *bm, BMOperator *op, const char *fmt, va_list vlist);
+
+/*test whether a named slot exists*/
+int BMO_HasSlot(struct BMOperator *op, const char *slotname);
+
+/*get a pointer to a slot. this may be removed layer on from the public API.*/
+BMOpSlot *BMO_GetSlot(struct BMOperator *op, const char *slotname);
+
+/*copies the data of a slot from one operator to another. src and dst are the
+ source/destination slot codes, respectively.*/
+void BMO_CopySlot(struct BMOperator *source_op, struct BMOperator *dest_op,
+ const char *src, const char *dst);
+
+/*remove tool flagged elements*/
+void BM_remove_tagged_faces(struct BMesh *bm, int flag);
+void BM_remove_tagged_edges(struct BMesh *bm, int flag);
+void BM_remove_tagged_verts(struct BMesh *bm, int flag);
+
+void BMO_Set_OpFlag(struct BMesh *bm, struct BMOperator *op, int flag);
+void BMO_Clear_OpFlag(struct BMesh *bm, struct BMOperator *op, int flag);
+
+void BMO_Set_Float(struct BMOperator *op, const char *slotname, float f);
+float BMO_Get_Float(BMOperator *op, const char *slotname);
+void BMO_Set_Int(struct BMOperator *op, const char *slotname, int i);
+int BMO_Get_Int(BMOperator *op, const char *slotname);
+
+/*don't pass in arrays that are supposed to map to elements this way.
+
+ so, e.g. passing in list of floats per element in another slot is bad.
+ passing in, e.g. pointer to an editmesh for the conversion operator is fine
+ though.*/
+void BMO_Set_Pnt(struct BMOperator *op, const char *slotname, void *p);
+void *BMO_Get_Pnt(BMOperator *op, const char *slotname);
+void BMO_Set_Vec(struct BMOperator *op, const char *slotname, float *vec);
+void BMO_Get_Vec(BMOperator *op, const char *slotname, float *vec_out);
+
+/*only supports square mats*/
+/*size must be 3 or 4; this api is meant only for transformation matrices.
+ note that internally the matrix is stored in 4x4 form, and it's safe to
+ call whichever BMO_Get_Mat* function you want.*/
+void BMO_Set_Mat(struct BMOperator *op, const char *slotname, float *mat, int size);
+void BMO_Get_Mat4(struct BMOperator *op, const char *slotname, float mat[4][4]);
+void BMO_Get_Mat3(struct BMOperator *op, const char *slotname, float mat[3][3]);
+
+void BMO_Clear_Flag_All(BMesh *bm, BMOperator *op, int type, int flag);
+
+/*puts every element of type type (which is a bitmask) with tool flag flag,
+ into a slot.*/
+void BMO_Flag_To_Slot(struct BMesh *bm, struct BMOperator *op, const char *slotname, int flag, int type);
+
+/*tool-flags all elements inside an element slot array with flag flag.*/
+void BMO_Flag_Buffer(struct BMesh *bm, struct BMOperator *op, const char *slotname, int flag, int type);
+/*clears tool-flag flag from all elements inside a slot array.*/
+void BMO_Unflag_Buffer(struct BMesh *bm, struct BMOperator *op, const char *slotname, int flag, int type);
+
+/*tool-flags all elements inside an element slot array with flag flag.*/
+void BMO_HeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, const char *slotname, int flag, int type);
+/*clears tool-flag flag from all elements inside a slot array.*/
+void BMO_UnHeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, const char *slotname, int flag, int type);
+
+/*puts every element of type type (which is a bitmask) with header flag
+ flag, into a slot. note: ignores hidden elements (e.g. elements with
+ header flag BM_HIDDEN set).*/
+void BMO_HeaderFlag_To_Slot(struct BMesh *bm, struct BMOperator *op, const char *slotname, int flag, int type);
+
+/*counts number of elements inside a slot array.*/
+int BMO_CountSlotBuf(struct BMesh *bm, struct BMOperator *op, const char *slotname);
+int BMO_CountSlotMap(struct BMesh *bm, struct BMOperator *op, const char *slotname);
+
+/*Counts the number of edges with tool flag toolflag around
+ v*/
+int BMO_Vert_CountEdgeFlags(BMesh *bm, BMVert *v, int toolflag);
+
+/*inserts a key/value mapping into a mapping slot. note that it copies the
+ value, it doesn't store a reference to it.*/
+//BM_INLINE void BMO_Insert_Mapping(BMesh *bm, BMOperator *op, const char *slotname,
+ //void *element, void *data, int len);
+
+/*inserts a key/float mapping pair into a mapping slot.*/
+//BM_INLINE void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, const char *slotname,
+ //void *element, float val);
+
+//returns 1 if the specified pointer is in the map.
+//BM_INLINE int BMO_InMap(BMesh *bm, BMOperator *op, const char *slotname, void *element);
+
+/*returns a point to the value of a specific key.*/
+//BM_INLINE void *BMO_Get_MapData(BMesh *bm, BMOperator *op, const char *slotname, void *element);
+
+/*returns the float part of a key/float pair.*/
+//BM_INLINE float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, const char *slotname, void *element);
+
+/*flags all elements in a mapping. note that the mapping must only have
+ bmesh elements in it.*/
+void BMO_Mapping_To_Flag(struct BMesh *bm, struct BMOperator *op,
+ const char *slotname, int flag);
+
+/*pointer versoins of BMO_Get_MapFloat and BMO_Insert_MapFloat.
+
+ do NOT use these for non-operator-api-allocated memory! instead
+ use BMO_Get_MapData and BMO_Insert_Mapping, which copies the data.*/
+//BM_INLINE void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, const char *slotname,
+ //void *key, void *val);
+//BM_INLINE void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, const char *slotname,
+ //void *key);
+
+/*this part of the API is used to iterate over element buffer or
+ mapping slots.
+
+ for example, iterating over the faces in a slot is:
+
+ BMOIter oiter;
+ BMFace *f;
+
+ f = BMO_IterNew(&oiter, bm, some_operator, "slotname", BM_FACE);
+ for (; f; f=BMO_IterStep(&oiter)) {
+ /do something with the face
+ }
+
+ another example, iterating over a mapping:
+ BMOIter oiter;
+ void *key;
+ void *val;
+
+ key = BMO_IterNew(&oiter, bm, some_operator, "slotname", 0);
+ for (; key; key=BMO_IterStep(&oiter)) {
+ val = BMO_IterMapVal(&oiter);
+ //do something with the key/val pair
+ //note that val is a pointer to the val data,
+ //whether it's a float, pointer, whatever.
+ //
+ // so to get a pointer, for example, use:
+ // *((void**)BMO_IterMapVal(&oiter));
+ //or something like that.
+ }
+
+ */
+
+/*contents of this structure are private,
+ don't directly access.*/
+typedef struct BMOIter {
+ BMOpSlot *slot;
+ int cur; //for arrays
+ struct GHashIterator giter;
+ void *val;
+ int restrictmask;
+} BMOIter;
+
+void *BMO_FirstElem(BMOperator *op, const char *slotname);
+
+/*restrictmask restricts the iteration to certain element types
+ (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating
+ over an element buffer (not a mapping).*/
+void *BMO_IterNew(BMOIter *iter, BMesh *bm, BMOperator *op,
+ const char *slotname, int restrictmask);
+void *BMO_IterStep(BMOIter *iter);
+
+/*returns a pointer to the key value when iterating over mappings.
+ remember for pointer maps this will be a pointer to a pointer.*/
+void *BMO_IterMapVal(BMOIter *iter);
+
+/*use this for pointer mappings*/
+void *BMO_IterMapValp(BMOIter *iter);
+
+/*use this for float mappings*/
+float BMO_IterMapValf(BMOIter *iter);
+
+#define BMO_ITER(ele, iter, bm, op, slotname, restrict) \
+ ele = BMO_IterNew(iter, bm, op, slotname, restrict); \
+ for ( ; ele; ele=BMO_IterStep(iter))
+
+/******************* Inlined Functions********************/
+typedef void (*opexec)(struct BMesh *bm, struct BMOperator *op);
+
+/*mappings map elements to data, which
+ follows the mapping struct in memory.*/
+typedef struct element_mapping {
+ BMHeader *element;
+ int len;
+} element_mapping;
+
+extern const int BMOP_OPSLOT_TYPEINFO[];
+
+BM_INLINE void BMO_Insert_Mapping(BMesh *UNUSED(bm), BMOperator *op, const char *slotname,
+ void *element, void *data, int len) {
+ element_mapping *mapping;
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ /*sanity check*/
+ if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
+
+ mapping = (element_mapping*) BLI_memarena_alloc(op->arena, sizeof(*mapping) + len);
+
+ mapping->element = (BMHeader*) element;
+ mapping->len = len;
+ memcpy(mapping+1, data, len);
+
+ if (!slot->data.ghash) {
+ slot->data.ghash = BLI_ghash_new(BLI_ghashutil_ptrhash,
+ BLI_ghashutil_ptrcmp, "bmesh op");
+ }
+
+ BLI_ghash_insert(slot->data.ghash, element, mapping);
+}
+
+BM_INLINE void BMO_Insert_MapInt(BMesh *bm, BMOperator *op, const char *slotname,
+ void *element, int val)
+{
+ BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(int));
+}
+
+BM_INLINE void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, const char *slotname,
+ void *element, float val)
+{
+ BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(float));
+}
+
+BM_INLINE void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, const char *slotname,
+ void *element, void *val)
+{
+ BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(void*));
+}
+
+BM_INLINE int BMO_InMap(BMesh *UNUSED(bm), BMOperator *op, const char *slotname, void *element)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ /*sanity check*/
+ if (slot->slottype != BMOP_OPSLOT_MAPPING) return 0;
+ if (!slot->data.ghash) return 0;
+
+ return BLI_ghash_haskey(slot->data.ghash, element);
+}
+
+BM_INLINE void *BMO_Get_MapData(BMesh *UNUSED(bm), BMOperator *op, const char *slotname,
+ void *element)
+{
+ element_mapping *mapping;
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ /*sanity check*/
+ if (slot->slottype != BMOP_OPSLOT_MAPPING) return NULL;
+ if (!slot->data.ghash) return NULL;
+
+ mapping = (element_mapping*) BLI_ghash_lookup(slot->data.ghash, element);
+
+ if (!mapping) return NULL;
+
+ return mapping + 1;
+}
+
+BM_INLINE float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, const char *slotname,
+ void *element)
+{
+ float *val = (float*) BMO_Get_MapData(bm, op, slotname, element);
+ if (val) return *val;
+
+ return 0.0f;
+}
+
+BM_INLINE int BMO_Get_MapInt(BMesh *bm, BMOperator *op, const char *slotname,
+ void *element)
+{
+ int *val = (int*) BMO_Get_MapData(bm, op, slotname, element);
+ if (val) return *val;
+
+ return 0;
+}
+
+BM_INLINE void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, const char *slotname,
+ void *element)
+{
+ void **val = (void**) BMO_Get_MapData(bm, op, slotname, element);
+ if (val) return *val;
+
+ return NULL;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BMESH_OPERATOR_API_H */
diff --git a/source/blender/bmesh/bmesh_operators.h b/source/blender/bmesh/bmesh_operators.h
new file mode 100644
index 00000000000..c27cb72ecc7
--- /dev/null
+++ b/source/blender/bmesh/bmesh_operators.h
@@ -0,0 +1,95 @@
+#ifndef _BMESH_OPERATORS_H
+#define _BMESH_OPERATORS_H
+
+/*see comments in intern/bmesh_opdefines.c for documentation of specific operators*/
+
+/*--------defines/enumerations for specific operators-------*/
+
+/*del operator "context" slot values*/
+enum {
+ DEL_VERTS = 1,
+ DEL_EDGES,
+ DEL_ONLYFACES,
+ DEL_EDGESFACES,
+ DEL_FACES,
+ DEL_ALL ,
+ DEL_ONLYTAGGED
+};
+
+/*quad innervert values*/
+enum {
+ SUBD_INNERVERT,
+ SUBD_PATH,
+ SUBD_FAN,
+ SUBD_STRAIGHT_CUT
+};
+
+/* similar face selection slot values */
+enum {
+ SIMFACE_MATERIAL = 201,
+ SIMFACE_IMAGE,
+ SIMFACE_AREA,
+ SIMFACE_PERIMETER,
+ SIMFACE_NORMAL,
+ SIMFACE_COPLANAR
+};
+
+/* similar edge selection slot values */
+enum {
+ SIMEDGE_LENGTH = 101,
+ SIMEDGE_DIR,
+ SIMEDGE_FACE,
+ SIMEDGE_FACE_ANGLE,
+ SIMEDGE_CREASE,
+ SIMEDGE_SEAM,
+ SIMEDGE_SHARP
+};
+
+/* similar vertex selection slot values */
+enum {
+ SIMVERT_NORMAL = 0,
+ SIMVERT_FACE,
+ SIMVERT_VGROUP
+};
+
+enum {
+ OPUVC_AXIS_X = 1,
+ OPUVC_AXIS_Y
+};
+
+enum {
+ DIRECTION_CW = 1,
+ DIRECTION_CCW
+};
+
+/* vertex path selection values */
+enum {
+ VPATH_SELECT_EDGE_LENGTH = 0,
+ VPATH_SELECT_TOPOLOGICAL
+};
+
+extern BMOpDefine *opdefines[];
+extern int bmesh_total_ops;
+
+/*------specific operator helper functions-------*/
+
+/*executes the duplicate operation, feeding elements of
+ type flag etypeflag and header flag flag to it. note,
+ to get more useful information (such as the mapping from
+ original to new elements) you should run the dupe op manually.*/
+struct Object;
+struct EditMesh;
+
+void BMOP_DupeFromFlag(struct BMesh *bm, int etypeflag, int flag);
+void BM_esubdivideflag(struct Object *obedit, BMesh *bm, int flag, float smooth,
+ float fractal, int beauty, int numcuts, int seltype,
+ int cornertype, int singleedge, int gridfill, int seed);
+void BM_extrudefaceflag(BMesh *bm, int flag);
+
+/*this next one return 1 if they did anything, or zero otherwise.
+ they're kindof a hackish way to integrate with fkey, until
+ such time as fkey is completely bmeshafied.*/
+/*this doesn't display errors to the user, btw*/
+int BM_ConnectVerts(struct EditMesh *em, int flag);
+
+#endif
diff --git a/source/blender/bmesh/bmesh_queries.h b/source/blender/bmesh/bmesh_queries.h
new file mode 100644
index 00000000000..4f185d8725c
--- /dev/null
+++ b/source/blender/bmesh/bmesh_queries.h
@@ -0,0 +1,89 @@
+#ifndef BMESH_QUERIES_H
+#define BMESH_QUERIES_H
+#include <stdio.h>
+
+/*Queries*/
+
+/*get the area of face f*/
+float BM_face_area(BMFace *f);
+
+/*counts number of elements of type type are in the mesh.*/
+int BM_Count_Element(struct BMesh *bm, int type);
+
+/*returns true if v is in f*/
+int BM_Vert_In_Face(struct BMFace *f, struct BMVert *v);
+
+// int BM_Verts_In_Face(struct BMFace *f, struct BMVert **varr, int len);
+int BM_Verts_In_Face(struct BMesh *bm, struct BMFace *f, struct BMVert **varr, int len);
+
+int BM_Edge_In_Face(struct BMFace *f, struct BMEdge *e);
+
+int BM_Vert_In_Edge(struct BMEdge *e, struct BMVert *v);
+
+/*get opposing vert from v in edge e.*/
+struct BMVert *BM_OtherEdgeVert(struct BMEdge *e, struct BMVert *v);
+
+/*finds other loop that shares v with e's loop in f.*/
+struct BMLoop *BM_OtherFaceLoop(BMEdge *e, BMFace *f, BMVert *v);
+
+//#define BM_OtherEdgeVert(e, v) (v==e->v1?e->v2:e->v1)
+
+/*returns the edge existing between v1 and v2, or NULL if there isn't one.*/
+struct BMEdge *BM_Edge_Exist(struct BMVert *v1, struct BMVert *v2);
+
+
+/*returns number of edges aroudn a vert*/
+int BM_Vert_EdgeCount(struct BMVert *v);
+
+/*returns number of faces around an edge*/
+int BM_Edge_FaceCount(struct BMEdge *e);
+
+/*returns number of faces around a vert.*/
+int BM_Vert_FaceCount(struct BMVert *v);
+
+
+/*returns true if v is a wire vert*/
+int BM_Wire_Vert(struct BMesh *bm, struct BMVert *v);
+
+/*returns true if e is a wire edge*/
+int BM_Wire_Edge(struct BMesh *bm, struct BMEdge *e);
+
+/*returns true if v is part of a non-manifold edge in the mesh,
+ I believe this includes if it's part of both a wire edge and
+ a face.*/
+int BM_Nonmanifold_Vert(struct BMesh *bm, struct BMVert *v);
+
+/*returns true if e is shared by more then two faces.*/
+int BM_Nonmanifold_Edge(struct BMesh *bm, struct BMEdge *e);
+
+/*returns true if e is a boundary edge, e.g. has only 1 face bordering it.*/
+int BM_Boundary_Edge(struct BMEdge *e);
+
+
+/*returns angle of two faces surrounding an edge. note there must be
+ exactly two faces sharing the edge.*/
+float BM_Face_Angle(struct BMesh *bm, struct BMEdge *e);
+
+/*checks overlapping of existing faces with the verts in varr.*/
+int BM_Exist_Face_Overlaps(struct BMesh *bm, struct BMVert **varr, int len, struct BMFace **existface);
+
+/*checks if a face defined by varr already exists.*/
+int BM_Face_Exists(BMesh *bm, BMVert **varr, int len, BMFace **existface);
+
+
+/*returns number of edges f1 and f2 share.*/
+int BM_Face_Sharededges(struct BMFace *f1, struct BMFace *f2);
+
+/*returns number of faces e1 and e2 share.*/
+int BM_Edge_Share_Faces(struct BMEdge *e1, struct BMEdge *e2);
+
+/*checks if a face is valid in the data structure*/
+int BM_Validate_Face(BMesh *bm, BMFace *face, FILE *err);
+
+/*each pair of loops defines a new edge, a split. this function goes
+ through and sets pairs that are geometrically invalid to null. a
+ split is invalid, if it forms a concave angle or it intersects other
+ edges in the face.*/
+void BM_LegalSplits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len);
+
+#endif
diff --git a/source/blender/bmesh/bmesh_walkers.h b/source/blender/bmesh/bmesh_walkers.h
new file mode 100644
index 00000000000..e7ab636f361
--- /dev/null
+++ b/source/blender/bmesh/bmesh_walkers.h
@@ -0,0 +1,94 @@
+#ifndef BM_WALKERS_H
+#define BM_WALKERS_H
+
+#include "BLI_ghash.h"
+
+/*
+ NOTE: do NOT modify topology while walking a mesh!
+*/
+
+typedef enum {
+ BMW_DEPTH_FIRST,
+ BMW_BREADTH_FIRST,
+} BMWOrder;
+
+/*Walkers*/
+typedef struct BMWalker {
+ void (*begin) (struct BMWalker *walker, void *start);
+ void *(*step) (struct BMWalker *walker);
+ void *(*yield)(struct BMWalker *walker);
+ int structsize;
+ BMWOrder order;
+ int flag;
+
+ BMesh *bm;
+ BLI_mempool *worklist;
+ ListBase states;
+ int restrictflag;
+ GHash *visithash;
+ int depth;
+} BMWalker;
+
+/*initialize a walker. searchmask restricts some (not all) walkers to
+ elements with a specific tool flag set. flags is specific to each walker.*/
+void BMW_Init(struct BMWalker *walker, BMesh *bm, int type, int searchmask, int flags);
+void *BMW_Begin(BMWalker *walker, void *start);
+void *BMW_Step(struct BMWalker *walker);
+void BMW_End(struct BMWalker *walker);
+int BMW_CurrentDepth(BMWalker *walker);
+
+/*these are used by custom walkers*/
+void *BMW_currentstate(BMWalker *walker);
+void *BMW_addstate(BMWalker *walker);
+void BMW_removestate(BMWalker *walker);
+void *BMW_walk(BMWalker *walker);
+void BMW_reset(BMWalker *walker);
+
+/*
+example of usage, walking over an island of tool flagged faces:
+
+BMWalker walker;
+BMFace *f;
+
+BMW_Init(&walker, bm, BMW_ISLAND, SOME_OP_FLAG);
+f = BMW_Begin(&walker, some_start_face);
+for (; f; f=BMW_Step(&walker)) {
+ //do something with f
+}
+BMW_End(&walker);
+*/
+
+enum {
+ /*walk over connected geometry. can restrict to a search flag,
+ or not, it's optional.
+
+ takes a vert as an arugment, and spits out edges, restrict flag acts
+ on the edges as well.*/
+ BMW_SHELL,
+ /*walk over an edge loop. search flag doesn't do anything.*/
+ BMW_LOOP,
+ BMW_FACELOOP,
+ BMW_EDGERING,
+ /*#define BMW_RING 2*/
+ //walk over uv islands; takes a loop as input. restrict flag
+ //restricts the walking to loops whose vert has restrict flag set as a
+ //tool flag.
+ //
+ //the flag parameter to BMW_Init maps to a loop customdata layer index.
+ BMW_LOOPDATA_ISLAND,
+ /*walk over an island of flagged faces. note, that this doesn't work on
+ non-manifold geometry. it might be better to rewrite this to extract
+ boundary info from the island walker, rather then directly walking
+ over the boundary. raises an error if it encouters nonmanifold
+ geometry.*/
+ BMW_ISLANDBOUND,
+ /*walk over all faces in an island of tool flagged faces.*/
+ BMW_ISLAND,
+ /*walk from a vertex to all connected vertices.*/
+ BMW_CONNECTED_VERTEX,
+ /*do not intitialze function pointers and struct size in BMW_Init*/
+ BMW_CUSTOM,
+ BMW_MAXWALKERS
+};
+
+#endif
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/bmesh/editmesh_tools.c
index 5455bf966ef..c62e7aef40d 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/bmesh/editmesh_tools.c
@@ -1,4 +1,6 @@
-/*
+/**
+ * $Id:
+ *
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -13,9 +15,9 @@
*
* 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.
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * The Original Code is Copyright (C) 2004 by Blender Foundation.
+ * The Original Code is Copyright (C) 2004 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
@@ -25,11 +27,6 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/editors/mesh/editmesh_tools.c
- * \ingroup edmesh
- */
-
-
/*
editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise in mods.c
@@ -39,70 +36,85 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
#include <stdlib.h>
#include <string.h>
#include <math.h>
-#include <float.h>
-#include "BLO_sys_types.h" // for intptr_t support
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
#include "DNA_key_types.h"
-#include "MEM_guardedalloc.h"
-
-#include "RNA_define.h"
-#include "RNA_access.h"
-
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "BLI_editVert.h"
#include "BLI_rand.h"
#include "BLI_ghash.h"
#include "BLI_linklist.h"
#include "BLI_heap.h"
-#include "BLI_scanfill.h"
-#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_customdata.h"
#include "BKE_global.h"
-#include "BKE_key.h"
+#include "BKE_library.h"
#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
#include "BKE_bmesh.h"
-#include "BKE_report.h"
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
-#include "WM_api.h"
-#include "WM_types.h"
+#include "BIF_cursors.h"
+#include "BIF_editmesh.h"
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+#include "BIF_graphics.h"
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_resources.h"
+#include "BIF_toolbox.h"
+#include "BIF_transform.h"
+#include "transform.h"
+
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
-#include "ED_mesh.h"
-#include "ED_screen.h"
-#include "ED_transform.h"
-#include "ED_view3d.h"
-#include "ED_object.h"
+#include "BDR_drawobject.h"
+#include "BDR_editobject.h"
+#include "BSE_view.h"
+#include "BSE_edit.h"
-#include "mesh_intern.h"
+#include "blendef.h"
+#include "multires.h"
+#include "mydevice.h"
-/* XXX */
-static void waitcursor(int UNUSED(val)) {}
-#define add_numbut(a, b, c, d, e, f, g) {}
+#include "editmesh.h"
-/* XXX */
+#include "MTC_vectorops.h"
-/* RNA corner cut enum property - used in multiple files for tools
- * that need this property for esubdivideflag() */
-EnumPropertyItem corner_type_items[] = {
- {SUBDIV_CORNER_PATH, "PATH", 0, "Path", ""},
- {SUBDIV_CORNER_INNERVERT, "INNER_VERTEX", 0, "Inner Vertex", ""},
- {SUBDIV_CORNER_FAN, "FAN", 0, "Fan", ""},
- {0, NULL, 0, NULL, NULL}};
+#include "PIL_time.h"
+#include "BLO_sys_types.h" // for intptr_t support
/* local prototypes ---------------*/
-static void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace *efa);
-int EdgeLoopDelete(EditMesh *em, wmOperator *op);
+void bevel_menu(void);
+static void free_tagged_edges_faces(EditEdge *eed, EditFace *efa);
/********* qsort routines *********/
@@ -130,7 +142,7 @@ struct facesort {
static int vergface(const void *v1, const void *v2)
{
const struct facesort *x1=v1, *x2=v2;
-
+
if( x1->x > x2->x ) return 1;
else if( x1->x < x2->x) return -1;
return 0;
@@ -139,11 +151,14 @@ static int vergface(const void *v1, const void *v2)
/* *********************************** */
-static void convert_to_triface(EditMesh *em, int direction)
+void convert_to_triface(int direction)
{
+ EditMesh *em = G.editMesh;
EditFace *efa, *efan, *next;
float fac;
-
+
+ if(multires_test()) return;
+
efa= em->faces.last;
while(efa) {
next= efa->prev;
@@ -153,31 +168,36 @@ static void convert_to_triface(EditMesh *em, int direction)
fac= len_v3v3(efa->v1->co, efa->v3->co) - len_v3v3(efa->v2->co, efa->v4->co);
/* this makes sure exact squares get split different in both cases */
if( (direction==0 && fac<FLT_EPSILON) || (direction && fac>0.0f) ) {
- efan= EM_face_from_faces(em, efa, NULL, 0, 1, 2, -1);
+ efan= EM_face_from_faces(efa, NULL, 0, 1, 2, -1);
if(efa->f & SELECT) EM_select_face(efan, 1);
- efan= EM_face_from_faces(em, efa, NULL, 0, 2, 3, -1);
+ efan= EM_face_from_faces(efa, NULL, 0, 2, 3, -1);
if(efa->f & SELECT) EM_select_face(efan, 1);
}
else {
- efan= EM_face_from_faces(em, efa, NULL, 0, 1, 3, -1);
+ efan= EM_face_from_faces(efa, NULL, 0, 1, 3, -1);
if(efa->f & SELECT) EM_select_face(efan, 1);
- efan= EM_face_from_faces(em, efa, NULL, 1, 2, 3, -1);
+ efan= EM_face_from_faces(efa, NULL, 1, 2, 3, -1);
if(efa->f & SELECT) EM_select_face(efan, 1);
}
-
+
BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
+ free_editface(efa);
}
}
efa= next;
}
+
+ EM_fgon_flags(); // redo flags and indices for fgons
- EM_fgon_flags(em); // redo flags and indices for fgons
-
-
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+ BIF_undo_push("Convert Quads to Triangles");
+
}
-int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /* return amount */
+int removedoublesflag(short flag, short automerge, float limit) /* return amount */
{
/*
flag - Test with vert->flags
@@ -185,7 +205,8 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
Used for "Auto Weld" mode. warning.
limit - Quick manhattan distance between verts.
*/
-
+
+ EditMesh *em = G.editMesh;
/* all verts with (flag & 'flag') are being evaluated */
EditVert *eve, *v1, *nextve;
EditEdge *eed, *e1, *nexted;
@@ -193,8 +214,10 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
xvertsort *sortblock, *sb, *sb1;
struct facesort *vlsortblock, *vsb, *vsb1;
int a, b, test, amount;
+
+ if(multires_test()) return 0;
-
+
/* flag 128 is cleared, count */
/* Normal non weld operation */
@@ -220,9 +243,9 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
}
qsort(sortblock, amount, sizeof(xvertsort), vergxco);
-
+
/* test for doubles */
- sb= sortblock;
+ sb= sortblock;
if (automerge) {
for(a=0; a<amount; a++, sb++) {
eve= sb->v1;
@@ -230,12 +253,12 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
sb1= sb+1;
for(b=a+1; b<amount && (eve->f & 128)==0; b++, sb1++) {
if(sb1->x - sb->x > limit) break;
-
+
/* when automarge, only allow unselected->selected */
v1= sb1->v1;
if( (v1->f & 128)==0 ) {
if ((eve->f & flag)==0 && (v1->f & flag)==1) {
- if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
+ if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
(float)fabs(v1->co[1]-eve->co[1])<=limit &&
(float)fabs(v1->co[2]-eve->co[2])<=limit)
{ /* unique bit */
@@ -243,7 +266,7 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
eve->tmp.v = v1;
}
} else if( (eve->f & flag)==1 && (v1->f & flag)==0 ) {
- if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
+ if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
(float)fabs(v1->co[1]-eve->co[1])<=limit &&
(float)fabs(v1->co[2]-eve->co[2])<=limit)
{ /* unique bit */
@@ -264,10 +287,10 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
/* first test: simpel dist */
if(sb1->x - sb->x > limit) break;
v1= sb1->v1;
-
+
/* second test: is vertex allowed */
if( (v1->f & 128)==0 ) {
- if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
+ if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
(float)fabs(v1->co[1]-eve->co[1])<=limit &&
(float)fabs(v1->co[2]-eve->co[2])<=limit)
{
@@ -280,12 +303,12 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
}
}
MEM_freeN(sortblock);
-
+
if (!automerge)
for(eve = em->verts.first; eve; eve=eve->next)
if((eve->f & flag) && (eve->f & 128))
- EM_data_interp_from_verts(em, eve, eve->tmp.v, eve->tmp.v, 0.5f);
-
+ EM_data_interp_from_verts(eve, eve->tmp.v, eve->tmp.v, 0.5f);
+
/* test edges and insert again */
eed= em->edges.first;
while(eed) {
@@ -298,18 +321,18 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
if(eed->f2==0) {
if( (eed->v1->f & 128) || (eed->v2->f & 128) ) {
- remedge(em, eed);
+ remedge(eed);
if(eed->v1->f & 128) eed->v1 = eed->v1->tmp.v;
if(eed->v2->f & 128) eed->v2 = eed->v2->tmp.v;
- e1= addedgelist(em, eed->v1, eed->v2, eed);
+ e1= addedgelist(eed->v1, eed->v2, eed);
if(e1) {
e1->f2= 1;
if(eed->f & SELECT)
e1->f |= SELECT;
}
- if(e1!=eed) free_editedge(em, eed);
+ if(e1!=eed) free_editedge(eed);
}
}
eed= nexted;
@@ -324,7 +347,7 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
else if(efa->v2->f & 128) efa->f1= 1;
else if(efa->v3->f & 128) efa->f1= 1;
else if(efa->v4 && (efa->v4->f & 128)) efa->f1= 1;
-
+
if(efa->f1==1) amount++;
efa= efa->next;
}
@@ -334,12 +357,12 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
while(efa) {
nextvl= efa->next;
if(efa->f1==1) {
-
+
if(efa->v1->f & 128) efa->v1= efa->v1->tmp.v;
if(efa->v2->f & 128) efa->v2= efa->v2->tmp.v;
if(efa->v3->f & 128) efa->v3= efa->v3->tmp.v;
if(efa->v4 && (efa->v4->f & 128)) efa->v4= efa->v4->tmp.v;
-
+
test= 0;
if(efa->v1==efa->v2) test+=1;
if(efa->v2==efa->v3) test+=2;
@@ -347,7 +370,7 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
if(efa->v4==efa->v1) test+=8;
if(efa->v3==efa->v4) test+=16;
if(efa->v2==efa->v4) test+=32;
-
+
if(test) {
if(efa->v4) {
if(test==1 || test==2) {
@@ -355,7 +378,7 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
efa->v3= efa->v4;
efa->v4= 0;
- EM_data_interp_from_faces(em, efa, NULL, efa, 0, 2, 3, 3);
+ EM_data_interp_from_faces(efa, NULL, efa, 0, 2, 3, 3);
test= 0;
}
@@ -365,28 +388,28 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
}
else {
BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
+ free_editface(efa);
amount--;
}
}
else {
BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
+ free_editface(efa);
amount--;
}
}
-
+
if(test==0) {
/* set edge pointers */
- efa->e1= findedgelist(em, efa->v1, efa->v2);
- efa->e2= findedgelist(em, efa->v2, efa->v3);
+ efa->e1= findedgelist(efa->v1, efa->v2);
+ efa->e2= findedgelist(efa->v2, efa->v3);
if(efa->v4==0) {
- efa->e3= findedgelist(em, efa->v3, efa->v1);
+ efa->e3= findedgelist(efa->v3, efa->v1);
efa->e4= 0;
}
else {
- efa->e3= findedgelist(em, efa->v3, efa->v4);
- efa->e4= findedgelist(em, efa->v4, efa->v1);
+ efa->e3= findedgelist(efa->v3, efa->v4);
+ efa->e4= findedgelist(efa->v4, efa->v1);
}
}
}
@@ -420,9 +443,9 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
}
efa= efa->next;
}
-
+
qsort(vlsortblock, amount, sizeof(struct facesort), vergface);
-
+
vsb= vlsortblock;
for(a=0; a<amount; a++) {
efa= vsb->efa;
@@ -430,36 +453,36 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
vsb1= vsb+1;
for(b=a+1; b<amount; b++) {
-
+
/* first test: same pointer? */
if(vsb->x != vsb1->x) break;
-
+
/* second test: is test permitted? */
efa= vsb1->efa;
if( (efa->f1 & 128)==0 ) {
if( compareface(efa, vsb->efa)) efa->f1 |= 128;
-
+
}
vsb1++;
}
}
vsb++;
}
-
+
MEM_freeN(vlsortblock);
-
+
/* remove double faces */
efa= (struct EditFace *)em->faces.first;
while(efa) {
nextvl= efa->next;
if(efa->f1 & 128) {
BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
+ free_editface(efa);
}
efa= nextvl;
}
}
-
+
/* remove double vertices */
a= 0;
eve= (struct EditVert *)em->verts.first;
@@ -469,137 +492,83 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /
if(eve->f & 128) {
a++;
BLI_remlink(&em->verts, eve);
- free_editvert(em, eve);
+ free_editvert(eve);
}
}
eve= nextve;
}
- return a; /* amount */
-}
-
-static int removedoublesflag_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- int totvert= em->totvert, totedge= em->totedge, totface= em->totface;
-
- int count = removedoublesflag(em,1,0,RNA_float_get(op->ptr, "limit"));
-
- if (totvert != em->totvert || totedge != em->totedge || totface != em->totface) {
- recalc_editnormals(em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+#ifdef WITH_VERSE
+ if((a>0) && (G.editMesh->vnode)) {
+ sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
}
+#endif
- BKE_reportf(op->reports, RPT_INFO, "Removed %d vert%s", count, (count==1)?"ex":"ices");
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_remove_doubles(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Remove Doubles";
- ot->description= "Remove duplicate vertices";
- ot->idname= "MESH_OT_remove_doubles";
-
- /* api callbacks */
- ot->exec= removedoublesflag_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- prop= RNA_def_float(ot->srna, "limit", 0.0001f, 0.000001f, 50.0f, "Merge Threshold", "Minimum distance between merged verts", 0.00001f, 2.0f);
- RNA_def_property_ui_range(prop, 0.000001f, 50.0f, 0.001, 5);
+ return a; /* amount */
}
-// XXX is this needed?
/* called from buttons */
-static void xsortvert_flag__doSetX(void *userData, EditVert *UNUSED(eve), int x, int UNUSED(y), int index)
+static void xsortvert_flag__doSetX(void *userData, EditVert *eve, int x, int y, int index)
{
xvertsort *sortblock = userData;
sortblock[index].x = x;
}
-
-/* all verts with (flag & 'flag') are sorted */
-static void xsortvert_flag(bContext *C, int flag)
+void xsortvert_flag(int flag)
{
- ViewContext vc;
+ EditMesh *em = G.editMesh;
+ /* all verts with (flag & 'flag') are sorted */
EditVert *eve;
xvertsort *sortblock;
ListBase tbase;
- int i, amount;
-
- em_setup_viewcontext(C, &vc);
-
- amount = BLI_countlist(&vc.em->verts);
+ int i, amount = BLI_countlist(&em->verts);
+
+ if(multires_test()) return;
+
sortblock = MEM_callocN(sizeof(xvertsort)*amount,"xsort");
- for (i=0,eve= vc.em->verts.first; eve; i++,eve=eve->next)
+ for (i=0,eve=em->verts.first; eve; i++,eve=eve->next)
if(eve->f & flag)
sortblock[i].v1 = eve;
-
- ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
- mesh_foreachScreenVert(&vc, xsortvert_flag__doSetX, sortblock, 0);
-
+ mesh_foreachScreenVert(xsortvert_flag__doSetX, sortblock, 0);
qsort(sortblock, amount, sizeof(xvertsort), vergxco);
-
+
/* make temporal listbase */
tbase.first= tbase.last= 0;
for (i=0; i<amount; i++) {
eve = sortblock[i].v1;
if (eve) {
- BLI_remlink(&vc.em->verts, eve);
+ BLI_remlink(&em->verts, eve);
BLI_addtail(&tbase, eve);
}
}
-
- BLI_movelisttolist(&vc.em->verts, &tbase);
-
+
+ addlisttolist(&em->verts, &tbase);
+
MEM_freeN(sortblock);
-}
-
-static int mesh_vertices_sort_exec(bContext *C, wmOperator *UNUSED(op))
-{
- xsortvert_flag(C, SELECT);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_vertices_sort(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Vertex Sort";
- ot->description= "Sort vertex order";
- ot->idname= "MESH_OT_vertices_sort";
-
- /* api callbacks */
- ot->exec= mesh_vertices_sort_exec;
-
- ot->poll= EM_view3d_poll; /* uses view relative X axis to sort verts */
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+ BIF_undo_push("Xsort");
+
}
-
/* called from buttons */
-static void hashvert_flag(EditMesh *em, int flag)
+void hashvert_flag(int flag)
{
/* switch vertex order using hash table */
+ EditMesh *em = G.editMesh;
EditVert *eve;
struct xvertsort *sortblock, *sb, onth, *newsort;
ListBase tbase;
int amount, a, b;
-
+
+ if(multires_test()) return;
+
/* count */
eve= em->verts.first;
amount= 0;
@@ -608,7 +577,7 @@ static void hashvert_flag(EditMesh *em, int flag)
eve= eve->next;
}
if(amount==0) return;
-
+
/* allocate memory */
sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*amount,"sortremovedoub");
eve= em->verts.first;
@@ -621,7 +590,7 @@ static void hashvert_flag(EditMesh *em, int flag)
}
BLI_srand(1);
-
+
sb= sortblock;
for(a=0; a<amount; a++, sb++) {
b= (int)(amount*BLI_drand());
@@ -642,358 +611,202 @@ static void hashvert_flag(EditMesh *em, int flag)
BLI_addtail(&tbase, eve);
sb++;
}
-
- BLI_movelisttolist(&em->verts, &tbase);
-
+
+ addlisttolist(&em->verts, &tbase);
+
MEM_freeN(sortblock);
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+ BIF_undo_push("Hash");
}
-static int mesh_vertices_randomize_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
- hashvert_flag(em, SELECT);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_vertices_randomize(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Vertex Randomize";
- ot->description= "Randomize vertex order";
- ot->idname= "MESH_OT_vertices_randomize";
-
- /* api callbacks */
- ot->exec= mesh_vertices_randomize_exec;
-
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-
/* generic extern called extruder */
-static void extrude_mesh(Object *obedit, EditMesh *em, wmOperator *op, short type)
+void extrude_mesh(void)
{
float nor[3]= {0.0, 0.0, 0.0};
- short transmode= 0;
+ short nr, transmode= 0;
- if(type<1) return;
-
- if(type==1) transmode= extrudeflag(obedit, em, SELECT, nor, 0);
- else if(type==4) transmode= extrudeflag_verts_indiv(em, SELECT, nor);
- else if(type==3) transmode= extrudeflag_edges_indiv(em, SELECT, nor);
- else transmode= extrudeflag_face_indiv(em, SELECT, nor);
-
- EM_stats_update(em);
+ TEST_EDITMESH
+ if(multires_test()) return;
+
+ if(G.scene->selectmode & SCE_SELECT_VERTEX) {
+ if(G.totvertsel==0) nr= 0;
+ else if(G.totvertsel==1) nr= 4;
+ else if(G.totedgesel==0) nr= 4;
+ else if(G.totfacesel==0)
+ nr= pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4");
+ else if(G.totfacesel==1)
+ nr= pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4");
+ else
+ nr= pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4");
+ }
+ else if(G.scene->selectmode & SCE_SELECT_EDGE) {
+ if (G.totedgesel==0) nr = 0;
+ else if (G.totedgesel==1) nr = 3;
+ else if(G.totfacesel==0) nr = 3;
+ else if(G.totfacesel==1)
+ nr= pupmenu("Extrude %t|Region %x1|Only Edges%x3");
+ else
+ nr= pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
+ }
+ else {
+ if (G.totfacesel == 0) nr = 0;
+ else if (G.totfacesel == 1) nr = 1;
+ else
+ nr= pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
+ }
+
+ if(nr<1) return;
+ if(nr==1) transmode= extrudeflag(SELECT, nor);
+ else if(nr==4) transmode= extrudeflag_verts_indiv(SELECT, nor);
+ else if(nr==3) transmode= extrudeflag_edges_indiv(SELECT, nor);
+ else transmode= extrudeflag_face_indiv(SELECT, nor);
+
if(transmode==0) {
- BKE_report(op->reports, RPT_WARNING, "Not a valid selection for extrude");
+ error("No valid selection");
}
else {
- EM_fgon_flags(em);
-
- /* We need to force immediate calculation here because
+ EM_fgon_flags();
+ countall();
+
+ /* We need to force immediate calculation here because
* transform may use derived objects (which are now stale).
*
* This shouldn't be necessary, derived queries should be
* automatically building this data if invalid. Or something.
*/
- DAG_id_tag_update(obedit->data, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ object_handle_update(G.obedit);
/* individual faces? */
-// BIF_TransformSetUndo("Extrude");
- if(type==2) {
-// initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR);
-// Transform();
+ BIF_TransformSetUndo("Extrude");
+ if(nr==2) {
+ initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR);
+ Transform();
}
else {
-// initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR);
+ initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR);
if(transmode=='n') {
- mul_m4_v3(obedit->obmat, nor);
- sub_v3_v3(nor, obedit->obmat[3]);
-// BIF_setSingleAxisConstraint(nor, "along normal");
+ mul_m4_v3(G.obedit->obmat, nor);
+ sub_v3_v3v3(nor, nor, G.obedit->obmat[3]);
+ BIF_setSingleAxisConstraint(nor, "along normal");
}
-// Transform();
+ Transform();
}
}
}
-// XXX should be a menu item
-static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- extrude_mesh(obedit, em, op, RNA_enum_get(op->ptr, "type"));
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-/* extrude without transform */
-static int mesh_extrude_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
-
- extrude_mesh(obedit, em, op, RNA_enum_get(op->ptr, "type"));
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-static EnumPropertyItem extrude_items[] = {
- {1, "REGION", 0, "Region", ""},
- {2, "FACES", 0, "Individual Faces", ""},
- {3, "EDGES", 0, "Only Edges", ""},
- {4, "VERTS", 0, "Only Vertices", ""},
- {0, NULL, 0, NULL, NULL}};
-
-
-static EnumPropertyItem *mesh_extrude_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
+void split_mesh(void)
{
- EnumPropertyItem *item= NULL;
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em;
-
- int totitem= 0;
-
- if(obedit==NULL || obedit->type != OB_MESH)
- return extrude_items;
-
- em = BKE_mesh_get_editmesh(obedit->data);
-
- EM_stats_update(em);
-
- if(em->selectmode & SCE_SELECT_VERTEX) {
- if(em->totvertsel==0) {}
- else if(em->totvertsel==1) { RNA_enum_item_add(&item, &totitem, &extrude_items[3]); }
- else if(em->totedgesel==0) { RNA_enum_item_add(&item, &totitem, &extrude_items[3]); }
- else if(em->totfacesel==0) {
- RNA_enum_item_add(&item, &totitem, &extrude_items[2]);
- RNA_enum_item_add(&item, &totitem, &extrude_items[3]);
- }
- else if(em->totfacesel==1) {
- RNA_enum_item_add(&item, &totitem, &extrude_items[0]);
- RNA_enum_item_add(&item, &totitem, &extrude_items[2]);
- RNA_enum_item_add(&item, &totitem, &extrude_items[3]);
- }
- else {
- RNA_enum_item_add(&item, &totitem, &extrude_items[0]);
- RNA_enum_item_add(&item, &totitem, &extrude_items[1]);
- RNA_enum_item_add(&item, &totitem, &extrude_items[2]);
- RNA_enum_item_add(&item, &totitem, &extrude_items[3]);
- }
- }
- else if(em->selectmode & SCE_SELECT_EDGE) {
- if (em->totedgesel==0) {}
- else if (em->totedgesel==1) { RNA_enum_item_add(&item, &totitem, &extrude_items[2]); }
- else if(em->totfacesel==0) { RNA_enum_item_add(&item, &totitem, &extrude_items[2]); }
- else if(em->totfacesel==1) {
- RNA_enum_item_add(&item, &totitem, &extrude_items[0]);
- RNA_enum_item_add(&item, &totitem, &extrude_items[2]);
- }
- else {
- RNA_enum_item_add(&item, &totitem, &extrude_items[0]);
- RNA_enum_item_add(&item, &totitem, &extrude_items[1]);
- RNA_enum_item_add(&item, &totitem, &extrude_items[2]);
- }
- }
- else {
- if (em->totfacesel == 0) {}
- else if (em->totfacesel == 1) { RNA_enum_item_add(&item, &totitem, &extrude_items[0]); }
- else {
- RNA_enum_item_add(&item, &totitem, &extrude_items[0]);
- RNA_enum_item_add(&item, &totitem, &extrude_items[1]);
- }
- }
- if(item) {
- RNA_enum_item_end(&item, &totitem);
- *free= 1;
- return item;
- }
- else {
- return NULL;
- }
-}
+ TEST_EDITMESH
+ if(multires_test()) return;
-void MESH_OT_extrude(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Extrude";
- ot->description= "Extrude selected vertices, edges or faces";
- ot->idname= "MESH_OT_extrude";
-
- /* api callbacks */
- ot->invoke= mesh_extrude_invoke;
- ot->exec= mesh_extrude_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- prop= RNA_def_enum(ot->srna, "type", extrude_items, 0, "Type", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- RNA_def_enum_funcs(prop, mesh_extrude_itemf);
- ot->prop= prop;
-}
-
-static int split_mesh(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ if(okee(" Split ")==0) return;
- WM_cursor_wait(1);
+ waitcursor(1);
/* make duplicate first */
- adduplicateflag(em, SELECT);
+ adduplicateflag(SELECT);
/* old faces have flag 128 set, delete them */
- delfaceflag(em, 128);
- recalc_editnormals(em);
-
- WM_cursor_wait(0);
+ delfaceflag(128);
+ recalc_editnormals();
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+ waitcursor(0);
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
-void MESH_OT_split(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Split";
- ot->description= "Split selected geometry into separate disconnected mesh";
- ot->idname= "MESH_OT_split";
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
- /* api callbacks */
- ot->exec= split_mesh;
- ot->poll= ED_operator_editmesh;
+ BIF_undo_push("Split");
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
-
-static int extrude_repeat_mesh_exec(bContext *C, wmOperator *op)
+void extrude_repeat_mesh(int steps, float offs)
{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- int steps = RNA_int_get(op->ptr,"steps");
-
- float offs = RNA_float_get(op->ptr,"offset");
-
float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0};
short a;
+ TEST_EDITMESH
+ if(multires_test()) return;
+
/* dvec */
- RNA_float_get_array(op->ptr, "direction", dvec);
+ dvec[0]= G.vd->persinv[2][0];
+ dvec[1]= G.vd->persinv[2][1];
+ dvec[2]= G.vd->persinv[2][2];
normalize_v3(dvec);
dvec[0]*= offs;
dvec[1]*= offs;
dvec[2]*= offs;
/* base correction */
- copy_m3_m4(bmat, obedit->obmat);
+ copy_m3_m4(bmat, G.obedit->obmat);
invert_m3_m3(tmat, bmat);
mul_m3_v3(tmat, dvec);
for(a=0; a<steps; a++) {
- extrudeflag(obedit, em, SELECT, nor, 0);
- translateflag(em, SELECT, dvec);
+ extrudeflag(SELECT, nor);
+ translateflag(SELECT, dvec);
}
+
+ recalc_editnormals();
+
+ EM_fgon_flags();
+ countall();
+
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
- recalc_editnormals(em);
-
- EM_fgon_flags(em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-/* get center and axis, in global coords */
-static int extrude_repeat_mesh_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
-{
- RegionView3D *rv3d= ED_view3d_context_rv3d(C);
-
- if(rv3d)
- RNA_float_set_array(op->ptr, "direction", rv3d->persinv[2]);
-
- return extrude_repeat_mesh_exec(C, op);
+ BIF_undo_push("Extrude Repeat");
}
-void MESH_OT_extrude_repeat(wmOperatorType *ot)
+void spin_mesh(int steps, float degr, float *dvec, int mode)
{
- /* identifiers */
- ot->name= "Extrude Repeat Mesh";
- ot->description= "Extrude selected vertices, edges or faces repeatedly";
- ot->idname= "MESH_OT_extrude_repeat";
-
- /* api callbacks */
- ot->invoke= extrude_repeat_mesh_invoke;
- ot->exec= extrude_repeat_mesh_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, 100.0f);
- RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, 180);
- RNA_def_float_vector(ot->srna, "direction", 3, NULL, -FLT_MAX, FLT_MAX, "Direction", "Direction of extrude", -FLT_MAX, FLT_MAX);
-}
-
-/* ************************** spin operator ******************** */
-
-
-static int spin_mesh(bContext *C, wmOperator *op, float *dvec, int steps, float degr, int dupli )
-{
- Object *obedit= CTX_data_edit_object(C);
- ToolSettings *ts= CTX_data_tool_settings(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ EditMesh *em = G.editMesh;
EditVert *eve,*nextve;
- float nor[3]= {0.0f, 0.0f, 0.0f};
- float si, n[3], q[4], cmat[3][3], imat[3][3], tmat[3][3];
- float cent[3], bmat[3][3];
+ float nor[3]= {0.0, 0.0, 0.0};
+ float *curs, si,n[3],q[4],cmat[3][3],imat[3][3], tmat[3][3];
+ float cent[3],bmat[3][3];
float phi;
- short a, ok= 1;
-
- RNA_float_get_array(op->ptr, "center", cent);
+ short a,ok;
+ TEST_EDITMESH
+ if(multires_test()) return;
+
/* imat and center and size */
- copy_m3_m4(bmat, obedit->obmat);
+ copy_m3_m4(bmat, G.obedit->obmat);
invert_m3_m3(imat,bmat);
- cent[0]-= obedit->obmat[3][0];
- cent[1]-= obedit->obmat[3][1];
- cent[2]-= obedit->obmat[3][2];
+ curs= give_cursor();
+ VECCOPY(cent, curs);
+ cent[0]-= G.obedit->obmat[3][0];
+ cent[1]-= G.obedit->obmat[3][1];
+ cent[2]-= G.obedit->obmat[3][2];
mul_m3_v3(imat, cent);
- phi= degr*(float)M_PI/360.0f;
+ phi= degr*M_PI/360.0;
phi/= steps;
- if(ts->editbutflag & B_CLOCKWISE) phi= -phi;
+ if(G.scene->toolsettings->editbutflag & B_CLOCKWISE) phi= -phi;
- RNA_float_get_array(op->ptr, "axis", n);
+ if(dvec) {
+ n[0]= G.vd->viewinv[1][0];
+ n[1]= G.vd->viewinv[1][1];
+ n[2]= G.vd->viewinv[1][2];
+ } else {
+ n[0]= G.vd->viewinv[2][0];
+ n[1]= G.vd->viewinv[2][1];
+ n[2]= G.vd->viewinv[2][2];
+ }
normalize_v3(n);
q[0]= (float)cos(phi);
@@ -1006,21 +819,20 @@ static int spin_mesh(bContext *C, wmOperator *op, float *dvec, int steps, float
mul_m3_m3m3(tmat,cmat,bmat);
mul_m3_m3m3(bmat,imat,tmat);
- if(dupli==0)
- if(ts->editbutflag & B_KEEPORIG)
- adduplicateflag(em, 1);
+ if(mode==0) if(G.scene->toolsettings->editbutflag & B_KEEPORIG) adduplicateflag(1);
+ ok= 1;
- for(a=0; a<steps; a++) {
- if(dupli==0) ok= extrudeflag(obedit, em, SELECT, nor, 0);
- else adduplicateflag(em, SELECT);
-
- if(ok==0)
+ for(a=0;a<steps;a++) {
+ if(mode==0) ok= extrudeflag(SELECT, nor);
+ else adduplicateflag(SELECT);
+ if(ok==0) {
+ error("No valid vertices are selected");
break;
-
- rotateflag(em, SELECT, cent, bmat);
+ }
+ rotateflag(SELECT, cent, bmat);
if(dvec) {
mul_m3_v3(bmat,dvec);
- translateflag(em, SELECT, dvec);
+ translateflag(SELECT, dvec);
}
}
@@ -1031,96 +843,41 @@ static int spin_mesh(bContext *C, wmOperator *op, float *dvec, int steps, float
nextve= eve->next;
if(eve->f & SELECT) {
BLI_remlink(&em->verts,eve);
- free_editvert(em, eve);
+ free_editvert(eve);
}
eve= nextve;
}
}
- else {
- recalc_editnormals(em);
+ recalc_editnormals();
- EM_fgon_flags(em);
-
- DAG_id_tag_update(obedit->data, 0);
- }
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return ok;
-}
-
-static int spin_mesh_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- int ok;
-
- ok= spin_mesh(C, op, NULL, RNA_int_get(op->ptr,"steps"), RNA_float_get(op->ptr,"degrees"), RNA_boolean_get(op->ptr,"dupli"));
- if(ok==0) {
- BKE_report(op->reports, RPT_WARNING, "No valid vertices are selected");
- return OPERATOR_CANCELLED;
- }
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-/* get center and axis, in global coords */
-static int spin_mesh_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
-{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d= ED_view3d_context_rv3d(C);
-
- RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d));
- RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[2]);
-
- return spin_mesh_exec(C, op);
-}
-
-void MESH_OT_spin(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Spin";
- ot->description= "Extrude selected vertices in a circle around the cursor in indicated viewport";
- ot->idname= "MESH_OT_spin";
-
- /* api callbacks */
- ot->invoke= spin_mesh_invoke;
- ot->exec= spin_mesh_exec;
- ot->poll= EM_view3d_poll;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, 128);
- RNA_def_boolean(ot->srna, "dupli", 0, "Dupli", "Make Duplicates");
- RNA_def_float(ot->srna, "degrees", 90.0f, -FLT_MAX, FLT_MAX, "Degrees", "Degrees", -360.0f, 360.0f);
-
- RNA_def_float_vector_xyz(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX);
- RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX);
+ EM_fgon_flags();
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
+ if(dvec==NULL) BIF_undo_push("Spin");
}
-static int screw_mesh_exec(bContext *C, wmOperator *op)
+void screw_mesh(int steps, int turns)
{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ EditMesh *em = G.editMesh;
EditVert *eve,*v1=0,*v2=0;
EditEdge *eed;
float dvec[3], nor[3];
- int steps, turns;
-
- turns= RNA_int_get(op->ptr, "turns");
- steps= RNA_int_get(op->ptr, "steps");
+ TEST_EDITMESH
+ if(multires_test()) return;
+
/* clear flags */
- for(eve= em->verts.first; eve; eve= eve->next)
+ eve= em->verts.first;
+ while(eve) {
eve->f1= 0;
-
+ eve= eve->next;
+ }
/* edges set flags in verts */
- for(eed= em->edges.first; eed; eed= eed->next) {
+ eed= em->edges.first;
+ while(eed) {
if(eed->v1->f & SELECT) {
if(eed->v2->f & SELECT) {
/* watch: f1 is a byte */
@@ -1128,101 +885,61 @@ static int screw_mesh_exec(bContext *C, wmOperator *op)
if(eed->v2->f1<2) eed->v2->f1++;
}
}
+ eed= eed->next;
}
/* find two vertices with eve->f1==1, more or less is wrong */
- for(eve= em->verts.first; eve; eve= eve->next) {
+ eve= em->verts.first;
+ while(eve) {
if(eve->f1==1) {
- if(v1==NULL) v1= eve;
- else if(v2==NULL) v2= eve;
+ if(v1==0) v1= eve;
+ else if(v2==0) v2= eve;
else {
- v1= NULL;
+ v1=0;
break;
}
}
+ eve= eve->next;
}
- if(v1==NULL || v2==NULL) {
- BKE_report(op->reports, RPT_WARNING, "You have to select a string of connected vertices too");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
+ if(v1==0 || v2==0) {
+ error("You have to select a string of connected vertices too");
+ return;
}
/* calculate dvec */
- dvec[0]= ( v1->co[0]- v2->co[0] )/steps;
- dvec[1]= ( v1->co[1]- v2->co[1] )/steps;
- dvec[2]= ( v1->co[2]- v2->co[2] )/steps;
-
- VECCOPY(nor, obedit->obmat[2]);
-
- if(nor[0]*dvec[0]+nor[1]*dvec[1]+nor[2]*dvec[2]>0.0f) {
- negate_v3(dvec);
- }
+ dvec[0]= ( (v1->co[0]- v2->co[0]) )/(steps);
+ dvec[1]= ( (v1->co[1]- v2->co[1]) )/(steps);
+ dvec[2]= ( (v1->co[2]- v2->co[2]) )/(steps);
- if(spin_mesh(C, op, dvec, turns*steps, 360.0f*turns, 0)) {
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+ VECCOPY(nor, G.obedit->obmat[2]);
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
+ if(nor[0]*dvec[0]+nor[1]*dvec[1]+nor[2]*dvec[2]>0.000) {
+ dvec[0]= -dvec[0];
+ dvec[1]= -dvec[1];
+ dvec[2]= -dvec[2];
}
- else {
- BKE_report(op->reports, RPT_WARNING, "No valid vertices are selected");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
-}
-
-/* get center and axis, in global coords */
-static int screw_mesh_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
-{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d= ED_view3d_context_rv3d(C);
- RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d));
- RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[1]);
+ spin_mesh(turns*steps, turns*360, dvec, 0);
- return screw_mesh_exec(C, op);
+ BIF_undo_push("Spin");
}
-void MESH_OT_screw(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Screw";
- ot->description= "Extrude selected vertices in screw-shaped rotation around the cursor in indicated viewport";
- ot->idname= "MESH_OT_screw";
-
- /* api callbacks */
- ot->invoke= screw_mesh_invoke;
- ot->exec= screw_mesh_exec;
- ot->poll= EM_view3d_poll;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /*props */
- RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, 256);
- RNA_def_int(ot->srna, "turns", 1, 0, INT_MAX, "Turns", "Turns", 0, 256);
- RNA_def_float_vector_xyz(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX);
- RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX);
-}
-
-static void erase_edges(EditMesh *em, ListBase *l)
+static void erase_edges(ListBase *l)
{
EditEdge *ed, *nexted;
-
+
ed = (EditEdge *) l->first;
while(ed) {
nexted= ed->next;
if( (ed->v1->f & SELECT) || (ed->v2->f & SELECT) ) {
- remedge(em, ed);
- free_editedge(em, ed);
+ remedge(ed);
+ free_editedge(ed);
}
ed= nexted;
}
}
-static void erase_faces(EditMesh *em, ListBase *l)
+static void erase_faces(ListBase *l)
{
EditFace *f, *nextf;
@@ -1232,13 +949,13 @@ static void erase_faces(EditMesh *em, ListBase *l)
nextf= f->next;
if( faceselectedOR(f, SELECT) ) {
BLI_remlink(l, f);
- free_editface(em, f);
+ free_editface(f);
}
f = nextf;
}
-}
+}
-static void erase_vertices(EditMesh *em, ListBase *l)
+static void erase_vertices(ListBase *l)
{
EditVert *v, *nextv;
@@ -1247,37 +964,42 @@ static void erase_vertices(EditMesh *em, ListBase *l)
nextv= v->next;
if(v->f & 1) {
BLI_remlink(l, v);
- free_editvert(em, v);
+ free_editvert(v);
}
v = nextv;
}
}
-static void delete_mesh(EditMesh *em, wmOperator *op, int event)
+void delete_mesh(void)
{
+ EditMesh *em = G.editMesh;
EditFace *efa, *nextvl;
EditVert *eve,*nextve;
EditEdge *eed,*nexted;
+ short event;
int count;
- /* const char *str="Erase"; */
-
+ char *str="Erase";
+ TEST_EDITMESH
+ if(multires_test()) return;
+
+ event= pupmenu("Erase %t|Vertices%x10|Edges%x1|Faces%x2|All%x3|Edges & Faces%x4|Only Faces%x5|Edge Loop%x6");
if(event<1) return;
if(event==10 ) {
- /* str= "Erase Vertices"; */
- erase_edges(em, &em->edges);
- erase_faces(em, &em->faces);
- erase_vertices(em, &em->verts);
- }
+ str= "Erase Vertices";
+ erase_edges(&em->edges);
+ erase_faces(&em->faces);
+ erase_vertices(&em->verts);
+ }
else if(event==6) {
- if(!EdgeLoopDelete(em, op))
+ if(!EdgeLoopDelete())
return;
- /* str= "Erase Edge Loop"; */
+ str= "Erase Edge Loop";
}
else if(event==4) {
- /* str= "Erase Edges & Faces"; */
+ str= "Erase Edges & Faces";
efa= em->faces.first;
while(efa) {
nextvl= efa->next;
@@ -1289,7 +1011,7 @@ static void delete_mesh(EditMesh *em, wmOperator *op, int event)
if(efa->e4 && (efa->e4->f & SELECT)) count++;
if(count) {
BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
+ free_editface(efa);
}
efa= nextvl;
}
@@ -1297,8 +1019,8 @@ static void delete_mesh(EditMesh *em, wmOperator *op, int event)
while(eed) {
nexted= eed->next;
if(eed->f & SELECT) {
- remedge(em, eed);
- free_editedge(em, eed);
+ remedge(eed);
+ free_editedge(eed);
}
eed= nexted;
}
@@ -1310,16 +1032,16 @@ static void delete_mesh(EditMesh *em, wmOperator *op, int event)
if( efa->v2->f & SELECT) event++;
if( efa->v3->f & SELECT) event++;
if(efa->v4 && (efa->v4->f & SELECT)) event++;
-
+
if(event>1) {
BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
+ free_editface(efa);
}
efa= nextvl;
}
- }
+ }
else if(event==1) {
- /* str= "Erase Edges"; */
+ str= "Erase Edges";
// faces first
efa= em->faces.first;
while(efa) {
@@ -1329,10 +1051,10 @@ static void delete_mesh(EditMesh *em, wmOperator *op, int event)
if( efa->e2->f & SELECT) event++;
if( efa->e3->f & SELECT) event++;
if(efa->e4 && (efa->e4->f & SELECT)) event++;
-
+
if(event) {
BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
+ free_editface(efa);
}
efa= nextvl;
}
@@ -1340,8 +1062,8 @@ static void delete_mesh(EditMesh *em, wmOperator *op, int event)
while(eed) {
nexted= eed->next;
if(eed->f & SELECT) {
- remedge(em, eed);
- free_editedge(em, eed);
+ remedge(eed);
+ free_editedge(eed);
}
eed= nexted;
}
@@ -1357,90 +1079,135 @@ static void delete_mesh(EditMesh *em, wmOperator *op, int event)
nextve= eve->next;
if(eve->f & SELECT) {
BLI_remlink(&em->verts,eve);
- free_editvert(em, eve);
+ free_editvert(eve);
}
eve= nextve;
}
}
else if(event==2) {
- /* str="Erase Faces"; */
- delfaceflag(em, SELECT);
+ str="Erase Faces";
+ delfaceflag(SELECT);
}
else if(event==3) {
- /* str= "Erase All"; */
- if(em->verts.first) free_vertlist(em, &em->verts);
- if(em->edges.first) free_edgelist(em, &em->edges);
- if(em->faces.first) free_facelist(em, &em->faces);
+ str= "Erase All";
+ if(em->verts.first) free_vertlist(&em->verts);
+ if(em->edges.first) free_edgelist(&em->edges);
+ if(em->faces.first) free_facelist(&em->faces);
if(em->selected.first) BLI_freelistN(&(em->selected));
}
else if(event==5) {
- /* str= "Erase Only Faces"; */
+ str= "Erase Only Faces";
efa= em->faces.first;
while(efa) {
nextvl= efa->next;
if(efa->f & SELECT) {
BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
+ free_editface(efa);
}
efa= nextvl;
}
}
- EM_fgon_flags(em); // redo flags and indices for fgons
+ EM_fgon_flags(); // redo flags and indices for fgons
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ BIF_undo_push(str);
}
-/* Note, these values must match delete_mesh() event values */
-static EnumPropertyItem prop_mesh_delete_types[] = {
- {10,"VERT", 0, "Vertices", ""},
- {1, "EDGE", 0, "Edges", ""},
- {2, "FACE", 0, "Faces", ""},
- {3, "ALL", 0, "All", ""},
- {4, "EDGE_FACE",0, "Edges & Faces", ""},
- {5, "ONLY_FACE",0, "Only Faces", ""},
- {6, "EDGE_LOOP",0, "Edge Loop", ""},
- {0, NULL, 0, NULL, NULL}
-};
-static int delete_mesh_exec(bContext *C, wmOperator *op)
+/* Got this from scanfill.c. You will need to juggle around the
+ * callbacks for the scanfill.c code a bit for this to work. */
+void fill_mesh(void)
{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
- int type= RNA_enum_get(op->ptr, "type");
-
- if(type==6)
- return WM_operator_name_call(C, "MESH_OT_delete_edgeloop", WM_OP_EXEC_DEFAULT, NULL);
+ EditMesh *em = G.editMesh;
+ EditVert *eve,*v1;
+ EditEdge *eed,*e1,*nexted;
+ EditFace *efa,*nextvl, *efan;
+ short ok;
- delete_mesh(em, op, type);
+ if(G.obedit==0 || (G.obedit->type!=OB_MESH)) return;
+ if(multires_test()) return;
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+ waitcursor(1);
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
+ /* copy all selected vertices */
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & SELECT) {
+ v1= BLI_addfillvert(eve->co);
+ eve->tmp.v= v1;
+ v1->tmp.v= eve;
+ v1->xs= 0; // used for counting edges
+ }
+ eve= eve->next;
+ }
+ /* copy all selected edges */
+ eed= em->edges.first;
+ while(eed) {
+ if( (eed->v1->f & SELECT) && (eed->v2->f & SELECT) ) {
+ e1= BLI_addfilledge(eed->v1->tmp.v, eed->v2->tmp.v);
+ e1->v1->xs++;
+ e1->v2->xs++;
+ }
+ eed= eed->next;
+ }
+ /* from all selected faces: remove vertices and edges to prevent doubles */
+ /* all edges add values, faces subtract,
+ then remove edges with vertices ->xs<2 */
+ efa= em->faces.first;
+ ok= 0;
+ while(efa) {
+ nextvl= efa->next;
+ if( faceselectedAND(efa, 1) ) {
+ efa->v1->tmp.v->xs--;
+ efa->v2->tmp.v->xs--;
+ efa->v3->tmp.v->xs--;
+ if(efa->v4) efa->v4->tmp.v->xs--;
+ ok= 1;
+
+ }
+ efa= nextvl;
+ }
+ if(ok) { /* there are faces selected */
+ eed= filledgebase.first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->v1->xs<2 || eed->v2->xs<2) {
+ BLI_remlink(&filledgebase,eed);
+ }
+ eed= nexted;
+ }
+ }
-void MESH_OT_delete(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Delete";
- ot->description= "Delete selected vertices, edges or faces";
- ot->idname= "MESH_OT_delete";
+ if(BLI_edgefill(0, (G.obedit && G.obedit->actcol)?(G.obedit->actcol-1):0)) {
+ efa= fillfacebase.first;
+ while(efa) {
+ /* normals default pointing up */
+ efan= addfacelist(efa->v3->tmp.v, efa->v2->tmp.v,
+ efa->v1->tmp.v, 0, NULL, NULL);
+ if(efan) EM_select_face(efan, 1);
+ efa= efa->next;
+ }
+ }
- /* api callbacks */
- ot->invoke= WM_menu_invoke;
- ot->exec= delete_mesh_exec;
+ BLI_end_edgefill();
- ot->poll= ED_operator_editmesh;
+ waitcursor(0);
+ EM_select_flush();
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
- /*props */
- ot->prop= RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, 10, "Type", "Method used for deleting mesh data");
+ BIF_undo_push("Fill");
}
-
-
/*GB*/
/*-------------------------------------------------------------------------------*/
/*--------------------------- Edge Based Subdivide ------------------------------*/
@@ -1454,76 +1221,75 @@ void MESH_OT_delete(wmOperatorType *ot)
#define DOUBLEOPFILL 16
/* calculates offset for co, based on fractal, sphere or smooth settings */
-static void alter_co(float *co, EditEdge *edge, float smooth, float fractal, int beauty, float perc)
+static void alter_co(float *co, EditEdge *edge, float rad, int beauty, float perc)
{
float vec1[3], fac;
-
+
if(beauty & B_SMOOTH) {
/* we calculate an offset vector vec1[], to be added to *co */
float len, fac, nor[3], nor1[3], nor2[3];
-
+
sub_v3_v3v3(nor, edge->v1->co, edge->v2->co);
len= 0.5f*normalize_v3(nor);
-
- copy_v3_v3(nor1, edge->v1->no);
- copy_v3_v3(nor2, edge->v2->no);
-
+
+ VECCOPY(nor1, edge->v1->no);
+ VECCOPY(nor2, edge->v2->no);
+
/* cosine angle */
fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
-
+
vec1[0]= fac*nor1[0];
vec1[1]= fac*nor1[1];
vec1[2]= fac*nor1[2];
-
+
/* cosine angle */
fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
-
+
vec1[0]+= fac*nor2[0];
vec1[1]+= fac*nor2[1];
vec1[2]+= fac*nor2[2];
-
- /* falloff for multi subdivide */
- smooth *= sqrtf(fabs(1.0f - 2.0f*fabsf(0.5f-perc)));
-
- vec1[0]*= smooth*len;
- vec1[1]*= smooth*len;
- vec1[2]*= smooth*len;
-
+
+ vec1[0]*= rad*len;
+ vec1[1]*= rad*len;
+ vec1[2]*= rad*len;
+
co[0] += vec1[0];
co[1] += vec1[1];
co[2] += vec1[2];
}
- else if(beauty & B_SPHERE) { /* subdivide sphere */
- normalize_v3(co);
- co[0]*= smooth;
- co[1]*= smooth;
- co[2]*= smooth;
- }
+ else {
+ if(rad > 0.0) { /* subdivide sphere */
+ normalize_v3(co);
+ co[0]*= rad;
+ co[1]*= rad;
+ co[2]*= rad;
+ }
+ else if(rad< 0.0) { /* fractal subdivide */
+ fac= rad* len_v3v3(edge->v1->co, edge->v2->co);
+ vec1[0]= fac*(float)(0.5-BLI_drand());
+ vec1[1]= fac*(float)(0.5-BLI_drand());
+ vec1[2]= fac*(float)(0.5-BLI_drand());
+ add_v3_v3v3(co, co, vec1);
+ }
- if(beauty & B_FRACTAL) {
- fac= fractal*len_v3v3(edge->v1->co, edge->v2->co);
- vec1[0]= fac*(float)(0.5-BLI_drand());
- vec1[1]= fac*(float)(0.5-BLI_drand());
- vec1[2]= fac*(float)(0.5-BLI_drand());
- add_v3_v3(co, vec1);
}
}
/* assumes in the edge is the correct interpolated vertices already */
-/* percent defines the interpolation, smooth, fractal and beauty are for special options */
+/* percent defines the interpolation, rad and beauty are for special options */
/* results in new vertex with correct coordinate, vertex normal and weight group info */
-static EditVert *subdivide_edge_addvert(EditMesh *em, EditEdge *edge, float smooth, float fractal, int beauty, float percent)
+static EditVert *subdivide_edge_addvert(EditEdge *edge, float rad, int beauty, float percent)
{
EditVert *ev;
float co[3];
-
+
co[0] = (edge->v2->co[0]-edge->v1->co[0])*percent + edge->v1->co[0];
co[1] = (edge->v2->co[1]-edge->v1->co[1])*percent + edge->v1->co[1];
- co[2] = (edge->v2->co[2]-edge->v1->co[2])*percent + edge->v1->co[2];
-
+ co[2] = (edge->v2->co[2]-edge->v1->co[2])*percent + edge->v1->co[2];
+
/* offset for smooth or sphere or fractal */
- alter_co(co, edge, smooth, fractal, beauty, percent);
-
+ alter_co(co, edge, rad, beauty, percent);
+
/* clip if needed by mirror modifier */
if (edge->v1->f2) {
if ( edge->v1->f2 & edge->v2->f2 & 1) {
@@ -1536,18 +1302,18 @@ static EditVert *subdivide_edge_addvert(EditMesh *em, EditEdge *edge, float smoo
co[2]= 0.0f;
}
}
-
- ev = addvertlist(em, co, NULL);
-
+
+ ev = addvertlist(co, NULL);
+
/* vert data (vgroups, ..) */
- EM_data_interp_from_verts(em, edge->v1, edge->v2, ev, percent);
-
+ EM_data_interp_from_verts(edge->v1, edge->v2, ev, percent);
+
/* normal */
ev->no[0] = (edge->v2->no[0]-edge->v1->no[0])*percent + edge->v1->no[0];
ev->no[1] = (edge->v2->no[1]-edge->v1->no[1])*percent + edge->v1->no[1];
ev->no[2] = (edge->v2->no[2]-edge->v1->no[2])*percent + edge->v1->no[2];
normalize_v3(ev->no);
-
+
return ev;
}
@@ -1555,16 +1321,17 @@ static void flipvertarray(EditVert** arr, short size)
{
EditVert *hold;
int i;
-
+
for(i=0; i<size/2; i++) {
hold = arr[i];
arr[i] = arr[size-i-1];
- arr[size-i-1] = hold;
+ arr[size-i-1] = hold;
}
}
-static void facecopy(EditMesh *em, EditFace *source, EditFace *target)
+static void facecopy(EditFace *source, EditFace *target)
{
+ EditMesh *em= G.editMesh;
float *v1 = source->v1->co, *v2 = source->v2->co, *v3 = source->v3->co;
float *v4 = source->v4? source->v4->co: NULL;
float w[4][4];
@@ -1572,35 +1339,34 @@ static void facecopy(EditMesh *em, EditFace *source, EditFace *target)
CustomData_em_copy_data(&em->fdata, &em->fdata, source->data, &target->data);
target->mat_nr = source->mat_nr;
- target->flag = source->flag;
+ target->flag = source->flag;
target->h = source->h;
-
+
interp_weights_face_v3( w[0],v1, v2, v3, v4, target->v1->co);
interp_weights_face_v3( w[1],v1, v2, v3, v4, target->v2->co);
interp_weights_face_v3( w[2],v1, v2, v3, v4, target->v3->co);
if (target->v4)
interp_weights_face_v3( w[3],v1, v2, v3, v4, target->v4->co);
-
- CustomData_em_validate_data(&em->fdata, target->data, target->v4 ? 4 : 3);
+
CustomData_em_interp(&em->fdata, &source->data, NULL, (float*)w, 1, target->data);
}
-static void fill_quad_single(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, int seltype)
+static void fill_quad_single(EditFace *efa, struct GHash *gh, int numcuts, int seltype)
{
EditEdge *cedge=NULL;
EditVert *v[4], **verts;
EditFace *hold;
- short start=0, /* end, */ /* UNUSED */ left, right, vertsize,i;
-
+ short start=0, end, left, right, vertsize,i;
+
v[0] = efa->v1;
v[1] = efa->v2;
v[2] = efa->v3;
- v[3] = efa->v4;
+ v[3] = efa->v4;
if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
- else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
- else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
- else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
+ else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
+ else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
+ else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
// Point verts to the array of new verts for cedge
verts = BLI_ghash_lookup(gh, cedge);
@@ -1612,79 +1378,79 @@ static void fill_quad_single(EditMesh *em, EditFace *efa, struct GHash *gh, int
// the array to the correct direction
if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);}
- /* end = (start+1)%4; */ /* UNUSED */
+ end = (start+1)%4;
left = (start+2)%4;
- right = (start+3)%4;
-
+ right = (start+3)%4;
+
/*
We should have something like this now
- end start
- 3 2 1 0
+ end start
+ 3 2 1 0
|---*---*---|
| |
+ | |
| |
- | |
- -------------
+ -------------
left right
where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
and 0,1,2... are the indexes of the new verts stored in verts
We will fill this case like this or this depending on even or odd cuts
-
+
|---*---*---| |---*---|
| / \ | | / \ |
- | / \ | | / \ |
+ | / \ | | / \ |
|/ \| |/ \|
- ------------- ---------
+ ------------- ---------
*/
// Make center face
if(vertsize % 2 == 0) {
- hold = addfacelist(em, verts[(vertsize-1)/2],verts[((vertsize-1)/2)+1],v[left],v[right], NULL,NULL);
+ hold = addfacelist(verts[(vertsize-1)/2],verts[((vertsize-1)/2)+1],v[left],v[right], NULL,NULL);
hold->e2->f2 |= EDGEINNER;
hold->e4->f2 |= EDGEINNER;
}else{
- hold = addfacelist(em, verts[(vertsize-1)/2],v[left],v[right],NULL, NULL,NULL);
+ hold = addfacelist(verts[(vertsize-1)/2],v[left],v[right],NULL, NULL,NULL);
hold->e1->f2 |= EDGEINNER;
hold->e3->f2 |= EDGEINNER;
}
- facecopy(em, efa,hold);
+ facecopy(efa,hold);
// Make side faces
for(i=0;i<(vertsize-1)/2;i++) {
- hold = addfacelist(em, verts[i],verts[i+1],v[right],NULL,NULL,NULL);
- facecopy(em, efa,hold);
+ hold = addfacelist(verts[i],verts[i+1],v[right],NULL,NULL,NULL);
+ facecopy(efa,hold);
if(i+1 != (vertsize-1)/2) {
- if(seltype == SUBDIV_SELECT_INNER) {
- hold->e2->f2 |= EDGEINNER;
- }
+ if(seltype == SUBDIV_SELECT_INNER) {
+ hold->e2->f2 |= EDGEINNER;
+ }
}
- hold = addfacelist(em, verts[vertsize-2-i],verts[vertsize-1-i],v[left],NULL,NULL,NULL);
- facecopy(em, efa,hold);
+ hold = addfacelist(verts[vertsize-2-i],verts[vertsize-1-i],v[left],NULL,NULL,NULL);
+ facecopy(efa,hold);
if(i+1 != (vertsize-1)/2) {
- if(seltype == SUBDIV_SELECT_INNER) {
- hold->e3->f2 |= EDGEINNER;
- }
+ if(seltype == SUBDIV_SELECT_INNER) {
+ hold->e3->f2 |= EDGEINNER;
+ }
}
- }
+ }
}
-static void fill_tri_single(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, int seltype)
+static void fill_tri_single(EditFace *efa, struct GHash *gh, int numcuts, int seltype)
{
EditEdge *cedge=NULL;
EditVert *v[3], **verts;
EditFace *hold;
- short start=0, /* end, */ /* UNUSED */ op, vertsize,i;
-
+ short start=0, end, op, vertsize,i;
+
v[0] = efa->v1;
v[1] = efa->v2;
- v[2] = efa->v3;
+ v[2] = efa->v3;
if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
- else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
- else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
+ else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
+ else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
// Point verts to the array of new verts for cedge
verts = BLI_ghash_lookup(gh, cedge);
@@ -1696,32 +1462,32 @@ static void fill_tri_single(EditMesh *em, EditFace *efa, struct GHash *gh, int n
// the array to the correct direction
if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);}
- /* end = (start+1)%3; */ /* UNUSED */
- op = (start+2)%3;
-
+ end = (start+1)%3;
+ op = (start+2)%3;
+
/*
We should have something like this now
- end start
- 3 2 1 0
+ end start
+ 3 2 1 0
|---*---*---|
\ |
- \ |
+ \ |
\ |
\ |
\ |
\ |
|op
-
+
where start,end,op are indexes of EditFace->v1, etc (stored in v)
and 0,1,2... are the indexes of the new verts stored in verts
We will fill this case like this or this depending on even or odd cuts
-
- 3 2 1 0
+
+ 3 2 1 0
|---*---*---|
\ \ \ |
- \ \ \ |
+ \ \ \ |
\ \ \ |
\ \ \|
\ \\|
@@ -1731,27 +1497,27 @@ static void fill_tri_single(EditMesh *em, EditFace *efa, struct GHash *gh, int n
// Make side faces
for(i=0;i<(vertsize-1);i++) {
- hold = addfacelist(em, verts[i],verts[i+1],v[op],NULL,NULL,NULL);
+ hold = addfacelist(verts[i],verts[i+1],v[op],NULL,NULL,NULL);
if(i+1 != vertsize-1) {
- if(seltype == SUBDIV_SELECT_INNER) {
- hold->e2->f2 |= EDGEINNER;
- }
+ if(seltype == SUBDIV_SELECT_INNER) {
+ hold->e2->f2 |= EDGEINNER;
+ }
}
- facecopy(em, efa,hold);
- }
+ facecopy(efa,hold);
+ }
}
-static void fill_quad_double_op(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
+static void fill_quad_double_op(EditFace *efa, struct GHash *gh, int numcuts)
{
EditEdge *cedge[2]={NULL, NULL};
EditVert *v[4], **verts[2];
EditFace *hold;
- short start=0, /*end,*/ left, /* right,*/ vertsize,i;
-
+ short start=0, end, left, right, vertsize,i;
+
v[0] = efa->v1;
v[1] = efa->v2;
v[2] = efa->v3;
- v[3] = efa->v4;
+ v[3] = efa->v4;
if(efa->e1->f & SELECT) { cedge[0] = efa->e1; cedge[1] = efa->e3; start = 0;}
else if(efa->e2->f & SELECT) { cedge[0] = efa->e2; cedge[1] = efa->e4; start = 1;}
@@ -1767,55 +1533,54 @@ static void fill_quad_double_op(EditMesh *em, EditFace *efa, struct GHash *gh, i
// the array to the correct direction
if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
- /* end = (start+1)%4; */ /* UNUSED */
+ end = (start+1)%4;
left = (start+2)%4;
- /* right = (start+3)%4; */ /* UNUSED */
- if(verts[1][0] != v[left]) {flipvertarray(verts[1],numcuts+2);}
+ right = (start+3)%4;
+ if(verts[1][0] != v[left]) {flipvertarray(verts[1],numcuts+2);}
/*
We should have something like this now
- end start
- 3 2 1 0
+ end start
+ 3 2 1 0
|---*---*---|
| |
+ | |
| |
- | |
- |---*---*---|
+ |---*---*---|
0 1 2 3
left right
We will fill this case like this or this depending on even or odd cuts
-
+
|---*---*---|
| | | |
+ | | | |
| | | |
- | | | |
- |---*---*---|
+ |---*---*---|
*/
-
+
// Make side faces
for(i=0;i<vertsize-1;i++) {
- hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-2-i],verts[1][vertsize-1-i],NULL,NULL);
+ hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-2-i],verts[1][vertsize-1-i],NULL,NULL);
if(i < vertsize-2) {
hold->e2->f2 |= EDGEINNER;
hold->e2->f2 |= DOUBLEOPFILL;
}
- facecopy(em, efa,hold);
- }
+ facecopy(efa,hold);
+ }
}
-static void fill_quad_double_adj_path(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
+static void fill_quad_double_adj_path(EditFace *efa, struct GHash *gh, int numcuts)
{
EditEdge *cedge[2]={NULL, NULL};
EditVert *v[4], **verts[2];
EditFace *hold;
short start=0, start2=0, vertsize,i;
- int ctrl= 0; // XXX
-
+
v[0] = efa->v1;
v[1] = efa->v2;
v[2] = efa->v3;
- v[3] = efa->v4;
+ v[3] = efa->v4;
if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;}
if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;}
@@ -1833,162 +1598,162 @@ static void fill_quad_double_adj_path(EditMesh *em, EditFace *efa, struct GHash
// the array to the correct direction
if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
- if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
/*
We should have something like this now
- end start
- 3 2 1 0
+ end start
+ 3 2 1 0
start2 0|---*---*---|
| |
1* |
| |
- 2* |
+ 2* |
| |
- end2 3|-----------|
+ end2 3|-----------|
We will fill this case like this or this depending on even or odd cuts
|---*---*---|
| / / / |
* / / |
| / / |
- * / |
+ * / |
| / |
- |-----------|
+ |-----------|
*/
// Make outside tris
- hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
+ hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
/* when ctrl is depressed, only want verts on the cutline selected */
- if (ctrl)
+ if (G.qual != LR_CTRLKEY)
hold->e3->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
- hold = addfacelist(em, verts[0][0],verts[1][vertsize-1],v[(start2+2)%4],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ hold = addfacelist(verts[0][0],verts[1][vertsize-1],v[(start2+2)%4],NULL,NULL,NULL);
/* when ctrl is depressed, only want verts on the cutline selected */
- if (ctrl)
- hold->e1->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
- //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
+ if (G.qual != LR_CTRLKEY)
+ hold->e1->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
// hold->e1->h |= EM_FGON;
- //}
+ //}
// Make side faces
for(i=0;i<numcuts;i++) {
- hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
+ hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
hold->e2->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
+ facecopy(efa,hold);
}
- //EM_fgon_flags(em);
-
+ //EM_fgon_flags();
+
}
-static void fill_quad_double_adj_fan(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
+static void fill_quad_double_adj_fan(EditFace *efa, struct GHash *gh, int numcuts)
{
EditEdge *cedge[2]={NULL, NULL};
EditVert *v[4], *op=NULL, **verts[2];
EditFace *hold;
- short start=0, start2=0, /* vertsize, */ /* UNUSED */ i;
-
+ short start=0, start2=0, vertsize,i;
+
v[0] = efa->v1;
v[1] = efa->v2;
v[2] = efa->v3;
- v[3] = efa->v4;
+ v[3] = efa->v4;
if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;}
if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;}
if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;}
if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;}
-
+
// Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
verts[0] = BLI_ghash_lookup(gh, cedge[0]);
verts[1] = BLI_ghash_lookup(gh, cedge[1]);
//This is the index size of the verts array
- /* vertsize = numcuts+2; */ /* UNUSED */
+ vertsize = numcuts+2;
// Is the original v1 the same as the first vert on the selected edge?
// if not, the edge is running the opposite direction in this face so flip
// the array to the correct direction
if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
- if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
/*
We should have something like this now
- end start
- 3 2 1 0
+ end start
+ 3 2 1 0
start2 0|---*---*---|
| |
1* |
| |
- 2* |
+ 2* |
| |
- end2 3|-----------|op
+ end2 3|-----------|op
We will fill this case like this or this (warning horrible ascii art follows)
|---*---*---|
| \ \ \ |
*---\ \ \ |
| \ \ \ \|
- *---- \ \ \ |
+ *---- \ \ \ |
| --- \\\|
- |-----------|
+ |-----------|
*/
for(i=0;i<=numcuts;i++) {
- hold = addfacelist(em, op,verts[1][numcuts-i],verts[1][numcuts-i+1],NULL,NULL,NULL);
+ hold = addfacelist(op,verts[1][numcuts-i],verts[1][numcuts-i+1],NULL,NULL,NULL);
hold->e1->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
+ facecopy(efa,hold);
- hold = addfacelist(em, op,verts[0][i],verts[0][i+1],NULL,NULL,NULL);
+ hold = addfacelist(op,verts[0][i],verts[0][i+1],NULL,NULL,NULL);
hold->e3->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
- }
+ facecopy(efa,hold);
+ }
}
-static void fill_quad_double_adj_inner(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
+static void fill_quad_double_adj_inner(EditFace *efa, struct GHash *gh, int numcuts)
{
EditEdge *cedge[2]={NULL, NULL};
EditVert *v[4], *op=NULL, **verts[2],**inner;
EditFace *hold;
- short start=0, start2=0, /* vertsize, */ /* UNUSED */ i;
+ short start=0, start2=0, vertsize,i;
float co[3];
-
+
v[0] = efa->v1;
v[1] = efa->v2;
v[2] = efa->v3;
- v[3] = efa->v4;
+ v[3] = efa->v4;
if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;}
if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;}
if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;}
if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;}
-
+
// Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
verts[0] = BLI_ghash_lookup(gh, cedge[0]);
verts[1] = BLI_ghash_lookup(gh, cedge[1]);
//This is the index size of the verts array
- /* vertsize = numcuts+2; */ /* UNUSED */
+ vertsize = numcuts+2;
// Is the original v1 the same as the first vert on the selected edge?
// if not, the edge is running the opposite direction in this face so flip
// the array to the correct direction
if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
- if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
/*
We should have something like this now
- end start
- 3 2 1 0
+ end start
+ 3 2 1 0
start2 0|---*---*---|
| |
1* |
| |
- 2* |
+ 2* |
| |
- end2 3|-----------|op
+ end2 3|-----------|op
We will fill this case like this or this (warning horrible ascii art follows)
|---*-----*---|
@@ -1996,71 +1761,71 @@ static void fill_quad_double_adj_inner(EditMesh *em, EditFace *efa, struct GHash
* \ / |
| * |
| / \ |
- * \ |
+ * \ |
| \ |
- |-------------|
+ |-------------|
*/
// Add Inner Vert(s)
inner = MEM_mallocN(sizeof(EditVert*)*numcuts,"New inner verts");
-
+
for(i=0;i<numcuts;i++) {
co[0] = (verts[0][numcuts-i]->co[0] + verts[1][i+1]->co[0] ) / 2 ;
co[1] = (verts[0][numcuts-i]->co[1] + verts[1][i+1]->co[1] ) / 2 ;
co[2] = (verts[0][numcuts-i]->co[2] + verts[1][i+1]->co[2] ) / 2 ;
- inner[i] = addvertlist(em, co, NULL);
+ inner[i] = addvertlist(co, NULL);
inner[i]->f2 |= EDGEINNER;
- EM_data_interp_from_verts(em, verts[0][numcuts-i], verts[1][i+1], inner[i], 0.5f);
+ EM_data_interp_from_verts(verts[0][numcuts-i], verts[1][i+1], inner[i], 0.5f);
}
-
+
// Add Corner Quad
- hold = addfacelist(em, verts[0][numcuts+1],verts[1][1],inner[0],verts[0][numcuts],NULL,NULL);
+ hold = addfacelist(verts[0][numcuts+1],verts[1][1],inner[0],verts[0][numcuts],NULL,NULL);
hold->e2->f2 |= EDGEINNER;
hold->e3->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
+ facecopy(efa,hold);
// Add Bottom Quads
- hold = addfacelist(em, verts[0][0],verts[0][1],inner[numcuts-1],op,NULL,NULL);
+ hold = addfacelist(verts[0][0],verts[0][1],inner[numcuts-1],op,NULL,NULL);
hold->e2->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
+ facecopy(efa,hold);
- hold = addfacelist(em, op,inner[numcuts-1],verts[1][numcuts],verts[1][numcuts+1],NULL,NULL);
+ hold = addfacelist(op,inner[numcuts-1],verts[1][numcuts],verts[1][numcuts+1],NULL,NULL);
hold->e2->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
-
- //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
+ facecopy(efa,hold);
+
+ //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
// hold->e1->h |= EM_FGON;
- //}
+ //}
// Add Fill Quads (if # cuts > 1)
for(i=0;i<numcuts-1;i++) {
- hold = addfacelist(em, inner[i],verts[1][i+1],verts[1][i+2],inner[i+1],NULL,NULL);
+ hold = addfacelist(inner[i],verts[1][i+1],verts[1][i+2],inner[i+1],NULL,NULL);
hold->e1->f2 |= EDGEINNER;
hold->e3->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
+ facecopy(efa,hold);
- hold = addfacelist(em, inner[i],inner[i+1],verts[0][numcuts-1-i],verts[0][numcuts-i],NULL,NULL);
+ hold = addfacelist(inner[i],inner[i+1],verts[0][numcuts-1-i],verts[0][numcuts-i],NULL,NULL);
hold->e2->f2 |= EDGEINNER;
hold->e4->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
-
- //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
+ facecopy(efa,hold);
+
+ //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
// hold->e1->h |= EM_FGON;
- //}
- }
-
- //EM_fgon_flags(em);
-
- MEM_freeN(inner);
+ //}
+ }
+
+ //EM_fgon_flags();
+
+ MEM_freeN(inner);
}
-static void fill_tri_double(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
+static void fill_tri_double(EditFace *efa, struct GHash *gh, int numcuts)
{
EditEdge *cedge[2]={NULL, NULL};
EditVert *v[3], **verts[2];
EditFace *hold;
short start=0, start2=0, vertsize,i;
-
+
v[0] = efa->v1;
v[1] = efa->v2;
v[2] = efa->v3;
@@ -2080,224 +1845,224 @@ static void fill_tri_double(EditMesh *em, EditFace *efa, struct GHash *gh, int n
// the array to the correct direction
if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
- if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
/*
We should have something like this now
- end start
- 3 2 1 0
+ end start
+ 3 2 1 0
start2 0|---*---*---|
- | /
- 1* /
- | /
- 2* /
- | /
- end2 3|
+ | /
+ 1* /
+ | /
+ 2* /
+ | /
+ end2 3|
We will fill this case like this or this depending on even or odd cuts
|---*---*---|
- | / / /
- * / /
- | / /
- * /
- | /
+ | / / /
+ * / /
+ | / /
+ * /
+ | /
|
*/
// Make outside tri
- hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
+ hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
hold->e3->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
+ facecopy(efa,hold);
// Make side faces
for(i=0;i<numcuts;i++) {
- hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
+ hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
hold->e2->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
- }
+ facecopy(efa,hold);
+ }
}
-static void fill_quad_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
+static void fill_quad_triple(EditFace *efa, struct GHash *gh, int numcuts)
{
EditEdge *cedge[3]={0};
EditVert *v[4], **verts[3];
EditFace *hold;
short start=0, start2=0, start3=0, vertsize, i, repeats;
-
+
v[0] = efa->v1;
v[1] = efa->v2;
v[2] = efa->v3;
- v[3] = efa->v4;
-
+ v[3] = efa->v4;
+
if(!(efa->e1->f & SELECT)) {
- cedge[0] = efa->e2;
- cedge[1] = efa->e3;
+ cedge[0] = efa->e2;
+ cedge[1] = efa->e3;
cedge[2] = efa->e4;
- start = 1;start2 = 2;start3 = 3;
+ start = 1;start2 = 2;start3 = 3;
}
if(!(efa->e2->f & SELECT)) {
- cedge[0] = efa->e3;
- cedge[1] = efa->e4;
+ cedge[0] = efa->e3;
+ cedge[1] = efa->e4;
cedge[2] = efa->e1;
- start = 2;start2 = 3;start3 = 0;
+ start = 2;start2 = 3;start3 = 0;
}
if(!(efa->e3->f & SELECT)) {
- cedge[0] = efa->e4;
- cedge[1] = efa->e1;
+ cedge[0] = efa->e4;
+ cedge[1] = efa->e1;
cedge[2] = efa->e2;
- start = 3;start2 = 0;start3 = 1;
+ start = 3;start2 = 0;start3 = 1;
}
if(!(efa->e4->f & SELECT)) {
- cedge[0] = efa->e1;
- cedge[1] = efa->e2;
+ cedge[0] = efa->e1;
+ cedge[1] = efa->e2;
cedge[2] = efa->e3;
- start = 0;start2 = 1;start3 = 2;
- }
+ start = 0;start2 = 1;start3 = 2;
+ }
// Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
verts[0] = BLI_ghash_lookup(gh, cedge[0]);
verts[1] = BLI_ghash_lookup(gh, cedge[1]);
verts[2] = BLI_ghash_lookup(gh, cedge[2]);
//This is the index size of the verts array
vertsize = numcuts+2;
-
+
// Is the original v1 the same as the first vert on the selected edge?
// if not, the edge is running the opposite direction in this face so flip
// the array to the correct direction
-
+
if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
- if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
- if(verts[2][0] != v[start3]) {flipvertarray(verts[2],numcuts+2);}
+ if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[2][0] != v[start3]) {flipvertarray(verts[2],numcuts+2);}
/*
We should have something like this now
-
- start2
- 3 2 1 0
- start3 0|---*---*---|3
+
+ start2
+ 3 2 1 0
+ start3 0|---*---*---|3
| |
1* *2
| |
- 2* *1
+ 2* *1
| |
- 3|-----------|0 start
-
- We will fill this case like this or this depending on even or odd cuts
+ 3|-----------|0 start
+
+ We will fill this case like this or this depending on even or odd cuts
there are a couple of differences. For odd cuts, there is a tri in the
middle as well as 1 quad at the bottom (not including the extra quads
- for odd cuts > 1
-
+ for odd cuts > 1
+
For even cuts, there is a quad in the middle and 2 quads on the bottom
-
+
they are numbered here for clarity
-
+
1 outer tris and bottom quads
2 inner tri or quad
3 repeating quads
-
+
|---*---*---*---|
|1/ / \ \ 1|
|/ 3 / \ 3 \|
* / 2 \ *
| / \ |
- |/ \ |
+ |/ \ |
*---------------*
| 3 |
- | |
+ | |
*---------------*
| |
- | 1 |
+ | 1 |
| |
|---------------|
-
+
|---*---*---*---*---|
- | 1/ / \ \ 1|
- | / / \ \ |
+ | 1/ / \ \ 1|
+ | / / \ \ |
|/ 3 / \ 3 \|
* / \ *
- | / \ |
- | / 2 \ |
+ | / \ |
+ | / 2 \ |
|/ \|
*-------------------*
| |
| 3 |
- | |
+ | |
*-------------------*
| |
| 1 |
- | |
+ | |
*-------------------*
| |
| 1 |
- | |
+ | |
|-------------------|
-
+
*/
// Make outside tris
- hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
+ hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
hold->e3->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
- hold = addfacelist(em, verts[1][vertsize-2],verts[1][vertsize-1],verts[2][1],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ hold = addfacelist(verts[1][vertsize-2],verts[1][vertsize-1],verts[2][1],NULL,NULL,NULL);
hold->e3->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
+ facecopy(efa,hold);
// Make bottom quad
- hold = addfacelist(em, verts[0][0],verts[0][1],verts[2][vertsize-2],verts[2][vertsize-1],NULL,NULL);
+ hold = addfacelist(verts[0][0],verts[0][1],verts[2][vertsize-2],verts[2][vertsize-1],NULL,NULL);
hold->e2->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
+ facecopy(efa,hold);
//If it is even cuts, add the 2nd lower quad
if(numcuts % 2 == 0) {
- hold = addfacelist(em, verts[0][1],verts[0][2],verts[2][vertsize-3],verts[2][vertsize-2],NULL,NULL);
+ hold = addfacelist(verts[0][1],verts[0][2],verts[2][vertsize-3],verts[2][vertsize-2],NULL,NULL);
hold->e2->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
+ facecopy(efa,hold);
// Also Make inner quad
- hold = addfacelist(em, verts[1][numcuts/2],verts[1][(numcuts/2)+1],verts[2][numcuts/2],verts[0][(numcuts/2)+1],NULL,NULL);
+ hold = addfacelist(verts[1][numcuts/2],verts[1][(numcuts/2)+1],verts[2][numcuts/2],verts[0][(numcuts/2)+1],NULL,NULL);
hold->e3->f2 |= EDGEINNER;
- //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
+ //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
// hold->e3->h |= EM_FGON;
//}
- facecopy(em, efa,hold);
+ facecopy(efa,hold);
repeats = (numcuts / 2) -1;
} else {
- // Make inner tri
- hold = addfacelist(em, verts[1][(numcuts/2)+1],verts[2][(numcuts/2)+1],verts[0][(numcuts/2)+1],NULL,NULL,NULL);
+ // Make inner tri
+ hold = addfacelist(verts[1][(numcuts/2)+1],verts[2][(numcuts/2)+1],verts[0][(numcuts/2)+1],NULL,NULL,NULL);
hold->e2->f2 |= EDGEINNER;
- //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
+ //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
// hold->e2->h |= EM_FGON;
//}
- facecopy(em, efa,hold);
+ facecopy(efa,hold);
repeats = ((numcuts+1) / 2)-1;
}
-
+
// cuts for 1 and 2 do not have the repeating quads
if(numcuts < 3) {repeats = 0;}
for(i=0;i<repeats;i++) {
//Make side repeating Quads
- hold = addfacelist(em, verts[1][i+1],verts[1][i+2],verts[0][vertsize-i-3],verts[0][vertsize-i-2],NULL,NULL);
- hold->e2->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
- hold = addfacelist(em, verts[1][vertsize-i-3],verts[1][vertsize-i-2],verts[2][i+1],verts[2][i+2],NULL,NULL);
+ hold = addfacelist(verts[1][i+1],verts[1][i+2],verts[0][vertsize-i-3],verts[0][vertsize-i-2],NULL,NULL);
+ hold->e2->f2 |= EDGEINNER;
+ facecopy(efa,hold);
+ hold = addfacelist(verts[1][vertsize-i-3],verts[1][vertsize-i-2],verts[2][i+1],verts[2][i+2],NULL,NULL);
hold->e4->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
+ facecopy(efa,hold);
}
- // Do repeating bottom quads
+ // Do repeating bottom quads
for(i=0;i<repeats;i++) {
- if(numcuts % 2 == 1) {
- hold = addfacelist(em, verts[0][1+i],verts[0][2+i],verts[2][vertsize-3-i],verts[2][vertsize-2-i],NULL,NULL);
+ if(numcuts % 2 == 1) {
+ hold = addfacelist(verts[0][1+i],verts[0][2+i],verts[2][vertsize-3-i],verts[2][vertsize-2-i],NULL,NULL);
} else {
- hold = addfacelist(em, verts[0][2+i],verts[0][3+i],verts[2][vertsize-4-i],verts[2][vertsize-3-i],NULL,NULL);
+ hold = addfacelist(verts[0][2+i],verts[0][3+i],verts[2][vertsize-4-i],verts[2][vertsize-3-i],NULL,NULL);
}
hold->e2->f2 |= EDGEINNER;
- facecopy(em, efa,hold);
- }
- //EM_fgon_flags(em);
+ facecopy(efa,hold);
+ }
+ //EM_fgon_flags();
}
-static void fill_quad_quadruple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, float smooth, float fractal, int beauty)
+static void fill_quad_quadruple(EditFace *efa, struct GHash *gh, int numcuts, float rad, int beauty)
{
EditVert **verts[4], ***innerverts;
- EditFace *hold;
+ EditFace *hold;
EditEdge temp;
- short /* vertsize, */ /* UNUSED */ i, j;
-
+ short vertsize, i, j;
+
// Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
verts[0] = BLI_ghash_lookup(gh, efa->e1);
verts[1] = BLI_ghash_lookup(gh, efa->e2);
@@ -2305,94 +2070,94 @@ static void fill_quad_quadruple(EditMesh *em, EditFace *efa, struct GHash *gh, i
verts[3] = BLI_ghash_lookup(gh, efa->e4);
//This is the index size of the verts array
- /* vertsize = numcuts+2; */ /* UNUSED */
+ vertsize = numcuts+2;
// Is the original v1 the same as the first vert on the selected edge?
// if not, the edge is running the opposite direction in this face so flip
// the array to the correct direction
if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
- if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
if(verts[2][0] == efa->v3) {flipvertarray(verts[2],numcuts+2);}
- if(verts[3][0] == efa->v4) {flipvertarray(verts[3],numcuts+2);}
+ if(verts[3][0] == efa->v4) {flipvertarray(verts[3],numcuts+2);}
/*
We should have something like this now
1
-
- 3 2 1 0
- 0|---*---*---|0
+
+ 3 2 1 0
+ 0|---*---*---|0
| |
1* *1
- 2 | | 4
- 2* *2
+ 2 | | 4
+ 2* *2
| |
- 3|---*---*---|3
+ 3|---*---*---|3
3 2 1 0
3
// we will fill a 2 dim array of editvert*s to make filling easier
// the innervert order is shown
- 0 0---1---2---3
+ 0 0---1---2---3
| | | |
- 1 0---1---2---3
+ 1 0---1---2---3
| | | |
- 2 0---1---2---3
+ 2 0---1---2---3
| | | |
- 3 0---1---2---3
-
+ 3 0---1---2---3
+
*/
- innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts outer array");
+ innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts outer array");
for(i=0;i<numcuts+2;i++) {
innerverts[i] = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts inner array");
- }
-
+ }
+
// first row is e1 last row is e3
for(i=0;i<numcuts+2;i++) {
innerverts[0][i] = verts[0][(numcuts+1)-i];
innerverts[numcuts+1][i] = verts[2][(numcuts+1)-i];
}
-
+
for(i=1;i<=numcuts;i++) {
/* we create a fake edge for the next loop */
temp.v2 = innerverts[i][0] = verts[1][i];
temp.v1 = innerverts[i][numcuts+1] = verts[3][i];
-
- for(j=1;j<=numcuts;j++) {
+
+ for(j=1;j<=numcuts;j++) {
float percent= (float)j/(float)(numcuts+1);
- innerverts[i][(numcuts+1)-j]= subdivide_edge_addvert(em, &temp, smooth, fractal, beauty, percent);
- }
- }
+ innerverts[i][(numcuts+1)-j]= subdivide_edge_addvert(&temp, rad, beauty, percent);
+ }
+ }
// Fill with faces
for(i=0;i<numcuts+1;i++) {
for(j=0;j<numcuts+1;j++) {
- hold = addfacelist(em, innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],innerverts[i+1][j+1],NULL,NULL);
- hold->e1->f2 = EDGENEW;
- hold->e2->f2 = EDGENEW;
- hold->e3->f2 = EDGENEW;
- hold->e4->f2 = EDGENEW;
-
+ hold = addfacelist(innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],innerverts[i+1][j+1],NULL,NULL);
+ hold->e1->f2 = EDGENEW;
+ hold->e2->f2 = EDGENEW;
+ hold->e3->f2 = EDGENEW;
+ hold->e4->f2 = EDGENEW;
+
if(i != 0) { hold->e1->f2 |= EDGEINNER; }
if(j != 0) { hold->e2->f2 |= EDGEINNER; }
if(i != numcuts) { hold->e3->f2 |= EDGEINNER; }
if(j != numcuts) { hold->e4->f2 |= EDGEINNER; }
-
- facecopy(em, efa,hold);
- }
+
+ facecopy(efa,hold);
+ }
}
// Clean up our dynamic multi-dim array
for(i=0;i<numcuts+2;i++) {
- MEM_freeN(innerverts[i]);
- }
+ MEM_freeN(innerverts[i]);
+ }
MEM_freeN(innerverts);
}
-static void fill_tri_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, float smooth, float fractal, int beauty)
+static void fill_tri_triple(EditFace *efa, struct GHash *gh, int numcuts, float rad, int beauty)
{
EditVert **verts[3], ***innerverts;
- short /* vertsize, */ /* UNUSED */ i, j;
- EditFace *hold;
+ short vertsize, i, j;
+ EditFace *hold;
EditEdge temp;
// Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
@@ -2401,27 +2166,27 @@ static void fill_tri_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int n
verts[2] = BLI_ghash_lookup(gh, efa->e3);
//This is the index size of the verts array
- /* vertsize = numcuts+2; */ /* UNUSED */
+ vertsize = numcuts+2;
// Is the original v1 the same as the first vert on the selected edge?
// if not, the edge is running the opposite direction in this face so flip
// the array to the correct direction
if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
- if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
- if(verts[2][0] != efa->v3) {flipvertarray(verts[2],numcuts+2);}
+ if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[2][0] != efa->v3) {flipvertarray(verts[2],numcuts+2);}
/*
We should have something like this now
3
-
- 3 2 1 0
- 0|---*---*---|3
- | /
- 1 1* *2
- | /
- 2* *1 2
- | /
- 3|/
+
+ 3 2 1 0
+ 0|---*---*---|3
+ | /
+ 1 1* *2
+ | /
+ 2* *1 2
+ | /
+ 3|/
0
we will fill a 2 dim array of editvert*s to make filling easier
@@ -2429,75 +2194,74 @@ static void fill_tri_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int n
3
0 0---1---2---3---4
- | / | / |/ | /
- 1 0---1----2---3
- 1 | / | / | /
+ | / | / |/ | /
+ 1 0---1----2---3
+ 1 | / | / | /
2 0----1---2 2
- | / | /
- |/ |/
- 3 0---1
+ | / | /
+ |/ |/
+ 3 0---1
| /
|/
- 4 0
-
+ 4 0
+
*/
-
- innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"tri-tri subdiv inner verts outer array");
+
+ innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"tri-tri subdiv inner verts outer array");
for(i=0;i<numcuts+2;i++) {
innerverts[i] = MEM_mallocN(sizeof(EditVert*)*((numcuts+2)-i),"tri-tri subdiv inner verts inner array");
}
//top row is e3 backwards
for(i=0;i<numcuts+2;i++) {
innerverts[0][i] = verts[2][(numcuts+1)-i];
- }
-
+ }
+
for(i=1;i<=numcuts+1;i++) {
//fake edge, first vert is from e1, last is from e2
temp.v1= innerverts[i][0] = verts[0][i];
temp.v2= innerverts[i][(numcuts+1)-i] = verts[1][(numcuts+1)-i];
-
+
for(j=1;j<(numcuts+1)-i;j++) {
float percent= (float)j/(float)((numcuts+1)-i);
- innerverts[i][((numcuts+1)-i)-j]= subdivide_edge_addvert(em, &temp, smooth, fractal, beauty, 1-percent);
+ innerverts[i][((numcuts+1)-i)-j]= subdivide_edge_addvert(&temp, rad, beauty, 1-percent);
}
}
// Now fill the verts with happy little tris :)
for(i=0;i<=numcuts+1;i++) {
- for(j=0;j<(numcuts+1)-i;j++) {
+ for(j=0;j<(numcuts+1)-i;j++) {
//We always do the first tri
- hold = addfacelist(em, innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],NULL,NULL,NULL);
- hold->e1->f2 |= EDGENEW;
- hold->e2->f2 |= EDGENEW;
- hold->e3->f2 |= EDGENEW;
+ hold = addfacelist(innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],NULL,NULL,NULL);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
if(i != 0) { hold->e1->f2 |= EDGEINNER; }
if(j != 0) { hold->e2->f2 |= EDGEINNER; }
if(j+1 != (numcuts+1)-i) {hold->e3->f2 |= EDGEINNER;}
-
- facecopy(em, efa,hold);
- //if there are more to come, we do the 2nd
+
+ facecopy(efa,hold);
+ //if there are more to come, we do the 2nd
if(j+1 <= numcuts-i) {
- hold = addfacelist(em, innerverts[i+1][j],innerverts[i+1][j+1],innerverts[i][j+1],NULL,NULL,NULL);
- facecopy(em, efa,hold);
- hold->e1->f2 |= EDGENEW;
- hold->e2->f2 |= EDGENEW;
- hold->e3->f2 |= EDGENEW;
+ hold = addfacelist(innerverts[i+1][j],innerverts[i+1][j+1],innerverts[i][j+1],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ hold->e1->f2 |= EDGENEW;
+ hold->e2->f2 |= EDGENEW;
+ hold->e3->f2 |= EDGENEW;
}
- }
+ }
}
// Clean up our dynamic multi-dim array
for(i=0;i<numcuts+2;i++) {
- MEM_freeN(innerverts[i]);
- }
+ MEM_freeN(innerverts[i]);
+ }
MEM_freeN(innerverts);
}
//Next two fill types are for knife exact only and are provided to allow for knifing through vertices
//This means there is no multicut!
-static void fill_quad_doublevert(EditMesh *em, EditFace *efa, int v1, int v2)
-{
+static void fill_quad_doublevert(EditFace *efa, int v1, int v2){
EditFace *hold;
/*
Depending on which two vertices have been knifed through (v1 and v2), we
@@ -2508,60 +2272,60 @@ static void fill_quad_doublevert(EditMesh *em, EditFace *efa, int v1, int v2)
| \ | | / |
--------X X--------
*/
-
+
if(v1 == 1 && v2 == 3){
- hold= addfacelist(em, efa->v1, efa->v2, efa->v3, 0, efa, NULL);
+ hold= addfacelist(efa->v1, efa->v2, efa->v3, 0, efa, NULL);
hold->e1->f2 |= EDGENEW;
hold->e2->f2 |= EDGENEW;
hold->e3->f2 |= EDGENEW;
hold->e3->f2 |= EDGEINNER;
- facecopy(em, efa, hold);
-
- hold= addfacelist(em, efa->v1, efa->v3, efa->v4, 0, efa, NULL);
+ facecopy(efa, hold);
+
+ hold= addfacelist(efa->v1, efa->v3, efa->v4, 0, efa, NULL);
hold->e1->f2 |= EDGENEW;
hold->e2->f2 |= EDGENEW;
hold->e3->f2 |= EDGENEW;
hold->e1->f2 |= EDGEINNER;
- facecopy(em, efa, hold);
+ facecopy(efa, hold);
}
else{
- hold= addfacelist(em, efa->v1, efa->v2, efa->v4, 0, efa, NULL);
+ hold= addfacelist(efa->v1, efa->v2, efa->v4, 0, efa, NULL);
hold->e1->f2 |= EDGENEW;
hold->e2->f2 |= EDGENEW;
hold->e3->f2 |= EDGENEW;
hold->e2->f2 |= EDGEINNER;
- facecopy(em, efa, hold);
-
- hold= addfacelist(em, efa->v2, efa->v3, efa->v4, 0, efa, NULL);
+ facecopy(efa, hold);
+
+ hold= addfacelist(efa->v2, efa->v3, efa->v4, 0, efa, NULL);
hold->e1->f2 |= EDGENEW;
hold->e2->f2 |= EDGENEW;
hold->e3->f2 |= EDGENEW;
hold->e3->f2 |= EDGEINNER;
- facecopy(em, efa, hold);
+ facecopy(efa, hold);
}
}
-static void fill_quad_singlevert(EditMesh *em, EditFace *efa, struct GHash *gh)
+static void fill_quad_singlevert(EditFace *efa, struct GHash *gh)
{
EditEdge *cedge=NULL;
EditVert *v[4], **verts;
EditFace *hold;
- short start=0, end, left, right /* , vertsize */ /* UNUSED */;
-
+ short start=0, end, left, right, vertsize;
+
v[0] = efa->v1;
v[1] = efa->v2;
v[2] = efa->v3;
- v[3] = efa->v4;
+ v[3] = efa->v4;
if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
- else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
- else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
- else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
+ else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
+ else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
+ else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
// Point verts to the array of new verts for cedge
verts = BLI_ghash_lookup(gh, cedge);
//This is the index size of the verts array
- /* vertsize = 3; */ /* UNUSED */
+ vertsize = 3;
// Is the original v1 the same as the first vert on the selected edge?
// if not, the edge is running the opposite direction in this face so flip
@@ -2570,25 +2334,25 @@ static void fill_quad_singlevert(EditMesh *em, EditFace *efa, struct GHash *gh)
if(verts[0] != v[start]) {flipvertarray(verts,3);}
end = (start+1)%4;
left = (start+2)%4;
- right = (start+3)%4;
+ right = (start+3)%4;
/*
We should have something like this now
- end start
- 2 1 0
+ end start
+ 2 1 0
|-----*-----|
| |
+ | |
| |
- | |
- -------------
+ -------------
left right
where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
and 0,1,2 are the indexes of the new verts stored in verts. We fill like
this, depending on whether its vertex 'left' or vertex 'right' thats
been knifed through...
-
+
|---*---| |---*---|
| / | | \ |
| / | | \ |
@@ -2598,72 +2362,74 @@ static void fill_quad_singlevert(EditMesh *em, EditFace *efa, struct GHash *gh)
if(v[left]->f1){
//triangle is composed of cutvert, end and left
- hold = addfacelist(em, verts[1],v[end],v[left],NULL, NULL,NULL);
+ hold = addfacelist(verts[1],v[end],v[left],NULL, NULL,NULL);
hold->e1->f2 |= EDGENEW;
hold->e2->f2 |= EDGENEW;
hold->e3->f2 |= EDGENEW;
hold->e3->f2 |= EDGEINNER;
- facecopy(em, efa, hold);
-
+ facecopy(efa, hold);
+
//quad is composed of cutvert, left, right and start
- hold = addfacelist(em, verts[1],v[left],v[right],v[start], NULL, NULL);
+ hold = addfacelist(verts[1],v[left],v[right],v[start], NULL, NULL);
hold->e1->f2 |= EDGENEW;
hold->e2->f2 |= EDGENEW;
hold->e3->f2 |= EDGENEW;
hold->e4->f2 |= EDGENEW;
hold->e1->f2 |= EDGEINNER;
- facecopy(em, efa, hold);
+ facecopy(efa, hold);
}
else if(v[right]->f1){
//triangle is composed of cutvert, right and start
- hold = addfacelist(em, verts[1],v[right],v[start], NULL, NULL, NULL);
+ hold = addfacelist(verts[1],v[right],v[start], NULL, NULL, NULL);
hold->e1->f2 |= EDGENEW;
hold->e2->f2 |= EDGENEW;
hold->e3->f2 |= EDGENEW;
hold->e1->f2 |= EDGEINNER;
- facecopy(em, efa, hold);
+ facecopy(efa, hold);
//quad is composed of cutvert, end, left, right
- hold = addfacelist(em, verts[1],v[end], v[left], v[right], NULL, NULL);
+ hold = addfacelist(verts[1],v[end], v[left], v[right], NULL, NULL);
hold->e1->f2 |= EDGENEW;
hold->e2->f2 |= EDGENEW;
hold->e3->f2 |= EDGENEW;
hold->e4->f2 |= EDGENEW;
hold->e4->f2 |= EDGEINNER;
- facecopy(em, efa, hold);
+ facecopy(efa, hold);
}
+
+}
-}
-
-// This function takes an example edge, the current point to create and
+// This function takes an example edge, the current point to create and
// the total # of points to create, then creates the point and return the
// editvert pointer to it.
-static EditVert *subdivideedgenum(EditMesh *em, EditEdge *edge, int curpoint, int totpoint, float smooth, float fractal, int beauty)
+static EditVert *subdivideedgenum(EditEdge *edge, int curpoint, int totpoint, float rad, int beauty)
{
EditVert *ev;
float percent;
-
+
if (beauty & (B_PERCENTSUBD) && totpoint == 1)
//percent=(float)(edge->tmp.l)/32768.0f;
percent= edge->tmp.fp;
else
percent= (float)curpoint/(float)(totpoint+1);
- ev= subdivide_edge_addvert(em, edge, smooth, fractal, beauty, percent);
+ ev= subdivide_edge_addvert(edge, rad, beauty, percent);
ev->f = edge->v1->f;
-
+
return ev;
}
-void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float fractal, int beauty, int numcuts, int corner_pattern, int seltype)
+void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype)
{
+ EditMesh *em = G.editMesh;
EditFace *ef;
EditEdge *eed, *cedge, *sort[4];
EditVert *eve, **templist;
struct GHash *gh;
float length[4], v1mat[3], v2mat[3], v3mat[3], v4mat[3];
int i, j, edgecount, touchcount, facetype,hold;
- ModifierData *md= obedit->modifiers.first;
- int ctrl= 0; // XXX
+ ModifierData *md= G.obedit->modifiers.first;
+
+ if(multires_test()) return;
//Set faces f1 to 0 cause we need it later
for(ef=em->faces.first;ef;ef = ef->next) ef->f1 = 0;
@@ -2675,22 +2441,22 @@ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float
for (; md; md=md->next) {
if ((md->type==eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
- MirrorModifierData *mmd = (MirrorModifierData*) md;
-
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
if(mmd->flag & MOD_MIR_CLIPPING) {
for (eve= em->verts.first; eve; eve= eve->next) {
eve->f2= 0;
switch(mmd->axis){
case 0:
- if (fabsf(eve->co[0]) < mmd->tolerance)
+ if (fabs(eve->co[0]) < mmd->tolerance)
eve->f2 |= 1;
break;
case 1:
- if (fabsf(eve->co[1]) < mmd->tolerance)
+ if (fabs(eve->co[1]) < mmd->tolerance)
eve->f2 |= 2;
break;
case 2:
- if (fabsf(eve->co[2]) < mmd->tolerance)
+ if (fabs(eve->co[2]) < mmd->tolerance)
eve->f2 |= 4;
break;
}
@@ -2698,23 +2464,23 @@ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float
}
}
}
-
+
//Flush vertex flags upward to the edges
for(eed = em->edges.first;eed;eed = eed->next) {
//if(eed->f & flag && eed->v1->f == eed->v2->f) {
- // eed->f |= eed->v1->f;
+ // eed->f |= eed->v1->f;
// }
- eed->f2 = 0;
+ eed->f2 = 0;
if(eed->f & flag) {
eed->f2 |= EDGEOLD;
}
}
-
+
// We store an array of verts for each edge that is subdivided,
// we put this array as a value in a ghash which is keyed by the EditEdge*
// Now for beauty subdivide deselect edges based on length
- if(beauty & B_BEAUTY) {
+ if(beauty & B_BEAUTY) {
for(ef = em->faces.first;ef;ef = ef->next) {
if(!ef->v4) {
continue;
@@ -2723,12 +2489,12 @@ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float
VECCOPY(v1mat, ef->v1->co);
VECCOPY(v2mat, ef->v2->co);
VECCOPY(v3mat, ef->v3->co);
- VECCOPY(v4mat, ef->v4->co);
- mul_mat3_m4_v3(obedit->obmat, v1mat);
- mul_mat3_m4_v3(obedit->obmat, v2mat);
- mul_mat3_m4_v3(obedit->obmat, v3mat);
- mul_mat3_m4_v3(obedit->obmat, v4mat);
-
+ VECCOPY(v4mat, ef->v4->co);
+ mul_mat3_m4_v3(G.obedit->obmat, v1mat);
+ mul_mat3_m4_v3(G.obedit->obmat, v2mat);
+ mul_mat3_m4_v3(G.obedit->obmat, v3mat);
+ mul_mat3_m4_v3(G.obedit->obmat, v4mat);
+
length[0] = len_v3v3(v1mat, v2mat);
length[1] = len_v3v3(v2mat, v3mat);
length[2] = len_v3v3(v3mat, v4mat);
@@ -2737,69 +2503,65 @@ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float
sort[1] = ef->e2;
sort[2] = ef->e3;
sort[3] = ef->e4;
-
-
+
+
// Beauty Short Edges
if(beauty & B_BEAUTY_SHORT) {
for(j=0;j<2;j++) {
hold = -1;
for(i=0;i<4;i++) {
if(length[i] < 0) {
- continue;
- } else if(hold == -1) {
- hold = i;
+ continue;
+ } else if(hold == -1) {
+ hold = i;
} else {
if(length[hold] < length[i]) {
- hold = i;
+ hold = i;
}
}
}
- if (hold > -1) {
- sort[hold]->f &= ~SELECT;
- sort[hold]->f2 |= EDGENEW;
- length[hold] = -1;
- }
- }
- }
-
+ sort[hold]->f &= ~SELECT;
+ sort[hold]->f2 |= EDGENEW;
+ length[hold] = -1;
+ }
+ }
+
// Beauty Long Edges
else {
- for(j=0;j<2;j++) {
+ for(j=0;j<2;j++) {
hold = -1;
for(i=0;i<4;i++) {
if(length[i] < 0) {
- continue;
- } else if(hold == -1) {
- hold = i;
+ continue;
+ } else if(hold == -1) {
+ hold = i;
} else {
if(length[hold] > length[i]) {
- hold = i;
+ hold = i;
}
}
}
- if (hold > -1) {
- sort[hold]->f &= ~SELECT;
- sort[hold]->f2 |= EDGENEW;
- length[hold] = -1;
- }
- }
- }
+ sort[hold]->f &= ~SELECT;
+ sort[hold]->f2 |= EDGENEW;
+ length[hold] = -1;
+ }
+ }
}
- }
+ }
}
- gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "subdivideedgenum gh");
+ gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
// If we are knifing, We only need the selected edges that were cut, so deselect if it was not cut
- if(beauty & B_KNIFE) {
- for(eed= em->edges.first;eed;eed=eed->next) {
+ if(beauty & B_KNIFE) {
+ for(eed= em->edges.first;eed;eed=eed->next) {
if( eed->tmp.fp == 0 ) {
EM_select_edge(eed,0);
}
}
- }
+ }
// So for each edge, if it is selected, we allocate an array of size cuts+2
- // so we can have a place for the v1, the new verts and v2
+ // so we can have a place for the v1, the new verts and v2
for(eed=em->edges.first;eed;eed = eed->next) {
if(eed->f & flag) {
templist = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"vertlist");
@@ -2807,22 +2569,22 @@ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float
for(i=0;i<numcuts;i++) {
// This function creates the new vert and returns it back
// to the array
- templist[i+1] = subdivideedgenum(em, eed, i+1, numcuts, smooth, fractal, beauty);
+ templist[i+1] = subdivideedgenum(eed, i+1, numcuts, rad, beauty);
//while we are here, we can copy edge info from the original edge
- cedge = addedgelist(em, templist[i],templist[i+1],eed);
+ cedge = addedgelist(templist[i],templist[i+1],eed);
// Also set the edge f2 to EDGENEW so that we can use this info later
cedge->f2 = EDGENEW;
}
templist[i+1] = eed->v2;
//Do the last edge too
- cedge = addedgelist(em, templist[i],templist[i+1],eed);
+ cedge = addedgelist(templist[i],templist[i+1],eed);
cedge->f2 = EDGENEW;
- // Now that the edge is subdivided, we can put its verts in the ghash
- BLI_ghash_insert(gh, eed, templist);
- }
+ // Now that the edge is subdivided, we can put its verts in the ghash
+ BLI_ghash_insert(gh, eed, templist);
+ }
}
-// DAG_id_tag_update(obedit->data, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
// Now for each face in the mesh we need to figure out How many edges were cut
// and which filling method to use for that face
for(ef = em->faces.first;ef;ef = ef->next) {
@@ -2834,7 +2596,7 @@ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float
if(ef->v4) {
facetype = 4;
if(ef->e4->f & flag) {edgecount++;}
- }
+ }
if(facetype == 4) {
switch(edgecount) {
case 0:
@@ -2846,19 +2608,19 @@ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float
if(ef->v3->f1) touchcount++;
if(ef->v4->f1) touchcount++;
if(touchcount == 2){
- if(ef->v1->f1 && ef->v3->f1){
+ if(ef->v1->f1 && ef->v3->f1){
ef->f1 = SELECT;
- fill_quad_doublevert(em, ef, 1, 3);
+ fill_quad_doublevert(ef, 1, 3);
}
else if(ef->v2->f1 && ef->v4->f1){
ef->f1 = SELECT;
- fill_quad_doublevert(em, ef, 2, 4);
+ fill_quad_doublevert(ef, 2, 4);
}
}
}
- break;
-
- case 1:
+ break;
+
+ case 1:
if(beauty & B_KNIFE && numcuts == 1){
/*Test for when knifing through an edge and one vert*/
touchcount = 0;
@@ -2866,87 +2628,87 @@ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float
if(ef->v2->f1) touchcount++;
if(ef->v3->f1) touchcount++;
if(ef->v4->f1) touchcount++;
-
+
if(touchcount == 1){
if( (ef->e1->f & flag && ( !ef->e1->v1->f1 && !ef->e1->v2->f1 )) ||
(ef->e2->f & flag && ( !ef->e2->v1->f1 && !ef->e2->v2->f1 )) ||
(ef->e3->f & flag && ( !ef->e3->v1->f1 && !ef->e3->v2->f1 )) ||
(ef->e4->f & flag && ( !ef->e4->v1->f1 && !ef->e4->v2->f1 )) ){
-
- ef->f1 = SELECT;
- fill_quad_singlevert(em, ef, gh);
+
+ ef->f1 = SELECT;
+ fill_quad_singlevert(ef, gh);
}
else{
ef->f1 = SELECT;
- fill_quad_single(em, ef, gh, numcuts, seltype);
+ fill_quad_single(ef, gh, numcuts, seltype);
}
}
- else{
- ef->f1 = SELECT;
- fill_quad_single(em, ef, gh, numcuts, seltype);
+ else{
+ ef->f1 = SELECT;
+ fill_quad_single(ef, gh, numcuts, seltype);
}
}
- else{
+ else{
ef->f1 = SELECT;
- fill_quad_single(em, ef, gh, numcuts, seltype);
+ fill_quad_single(ef, gh, numcuts, seltype);
}
- break;
+ break;
case 2: ef->f1 = SELECT;
// if there are 2, we check if edge 1 and 3 are either both on or off that way
// we can tell if the selected pair is Adjacent or Opposite of each other
- if((ef->e1->f & flag && ef->e3->f & flag) ||
+ if((ef->e1->f & flag && ef->e3->f & flag) ||
(ef->e2->f & flag && ef->e4->f & flag)) {
- fill_quad_double_op(em, ef, gh, numcuts);
+ fill_quad_double_op(ef, gh, numcuts);
}else{
- switch(corner_pattern) {
- case 0: fill_quad_double_adj_path(em, ef, gh, numcuts); break;
- case 1: fill_quad_double_adj_inner(em, ef, gh, numcuts); break;
- case 2: fill_quad_double_adj_fan(em, ef, gh, numcuts); break;
+ switch(G.scene->toolsettings->cornertype) {
+ case 0: fill_quad_double_adj_path(ef, gh, numcuts); break;
+ case 1: fill_quad_double_adj_inner(ef, gh, numcuts); break;
+ case 2: fill_quad_double_adj_fan(ef, gh, numcuts); break;
}
-
+
}
- break;
+ break;
case 3: ef->f1 = SELECT;
- fill_quad_triple(em, ef, gh, numcuts);
- break;
+ fill_quad_triple(ef, gh, numcuts);
+ break;
case 4: ef->f1 = SELECT;
- fill_quad_quadruple(em, ef, gh, numcuts, smooth, fractal, beauty);
- break;
+ fill_quad_quadruple(ef, gh, numcuts, rad, beauty);
+ break;
}
} else {
switch(edgecount) {
case 0: break;
case 1: ef->f1 = SELECT;
- fill_tri_single(em, ef, gh, numcuts, seltype);
- break;
+ fill_tri_single(ef, gh, numcuts, seltype);
+ break;
case 2: ef->f1 = SELECT;
- fill_tri_double(em, ef, gh, numcuts);
- break;
+ fill_tri_double(ef, gh, numcuts);
+ break;
case 3: ef->f1 = SELECT;
- fill_tri_triple(em, ef, gh, numcuts, smooth, fractal, beauty);
- break;
- }
- }
+ fill_tri_triple(ef, gh, numcuts, rad, beauty);
+ break;
+ }
+ }
}
-
+
// Delete Old Edges and Faces
for(eed = em->edges.first;eed;eed = eed->next) {
if(BLI_ghash_haskey(gh,eed)) {
- eed->f1 = SELECT;
+ eed->f1 = SELECT;
} else {
- eed->f1 = 0;
+ eed->f1 = 0;
}
- }
- free_tagged_edges_faces(em, em->edges.first, em->faces.first);
-
- if(seltype == SUBDIV_SELECT_ORIG && !ctrl) {
+ }
+ free_tagged_edges_faces(em->edges.first, em->faces.first);
+
+ if(seltype == SUBDIV_SELECT_ORIG && G.qual != LR_CTRLKEY) {
/* bugfix: vertex could get flagged as "not-selected"
// solution: clear flags before, not at the same time as setting SELECT flag -dg
*/
for(eed = em->edges.first;eed;eed = eed->next) {
if(!(eed->f2 & EDGENEW || eed->f2 & EDGEOLD)) {
eed->f &= !flag;
- EM_select_edge(eed,0);
+ EM_select_edge(eed,0);
}
}
for(eed = em->edges.first;eed;eed = eed->next) {
@@ -2955,18 +2717,18 @@ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float
EM_select_edge(eed,1);
}
}
- } else if ((seltype == SUBDIV_SELECT_INNER || seltype == SUBDIV_SELECT_INNER_SEL)|| ctrl) {
+ } else if ((seltype == SUBDIV_SELECT_INNER || seltype == SUBDIV_SELECT_INNER_SEL)|| G.qual == LR_CTRLKEY) {
for(eed = em->edges.first;eed;eed = eed->next) {
if(eed->f2 & EDGEINNER) {
eed->f |= flag;
- EM_select_edge(eed,1);
+ EM_select_edge(eed,1);
if(eed->v1->f & EDGEINNER) eed->v1->f |= SELECT;
if(eed->v2->f & EDGEINNER) eed->v2->f |= SELECT;
}else{
eed->f &= !flag;
- EM_select_edge(eed,0);
+ EM_select_edge(eed,0);
}
- }
+ }
} else if(seltype == SUBDIV_SELECT_LOOPCUT){
for(eed = em->edges.first;eed;eed = eed->next) {
if(eed->f2 & DOUBLEOPFILL){
@@ -2977,16 +2739,16 @@ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float
EM_select_edge(eed,0);
}
}
- }
- if(em->selectmode & SCE_SELECT_VERTEX) {
- for(eed = em->edges.first;eed;eed = eed->next) {
+ }
+ if(G.scene->selectmode & SCE_SELECT_VERTEX) {
+ for(eed = em->edges.first;eed;eed = eed->next) {
if(eed->f & SELECT) {
eed->v1->f |= SELECT;
eed->v2->f |= SELECT;
}
- }
+ }
}
-
+
//fix hide flags for edges. First pass, hide edges of hidden faces
for(ef=em->faces.first; ef; ef=ef->next){
if(ef->h){
@@ -3005,33 +2767,29 @@ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float
if(ef->e4) ef->e4->h &= ~1;
}
}
-
- //third pass: unhide edges that have both verts visible
- //(these were missed if all faces were hidden, bug #21976)
- for(eed=em->edges.first; eed; eed=eed->next){
- if(eed->v1->h == 0 && eed->v2->h == 0)
- eed->h &= ~1;
- }
-
- // Free the ghash and call MEM_freeN on all the value entries to return
+
+ // Free the ghash and call MEM_freeN on all the value entries to return
// that memory
- BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
-
- EM_selectmode_flush(em);
+ BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
+
+ EM_selectmode_flush();
for(ef=em->faces.first;ef;ef = ef->next) {
if(ef->e4) {
if( (ef->e1->f & SELECT && ef->e2->f & SELECT) &&
(ef->e3->f & SELECT && ef->e4->f & SELECT) ) {
- ef->f |= SELECT;
- }
+ ef->f |= SELECT;
+ }
} else {
if( (ef->e1->f & SELECT && ef->e2->f & SELECT) && ef->e3->f & SELECT) {
- ef->f |= SELECT;
+ ef->f |= SELECT;
}
}
}
-
- recalc_editnormals(em);
+
+ recalc_editnormals();
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
}
static int count_selected_edges(EditEdge *ed)
@@ -3069,15 +2827,15 @@ static int collect_quadedges(EVPTuple *efaa, EditEdge *eed, EditFace *efa)
i++;
}
else eed->tmp.p = NULL;
-
+
eed= eed->next;
}
-
-
+
+
/* find edges pointing to 2 faces by procedure:
-
+
- run through faces and their edges, increase
- face counter e->f1 for each face
+ face counter e->f1 for each face
*/
while(efa) {
@@ -3122,20 +2880,20 @@ static int collect_quadedges(EVPTuple *efaa, EditEdge *eed, EditFace *efa)
}
-/* returns vertices of two adjacent triangles forming a quad
+/* returns vertices of two adjacent triangles forming a quad
- can be righthand or lefthand
4-----3
|\ |
| \ 2 | <- efa1
- | \ |
- efa-> | 1 \ |
- | \|
+ | \ |
+ efa-> | 1 \ |
+ | \|
1-----2
*/
#define VTEST(face, num, other) \
- (face->v##num != other->v1 && face->v##num != other->v2 && face->v##num != other->v3)
+ (face->v##num != other->v1 && face->v##num != other->v2 && face->v##num != other->v3)
static void givequadverts(EditFace *efa, EditFace *efa1, EditVert **v1, EditVert **v2, EditVert **v3, EditVert **v4, int *vindex)
{
@@ -3157,24 +2915,24 @@ static void givequadverts(EditFace *efa, EditFace *efa1, EditVert **v1, EditVert
vindex[0]= 2;
vindex[1]= 0;
}
-
+
if VTEST(efa1, 1, efa) {
*v3= efa1->v1;
- *v4= (efa1->v2 == *v2)? efa1->v3: efa1->v2;
+ *v4= efa1->v2;
vindex[2]= 0;
- vindex[3]= (efa1->v2 == *v2)? 2: 1;
+ vindex[3]= 1;
}
else if VTEST(efa1, 2, efa) {
*v3= efa1->v2;
- *v4= (efa1->v3 == *v2)? efa1->v1: efa1->v3;
+ *v4= efa1->v3;
vindex[2]= 1;
- vindex[3]= (efa1->v3 == *v2)? 0: 2;
+ vindex[3]= 2;
}
else if VTEST(efa1, 3, efa) {
*v3= efa1->v3;
- *v4= (efa1->v1 == *v2)? efa1->v2: efa1->v1;
+ *v4= efa1->v1;
vindex[2]= 2;
- vindex[3]= (efa1->v1 == *v2)? 1: 0;
+ vindex[3]= 0;
}
else
*v3= *v4= NULL;
@@ -3190,8 +2948,9 @@ static void untag_edges(EditFace *f)
}
/** remove and free list of tagged edges and faces */
-static void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace *efa)
+static void free_tagged_edges_faces(EditEdge *eed, EditFace *efa)
{
+ EditMesh *em= G.editMesh;
EditEdge *nexted;
EditFace *nextvl;
@@ -3199,7 +2958,7 @@ static void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace *efa)
nextvl= efa->next;
if(efa->f1) {
BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
+ free_editface(efa);
}
else
/* avoid deleting edges that are still in use */
@@ -3210,109 +2969,282 @@ static void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace *efa)
while(eed) {
nexted= eed->next;
if(eed->f1) {
- remedge(em, eed);
- free_editedge(em, eed);
+ remedge(eed);
+ free_editedge(eed);
}
eed= nexted;
+ }
+}
+
+/* note; the EM_selectmode_set() calls here illustrate how badly constructed it all is... from before the
+ edge/face flags, with very mixed results.... */
+void beauty_fill(void)
+{
+ EditMesh *em = G.editMesh;
+ EditVert *v1, *v2, *v3, *v4;
+ EditEdge *eed, *nexted;
+ EditEdge dia1, dia2;
+ EditFace *efa, *w;
+ // void **efaar, **efaa;
+ EVPTuple *efaar;
+ EVPtr *efaa;
+ float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
+ int totedge, ok, notbeauty=8, onedone, vindex[4];
+
+ if(multires_test()) return;
+
+ /* - all selected edges with two faces
+ * - find the faces: store them in edges (using datablock)
+ * - per edge: - test convex
+ * - test edge: flip?
+ * - if true: remedge, addedge, all edges at the edge get new face pointers
+ */
+
+ EM_selectmode_set(); // makes sure in selectmode 'face' the edges of selected faces are selected too
+
+ totedge = count_selected_edges(em->edges.first);
+ if(totedge==0) return;
+
+ /* temp block with face pointers */
+ efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "beautyfill");
+
+ while (notbeauty) {
+ notbeauty--;
+
+ ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
+
+ /* there we go */
+ onedone= 0;
+
+ eed= em->edges.first;
+ while(eed) {
+ nexted= eed->next;
+
+ /* f2 is set in collect_quadedges() */
+ if(eed->f2==2 && eed->h==0) {
+
+ efaa = (EVPtr *) eed->tmp.p;
+
+ /* none of the faces should be treated before, nor be part of fgon */
+ ok= 1;
+ efa= efaa[0];
+ if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+ if(efa->fgonf) ok= 0;
+ efa= efaa[1];
+ if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+ if(efa->fgonf) ok= 0;
+
+ if(ok) {
+ /* test convex */
+ givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
+ if(v1 && v2 && v3 && v4) {
+ if( convex(v1->co, v2->co, v3->co, v4->co) ) {
+
+ /* test edges */
+ if( (v1) > (v3) ) {
+ dia1.v1= v3;
+ dia1.v2= v1;
+ }
+ else {
+ dia1.v1= v1;
+ dia1.v2= v3;
+ }
+
+ if( (v2) > (v4) ) {
+ dia2.v1= v4;
+ dia2.v2= v2;
+ }
+ else {
+ dia2.v1= v2;
+ dia2.v2= v4;
+ }
+
+ /* testing rule:
+ * the area divided by the total edge lengths
+ */
+
+ len1= len_v3v3(v1->co, v2->co);
+ len2= len_v3v3(v2->co, v3->co);
+ len3= len_v3v3(v3->co, v4->co);
+ len4= len_v3v3(v4->co, v1->co);
+ len5= len_v3v3(v1->co, v3->co);
+ len6= len_v3v3(v2->co, v4->co);
+
+ opp1= area_tri_v3(v1->co, v2->co, v3->co);
+ opp2= area_tri_v3(v1->co, v3->co, v4->co);
+
+ fac1= opp1/(len1+len2+len5) + opp2/(len3+len4+len5);
+
+ opp1= area_tri_v3(v2->co, v3->co, v4->co);
+ opp2= area_tri_v3(v2->co, v4->co, v1->co);
+
+ fac2= opp1/(len2+len3+len6) + opp2/(len4+len1+len6);
+
+ ok= 0;
+ if(fac1 > fac2) {
+ if(dia2.v1==eed->v1 && dia2.v2==eed->v2) {
+ eed->f1= 1;
+ efa= efaa[0];
+ efa->f1= 1;
+ efa= efaa[1];
+ efa->f1= 1;
+
+ w= EM_face_from_faces(efaa[0], efaa[1],
+ vindex[0], vindex[1], 4+vindex[2], -1);
+ w->f |= SELECT;
+
+
+ w= EM_face_from_faces(efaa[0], efaa[1],
+ vindex[0], 4+vindex[2], 4+vindex[3], -1);
+ w->f |= SELECT;
+
+ onedone= 1;
+ }
+ }
+ else if(fac1 < fac2) {
+ if(dia1.v1==eed->v1 && dia1.v2==eed->v2) {
+ eed->f1= 1;
+ efa= efaa[0];
+ efa->f1= 1;
+ efa= efaa[1];
+ efa->f1= 1;
+
+
+ w= EM_face_from_faces(efaa[0], efaa[1],
+ vindex[1], 4+vindex[2], 4+vindex[3], -1);
+ w->f |= SELECT;
+
+
+ w= EM_face_from_faces(efaa[0], efaa[1],
+ vindex[0], 4+vindex[1], 4+vindex[3], -1);
+ w->f |= SELECT;
+
+ onedone= 1;
+ }
+ }
+ }
+ }
+ }
+
+ }
+ eed= nexted;
+ }
+
+ free_tagged_edges_faces(em->edges.first, em->faces.first);
+
+ if(onedone==0) break;
+
+ EM_selectmode_set(); // new edges/faces were added
}
+
+ MEM_freeN(efaar);
+
+ EM_select_flush();
+
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+ BIF_undo_push("Beauty Fill");
}
/* ******************** BEGIN TRIANGLE TO QUAD ************************************* */
-static float measure_facepair(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, float limit)
-{
-
+static float measure_facepair(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, float limit){
+
/*gives a 'weight' to a pair of triangles that join an edge to decide how good a join they would make*/
/*Note: this is more complicated than it needs to be and should be cleaned up...*/
float measure = 0.0, noA1[3], noA2[3], noB1[3], noB2[3], normalADiff, normalBDiff,
edgeVec1[3], edgeVec2[3], edgeVec3[3], edgeVec4[3], diff,
minarea, maxarea, areaA, areaB;
-
+
/*First Test: Normal difference*/
normal_tri_v3( noA1,v1->co, v2->co, v3->co);
normal_tri_v3( noA2,v1->co, v3->co, v4->co);
-
+
if(noA1[0] == noA2[0] && noA1[1] == noA2[1] && noA1[2] == noA2[2]) normalADiff = 0.0;
- else normalADiff = RAD2DEGF(angle_v3v3(noA1, noA2));
+ else normalADiff = angle_v2v2(noA1, noA2);
//if(!normalADiff) normalADiff = 179;
normal_tri_v3( noB1,v2->co, v3->co, v4->co);
normal_tri_v3( noB2,v4->co, v1->co, v2->co);
-
+
if(noB1[0] == noB2[0] && noB1[1] == noB2[1] && noB1[2] == noB2[2]) normalBDiff = 0.0;
- else normalBDiff = RAD2DEGF(angle_v3v3(noB1, noB2));
+ else normalBDiff = angle_v2v2(noB1, noB2);
//if(!normalBDiff) normalBDiff = 179;
-
+
measure += (normalADiff/360) + (normalBDiff/360);
if(measure > limit) return measure;
-
+
/*Second test: Colinearity*/
sub_v3_v3v3(edgeVec1, v1->co, v2->co);
sub_v3_v3v3(edgeVec2, v2->co, v3->co);
sub_v3_v3v3(edgeVec3, v3->co, v4->co);
sub_v3_v3v3(edgeVec4, v4->co, v1->co);
-
+
diff = 0.0;
-
+
diff = (
- fabsf(RAD2DEGF(angle_v3v3(edgeVec1, edgeVec2)) - 90) +
- fabsf(RAD2DEGF(angle_v3v3(edgeVec2, edgeVec3)) - 90) +
- fabsf(RAD2DEGF(angle_v3v3(edgeVec3, edgeVec4)) - 90) +
- fabsf(RAD2DEGF(angle_v3v3(edgeVec4, edgeVec1)) - 90)) / 360;
+ fabs(angle_v2v2(edgeVec1, edgeVec2) - 90) +
+ fabs(angle_v2v2(edgeVec2, edgeVec3) - 90) +
+ fabs(angle_v2v2(edgeVec3, edgeVec4) - 90) +
+ fabs(angle_v2v2(edgeVec4, edgeVec1) - 90)) / 360;
if(!diff) return 0.0;
-
+
measure += diff;
if(measure > limit) return measure;
/*Third test: Concavity*/
areaA = area_tri_v3(v1->co, v2->co, v3->co) + area_tri_v3(v1->co, v3->co, v4->co);
areaB = area_tri_v3(v2->co, v3->co, v4->co) + area_tri_v3(v4->co, v1->co, v2->co);
-
+
if(areaA <= areaB) minarea = areaA;
else minarea = areaB;
-
+
if(areaA >= areaB) maxarea = areaA;
else maxarea = areaB;
-
+
if(!maxarea) measure += 1;
else measure += (1 - (minarea / maxarea));
return measure;
}
-#define T2QUV_LIMIT 0.005f
+#define T2QUV_LIMIT 0.005
#define T2QCOL_LIMIT 3
-static int compareFaceAttribs(EditMesh *em, EditFace *f1, EditFace *f2, EditEdge *eed)
+static int compareFaceAttribs(EditFace *f1, EditFace *f2, EditEdge *eed)
{
- /*Test to see if the per-face attributes for the joining edge match within limit*/
+ /*Test to see if the per-face attributes for the joining edge match within limit*/
MTFace *tf1, *tf2;
unsigned int *col1, *col2;
- short i,attrok=0, flag = 0, /* XXX scene->toolsettings->editbutflag,*/ fe1[2], fe2[2];
-
- tf1 = CustomData_em_get(&em->fdata, f1->data, CD_MTFACE);
- tf2 = CustomData_em_get(&em->fdata, f2->data, CD_MTFACE);
-
- col1 = CustomData_em_get(&em->fdata, f1->data, CD_MCOL);
- col2 = CustomData_em_get(&em->fdata, f2->data, CD_MCOL);
+ short i,attrok=0, flag = G.scene->toolsettings->editbutflag, fe1[2], fe2[2];
+
+ tf1 = CustomData_em_get(&G.editMesh->fdata, f1->data, CD_MTFACE);
+ tf2 = CustomData_em_get(&G.editMesh->fdata, f2->data, CD_MTFACE);
+ col1 = CustomData_em_get(&G.editMesh->fdata, f1->data, CD_MCOL);
+ col2 = CustomData_em_get(&G.editMesh->fdata, f2->data, CD_MCOL);
+
/*store indices for faceedges*/
f1->v1->f1 = 0;
f1->v2->f1 = 1;
f1->v3->f1 = 2;
-
+
fe1[0] = eed->v1->f1;
fe1[1] = eed->v2->f1;
-
+
f2->v1->f1 = 0;
f2->v2->f1 = 1;
f2->v3->f1 = 2;
-
+
fe2[0] = eed->v1->f1;
fe2[1] = eed->v2->f1;
-
+
/*compare faceedges for each face attribute. Additional per face attributes can be added later*/
/*do UVs*/
if(flag & B_JOINTRIA_UV){
-
+
if(tf1 == NULL || tf2 == NULL) attrok |= B_JOINTRIA_UV;
else if(tf1->tpage != tf2->tpage); /*do nothing*/
else{
@@ -3322,7 +3254,7 @@ static int compareFaceAttribs(EditMesh *em, EditFace *f1, EditFace *f2, EditEdge
}
}
}
-
+
/*do VCOLs*/
if(flag & B_JOINTRIA_VCOL){
if(!col1 || !col2) attrok |= B_JOINTRIA_VCOL;
@@ -3331,7 +3263,7 @@ static int compareFaceAttribs(EditMesh *em, EditFace *f1, EditFace *f2, EditEdge
for(i = 0; i < 2; i++){
f1vcol = (char *)&(col1[fe1[i]]);
f2vcol = (char *)&(col2[fe2[i]]);
-
+
/*compare f1vcol with f2vcol*/
if( f1vcol[1] + T2QCOL_LIMIT > f2vcol[1] && f1vcol[1] - T2QCOL_LIMIT < f2vcol[1] &&
f1vcol[2] + T2QCOL_LIMIT > f2vcol[2] && f1vcol[2] - T2QCOL_LIMIT < f2vcol[2] &&
@@ -3339,18 +3271,18 @@ static int compareFaceAttribs(EditMesh *em, EditFace *f1, EditFace *f2, EditEdge
}
}
}
-
+
if( ((attrok & B_JOINTRIA_UV) == (flag & B_JOINTRIA_UV)) && ((attrok & B_JOINTRIA_VCOL) == (flag & B_JOINTRIA_VCOL)) ) return 1;
return 0;
-}
-
+}
+
static int fplcmp(const void *v1, const void *v2)
{
const EditEdge *e1= *((EditEdge**)v1), *e2=*((EditEdge**)v2);
-
+
if( e1->crease > e2->crease) return 1;
else if( e1->crease < e2->crease) return -1;
-
+
return 0;
}
@@ -3358,8 +3290,9 @@ static int fplcmp(const void *v1, const void *v2)
#define T2QDELETE 1
#define T2QCOMPLEX 2
#define T2QJOIN 4
-void join_triangles(EditMesh *em)
+void join_triangles(void)
{
+ EditMesh *em=G.editMesh;
EditVert *v1, *v2, *v3, *v4, *eve;
EditEdge *eed, **edsortblock = NULL, **edb = NULL;
EditFace *efa;
@@ -3367,23 +3300,26 @@ void join_triangles(EditMesh *em)
EVPtr *efaa = NULL;
float *creases = NULL;
float measure; /*Used to set tolerance*/
- float limit = 0.8f; // XXX scene->toolsettings->jointrilimit;
+ float limit = G.scene->toolsettings->jointrilimit;
int i, ok, totedge=0, totseledge=0, complexedges, vindex[4];
+
+ /*test for multi-resolution data*/
+ if(multires_test()) return;
/*if we take a long time on very dense meshes we want waitcursor to display*/
waitcursor(1);
-
+
totseledge = count_selected_edges(em->edges.first);
if(totseledge==0) return;
-
+
/*abusing crease value to store weights for edge pairs. Nasty*/
for(eed=em->edges.first; eed; eed=eed->next) totedge++;
- if(totedge) creases = MEM_callocN(sizeof(float) * totedge, "Join Triangles Crease Array");
+ if(totedge) creases = MEM_callocN(sizeof(float) * totedge, "Join Triangles Crease Array");
for(eed=em->edges.first, i = 0; eed; eed=eed->next, i++){
- creases[i] = eed->crease;
+ creases[i] = eed->crease;
eed->crease = 0.0;
}
-
+
/*clear temp flags*/
for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = eve->f2 = 0;
for(eed=em->edges.first; eed; eed=eed->next) eed->f2 = eed->f1 = 0;
@@ -3393,11 +3329,11 @@ void join_triangles(EditMesh *em)
efaar= (EVPTuple *) MEM_callocN(totseledge * sizeof(EVPTuple), "Tri2Quad");
ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
complexedges = 0;
-
+
if(ok){
-
-
- /*clear tmp.l flag and store number of faces that are selected and coincident to current face here.*/
+
+
+ /*clear tmp.l flag and store number of faces that are selected and coincident to current face here.*/
for(eed=em->edges.first; eed; eed=eed->next){
/* eed->f2 is 2 only if this edge is part of exactly two
triangles, and both are selected, and it has EVPTuple assigned */
@@ -3407,7 +3343,7 @@ void join_triangles(EditMesh *em)
efaa[1]->tmp.l++;
}
}
-
+
for(eed=em->edges.first; eed; eed=eed->next){
if(eed->f2 == 2){
efaa= (EVPtr *) eed->tmp.p;
@@ -3416,46 +3352,48 @@ void join_triangles(EditMesh *em)
if(v1 && v2 && v3 && v4){
/*test if simple island first. This mimics 2.42 behaviour and the tests are less restrictive.*/
if(efaa[0]->tmp.l == 1 && efaa[1]->tmp.l == 1){
- eed->f1 |= T2QJOIN;
- efaa[0]->f1 = 1; //mark for join
- efaa[1]->f1 = 1; //mark for join
+ if( convex(v1->co, v2->co, v3->co, v4->co) ){
+ eed->f1 |= T2QJOIN;
+ efaa[0]->f1 = 1; //mark for join
+ efaa[1]->f1 = 1; //mark for join
+ }
}
- else{
-
+ else{
+
/* The face pair is part of a 'complex' island, so the rules for dealing with it are more involved.
Depending on what options the user has chosen, this face pair can be 'thrown out' based upon the following criteria:
-
+
1: the two faces do not share the same material
2: the edge joining the two faces is marked as sharp.
3: the two faces UV's do not make a good match
4: the two faces Vertex colors do not make a good match
-
+
If the face pair passes all the applicable tests, it is then given a 'weight' with the measure_facepair() function.
This measures things like concavity, colinearity ect. If this weight is below the threshold set by the user
the edge joining them is marked as being 'complex' and will be compared against other possible pairs which contain one of the
same faces in the current pair later.
-
+
This technique is based upon an algorithm that Campbell Barton developed for his Tri2Quad script that was previously part of
the python scripts bundled with Blender releases.
*/
-
-// XXX if(scene->toolsettings->editbutflag & B_JOINTRIA_SHARP && eed->sharp); /*do nothing*/
-// else if(scene->toolsettings->editbutflag & B_JOINTRIA_MAT && efaa[0]->mat_nr != efaa[1]->mat_nr); /*do nothing*/
-// else if(((scene->toolsettings->editbutflag & B_JOINTRIA_UV) || (scene->toolsettings->editbutflag & B_JOINTRIA_VCOL)) &&
- compareFaceAttribs(em, efaa[0], efaa[1], eed); // XXX == 0); /*do nothing*/
-// else{
+
+ if(G.scene->toolsettings->editbutflag & B_JOINTRIA_SHARP && eed->sharp); /*do nothing*/
+ else if(G.scene->toolsettings->editbutflag & B_JOINTRIA_MAT && efaa[0]->mat_nr != efaa[1]->mat_nr); /*do nothing*/
+ else if(((G.scene->toolsettings->editbutflag & B_JOINTRIA_UV) || (G.scene->toolsettings->editbutflag & B_JOINTRIA_VCOL)) &&
+ compareFaceAttribs(efaa[0], efaa[1], eed) == 0); /*do nothing*/
+ else{
measure = measure_facepair(v1, v2, v3, v4, limit);
if(measure < limit){
complexedges++;
eed->f1 |= T2QCOMPLEX;
eed->crease = measure; /*we dont mark edges for join yet*/
}
-// }
+ }
}
}
}
}
-
+
/*Quicksort the complex edges according to their weighting*/
if(complexedges){
edsortblock = edb = MEM_callocN(sizeof(EditEdge*) * complexedges, "Face Pairs quicksort Array");
@@ -3467,7 +3405,7 @@ void join_triangles(EditMesh *em)
}
qsort(edsortblock, complexedges, sizeof(EditEdge*), fplcmp);
/*now go through and mark the edges who get the highest weighting*/
- for(edb=edsortblock, i=0; i < complexedges; edb++, i++){
+ for(edb=edsortblock, i=0; i < complexedges; edb++, i++){
efaa = (EVPtr *)((*edb)->tmp.p); /*suspect!*/
if( !efaa[0]->f1 && !efaa[1]->f1){
efaa[0]->f1 = 1; //mark for join
@@ -3476,18 +3414,18 @@ void join_triangles(EditMesh *em)
}
}
}
-
- /*finally go through all edges marked for join (simple and complex) and create new faces*/
+
+ /*finally go through all edges marked for join (simple and complex) and create new faces*/
for(eed=em->edges.first; eed; eed=eed->next){
if(eed->f1 & T2QJOIN){
efaa= (EVPtr *)eed->tmp.p;
v1 = v2 = v3 = v4 = NULL;
givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
- if((v1 && v2 && v3 && v4) && (exist_face(em, v1, v2, v3, v4)==0)){ /*exist_face is very slow! Needs to be addressed.*/
+ if((v1 && v2 && v3 && v4) && (exist_face(v1, v2, v3, v4)==0)){ /*exist_face is very slow! Needs to be adressed.*/
/*flag for delete*/
eed->f1 |= T2QDELETE;
/*create new quad and select*/
- efa = EM_face_from_faces(em, efaa[0], efaa[1], vindex[0], vindex[1], 4+vindex[2], 4+vindex[3]);
+ efa = EM_face_from_faces(efaa[0], efaa[1], vindex[0], vindex[1], 4+vindex[2], 4+vindex[3]);
EM_select_face(efa,1);
}
else{
@@ -3497,30 +3435,39 @@ void join_triangles(EditMesh *em)
}
}
}
-
+
/*free data and cleanup*/
if(creases){
- for(eed=em->edges.first, i = 0; eed; eed=eed->next, i++) eed->crease = creases[i];
+ for(eed=em->edges.first, i = 0; eed; eed=eed->next, i++) eed->crease = creases[i];
MEM_freeN(creases);
}
for(eed=em->edges.first; eed; eed=eed->next){
if(eed->f1 & T2QDELETE) eed->f1 = 1;
else eed->f1 = 0;
}
- free_tagged_edges_faces(em, em->edges.first, em->faces.first);
+ free_tagged_edges_faces(em->edges.first, em->faces.first);
if(efaar) MEM_freeN(efaar);
if(edsortblock) MEM_freeN(edsortblock);
-
- EM_selectmode_flush(em);
-
+
+ EM_selectmode_flush();
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ #ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+ #endif
+ waitcursor(0);
+ BIF_undo_push("Convert Triangles to Quads");
}
/* ******************** END TRIANGLE TO QUAD ************************************* */
#define FACE_MARKCLEAR(f) (f->f1 = 1)
-/* quick hack, basically a copy of beautify_fill */
-static void edge_flip(EditMesh *em)
+/* quick hack, basically a copy of beauty_fill */
+void edge_flip(void)
{
+ EditMesh *em = G.editMesh;
EditVert *v1, *v2, *v3, *v4;
EditEdge *eed, *nexted;
EditFace *efa, *w;
@@ -3528,7 +3475,7 @@ static void edge_flip(EditMesh *em)
EVPTuple *efaar;
EVPtr *efaa;
int totedge, ok, vindex[4];
-
+
/* - all selected edges with two faces
* - find the faces: store them in edges (using datablock)
* - per edge: - test convex
@@ -3536,7 +3483,7 @@ static void edge_flip(EditMesh *em)
- if true: remedge, addedge, all edges at the edge get new face pointers
*/
- EM_selectmode_flush(em); // makes sure in selectmode 'face' the edges of selected faces are selected too
+ EM_selectmode_flush(); // makes sure in selectmode 'face' the edges of selected faces are selected too
totedge = count_selected_edges(em->edges.first);
if(totedge==0) return;
@@ -3545,15 +3492,15 @@ static void edge_flip(EditMesh *em)
efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "edgeflip");
ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
-
+
eed= em->edges.first;
while(eed) {
nexted= eed->next;
-
+
if(eed->f2==2) { /* points to 2 faces */
-
+
efaa= (EVPtr *) eed->tmp.p;
-
+
/* don't do it if flagged */
ok= 1;
@@ -3561,7 +3508,7 @@ static void edge_flip(EditMesh *em)
if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
efa= efaa[1];
if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
-
+
if(ok) {
/* test convex */
givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
@@ -3570,23 +3517,23 @@ static void edge_flip(EditMesh *em)
4-----3 4-----3
|\ | | /|
| \ 1 | | 1 / |
- | \ | -> | / |
- | 0 \ | | / 0 |
+ | \ | -> | / |
+ | 0 \ | | / 0 |
| \| |/ |
1-----2 1-----2
*/
/* make new faces */
if (v1 && v2 && v3) {
if( convex(v1->co, v2->co, v3->co, v4->co) ) {
- if(exist_face(em, v1, v2, v3, v4)==0) {
- /* outch this may break seams */
- w= EM_face_from_faces(em, efaa[0], efaa[1], vindex[0],
+ if(exist_face(v1, v2, v3, v4)==0) {
+ /* outch this may break seams */
+ w= EM_face_from_faces(efaa[0], efaa[1], vindex[0],
vindex[1], 4+vindex[2], -1);
EM_select_face(w, 1);
/* outch this may break seams */
- w= EM_face_from_faces(em, efaa[0], efaa[1], vindex[0],
+ w= EM_face_from_faces(efaa[0], efaa[1], vindex[0],
4+vindex[2], 4+vindex[3], -1);
EM_select_face(w, 1);
@@ -3594,8 +3541,8 @@ static void edge_flip(EditMesh *em)
/* tag as to-be-removed */
FACE_MARKCLEAR(efaa[1]);
FACE_MARKCLEAR(efaa[0]);
- eed->f1 = 1;
-
+ eed->f1 = 1;
+
} /* endif test convex */
}
}
@@ -3604,35 +3551,29 @@ static void edge_flip(EditMesh *em)
}
/* clear tagged edges and faces: */
- free_tagged_edges_faces(em, em->edges.first, em->faces.first);
-
+ free_tagged_edges_faces(em->edges.first, em->faces.first);
+
MEM_freeN(efaar);
+
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+ BIF_undo_push("Flip Triangle Edges");
+
}
-#define DIRECTION_CW 1
-#define DIRECTION_CCW 2
-
-static const EnumPropertyItem direction_items[]= {
- {DIRECTION_CW, "CW", 0, "Clockwise", ""},
- {DIRECTION_CCW, "CCW", 0, "Counter Clockwise", ""},
- {0, NULL, 0, NULL, NULL}};
-
-#define AXIS_X 1
-#define AXIS_Y 2
-
-static const EnumPropertyItem axis_items_xy[]= {
- {AXIS_X, "X", 0, "X", ""},
- {AXIS_Y, "Y", 0, "Y", ""},
- {0, NULL, 0, NULL, NULL}};
-
-static void edge_rotate(EditMesh *em, wmOperator *op, EditEdge *eed, int dir)
+static void edge_rotate(EditEdge *eed,int dir)
{
+ EditMesh *em = G.editMesh;
EditVert **verts[2];
- EditFace *face[2], *efa /* , *newFace[2] */ /* UNUSED */;
+ EditFace *face[2], *efa, *newFace[2];
EditEdge **edges[2], **hiddenedges, *srchedge;
int facecount, p1, p2, p3, p4, fac1, fac2, i, j;
int numhidden, numshared, p[2][4];
-
+
/* check to make sure that the edge is only part of 2 faces */
facecount = 0;
for(efa = em->faces.first;efa;efa = efa->next) {
@@ -3647,17 +3588,17 @@ static void edge_rotate(EditMesh *em, wmOperator *op, EditEdge *eed, int dir)
}
}
}
-
+
if(facecount < 2)
return;
/* how many edges does each face have */
- if(face[0]->e4) fac1= 4;
+ if(face[0]->e4) fac1= 4;
else fac1= 3;
if(face[1]->e4) fac2= 4;
else fac2= 3;
-
+
/* make a handy array for verts and edges */
verts[0]= &face[0]->v1;
edges[0]= &face[0]->e1;
@@ -3673,7 +3614,11 @@ static void edge_rotate(EditMesh *em, wmOperator *op, EditEdge *eed, int dir)
if(numshared > 1)
return;
-
+
+ /* coplaner faces only please */
+ if(dot_v3v3(face[0]->n,face[1]->n) <= 0.000001)
+ return;
+
/* we want to construct an array of vertex indicis in both faces, starting at
the last vertex of the edge being rotated.
- first we find the two vertices that lie on the rotating edge
@@ -3687,12 +3632,12 @@ static void edge_rotate(EditMesh *em, wmOperator *op, EditEdge *eed, int dir)
if(eed->v1 == verts[1][i]) p3 = i;
if(eed->v2 == verts[1][i]) p4 = i;
}
-
+
if((p1+1)%fac1 == p2)
SWAP(int, p1, p2);
if((p3+1)%fac2 == p4)
SWAP(int, p3, p4);
-
+
for (i = 0; i < 4; i++) {
p[0][i]= (p1 + i)%fac1;
p[1][i]= (p3 + i)%fac2;
@@ -3706,11 +3651,11 @@ static void edge_rotate(EditMesh *em, wmOperator *op, EditEdge *eed, int dir)
hiddenedges = MEM_mallocN(sizeof(EditVert*)*numhidden+1, "RotateEdgeHiddenVerts");
if(!hiddenedges) {
- BKE_report(op->reports, RPT_ERROR, "Memory allocation failed");
- return;
- }
+ error("Malloc Was not happy!");
+ return;
+ }
- numhidden = 0;
+ numhidden = 0;
for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next)
if(srchedge->h && (srchedge->v1->f & SELECT || srchedge->v2->f & SELECT))
hiddenedges[numhidden++] = srchedge;
@@ -3719,54 +3664,54 @@ static void edge_rotate(EditMesh *em, wmOperator *op, EditEdge *eed, int dir)
if(fac1 == 3 && fac2 == 3) {
/* no need of reverse setup */
- /* newFace[0]= */ /* UNUSED */EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
- /* newFace[1]= */ /* UNUSED */EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
+ newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
}
else if(fac1 == 4 && fac2 == 3) {
- if(dir == DIRECTION_CCW) {
- /* newFace[0]= */ /* UNUSED */EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
- /* newFace[1]= */ /* UNUSED */EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
- } else if (dir == DIRECTION_CW) {
- /* newFace[0]= */ /* UNUSED */EM_face_from_faces(em, face[0], face[1], p[0][2], 4+p[1][1], p[0][0], p[0][1]);
- /* newFace[1]= */ /* UNUSED */EM_face_from_faces(em, face[1], face[0], 4+p[0][2], p[1][0], p[1][1], -1);
-
+ if(dir == 1) {
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
+ newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
+ } else if (dir == 2) {
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][2], 4+p[1][1], p[0][0], p[0][1]);
+ newFace[1]= EM_face_from_faces(face[1], face[0], 4+p[0][2], p[1][0], p[1][1], -1);
+
verts[0][p[0][2]]->f |= SELECT;
- verts[1][p[1][1]]->f |= SELECT;
+ verts[1][p[1][1]]->f |= SELECT;
}
}
else if(fac1 == 3 && fac2 == 4) {
- if(dir == DIRECTION_CCW) {
- /* newFace[0]= */ /* UNUSED */EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
- /* newFace[1]= */ /* UNUSED */EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
- } else if (dir == DIRECTION_CW) {
- /* newFace[0]= */ /* UNUSED */EM_face_from_faces(em, face[0], face[1], p[0][0], p[0][1], 4+p[1][2], -1);
- /* newFace[1]= */ /* UNUSED */EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], 4+p[0][2]);
-
+ if(dir == 1) {
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
+ newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
+ } else if (dir == 2) {
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][0], p[0][1], 4+p[1][2], -1);
+ newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], 4+p[0][2]);
+
verts[0][p[0][1]]->f |= SELECT;
- verts[1][p[1][2]]->f |= SELECT;
+ verts[1][p[1][2]]->f |= SELECT;
}
-
+
}
else if(fac1 == 4 && fac2 == 4) {
- if(dir == DIRECTION_CCW) {
- /* newFace[0]= */ /* UNUSED */EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
- /* newFace[1]= */ /* UNUSED */EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
- } else if (dir == DIRECTION_CW) {
- /* newFace[0]= */ /* UNUSED */EM_face_from_faces(em, face[0], face[1], p[0][2], p[0][3], 4+p[1][1], 4+p[1][2]);
- /* newFace[1]= */ /* UNUSED */EM_face_from_faces(em, face[1], face[0], p[1][2], p[1][3], 4+p[0][1], 4+p[0][2]);
-
+ if(dir == 1) {
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
+ newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
+ } else if (dir == 2) {
+ newFace[0]= EM_face_from_faces(face[0], face[1], p[0][2], p[0][3], 4+p[1][1], 4+p[1][2]);
+ newFace[1]= EM_face_from_faces(face[1], face[0], p[1][2], p[1][3], 4+p[0][1], 4+p[0][2]);
+
verts[0][p[0][2]]->f |= SELECT;
- verts[1][p[1][2]]->f |= SELECT;
+ verts[1][p[1][2]]->f |= SELECT;
}
- }
+ }
else
return; /* This should never happen */
- if(dir == DIRECTION_CCW || (fac1 == 3 && fac2 == 3)) {
+ if(dir == 1 || (fac1 == 3 && fac2 == 3)) {
verts[0][p[0][1]]->f |= SELECT;
verts[1][p[1][1]]->f |= SELECT;
}
-
+
/* copy old edge's flags to new center edge*/
for(srchedge=em->edges.first;srchedge;srchedge=srchedge->next) {
if((srchedge->v1->f & SELECT) && (srchedge->v2->f & SELECT)) {
@@ -3778,47 +3723,44 @@ static void edge_rotate(EditMesh *em, wmOperator *op, EditEdge *eed, int dir)
srchedge->bweight = eed->bweight;
}
}
-
+
/* resetting hidden flag */
for(numhidden--; numhidden>=0; numhidden--)
hiddenedges[numhidden]->h= 1;
-
+
/* check for orhphan edges */
for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next)
- srchedge->f1= -1;
-
+ srchedge->f1= -1;
+
/* cleanup */
MEM_freeN(hiddenedges);
-
+
/* get rid of the old edge and faces*/
- remedge(em, eed);
- free_editedge(em, eed);
+ remedge(eed);
+ free_editedge(eed);
BLI_remlink(&em->faces, face[0]);
- free_editface(em, face[0]);
+ free_editface(face[0]);
BLI_remlink(&em->faces, face[1]);
- free_editface(em, face[1]);
+ free_editface(face[1]);
}
/* only accepts 1 selected edge, or 2 selected faces */
-static int edge_rotate_selected(bContext *C, wmOperator *op)
+void edge_rotate_selected(int dir)
{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
EditEdge *eed;
EditFace *efa;
- int dir = RNA_enum_get(op->ptr, "direction"); // dir == 2 when clockwise and ==1 for counter CW.
short edgeCount = 0;
-
+
/*clear new flag for new edges, count selected edges */
- for(eed= em->edges.first; eed; eed= eed->next) {
+ for(eed= G.editMesh->edges.first; eed; eed= eed->next) {
eed->f1= 0;
eed->f2 &= ~2;
- if(eed->f & SELECT) edgeCount++;
+ if(eed->f & SELECT) edgeCount++;
}
-
+
if(edgeCount>1) {
/* more selected edges, check faces */
- for(efa= em->faces.first; efa; efa= efa->next) {
+ for(efa= G.editMesh->faces.first; efa; efa= efa->next) {
if(efa->f & SELECT) {
efa->e1->f1++;
efa->e2->f1++;
@@ -3827,81 +3769,734 @@ static int edge_rotate_selected(bContext *C, wmOperator *op)
}
}
edgeCount= 0;
- for(eed= em->edges.first; eed; eed= eed->next) {
+ for(eed= G.editMesh->edges.first; eed; eed= eed->next) {
if(eed->f1==2) edgeCount++;
}
if(edgeCount==1) {
- for(eed= em->edges.first; eed; eed= eed->next) {
+ for(eed= G.editMesh->edges.first; eed; eed= eed->next) {
if(eed->f1==2) {
- edge_rotate(em, op, eed,dir);
+ edge_rotate(eed,dir);
break;
}
}
}
- else
- {
- BKE_report(op->reports, RPT_WARNING, "Select one edge or two adjacent faces");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
+ else error("Select one edge or two adjacent faces");
}
else if(edgeCount==1) {
- for(eed= em->edges.first; eed; eed= eed->next) {
+ for(eed= G.editMesh->edges.first; eed; eed= eed->next) {
if(eed->f & SELECT) {
EM_select_edge(eed, 0);
- edge_rotate(em, op, eed,dir);
+ edge_rotate(eed,dir);
break;
}
}
}
- else {
- BKE_report(op->reports, RPT_WARNING, "Select one edge or two adjacent faces");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
+ else error("Select one edge or two adjacent faces");
+
/* flush selected vertices (again) to edges/faces */
- EM_select_flush(em);
+ EM_select_flush();
+
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode)
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+
+ BIF_undo_push("Rotate Edge");
+}
+
+/******************* BEVEL CODE STARTS HERE ********************/
+
+static void bevel_displace_vec(float *midvec, float *v1, float *v2, float *v3, float d, float no[3])
+{
+ float a[3], c[3], n_a[3], n_c[3], mid[3], ac, ac2, fac;
- BKE_mesh_end_editmesh(obedit->data, em);
+ sub_v3_v3v3(a, v1, v2);
+ sub_v3_v3v3(c, v3, v2);
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+ cross_v3_v3v3(n_a, a, no);
+ normalize_v3(n_a);
+ cross_v3_v3v3(n_c, no, c);
+ normalize_v3(n_c);
- return OPERATOR_FINISHED;
+ normalize_v3(a);
+ normalize_v3(c);
+ ac = dot_v3v3(a, c);
+
+ if (ac == 1 || ac == -1) {
+ midvec[0] = midvec[1] = midvec[2] = 0;
+ return;
+ }
+ ac2 = ac * ac;
+ fac = (float)sqrt((ac2 + 2*ac + 1)/(1 - ac2) + 1);
+ add_v3_v3v3(mid, n_c, n_a);
+ normalize_v3(mid);
+ mul_v3_fl(mid, d * fac);
+ add_v3_v3v3(mid, mid, v2);
+ copy_v3_v3(midvec, mid);
}
-void MESH_OT_edge_rotate(wmOperatorType *ot)
+/* Finds the new point using the sinus law to extrapolate a triangle
+ Lots of sqrts which would not be good for a real time algo
+ Using the mid point of the extrapolation of both sides
+ Useless for coplanar quads, but that doesn't happen too often */
+static void fix_bevel_wrap(float *midvec, float *v1, float *v2, float *v3, float *v4, float d, float no[3])
{
- /* identifiers */
- ot->name= "Rotate Selected Edge";
- ot->description= "Rotate selected edge or adjoining faces";
- ot->idname= "MESH_OT_edge_rotate";
+ float a[3], b[3], c[3], l_a, l_b, l_c, s_a, s_b, s_c, Pos1[3], Pos2[3], Dir[3];
+
+ sub_v3_v3v3(a, v3, v2);
+ l_a = normalize_v3(a);
+ sub_v3_v3v3(b, v4, v3);
+ normalize_v3(b);
+ sub_v3_v3v3(c, v1, v2);
+ normalize_v3(c);
+
+ s_b = dot_v3v3(a, c);
+ s_b = (float)sqrt(1 - (s_b * s_b));
+ s_a = dot_v3v3(b, c);
+ s_a = (float)sqrt(1 - (s_a * s_a));
+ mul_v3_fl(a, -1);
+ s_c = dot_v3v3(a, b);
+ s_c = (float)sqrt(1 - (s_c * s_c));
+
+ l_b = s_b * l_a / s_a;
+ l_c = s_c * l_a / s_a;
- /* api callbacks */
- ot->exec= edge_rotate_selected;
- ot->poll= ED_operator_editmesh;
+ mul_v3_fl(b, l_b);
+ mul_v3_fl(c, l_c);
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+ add_v3_v3v3(Pos1, v2, c);
+ add_v3_v3v3(Pos2, v3, b);
+
+ add_v3_v3v3(Dir, Pos1, Pos2);
+ mul_v3_fl(Dir, 0.5);
+
+ bevel_displace_vec(midvec, v3, Dir, v2, d, no);
- /* props */
- RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate the edge around");
}
-/******************* BEVEL CODE STARTS HERE ********************/
+static char detect_wrap(float *o_v1, float *o_v2, float *v1, float *v2, float *no)
+{
+ float o_a[3], a[3], o_c[3], c[3];
+
+ sub_v3_v3v3(o_a, o_v1, o_v2);
+ sub_v3_v3v3(a, v1, v2);
+
+ cross_v3_v3v3(o_c, o_a, no);
+ cross_v3_v3v3(c, a, no);
+
+ if (dot_v3v3(c, o_c) <= 0)
+ return 1;
+ else
+ return 0;
+}
+
+// Detects and fix a quad wrapping after the resize
+// Arguments are the orginal verts followed by the final verts and then the bevel size and the normal
+static void fix_bevel_quad_wrap(float *o_v1, float *o_v2, float *o_v3, float *o_v4, float *v1, float *v2, float *v3, float *v4, float d, float *no)
+{
+ float vec[3];
+ char wrap[4];
+
+ // Quads can wrap partially. Watch out
+ wrap[0] = detect_wrap(o_v1, o_v2, v1, v2, no); // Edge 1-2
+ wrap[1] = detect_wrap(o_v2, o_v3, v2, v3, no); // Edge 2-3
+ wrap[2] = detect_wrap(o_v3, o_v4, v3, v4, no); // Edge 3-4
+ wrap[3] = detect_wrap(o_v4, o_v1, v4, v1, no); // Edge 4-1
+
+ // Edge 1 inverted
+ if (wrap[0] == 1 && wrap[1] == 0 && wrap[2] == 0 && wrap[3] == 0) {
+ fix_bevel_wrap(vec, o_v2, o_v3, o_v4, o_v1, d, no);
+ VECCOPY(v1, vec);
+ VECCOPY(v2, vec);
+ }
+ // Edge 2 inverted
+ else if (wrap[0] == 0 && wrap[1] == 1 && wrap[2] == 0 && wrap[3] == 0) {
+ fix_bevel_wrap(vec, o_v3, o_v4, o_v1, o_v2, d, no);
+ VECCOPY(v2, vec);
+ VECCOPY(v3, vec);
+ }
+ // Edge 3 inverted
+ else if (wrap[0] == 0 && wrap[1] == 0 && wrap[2] == 1 && wrap[3] == 0) {
+ fix_bevel_wrap(vec, o_v4, o_v1, o_v2, o_v3, d, no);
+ VECCOPY(v3, vec);
+ VECCOPY(v4, vec);
+ }
+ // Edge 4 inverted
+ else if (wrap[0] == 0 && wrap[1] == 0 && wrap[2] == 0 && wrap[3] == 1) {
+ fix_bevel_wrap(vec, o_v1, o_v2, o_v3, o_v4, d, no);
+ VECCOPY(v4, vec);
+ VECCOPY(v1, vec);
+ }
+ // Edge 2 and 4 inverted
+ else if (wrap[0] == 0 && wrap[1] == 1 && wrap[2] == 0 && wrap[3] == 1) {
+ add_v3_v3v3(vec, v2, v3);
+ mul_v3_fl(vec, 0.5);
+ VECCOPY(v2, vec);
+ VECCOPY(v3, vec);
+ add_v3_v3v3(vec, v1, v4);
+ mul_v3_fl(vec, 0.5);
+ VECCOPY(v1, vec);
+ VECCOPY(v4, vec);
+ }
+ // Edge 1 and 3 inverted
+ else if (wrap[0] == 1 && wrap[1] == 0 && wrap[2] == 1 && wrap[3] == 0) {
+ add_v3_v3v3(vec, v1, v2);
+ mul_v3_fl(vec, 0.5);
+ VECCOPY(v1, vec);
+ VECCOPY(v2, vec);
+ add_v3_v3v3(vec, v3, v4);
+ mul_v3_fl(vec, 0.5);
+ VECCOPY(v3, vec);
+ VECCOPY(v4, vec);
+ }
+ // Totally inverted
+ else if (wrap[0] == 1 && wrap[1] == 1 && wrap[2] == 1 && wrap[3] == 1) {
+ add_v3_v3v3(vec, v1, v2);
+ add_v3_v3v3(vec, vec, v3);
+ add_v3_v3v3(vec, vec, v4);
+ mul_v3_fl(vec, 0.25);
+ VECCOPY(v1, vec);
+ VECCOPY(v2, vec);
+ VECCOPY(v3, vec);
+ VECCOPY(v4, vec);
+ }
+
+}
+
+// Detects and fix a tri wrapping after the resize
+// Arguments are the orginal verts followed by the final verts and the normal
+// Triangles cannot wrap partially (not in this situation
+static void fix_bevel_tri_wrap(float *o_v1, float *o_v2, float *o_v3, float *v1, float *v2, float *v3, float *no)
+{
+ if (detect_wrap(o_v1, o_v2, v1, v2, no)) {
+ float vec[3];
+ add_v3_v3v3(vec, o_v1, o_v2);
+ add_v3_v3v3(vec, vec, o_v3);
+ mul_v3_fl(vec, 1.0f/3.0f);
+ VECCOPY(v1, vec);
+ VECCOPY(v2, vec);
+ VECCOPY(v3, vec);
+ }
+}
+
+static void bevel_shrink_faces(float d, int flag)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+ float vec[3], no[3], v1[3], v2[3], v3[3], v4[3];
- /* XXX old bevel not ported yet */
+ /* move edges of all faces with efa->f1 & flag closer towards their centers */
+ efa= em->faces.first;
+ while (efa) {
+ if (efa->f1 & flag) {
+ VECCOPY(v1, efa->v1->co);
+ VECCOPY(v2, efa->v2->co);
+ VECCOPY(v3, efa->v3->co);
+ VECCOPY(no, efa->n);
+ if (efa->v4 == NULL) {
+ bevel_displace_vec(vec, v1, v2, v3, d, no);
+ VECCOPY(efa->v2->co, vec);
+ bevel_displace_vec(vec, v2, v3, v1, d, no);
+ VECCOPY(efa->v3->co, vec);
+ bevel_displace_vec(vec, v3, v1, v2, d, no);
+ VECCOPY(efa->v1->co, vec);
+
+ fix_bevel_tri_wrap(v1, v2, v3, efa->v1->co, efa->v2->co, efa->v3->co, no);
+ } else {
+ VECCOPY(v4, efa->v4->co);
+ bevel_displace_vec(vec, v1, v2, v3, d, no);
+ VECCOPY(efa->v2->co, vec);
+ bevel_displace_vec(vec, v2, v3, v4, d, no);
+ VECCOPY(efa->v3->co, vec);
+ bevel_displace_vec(vec, v3, v4, v1, d, no);
+ VECCOPY(efa->v4->co, vec);
+ bevel_displace_vec(vec, v4, v1, v2, d, no);
+ VECCOPY(efa->v1->co, vec);
-static void UNUSED_FUNCTION(bevel_menu)(EditMesh *em)
+ fix_bevel_quad_wrap(v1, v2, v3, v4, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, d, no);
+ }
+ }
+ efa= efa->next;
+ }
+}
+
+static void bevel_shrink_draw(float d, int flag)
{
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+ float vec[3], no[3], v1[3], v2[3], v3[3], v4[3], fv1[3], fv2[3], fv3[3], fv4[3];
+
+ /* move edges of all faces with efa->f1 & flag closer towards their centers */
+ efa= em->faces.first;
+ while (efa) {
+ VECCOPY(v1, efa->v1->co);
+ VECCOPY(v2, efa->v2->co);
+ VECCOPY(v3, efa->v3->co);
+ VECCOPY(no, efa->n);
+ if (efa->v4 == NULL) {
+ bevel_displace_vec(vec, v1, v2, v3, d, no);
+ VECCOPY(fv2, vec);
+ bevel_displace_vec(vec, v2, v3, v1, d, no);
+ VECCOPY(fv3, vec);
+ bevel_displace_vec(vec, v3, v1, v2, d, no);
+ VECCOPY(fv1, vec);
+
+ fix_bevel_tri_wrap(v1, v2, v3, fv1, fv2, fv3, no);
+
+ glBegin(GL_LINES);
+ glVertex3fv(fv1);
+ glVertex3fv(fv2);
+ glEnd();
+ glBegin(GL_LINES);
+ glVertex3fv(fv2);
+ glVertex3fv(fv3);
+ glEnd();
+ glBegin(GL_LINES);
+ glVertex3fv(fv1);
+ glVertex3fv(fv3);
+ glEnd();
+ } else {
+ VECCOPY(v4, efa->v4->co);
+ bevel_displace_vec(vec, v4, v1, v2, d, no);
+ VECCOPY(fv1, vec);
+ bevel_displace_vec(vec, v1, v2, v3, d, no);
+ VECCOPY(fv2, vec);
+ bevel_displace_vec(vec, v2, v3, v4, d, no);
+ VECCOPY(fv3, vec);
+ bevel_displace_vec(vec, v3, v4, v1, d, no);
+ VECCOPY(fv4, vec);
+
+ fix_bevel_quad_wrap(v1, v2, v3, v4, fv1, fv2, fv3, fv4, d, no);
+
+ glBegin(GL_LINES);
+ glVertex3fv(fv1);
+ glVertex3fv(fv2);
+ glEnd();
+ glBegin(GL_LINES);
+ glVertex3fv(fv2);
+ glVertex3fv(fv3);
+ glEnd();
+ glBegin(GL_LINES);
+ glVertex3fv(fv3);
+ glVertex3fv(fv4);
+ glEnd();
+ glBegin(GL_LINES);
+ glVertex3fv(fv1);
+ glVertex3fv(fv4);
+ glEnd();
+ }
+ efa= efa->next;
+ }
+}
+
+static void bevel_mesh(float bsize, int allfaces)
+{
+ EditMesh *em = G.editMesh;
+//#define BEV_DEBUG
+/* Enables debug printfs and assigns material indices: */
+/* 2 = edge quad */
+/* 3 = fill polygon (vertex clusters) */
+
+ EditFace *efa, *example; //, *nextvl;
+ EditEdge *eed, *eed2;
+ EditVert *neweve[1024], *eve, *eve2, *eve3, *v1, *v2, *v3, *v4; //, *eve4;
+ //short found4, search;
+ //float f1, f2, f3, f4;
+ float cent[3], min[3], max[3];
+ int a, b, c;
+ float limit= 0.001f;
+
+ if(multires_test()) return;
+
+ waitcursor(1);
+
+ removedoublesflag(1, 0, limit);
+
+ /* tag all original faces */
+ efa= em->faces.first;
+ while (efa) {
+ efa->f1= 0;
+ if (faceselectedAND(efa, 1)||allfaces) {
+ efa->f1= 1;
+ efa->v1->f |= 128;
+ efa->v2->f |= 128;
+ efa->v3->f |= 128;
+ if (efa->v4) efa->v4->f |= 128;
+ }
+ efa->v1->f &= ~64;
+ efa->v2->f &= ~64;
+ efa->v3->f &= ~64;
+ if (efa->v4) efa->v4->f &= ~64;
+
+ efa= efa->next;
+ }
+
+#ifdef BEV_DEBUG
+ fprintf(stderr,"bevel_mesh: split\n");
+#endif
+
+ efa= em->faces.first;
+ while (efa) {
+ if (efa->f1 & 1) {
+ efa->f1-= 1;
+ v1= addvertlist(efa->v1->co, efa->v1);
+ v1->f= efa->v1->f & ~128;
+ efa->v1->tmp.v = v1;
+
+ v1= addvertlist(efa->v2->co, efa->v2);
+ v1->f= efa->v2->f & ~128;
+ efa->v2->tmp.v = v1;
+
+ v1= addvertlist(efa->v3->co, efa->v3);
+ v1->f= efa->v3->f & ~128;
+ efa->v3->tmp.v = v1;
+
+ if (efa->v4) {
+ v1= addvertlist(efa->v4->co, efa->v4);
+ v1->f= efa->v4->f & ~128;
+ efa->v4->tmp.v = v1;
+ }
+
+ /* Needs better adaption of creases? */
+ addedgelist(efa->e1->v1->tmp.v,
+ efa->e1->v2->tmp.v,
+ efa->e1);
+ addedgelist(efa->e2->v1->tmp.v,
+ efa->e2->v2->tmp.v,
+ efa->e2);
+ addedgelist(efa->e3->v1->tmp.v,
+ efa->e3->v2->tmp.v,
+ efa->e3);
+ if (efa->e4) addedgelist(efa->e4->v1->tmp.v,
+ efa->e4->v2->tmp.v,
+ efa->e4);
+
+ if(efa->v4) {
+ v1 = efa->v1->tmp.v;
+ v2 = efa->v2->tmp.v;
+ v3 = efa->v3->tmp.v;
+ v4 = efa->v4->tmp.v;
+ addfacelist(v1, v2, v3, v4, efa,NULL);
+ } else {
+ v1= efa->v1->tmp.v;
+ v2= efa->v2->tmp.v;
+ v3= efa->v3->tmp.v;
+ addfacelist(v1, v2, v3, 0, efa,NULL);
+ }
+
+ efa= efa-> next;
+ } else {
+ efa= efa->next;
+ }
+ }
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if( (efa->v1->f & 128) && (efa->v2->f & 128) && (efa->v3->f & 128) ) {
+ if(efa->v4==NULL || (efa->v4->f & 128)) efa->f |= 128;
+ }
+ }
+
+ delfaceflag(128); // works with face flag now
+
+ /* tag all faces for shrink*/
+ efa= em->faces.first;
+ while (efa) {
+ if (faceselectedAND(efa, 1)||allfaces) {
+ efa->f1= 2;
+ }
+ efa= efa->next;
+ }
+
+#ifdef BEV_DEBUG
+ fprintf(stderr,"bevel_mesh: make edge quads\n");
+#endif
+
+ /* find edges that are on each other and make quads between them */
+
+ eed= em->edges.first;
+ while(eed) {
+ eed->f2= eed->f1= 0;
+ if ( ((eed->v1->f & eed->v2->f) & 1) || allfaces)
+ eed->f1 |= 4; /* original edges */
+ eed->tmp.v = 0;
+ eed= eed->next;
+ }
+
+ eed= em->edges.first;
+ while (eed) {
+ if ( ((eed->f1 & 2)==0) && (eed->f1 & 4) ) {
+ eed2= em->edges.first;
+ while (eed2) {
+ if ( (eed2 != eed) && ((eed2->f1 & 2)==0) && (eed->f1 & 4) ) {
+ if (
+ (eed->v1 != eed2->v1) &&
+ (eed->v1 != eed2->v2) &&
+ (eed->v2 != eed2->v1) &&
+ (eed->v2 != eed2->v2) && (
+ ( compare_v3v3(eed->v1->co, eed2->v1->co, limit) &&
+ compare_v3v3(eed->v2->co, eed2->v2->co, limit) ) ||
+ ( compare_v3v3(eed->v1->co, eed2->v2->co, limit) &&
+ compare_v3v3(eed->v2->co, eed2->v1->co, limit) ) ) )
+ {
+
+#ifdef BEV_DEBUG
+ fprintf(stderr, "bevel_mesh: edge quad\n");
+#endif
+
+ eed->f1 |= 2; /* these edges are finished */
+ eed2->f1 |= 2;
+
+ example= NULL;
+ efa= em->faces.first; /* search example face (for mat_nr, ME_SMOOTH, ...) */
+ while (efa) {
+ if ( (efa->e1 == eed) ||
+ (efa->e2 == eed) ||
+ (efa->e3 == eed) ||
+ (efa->e4 && (efa->e4 == eed)) ) {
+ example= efa;
+ efa= NULL;
+ }
+ if (efa) efa= efa->next;
+ }
+
+ neweve[0]= eed->v1; neweve[1]= eed->v2;
+ neweve[2]= eed2->v1; neweve[3]= eed2->v2;
+
+ if(exist_face(neweve[0], neweve[1], neweve[2], neweve[3])==0) {
+ efa= NULL;
+
+ if (compare_v3v3(eed->v1->co, eed2->v2->co, limit)) {
+ efa= addfacelist(neweve[0], neweve[1], neweve[2], neweve[3], example,NULL);
+ } else {
+ efa= addfacelist(neweve[0], neweve[2], neweve[3], neweve[1], example,NULL);
+ }
+
+ if(efa) {
+ float inp;
+ normal_tri_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co);
+ inp= efa->n[0]*G.vd->viewmat[0][2] + efa->n[1]*G.vd->viewmat[1][2] + efa->n[2]*G.vd->viewmat[2][2];
+ if(inp < 0.0) flipface(efa);
+#ifdef BEV_DEBUG
+ efa->mat_nr= 1;
+#endif
+ } else fprintf(stderr,"bevel_mesh: error creating face\n");
+ }
+ eed2= NULL;
+ }
+ }
+ if (eed2) eed2= eed2->next;
+ }
+ }
+ eed= eed->next;
+ }
+
+ eed= em->edges.first;
+ while(eed) {
+ eed->f2= eed->f1= 0;
+ eed->f1= 0;
+ eed->v1->f1 &= ~1;
+ eed->v2->f1 &= ~1;
+ eed->tmp.v = 0;
+ eed= eed->next;
+ }
+
+#ifdef BEV_DEBUG
+ fprintf(stderr,"bevel_mesh: find clusters\n");
+#endif
+
+ /* Look for vertex clusters */
+
+ eve= em->verts.first;
+ while (eve) {
+ eve->f &= ~(64|128);
+ eve->tmp.v = NULL;
+ eve= eve->next;
+ }
+
+ /* eve->f: 128: first vertex in a list (->tmp.v) */
+ /* 64: vertex is in a list */
+
+ eve= em->verts.first;
+ while (eve) {
+ eve2= em->verts.first;
+ eve3= NULL;
+ while (eve2) {
+ if ((eve2 != eve) && ((eve2->f & (64|128))==0)) {
+ if (compare_v3v3(eve->co, eve2->co, limit)) {
+ if ((eve->f & (128|64)) == 0) {
+ /* fprintf(stderr,"Found vertex cluster:\n *\n *\n"); */
+ eve->f |= 128;
+ eve->tmp.v = eve2;
+ eve3= eve2;
+ } else if ((eve->f & 64) == 0) {
+ /* fprintf(stderr," *\n"); */
+ if (eve3) eve3->tmp.v = eve2;
+ eve2->f |= 64;
+ eve3= eve2;
+ }
+ }
+ }
+ eve2= eve2->next;
+ if (!eve2) {
+ if (eve3) eve3->tmp.v = NULL;
+ }
+ }
+ eve= eve->next;
+ }
+
+#ifdef BEV_DEBUG
+ fprintf(stderr,"bevel_mesh: shrink faces\n");
+#endif
+
+ bevel_shrink_faces(bsize, 2);
+
+#ifdef BEV_DEBUG
+ fprintf(stderr,"bevel_mesh: fill clusters\n");
+#endif
+
+ /* Make former vertex clusters faces */
+
+ eve= em->verts.first;
+ while (eve) {
+ eve->f &= ~64;
+ eve= eve->next;
+ }
+
+ eve= em->verts.first;
+ while (eve) {
+ if (eve->f & 128) {
+ eve->f &= ~128;
+ a= 0;
+ neweve[a]= eve;
+ eve2 = eve->tmp.v;
+ while (eve2) {
+ a++;
+ neweve[a]= eve2;
+ eve2 = eve2->tmp.v;
+ }
+ a++;
+ efa= NULL;
+ if (a>=3) {
+ example= NULL;
+ efa= em->faces.first; /* search example face */
+ while (efa) {
+ if ( (efa->v1 == neweve[0]) ||
+ (efa->v2 == neweve[0]) ||
+ (efa->v3 == neweve[0]) ||
+ (efa->v4 && (efa->v4 == neweve[0])) ) {
+ example= efa;
+ efa= NULL;
+ }
+ if (efa) efa= efa->next;
+ }
+#ifdef BEV_DEBUG
+ fprintf(stderr,"bevel_mesh: Making %d-gon\n", a);
+#endif
+ if (a>4) {
+ cent[0]= cent[1]= cent[2]= 0.0;
+ INIT_MINMAX(min, max);
+ for (b=0; b<a; b++) {
+ add_v3_v3v3(cent, cent, neweve[b]->co);
+ DO_MINMAX(neweve[b]->co, min, max);
+ }
+ cent[0]= (min[0]+max[0])/2;
+ cent[1]= (min[1]+max[1])/2;
+ cent[2]= (min[2]+max[2])/2;
+ eve2= addvertlist(cent, NULL);
+ eve2->f |= 1;
+ eed= em->edges.first;
+ while (eed) {
+ c= 0;
+ for (b=0; b<a; b++)
+ if ((neweve[b]==eed->v1) || (neweve[b]==eed->v2)) c++;
+ if (c==2) {
+ if(exist_face(eed->v1, eed->v2, eve2, 0)==0) {
+ efa= addfacelist(eed->v1, eed->v2, eve2, 0, example,NULL);
+#ifdef BEV_DEBUG
+ efa->mat_nr= 2;
+#endif
+ }
+ }
+ eed= eed->next;
+ }
+ } else if (a==4) {
+ if(exist_face(neweve[0], neweve[1], neweve[2], neweve[3])==0) {
+ /* the order of vertices can be anything, three cases to check */
+ if( convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co) ) {
+ efa= addfacelist(neweve[0], neweve[1], neweve[2], neweve[3], NULL, NULL);
+ }
+ else if( convex(neweve[0]->co, neweve[2]->co, neweve[3]->co, neweve[1]->co) ) {
+ efa= addfacelist(neweve[0], neweve[2], neweve[3], neweve[1], NULL, NULL);
+ }
+ else if( convex(neweve[0]->co, neweve[2]->co, neweve[1]->co, neweve[3]->co) ) {
+ efa= addfacelist(neweve[0], neweve[2], neweve[1], neweve[3], NULL, NULL);
+ }
+ }
+ }
+ else if (a==3) {
+ if(exist_face(neweve[0], neweve[1], neweve[2], 0)==0)
+ efa= addfacelist(neweve[0], neweve[1], neweve[2], 0, example, NULL);
+ }
+ if(efa) {
+ float inp;
+ normal_tri_v3( efa->n,neweve[0]->co, neweve[1]->co, neweve[2]->co);
+ inp= efa->n[0]*G.vd->viewmat[0][2] + efa->n[1]*G.vd->viewmat[1][2] + efa->n[2]*G.vd->viewmat[2][2];
+ if(inp < 0.0) flipface(efa);
+#ifdef BEV_DEBUG
+ efa->mat_nr= 2;
+#endif
+ }
+ }
+ }
+ eve= eve->next;
+ }
+
+ eve= em->verts.first;
+ while (eve) {
+ eve->f1= 0;
+ eve->f &= ~(128|64);
+ eve->tmp.v= NULL;
+ eve= eve->next;
+ }
+
+ recalc_editnormals();
+ waitcursor(0);
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
+ removedoublesflag(1, 0, limit);
+
+ /* flush selected vertices to edges/faces */
+ EM_select_flush();
+
+#undef BEV_DEBUG
+}
+
+static void bevel_mesh_recurs(float bsize, short recurs, int allfaces)
+{
+ float d;
+ short nr;
+
+ d= bsize;
+ for (nr=0; nr<recurs; nr++) {
+ bevel_mesh(d, allfaces);
+ if (nr==0) d /= 3; else d /= 2;
+ }
+}
+
+void bevel_menu(void) {
BME_Mesh *bm;
BME_TransData_Head *td;
-// TransInfo *t;
+ TransInfo *t;
int options, res, gbm_free = 0;
-// t = BIF_GetTransInfo();
+ t = BIF_GetTransInfo();
if (!G.editBMesh) {
G.editBMesh = MEM_callocN(sizeof(*(G.editBMesh)),"bevel_menu() G.editBMesh");
gbm_free = 1;
@@ -3913,21 +4508,21 @@ static void UNUSED_FUNCTION(bevel_menu)(EditMesh *em)
while(G.editBMesh->options & BME_BEVEL_RUNNING) {
options = G.editBMesh->options;
res = G.editBMesh->res;
- bm = BME_editmesh_to_bmesh(em);
-// BIF_undo_push("Pre-Bevel");
- free_editMesh(em);
+ bm = BME_editmesh_to_bmesh(G.editMesh);
+ BIF_undo_push("Pre-Bevel");
+ free_editMesh(G.editMesh);
BME_bevel(bm,0.1f,res,options,0,0,&td);
- BME_bmesh_to_editmesh(bm, td, em);
- EM_selectmode_flush(em);
+ BME_bmesh_to_editmesh(bm, td);
+ EM_selectmode_flush();
G.editBMesh->bm = bm;
G.editBMesh->td = td;
-// initTransform(TFM_BEVEL,CTX_BMESH);
-// Transform();
+ initTransform(TFM_BEVEL,CTX_BMESH);
+ Transform();
BME_free_transdata(td);
BME_free_mesh(bm);
-// if (t->state != TRANS_CONFIRM) {
-// BIF_undo();
-// }
+ if (t->state != TRANS_CONFIRM) {
+ BIF_undo();
+ }
if (options == G.editBMesh->options) {
G.editBMesh->options &= ~BME_BEVEL_RUNNING;
}
@@ -3940,34 +4535,128 @@ static void UNUSED_FUNCTION(bevel_menu)(EditMesh *em)
}
-/* *********** END BEVEL *********/
-
-/* this utility function checks to see if 2 edit edges share a face,
-returns 1 if they do
-returns 0 if they do not, or if the function is passed the same edge 2 times
-*/
-short sharesFace(EditMesh *em, EditEdge* e1, EditEdge* e2)
+void bevel_menu_old()
{
- EditFace *search=NULL;
+ char Finished = 0, Canceled = 0, str[100], Recalc = 0;
+ short mval[2], oval[2], curval[2], event = 0, recurs = 1, nr;
+ float vec[3], d, drawd=0.0, center[3], fac = 1;
+
+ getmouseco_areawin(mval);
+ oval[0] = mval[0]; oval[1] = mval[1];
+
+ // Silly hackish code to initialise the variable (warning if not done)
+ // while still drawing in the first iteration (and without using another variable)
+ curval[0] = mval[0] + 1; curval[1] = mval[1] + 1;
- search = em->faces.first;
- if (e1 == e2){
- return 0 ;
+ // Init grabz for window to vec conversions
+ initgrabz(-G.vd->ofs[0], -G.vd->ofs[1], -G.vd->ofs[2]);
+ window_to_3d(center, mval[0], mval[1]);
+
+ if(button(&recurs, 1, 4, "Recursion:")==0) return;
+
+ for (nr=0; nr<recurs-1; nr++) {
+ if (nr==0) fac += 1.0f/3.0f; else fac += 1.0f/(3 * nr * 2.0f);
}
- while(search){
- if(
- ((search->e1 == e1 || search->e2 == e1) || (search->e3 == e1 || search->e4 == e1)) &&
- ((search->e1 == e2 || search->e2 == e2) || (search->e3 == e2 || search->e4 == e2))
- ) {
- return 1;
- }
- search = search->next;
+
+ EM_set_flag_all(SELECT);
+
+ SetBlenderCursor(SYSCURSOR);
+
+ while (Finished == 0)
+ {
+ getmouseco_areawin(mval);
+ if (mval[0] != curval[0] || mval[1] != curval[1] || (Recalc == 1))
+ {
+ Recalc = 0;
+ curval[0] = mval[0];
+ curval[1] = mval[1];
+
+ window_to_3d(vec, mval[0]-oval[0], mval[1]-oval[1]);
+ d = normalize_v3(vec) / 10;
+
+
+ drawd = d * fac;
+ if (G.qual & LR_CTRLKEY)
+ drawd = (float) floor(drawd * 10.0f)/10.0f;
+ if (G.qual & LR_SHIFTKEY)
+ drawd /= 10;
+
+ /*------------- Preview lines--------------- */
+
+ /* uses callback mechanism to draw it all in current area */
+ scrarea_do_windraw(curarea);
+
+ /* set window matrix to perspective, default an area returns with buttons transform */
+ persp(PERSP_VIEW);
+ /* make a copy, for safety */
+ glPushMatrix();
+ /* multiply with the object transformation */
+ mymultmatrix(G.obedit->obmat);
+
+ glColor3ub(255, 255, 0);
+
+ // PREVIEW CODE GOES HERE
+ bevel_shrink_draw(drawd, 2);
+
+ /* restore matrix transform */
+ glPopMatrix();
+
+ sprintf(str, "Bevel Size: %.4f LMB to confirm, RMB to cancel, SPACE to input directly.", drawd);
+ headerprint(str);
+
+ /* this also verifies other area/windows for clean swap */
+ screen_swapbuffers();
+
+ persp(PERSP_WIN);
+
+ glDrawBuffer(GL_FRONT);
+
+ BIF_ThemeColor(TH_WIRE);
+
+ setlinestyle(3);
+ glBegin(GL_LINE_STRIP);
+ glVertex2sv(mval);
+ glVertex2sv(oval);
+ glEnd();
+ setlinestyle(0);
+
+ persp(PERSP_VIEW);
+ bglFlush(); // flush display for frontbuffer
+ glDrawBuffer(GL_BACK);
+ }
+ while(qtest()) {
+ short val=0;
+ event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle
+
+ /* val==0 on key-release event */
+ if(val && (event==ESCKEY || event==RIGHTMOUSE || event==LEFTMOUSE || event==RETKEY || event==ESCKEY)) {
+ if (event==RIGHTMOUSE || event==ESCKEY)
+ Canceled = 1;
+ Finished = 1;
+ }
+ else if (val && event==SPACEKEY) {
+ if (fbutton(&d, 0.000, 10.000, 10, 0, "Width:")!=0) {
+ drawd = d * fac;
+ Finished = 1;
+ }
+ }
+ else if (val) {
+ /* On any other keyboard event, recalc */
+ Recalc = 1;
+ }
+
+ }
+ }
+ if (Canceled==0) {
+ SetBlenderCursor(BC_WAITCURSOR);
+ bevel_mesh_recurs(drawd/fac, recurs, 1);
+ righthandfaces(1);
+ SetBlenderCursor(SYSCURSOR);
+ BIF_undo_push("Bevel");
}
- return 0;
}
-#if 0
-
+/* *********** END BEVEL *********/
typedef struct SlideUv {
float origuv[2];
float *uv_up, *uv_down;
@@ -3980,15 +4669,31 @@ typedef struct SlideVert {
EditVert origvert;
} SlideVert;
-int EdgeSlide(EditMesh *em, wmOperator *op, short immediate, float imperc)
-{
- return 0;
-/* XXX REFACTOR - #if 0'd for now, otherwise can't make 64bit windows builds on 64bit machine */
-useless:
- goto useless // because it doesn't do anything right now
+int EdgeLoopDelete(void) {
+
+ /* temporal flag setting so we keep UVs when deleting edge loops,
+ * this is a bit of a hack but it works how you would want in almost all cases */
+ short uvcalc_flag_orig = G.scene->toolsettings->uvcalc_flag;
+ G.scene->toolsettings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
+
+ if(!EdgeSlide(1, 1)) {
+ return 0;
+ }
+
+ /* restore uvcalc flag */
+ G.scene->toolsettings->uvcalc_flag = uvcalc_flag_orig;
+
+ EM_select_more();
+ removedoublesflag(1,0, 0.001);
+ EM_select_flush();
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ return 1;
+}
-// NumInput num; XXX
- Mesh *me= NULL; // XXX
+int EdgeSlide(short immediate, float imperc)
+{
+ NumInput num;
+ EditMesh *em = G.editMesh;
EditFace *efa;
EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL;
EditVert *ev, *nearest;
@@ -3996,42 +4701,42 @@ useless:
GHash *vertgh;
SlideVert *tempsv;
- float perc = 0, percp = 0,vertdist; // XXX, projectMat[4][4];
+ float perc = 0, percp = 0,vertdist, projectMat[4][4], viewMat[4][4];
float shiftlabda= 0.0f,len = 0.0f;
int i = 0,j, numsel, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0,flip=0;
int wasshift = 0;
-
+
/* UV correction vars */
GHash **uvarray= NULL;
- int uvlay_tot= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
+ int uvlay_tot= CustomData_number_of_layers(&G.editMesh->fdata, CD_MTFACE);
int uvlay_idx;
- SlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL;
+ SlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL;
float uv_tmp[2];
LinkNode *fuv_link;
-
+
short event, draw=1;
- int mval[2], mvalo[2];
- char str[128];
+ short mval[2], mvalo[2];
+ char str[128];
float labda = 0.0f;
-
-// initNumInput(&num);
-
-// view3d_get_object_project_mat(curarea, obedit, projectMat);
-
- mvalo[0] = -1; mvalo[1] = -1;
- numsel =0;
-
+
+ initNumInput(&num);
+
+ view3d_get_object_project_mat(curarea, G.obedit, projectMat, viewMat);
+
+ mvalo[0] = -1; mvalo[1] = -1;
+ numsel =0;
+
// Get number of selected edges and clear some flags
for(eed=em->edges.first;eed;eed=eed->next) {
eed->f1 = 0;
- eed->f2 = 0;
+ eed->f2 = 0;
if(eed->f & SELECT) numsel++;
}
-
+
for(ev=em->verts.first;ev;ev=ev->next) {
- ev->f1 = 0;
- }
-
+ ev->f1 = 0;
+ }
+
//Make sure each edge only has 2 faces
// make sure loop doesn't cross face
for(efa=em->faces.first;efa;efa=efa->next) {
@@ -4040,51 +4745,51 @@ useless:
ct++;
efa->e1->f1++;
if(efa->e1->f1 > 2) {
- BKE_report(op->reports, RPT_ERROR, "3+ face edge");
- return 0;
+ error("3+ face edge");
+ return 0;
}
}
if(efa->e2->f & SELECT) {
ct++;
efa->e2->f1++;
if(efa->e2->f1 > 2) {
- BKE_report(op->reports, RPT_ERROR, "3+ face edge");
- return 0;
+ error("3+ face edge");
+ return 0;
}
}
if(efa->e3->f & SELECT) {
ct++;
efa->e3->f1++;
if(efa->e3->f1 > 2) {
- BKE_report(op->reports, RPT_ERROR, "3+ face edge");
- return 0;
+ error("3+ face edge");
+ return 0;
}
}
if(efa->e4 && efa->e4->f & SELECT) {
ct++;
efa->e4->f1++;
if(efa->e4->f1 > 2) {
- BKE_report(op->reports, RPT_ERROR, "3+ face edge");
- return 0;
+ error("3+ face edge");
+ return 0;
}
- }
- // Make sure loop is not 2 edges of same face
+ }
+ // Make sure loop is not 2 edges of same face
if(ct > 1) {
- BKE_report(op->reports, RPT_ERROR, "Loop crosses itself");
- return 0;
+ error("loop crosses itself");
+ return 0;
}
- }
+ }
// Get # of selected verts
- for(ev=em->verts.first;ev;ev=ev->next) {
+ for(ev=em->verts.first;ev;ev=ev->next) {
if(ev->f & SELECT) vertsel++;
- }
-
+ }
+
// Test for multiple segments
if(vertsel > numsel+1) {
- BKE_report(op->reports, RPT_ERROR, "Please choose a single edge loop");
- return 0;
- }
-
+ error("Was not a single edge loop");
+ return 0;
+ }
+
// Get the edgeloop in order - mark f1 with SELECT once added
for(eed=em->edges.first;eed;eed=eed->next) {
if((eed->f & SELECT) && !(eed->f1 & SELECT)) {
@@ -4093,35 +4798,35 @@ useless:
BLI_linklist_prepend(&edgelist,eed);
numadded++;
first = eed;
- last = eed;
+ last = eed;
eed->f1 = SELECT;
- } else {
+ } else {
if(editedge_getSharedVert(eed, last)) {
BLI_linklist_append(&edgelist,eed);
eed->f1 = SELECT;
numadded++;
- last = eed;
+ last = eed;
} else if(editedge_getSharedVert(eed, first)) {
BLI_linklist_prepend(&edgelist,eed);
eed->f1 = SELECT;
numadded++;
- first = eed;
- }
+ first = eed;
+ }
}
- }
+ }
if(eed->next == NULL && numadded != numsel) {
- eed=em->edges.first;
+ eed=em->edges.first;
timesthrough++;
}
-
+
// It looks like there was an unexpected case - Hopefully should not happen
if(timesthrough >= numsel*2) {
- BLI_linklist_free(edgelist,NULL);
- BKE_report(op->reports, RPT_ERROR, "Could not order loop");
- return 0;
+ BLI_linklist_free(edgelist,NULL);
+ error("could not order loop");
+ return 0;
}
}
-
+
// Put the verts in order in a linklist
look = edgelist;
while(look) {
@@ -4132,33 +4837,33 @@ useless:
//This is the first entry takes care of extra vert
if(eed->v1 != temp->v1 && eed->v1 != temp->v2) {
- BLI_linklist_append(&vertlist,eed->v1);
- eed->v1->f1 = 1;
+ BLI_linklist_append(&vertlist,eed->v1);
+ eed->v1->f1 = 1;
} else {
- BLI_linklist_append(&vertlist,eed->v2);
- eed->v2->f1 = 1;
- }
+ BLI_linklist_append(&vertlist,eed->v2);
+ eed->v2->f1 = 1;
+ }
} else {
//This is the case that we only have 1 edge
- BLI_linklist_append(&vertlist,eed->v1);
- eed->v1->f1 = 1;
+ BLI_linklist_append(&vertlist,eed->v1);
+ eed->v1->f1 = 1;
}
- }
+ }
// for all the entries
if(eed->v1->f1 != 1) {
- BLI_linklist_append(&vertlist,eed->v1);
- eed->v1->f1 = 1;
+ BLI_linklist_append(&vertlist,eed->v1);
+ eed->v1->f1 = 1;
} else if(eed->v2->f1 != 1) {
- BLI_linklist_append(&vertlist,eed->v2);
- eed->v2->f1 = 1;
- }
- look = look->next;
- }
-
+ BLI_linklist_append(&vertlist,eed->v2);
+ eed->v2->f1 = 1;
+ }
+ look = look->next;
+ }
+
// populate the SlideVerts
-
- vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "EdgeSlide gh");
- look = vertlist;
+
+ vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ look = vertlist;
while(look) {
i=0;
j=0;
@@ -4174,28 +4879,28 @@ useless:
tempsv->origvert.no[2] = ev->no[2];
// i is total edges that vert is on
// j is total selected edges that vert is on
-
+
for(eed=em->edges.first;eed;eed=eed->next) {
if(eed->v1 == ev || eed->v2 == ev) {
- i++;
+ i++;
if(eed->f & SELECT) {
- j++;
+ j++;
}
- }
+ }
}
// If the vert is in the middle of an edge loop, it touches 2 selected edges and 2 unselected edges
if(i == 4 && j == 2) {
for(eed=em->edges.first;eed;eed=eed->next) {
if(editedge_containsVert(eed, ev)) {
if(!(eed->f & SELECT)) {
- if(!tempsv->up) {
- tempsv->up = eed;
- } else if (!(tempsv->down)) {
- tempsv->down = eed;
- }
+ if(!tempsv->up) {
+ tempsv->up = eed;
+ } else if (!(tempsv->down)) {
+ tempsv->down = eed;
+ }
}
- }
- }
+ }
+ }
}
// If it is on the end of the loop, it touches 1 selected and as least 2 more unselected
if(i >= 3 && j == 1) {
@@ -4204,70 +4909,70 @@ useless:
for(efa = em->faces.first;efa;efa=efa->next) {
if(editface_containsEdge(efa, eed)) {
if(editedge_containsVert(efa->e1, ev) && efa->e1 != eed) {
- if(!tempsv->up) {
- tempsv->up = efa->e1;
- } else if (!(tempsv->down)) {
- tempsv->down = efa->e1;
- }
+ if(!tempsv->up) {
+ tempsv->up = efa->e1;
+ } else if (!(tempsv->down)) {
+ tempsv->down = efa->e1;
+ }
}
if(editedge_containsVert(efa->e2, ev) && efa->e2 != eed) {
- if(!tempsv->up) {
- tempsv->up = efa->e2;
- } else if (!(tempsv->down)) {
- tempsv->down = efa->e2;
- }
- }
+ if(!tempsv->up) {
+ tempsv->up = efa->e2;
+ } else if (!(tempsv->down)) {
+ tempsv->down = efa->e2;
+ }
+ }
if(editedge_containsVert(efa->e3, ev) && efa->e3 != eed) {
- if(!tempsv->up) {
- tempsv->up = efa->e3;
- } else if (!(tempsv->down)) {
- tempsv->down = efa->e3;
- }
- }
+ if(!tempsv->up) {
+ tempsv->up = efa->e3;
+ } else if (!(tempsv->down)) {
+ tempsv->down = efa->e3;
+ }
+ }
if(efa->e4) {
if(editedge_containsVert(efa->e4, ev) && efa->e4 != eed) {
- if(!tempsv->up) {
- tempsv->up = efa->e4;
- } else if (!(tempsv->down)) {
- tempsv->down = efa->e4;
- }
+ if(!tempsv->up) {
+ tempsv->up = efa->e4;
+ } else if (!(tempsv->down)) {
+ tempsv->down = efa->e4;
+ }
}
- }
-
+ }
+
}
}
- }
- }
- }
+ }
+ }
+ }
if(i > 4 && j == 2) {
BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
- BLI_linklist_free(vertlist,NULL);
- BLI_linklist_free(edgelist,NULL);
- return 0;
+ BLI_linklist_free(vertlist,NULL);
+ BLI_linklist_free(edgelist,NULL);
+ return 0;
}
BLI_ghash_insert(vertgh,ev,tempsv);
-
- look = look->next;
- }
-
+
+ look = look->next;
+ }
+
// make sure the UPs nad DOWNs are 'faceloops'
// Also find the nearest slidevert to the cursor
-// XXX getmouseco_areawin(mval);
- look = vertlist;
+ getmouseco_areawin(mval);
+ look = vertlist;
nearest = NULL;
- vertdist = -1;
- while(look) {
+ vertdist = -1;
+ while(look) {
tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
-
+
if(!tempsv->up || !tempsv->down) {
- BKE_report(op->reports, RPT_ERROR, "Missing rails");
+ error("Missing rails");
BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
- BLI_linklist_free(vertlist,NULL);
- BLI_linklist_free(edgelist,NULL);
+ BLI_linklist_free(vertlist,NULL);
+ BLI_linklist_free(edgelist,NULL);
return 0;
}
- if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
+ if(G.f & G_DRAW_EDGELEN) {
if(!(tempsv->up->f & SELECT)) {
tempsv->up->f |= SELECT;
tempsv->up->f2 |= 16;
@@ -4290,43 +4995,43 @@ useless:
if(sv) {
float tempdist, co[2];
- if(!sharesFace(em, tempsv->up,sv->up)) {
+ if(!sharesFace(tempsv->up,sv->up)) {
EditEdge *swap;
swap = sv->up;
sv->up = sv->down;
- sv->down = swap;
+ sv->down = swap;
}
-// view3d_project_float(curarea, tempsv->origvert.co, co, projectMat);
-
+ view3d_project_float(curarea, tempsv->origvert.co, co, projectMat);
+
tempdist = sqrt(pow(co[0] - mval[0],2)+pow(co[1] - mval[1],2));
if(vertdist < 0) {
vertdist = tempdist;
- nearest = (EditVert*)look->link;
+ nearest = (EditVert*)look->link;
} else if ( tempdist < vertdist ) {
vertdist = tempdist;
- nearest = (EditVert*)look->link;
- }
+ nearest = (EditVert*)look->link;
+ }
}
- }
-
-
-
- look = look->next;
- }
-
-
- if (uvlay_tot) { // XXX && (scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
+ }
+
+
+
+ look = look->next;
+ }
+
+
+ if (uvlay_tot && (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
int maxnum = 0;
uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array");
suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(SlideUv), "SlideUVs"); /* uvLayers * verts */
suv = NULL;
-
+
for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
-
- uvarray[uvlay_idx] = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "EdgeSlideUV gh");
-
+
+ uvarray[uvlay_idx] = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
for(ev=em->verts.first;ev;ev=ev->next) {
ev->tmp.l = 0;
}
@@ -4334,25 +5039,25 @@ useless:
while(look) {
float *uv_new;
tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
-
+
ev = look->link;
suv = NULL;
for(efa = em->faces.first;efa;efa=efa->next) {
if (ev->tmp.l != -1) { /* test for self, in this case its invalid */
int k=-1; /* face corner */
-
+
/* Is this vert in the faces corner? */
if (efa->v1==ev) k=0;
else if (efa->v2==ev) k=1;
else if (efa->v3==ev) k=2;
else if (efa->v4 && efa->v4==ev) k=3;
-
+
if (k != -1) {
MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx);
EditVert *ev_up, *ev_down;
-
+
uv_new = tf->uv[k];
-
+
if (ev->tmp.l) {
if (fabs(suv->origuv[0]-uv_new[0]) > 0.0001 || fabs(suv->origuv[1]-uv_new[1])) {
ev->tmp.l = -1; /* Tag as invalid */
@@ -4370,14 +5075,14 @@ useless:
suv->uv_up = suv->uv_down = NULL;
suv->origuv[0] = uv_new[0];
suv->origuv[1] = uv_new[1];
-
+
BLI_linklist_prepend(&suv->fuv_list, uv_new);
BLI_ghash_insert(uvarray[uvlay_idx],ev,suv);
-
+
suv_last++; /* advance to next slide UV */
maxnum++;
}
-
+
/* Now get the uvs along the up or down edge if we can */
if (suv) {
if (!suv->uv_up) {
@@ -4394,7 +5099,7 @@ useless:
else if (efa->v3==ev_down) suv->uv_down = tf->uv[2];
else if (efa->v4 && efa->v4==ev_down) suv->uv_down = tf->uv[3];
}
-
+
/* Copy the pointers to the face UV's */
BLI_linklist_prepend(&suv->fuv_list, uv_new);
}
@@ -4405,32 +5110,31 @@ useless:
}
} /* end uv layer loop */
} /* end uvlay_tot */
-
-
-
+
+
+
// we should have enough info now to slide
- len = 0.0f;
-
+ len = 0.0f;
+
percp = -1;
while(draw) {
- /* For the % calculation */
- int mval[2];
+ /* For the % calculation */
+ short mval[2];
float rc[2];
float v2[2], v3[2];
EditVert *centerVert, *upVert, *downVert;
-
-// XXX getmouseco_areawin(mval);
-
+
+ getmouseco_areawin(mval);
+
if (!immediate && (mval[0] == mvalo[0] && mval[1] == mvalo[1])) {
PIL_sleep_ms(10);
} else {
- char *p = str;
- int ctrl= 0, shift= 0; // XXX
+ char *p = str;;
mvalo[0] = mval[0];
mvalo[1] = mval[1];
-
+
tempsv = BLI_ghash_lookup(vertgh,nearest);
@@ -4438,55 +5142,55 @@ useless:
upVert = editedge_getOtherVert(tempsv->up, centerVert);
downVert = editedge_getOtherVert(tempsv->down, centerVert);
-// view3d_project_float(curarea, upVert->co, v2, projectMat);
-// view3d_project_float(curarea, downVert->co, v3, projectMat);
+ view3d_project_float(curarea, upVert->co, v2, projectMat);
+ view3d_project_float(curarea, downVert->co, v3, projectMat);
- /* Determine the % on which the loop should be cut */
+ /* Determine the % on which the loop should be cut */
- rc[0]= v3[0]-v2[0];
- rc[1]= v3[1]-v2[1];
+ rc[0]= v3[0]-v2[0];
+ rc[1]= v3[1]-v2[1];
len= rc[0]*rc[0]+ rc[1]*rc[1];
if (len==0) {len = 0.0001;}
- if (shift) {
+ if ((G.qual & LR_SHIFTKEY)==0) {
wasshift = 0;
- labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len;
+ labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len;
}
else {
if (wasshift==0) {
wasshift = 1;
shiftlabda = labda;
- }
- labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len / 10.0 + shiftlabda;
+ }
+ labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len / 10.0 + shiftlabda;
}
+
+ if(labda<=0.0) labda=0.0;
+ else if(labda>=1.0)labda=1.0;
- if(labda<=0.0) labda=0.0;
- else if(labda>=1.0)labda=1.0;
-
- perc=((1-labda)*2)-1;
-
- if(shift == 0 && ctrl==0) {
+ perc=((1-labda)*2)-1;
+
+ if(G.qual == 0) {
perc *= 100;
perc = floor(perc);
perc /= 100;
- } else if (ctrl) {
+ } else if (G.qual == LR_CTRLKEY) {
perc *= 10;
perc = floor(perc);
- perc /= 10;
- }
-
+ perc /= 10;
+ }
+
if(prop == 0) {
len = len_v3v3(upVert->co,downVert->co)*((perc+1)/2);
if(flip == 1) {
len = len_v3v3(upVert->co,downVert->co) - len;
- }
+ }
}
-
- if (0) // XXX hasNumInput(&num))
+
+ if (hasNumInput(&num))
{
-// XXX applyNumInput(&num, &perc);
-
+ applyNumInput(&num, &perc);
+
if (prop)
{
perc = MIN2(perc, 1);
@@ -4501,20 +5205,20 @@ useless:
//Adjust Edgeloop
if(immediate) {
- perc = imperc;
+ perc = imperc;
}
percp = perc;
if(prop) {
- look = vertlist;
- while(look) {
+ look = vertlist;
+ while(look) {
EditVert *tempev;
ev = look->link;
tempsv = BLI_ghash_lookup(vertgh,ev);
-
+
tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev);
interp_v3_v3v3(ev->co, tempsv->origvert.co, tempev->co, fabs(perc));
-
- if (0) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
+
+ if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
@@ -4527,14 +5231,14 @@ useless:
}
}
}
-
- look = look->next;
+
+ look = look->next;
}
}
else {
- //Non prop code
- look = vertlist;
- while(look) {
+ //Non prop code
+ look = vertlist;
+ while(look) {
float newlen;
ev = look->link;
tempsv = BLI_ghash_lookup(vertgh,ev);
@@ -4542,8 +5246,8 @@ useless:
if(newlen > 1.0) {newlen = 1.0;}
if(newlen < 0.0) {newlen = 0.0;}
if(flip == 0) {
- interp_v3_v3v3(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen));
- if (0) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
+ interp_v3_v3v3(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen));
+ if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
/* dont do anything if no UVs */
for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
@@ -4558,9 +5262,9 @@ useless:
}
}
} else{
- interp_v3_v3v3(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen));
-
- if (0) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
+ interp_v3_v3v3(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen));
+
+ if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
/* dont do anything if no UVs */
for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
@@ -4575,23 +5279,23 @@ useless:
}
}
}
- look = look->next;
+ look = look->next;
}
}
-
+
// Highlight the Control Edges
-// scrarea_do_windraw(curarea);
-// persp(PERSP_VIEW);
-// glPushMatrix();
-// mymultmatrix(obedit->obmat);
+ scrarea_do_windraw(curarea);
+ persp(PERSP_VIEW);
+ glPushMatrix();
+ mymultmatrix(G.obedit->obmat);
- glColor3ub(0, 255, 0);
+ glColor3ub(0, 255, 0);
glBegin(GL_LINES);
glVertex3fv(upVert->co);
glVertex3fv(downVert->co);
- glEnd();
-
+ glEnd();
+
if(prop == 0) {
// draw start edge for non-prop
glPointSize(5);
@@ -4600,25 +5304,25 @@ useless:
if(flip) {
glVertex3fv(upVert->co);
} else {
- glVertex3fv(downVert->co);
+ glVertex3fv(downVert->co);
}
- glEnd();
+ glEnd();
}
-
-
- glPopMatrix();
+
+
+ glPopMatrix();
if(prop) {
p += sprintf(str, "(P)ercentage: ");
} else {
p += sprintf(str, "Non (P)rop Length: ");
}
-
- if (0) // XXX hasNumInput(&num))
+
+ if (hasNumInput(&num))
{
char num_str[20];
-
- // XX outputNumInput(&num, num_str);
+
+ outputNumInput(&num, num_str);
p += sprintf(p, "%s", num_str);
}
else
@@ -4632,20 +5336,20 @@ useless:
p += sprintf(p, "%f", len);
}
}
-
-
+
+
if (prop == 0) {
p += sprintf(p, ", Press (F) to flip control side");
}
-// headerprint(str);
-// screen_swapbuffers();
+ headerprint(str);
+ screen_swapbuffers();
}
if(!immediate) {
while(qtest()) {
- short val=0;
- event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle
-
+ short val=0;
+ event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle
+
/* val==0 on key-release event */
if (val) {
if(ELEM(event, ESCKEY, RIGHTMOUSE)) {
@@ -4657,72 +5361,72 @@ useless:
} else if(ELEM3(event, PADENTER, LEFTMOUSE, RETKEY)) {
draw = 0; // End looping now
} else if(event==MIDDLEMOUSE) {
- perc = 0;
+ perc = 0;
immediate = 1;
} else if(event==PKEY) {
-// XXX initNumInput(&num); /* reset num input */
+ initNumInput(&num); /* reset num input */
if (prop) {
prop = 0;
-// XXX num.flag |= NUM_NO_NEGATIVE;
+ num.flag |= NUM_NO_NEGATIVE;
}
else {
prop = 1;
}
- mvalo[0] = -1;
+ mvalo[0] = -1;
} else if(event==FKEY) {
- (flip == 1) ? (flip = 0):(flip = 1);
- mvalo[0] = -1;
+ (flip == 1) ? (flip = 0):(flip = 1);
+ mvalo[0] = -1;
} else if(ELEM(event, RIGHTARROWKEY, WHEELUPMOUSE)) { // Scroll through Control Edges
- look = vertlist;
- while(look) {
+ look = vertlist;
+ while(look) {
if(nearest == (EditVert*)look->link) {
if(look->next == NULL) {
- nearest = (EditVert*)vertlist->link;
+ nearest = (EditVert*)vertlist->link;
} else {
nearest = (EditVert*)look->next->link;
- }
+ }
mvalo[0] = -1;
- break;
+ break;
}
- look = look->next;
- }
+ look = look->next;
+ }
} else if(ELEM(event, LEFTARROWKEY, WHEELDOWNMOUSE)) { // Scroll through Control Edges
- look = vertlist;
- while(look) {
+ look = vertlist;
+ while(look) {
if(look->next) {
if(look->next->link == nearest) {
nearest = (EditVert*)look->link;
mvalo[0] = -1;
break;
- }
+ }
} else {
if((EditVert*)vertlist->link == nearest) {
nearest = look->link;
mvalo[0] = -1;
- break;
- }
- }
- look = look->next;
- }
+ break;
+ }
+ }
+ look = look->next;
+ }
}
-
-// XXX if (handleNumInput(&num, event))
+
+ if (handleNumInput(&num, event))
{
mvalo[0] = -1; /* NEED A BETTER WAY TO TRIGGER REDRAW */
}
}
-
- }
+
+ }
} else {
draw = 0;
}
-// DAG_id_tag_update(obedit->data, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
}
-
-
- if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
+
+
+ if(G.f & G_DRAW_EDGELEN) {
look = vertlist;
- while(look) {
+ while(look) {
tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
if(tempsv != NULL) {
tempsv->up->f &= !SELECT;
@@ -4731,26 +5435,26 @@ useless:
look = look->next;
}
}
-
-// force_draw(0);
-
+
+ force_draw(0);
+
if(!immediate)
EM_automerge(0);
-// DAG_id_tag_update(obedit->data, 0);
-// scrarea_queue_winredraw(curarea);
-
- //BLI_ghash_free(edgesgh, freeGHash, NULL);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ scrarea_queue_winredraw(curarea);
+
+ //BLI_ghash_free(edgesgh, freeGHash, NULL);
BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
- BLI_linklist_free(vertlist,NULL);
- BLI_linklist_free(edgelist,NULL);
-
- if (uvlay_tot) { // XXX && (scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
+ BLI_linklist_free(vertlist,NULL);
+ BLI_linklist_free(edgelist,NULL);
+
+ if (uvlay_tot && (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
BLI_ghash_free(uvarray[uvlay_idx], NULL, NULL);
}
MEM_freeN(uvarray);
MEM_freeN(slideuvs);
-
+
suv = suv_last-1;
while (suv >= slideuvs) {
if (suv->fuv_list) {
@@ -4758,61 +5462,45 @@ useless:
}
suv--;
}
+
+ allqueue(REDRAWIMAGE, 0);
}
if(cancel == 1) {
return -1;
}
-
- return 1;
-}
-#endif // END OF XXX
-
-int EdgeLoopDelete(EditMesh *UNUSED(em), wmOperator *UNUSED(op))
-{
-#if 0 //XXX won't work with new edgeslide
-
- /* temporal flag setting so we keep UVs when deleting edge loops,
- * this is a bit of a hack but it works how you would want in almost all cases */
- // short uvcalc_flag_orig = 0; // XXX scene->toolsettings->uvcalc_flag;
- // scene->toolsettings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
-
- if(!EdgeSlide(em, op, 1, 1)) {
- return 0;
+ else {
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode) {
+ sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
}
-
- /* restore uvcalc flag */
- // scene->toolsettings->uvcalc_flag = uvcalc_flag_orig;
-
- EM_select_more(em);
- removedoublesflag(em, 1,0, 0.001);
- EM_select_flush(em);
- // DAG_id_tag_update(obedit->data, 0);
- return 1;
#endif
- return 0;
+ }
+ return 1;
}
-
/* -------------------- More tools ------------------ */
-#if 0
-void mesh_set_face_flags(EditMesh *em, short mode)
+
+void mesh_set_face_flags(short mode)
{
+ EditMesh *em = G.editMesh;
EditFace *efa;
MTFace *tface;
- short m_tex=0, m_shared=0,
+ short m_tex=0, m_tiles=0, m_shared=0,
m_light=0, m_invis=0, m_collision=0,
m_twoside=0, m_obcolor=0, m_halo=0,
m_billboard=0, m_shadow=0, m_text=0,
m_sort=0;
short flag = 0, change = 0;
-
-// XXX if (!EM_texFaceCheck()) {
-// error("not a mesh with uv/image layers");
-// return;
-// }
-
+
+ if (!EM_texFaceCheck()) {
+ error("not a mesh with uv/image layers");
+ return;
+ }
+
add_numbut(0, TOG|SHO, "Texture", 0, 0, &m_tex, NULL);
+ add_numbut(1, TOG|SHO, "Tiles", 0, 0, &m_tiles, NULL);
add_numbut(2, TOG|SHO, "Light", 0, 0, &m_light, NULL);
add_numbut(3, TOG|SHO, "Invisible", 0, 0, &m_invis, NULL);
add_numbut(4, TOG|SHO, "Collision", 0, 0, &m_collision, NULL);
@@ -4824,16 +5512,17 @@ void mesh_set_face_flags(EditMesh *em, short mode)
add_numbut(10, TOG|SHO, "Shadow", 0, 0, &m_shadow, NULL);
add_numbut(11, TOG|SHO, "Text", 0, 0, &m_text, NULL);
add_numbut(12, TOG|SHO, "Sort", 0, 0, &m_sort, NULL);
-
+
if (!do_clever_numbuts((mode ? "Set Flags" : "Clear Flags"), 13, REDRAW))
- return;
-
+ return;
+
/* these 2 cant both be on */
if (mode) /* are we seeting*/
if (m_halo)
m_billboard = 0;
-
+
if (m_tex) flag |= TF_TEX;
+ if (m_tiles) flag |= TF_TILES;
if (m_shared) flag |= TF_SHAREDCOL;
if (m_light) flag |= TF_LIGHT;
if (m_invis) flag |= TF_INVISIBLE;
@@ -4845,10 +5534,10 @@ void mesh_set_face_flags(EditMesh *em, short mode)
if (m_shadow) flag |= TF_SHADOW;
if (m_text) flag |= TF_BMFONT;
if (m_sort) flag |= TF_ALPHASORT;
-
+
if (flag==0)
return;
-
+
efa= em->faces.first;
while(efa) {
if(efa->f & SELECT) {
@@ -4859,80 +5548,111 @@ void mesh_set_face_flags(EditMesh *em, short mode)
}
efa= efa->next;
}
-
+
+ if (change) {
+ BIF_undo_push((mode ? "Set Flags" : "Clear Flags"));
+
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
}
-#endif
-/********************** Rip Operator *************************/
+void mesh_set_smooth_faces(short event)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+
+ if(G.obedit==0) return;
+
+ if(G.obedit->type != OB_MESH) return;
+
+ efa= em->faces.first;
+ while(efa) {
+ if(efa->f & SELECT) {
+ if(event==1) efa->flag |= ME_SMOOTH;
+ else if(event==0) efa->flag &= ~ME_SMOOTH;
+ }
+ efa= efa->next;
+ }
+
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+
+ if(event==1) BIF_undo_push("Set Smooth");
+ else if(event==0) BIF_undo_push("Set Solid");
+}
/* helper to find edge for edge_rip */
-static float mesh_rip_edgedist(ARegion *ar, float mat[][4], float *co1, float *co2, const int mval[2])
+static float mesh_rip_edgedist(float mat[][4], float *co1, float *co2, short *mval)
{
- float vec1[2], vec2[2], mvalf[2];
-
- ED_view3d_project_float(ar, co1, vec1, mat);
- ED_view3d_project_float(ar, co2, vec2, mat);
+ float vec1[3], vec2[3], mvalf[2];
+
+ view3d_project_float(curarea, co1, vec1, mat);
+ view3d_project_float(curarea, co2, vec2, mat);
mvalf[0]= (float)mval[0];
mvalf[1]= (float)mval[1];
-
+
return dist_to_line_segment_v2(mvalf, vec1, vec2);
}
/* helper for below */
-static void mesh_rip_setface(EditMesh *em, EditFace *sefa)
+static void mesh_rip_setface(EditFace *sefa)
{
/* put new vertices & edges in best face */
if(sefa->v1->tmp.v) sefa->v1= sefa->v1->tmp.v;
if(sefa->v2->tmp.v) sefa->v2= sefa->v2->tmp.v;
if(sefa->v3->tmp.v) sefa->v3= sefa->v3->tmp.v;
if(sefa->v4 && sefa->v4->tmp.v) sefa->v4= sefa->v4->tmp.v;
-
- sefa->e1= addedgelist(em, sefa->v1, sefa->v2, sefa->e1);
- sefa->e2= addedgelist(em, sefa->v2, sefa->v3, sefa->e2);
+
+ sefa->e1= addedgelist(sefa->v1, sefa->v2, sefa->e1);
+ sefa->e2= addedgelist(sefa->v2, sefa->v3, sefa->e2);
if(sefa->v4) {
- sefa->e3= addedgelist(em, sefa->v3, sefa->v4, sefa->e3);
- sefa->e4= addedgelist(em, sefa->v4, sefa->v1, sefa->e4);
+ sefa->e3= addedgelist(sefa->v3, sefa->v4, sefa->e3);
+ sefa->e4= addedgelist(sefa->v4, sefa->v1, sefa->e4);
}
- else
- sefa->e3= addedgelist(em, sefa->v3, sefa->v1, sefa->e3);
-
+ else
+ sefa->e3= addedgelist(sefa->v3, sefa->v1, sefa->e3);
+
}
/* based on mouse cursor position, it defines how is being ripped */
-static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+void mesh_rip(void)
{
- ARegion *ar= CTX_wm_region(C);
- RegionView3D *rv3d= ar->regiondata;
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ extern void faceloop_select(EditEdge *startedge, int select);
+ EditMesh *em = G.editMesh;
EditVert *eve, *nextve;
EditEdge *eed, *seed= NULL;
EditFace *efa, *sefa= NULL;
- float projectMat[4][4], vec[3], dist, mindist;
- short doit= 1;
- int *mval= event->mval;
-
+ float projectMat[4][4], viewMat[4][4], vec[3], dist, mindist;
+ short doit= 1, mval[2],propmode,prop;
+
+ propmode = G.scene->prop_mode;
+ G.scene->prop_mode = 0;
+ prop = G.scene->proportional;
+ G.scene->proportional = 0;
+
/* select flush... vertices are important */
- EM_selectmode_set(em);
-
- ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat);
+ EM_selectmode_set();
+
+ getmouseco_areawin(mval);
+ view3d_get_object_project_mat(curarea, G.obedit, projectMat, viewMat);
/* find best face, exclude triangles and break on face select or faces with 2 edges select */
mindist= 1000000.0f;
for(efa= em->faces.first; efa; efa=efa->next) {
- if( efa->f & 1)
+ if( efa->f & 1)
break;
if(efa->v4 && faceselectedOR(efa, SELECT) ) {
int totsel=0;
-
+
if(efa->e1->f & SELECT) totsel++;
if(efa->e2->f & SELECT) totsel++;
if(efa->e3->f & SELECT) totsel++;
if(efa->e4->f & SELECT) totsel++;
-
+
if(totsel>1)
break;
- ED_view3d_project_float(ar, efa->cent, vec, projectMat);
+ view3d_project_float(curarea, efa->cent, vec, projectMat);
dist= sqrt( (vec[0]-mval[0])*(vec[0]-mval[0]) + (vec[1]-mval[1])*(vec[1]-mval[1]) );
if(dist<mindist) {
mindist= dist;
@@ -4940,42 +5660,40 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
}
}
-
+
if(efa) {
- BKE_report(op->reports, RPT_WARNING, "Can't perform ripping with faces selected this way");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
+ error("Can't perform ripping with faces selected this way");
+ return;
}
if(sefa==NULL) {
- BKE_report(op->reports, RPT_WARNING, "No proper selection or faces included");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
+ error("No proper selection or faces included");
+ return;
}
-
+
/* duplicate vertices, new vertices get selected */
for(eve = em->verts.last; eve; eve= eve->prev) {
eve->tmp.v = NULL;
if(eve->f & SELECT) {
- eve->tmp.v = addvertlist(em, eve->co, eve);
+ eve->tmp.v = addvertlist(eve->co, eve);
eve->f &= ~SELECT;
eve->tmp.v->f |= SELECT;
}
}
-
+
/* find the best candidate edge */
/* or one of sefa edges is selected... */
if(sefa->e1->f & SELECT) seed= sefa->e2;
if(sefa->e2->f & SELECT) seed= sefa->e1;
if(sefa->e3->f & SELECT) seed= sefa->e2;
if(sefa->e4 && sefa->e4->f & SELECT) seed= sefa->e3;
-
+
/* or we do the distance trick */
if(seed==NULL) {
mindist= 1000000.0f;
if(sefa->e1->v1->tmp.v || sefa->e1->v2->tmp.v) {
- dist = mesh_rip_edgedist(ar, projectMat,
- sefa->e1->v1->co,
+ dist = mesh_rip_edgedist(projectMat,
+ sefa->e1->v1->co,
sefa->e1->v2->co, mval);
if(dist<mindist) {
seed= sefa->e1;
@@ -4983,8 +5701,8 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
}
if(sefa->e2->v1->tmp.v || sefa->e2->v2->tmp.v) {
- dist = mesh_rip_edgedist(ar, projectMat,
- sefa->e2->v1->co,
+ dist = mesh_rip_edgedist(projectMat,
+ sefa->e2->v1->co,
sefa->e2->v2->co, mval);
if(dist<mindist) {
seed= sefa->e2;
@@ -4992,8 +5710,8 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
}
if(sefa->e3->v1->tmp.v || sefa->e3->v2->tmp.v) {
- dist= mesh_rip_edgedist(ar, projectMat,
- sefa->e3->v1->co,
+ dist= mesh_rip_edgedist(projectMat,
+ sefa->e3->v1->co,
sefa->e3->v2->co, mval);
if(dist<mindist) {
seed= sefa->e3;
@@ -5001,8 +5719,8 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
}
if(sefa->e4 && (sefa->e4->v1->tmp.v || sefa->e4->v2->tmp.v)) {
- dist= mesh_rip_edgedist(ar, projectMat,
- sefa->e4->v1->co,
+ dist= mesh_rip_edgedist(projectMat,
+ sefa->e4->v1->co,
sefa->e4->v2->co, mval);
if(dist<mindist) {
seed= sefa->e4;
@@ -5010,27 +5728,25 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
}
}
-
+
if(seed==NULL) { // never happens?
- BKE_report(op->reports, RPT_WARNING, "No proper edge found to start");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
+ error("No proper edge found to start");
+ return;
}
-
- faceloop_select(em, seed, 2); // tmp abuse for finding all edges that need duplicated, returns OK faces with f1
+
+ faceloop_select(seed, 2); // tmp abuse for finding all edges that need duplicated, returns OK faces with f1
/* duplicate edges in the loop, with at least 1 vertex selected, needed for selection flip */
for(eed = em->edges.last; eed; eed= eed->prev) {
eed->tmp.v = NULL;
if((eed->v1->tmp.v) || (eed->v2->tmp.v)) {
EditEdge *newed;
-
- newed= addedgelist(em, eed->v1->tmp.v?eed->v1->tmp.v:eed->v1,
+
+ newed= addedgelist(eed->v1->tmp.v?eed->v1->tmp.v:eed->v1,
eed->v2->tmp.v?eed->v2->tmp.v:eed->v2, eed);
if(eed->f & SELECT) {
- EM_select_edge(eed, 0);
- EM_remove_selection(em, eed, EDITEDGE);
- EM_select_edge(newed, 1);
+ eed->f &= ~SELECT;
+ newed->f |= SELECT;
}
eed->tmp.v = (EditVert *)newed;
}
@@ -5040,28 +5756,28 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0;
/* put new vertices & edges && flag in best face */
- mesh_rip_setface(em, sefa);
-
+ mesh_rip_setface(sefa);
+
/* starting with neighbours of best face, we loop over the seam */
sefa->f1= 2;
doit= 1;
while(doit) {
doit= 0;
-
+
for(efa= em->faces.first; efa; efa=efa->next) {
/* new vert in face */
- if (efa->v1->tmp.v || efa->v2->tmp.v ||
+ if (efa->v1->tmp.v || efa->v2->tmp.v ||
efa->v3->tmp.v || (efa->v4 && efa->v4->tmp.v)) {
/* face is tagged with loop */
if(efa->f1==1) {
- mesh_rip_setface(em, efa);
+ mesh_rip_setface(efa);
efa->f1= 2;
doit= 1;
}
}
- }
+ }
}
-
+
/* remove loose edges, that were part of a ripped face */
for(eve = em->verts.first; eve; eve= eve->next) eve->f1= 0;
for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0;
@@ -5071,14 +5787,14 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
efa->e3->f1= 1;
if(efa->e4) efa->e4->f1= 1;
}
-
+
for(eed = em->edges.last; eed; eed= seed) {
seed= eed->prev;
if(eed->f1==0) {
- if(eed->v1->tmp.v || eed->v2->tmp.v ||
+ if(eed->v1->tmp.v || eed->v2->tmp.v ||
(eed->v1->f & SELECT) || (eed->v2->f & SELECT)) {
- remedge(em, eed);
- free_editedge(em, eed);
+ remedge(eed);
+ free_editedge(eed);
eed= NULL;
}
}
@@ -5087,239 +5803,227 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
eed->v2->f1= 1;
}
}
-
+
/* and remove loose selected vertices, that got duplicated accidentally */
for(eve = em->verts.first; eve; eve= nextve) {
nextve= eve->next;
if(eve->f1==0 && (eve->tmp.v || (eve->f & SELECT))) {
BLI_remlink(&em->verts,eve);
- free_editvert(em, eve);
+ free_editvert(eve);
}
}
+
+ countall(); // apparently always needed when adding stuff, derived mesh
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
-// RNA_enum_set(op->ptr, "proportional", 0);
-// RNA_boolean_set(op->ptr, "mirror", 0);
-// WM_operator_name_call(C, "TRANSFORM_OT_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_rip(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Rip";
- ot->description= "Rip selection from mesh (quads only)";
- ot->idname= "MESH_OT_rip";
-
- /* api callbacks */
- ot->invoke= mesh_rip_invoke;
- ot->poll= EM_view3d_poll;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+#ifdef WITH_VERSE
+ if(G.editMesh->vnode) {
+ sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
+ sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+ }
+#endif
- /* to give to transform */
- /* XXX Transform this in a macro */
- Transform_Properties(ot, P_CONSTRAINT|P_MIRROR);
+ BIF_TransformSetUndo("Rip");
+ initTransform(TFM_TRANSLATION, 0);
+ Transform();
+
+ G.scene->prop_mode = propmode;
+ G.scene->proportional = prop;
}
-
-/************************ Shape Operators *************************/
-
-static void shape_propagate(Object *obedit, EditMesh *em, wmOperator *op)
-{
+void shape_propagate(){
+ EditMesh *em = G.editMesh;
EditVert *ev = NULL;
- Mesh* me = (Mesh*)obedit->data;
+ Mesh* me = (Mesh*)G.obedit->data;
Key* ky = NULL;
KeyBlock* kb = NULL;
-
-
+ Base* base=NULL;
+
+
if(me->key){
ky = me->key;
} else {
- BKE_report(op->reports, RPT_WARNING, "Object Has No Key");
+ error("Object Has No Key");
return;
- }
+ }
if(ky->block.first){
for(ev = em->verts.first; ev ; ev = ev->next){
if(ev->f & SELECT){
for(kb=ky->block.first;kb;kb = kb->next){
- float *data;
- data = kb->data;
- VECCOPY(data+(ev->keyindex*3),ev->co);
+ float *data;
+ data = kb->data;
+ VECCOPY(data+(ev->keyindex*3),ev->co);
}
- }
- }
+ }
+ }
} else {
- BKE_report(op->reports, RPT_WARNING, "Object Has No Blendshapes");
- return;
+ error("Object Has No Blendshapes");
+ return;
}
-
-#if 0
+
//TAG Mesh Objects that share this data
- for(base = scene->base.first; base; base = base->next){
+ for(base = G.scene->base.first; base; base = base->next){
if(base->object && base->object->data == me){
base->object->recalc = OB_RECALC_DATA;
}
- }
-#endif
+ }
- DAG_id_tag_update(obedit->data, 0);
- return;
+ BIF_undo_push("Propagate Blendshape Verts");
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ return;
}
-
-static int shape_propagate_to_all_exec(bContext *C, wmOperator *op)
+void shape_copy_from_lerp(KeyBlock* thisBlock, KeyBlock* fromBlock)
{
- Object *obedit= CTX_data_edit_object(C);
- Mesh *me= obedit->data;
- EditMesh *em= BKE_mesh_get_editmesh(me);
-
- shape_propagate(obedit, em, op);
-
- DAG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
-
- return OPERATOR_FINISHED;
-}
-
-
-void MESH_OT_shape_propagate_to_all(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Shape Propagate";
- ot->description= "Apply selected vertex locations to all other shape keys";
- ot->idname= "MESH_OT_shape_propagate_to_all";
+ EditMesh *em = G.editMesh;
+ EditVert *ev = NULL;
+ short mval[2], curval[2], event = 0, finished = 0, canceled = 0, fullcopy=0 ;
+ float perc = 0;
+ char str[64];
+ float *data, *odata;
+
+ data = fromBlock->data;
+ odata = thisBlock->data;
+
+ getmouseco_areawin(mval);
+ curval[0] = mval[0] + 1; curval[1] = mval[1] + 1;
- /* api callbacks */
- ot->exec= shape_propagate_to_all_exec;
- ot->poll= ED_operator_editmesh;
+ while (finished == 0)
+ {
+ getmouseco_areawin(mval);
+ if (mval[0] != curval[0] || mval[1] != curval[1])
+ {
+
+ if(mval[0] > curval[0])
+ perc += 0.1;
+ else if(mval[0] < curval[0])
+ perc -= 0.1;
+
+ if(perc < 0) perc = 0;
+ if(perc > 1) perc = 1;
+
+ curval[0] = mval[0];
+ curval[1] = mval[1];
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
+ if(fullcopy == 1){
+ perc = 1;
+ }
-static int blend_from_shape_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- Mesh *me= obedit->data;
- Key *key= me->key;
- EditMesh *em= BKE_mesh_get_editmesh(me);
- EditVert *eve;
- KeyBlock *kb, *refkb= NULL;
- float *data, *refdata= NULL, co[3];
- float blend= RNA_float_get(op->ptr, "blend");
- int shape= RNA_enum_get(op->ptr, "shape");
- int add= RNA_boolean_get(op->ptr, "add");
- int blended= 0;
+ for(ev = em->verts.first; ev ; ev = ev->next){
+ if(ev->f & SELECT){
+ interp_v3_v3v3(ev->co,odata+(ev->keyindex*3),data+(ev->keyindex*3),perc);
+ }
+ }
+ sprintf(str,"Blending at %d%c MMB to Copy at 100%c",(int)(perc*100),'%','%');
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ headerprint(str);
+ force_draw(0);
- if(key && (kb= BLI_findlink(&key->block, shape))) {
- data= kb->data;
+ if(fullcopy == 1){
+ break;
+ }
- if(add) {
- refkb= BLI_findlink(&key->block, kb->relative);
- if(refkb)
- refdata = refkb->data;
+ } else {
+ PIL_sleep_ms(10);
}
- for(eve=em->verts.first; eve; eve=eve->next){
- if(eve->f & SELECT) {
- if(eve->keyindex >= 0 && eve->keyindex < kb->totelem) {
- copy_v3_v3(co, data + eve->keyindex*3);
-
- if(add) {
- /* in add mode, we add relative shape key offset */
- if(refdata && eve->keyindex < refkb->totelem)
- sub_v3_v3v3(co, co, refdata + eve->keyindex*3);
-
- madd_v3_v3fl(eve->co, co, blend);
- }
- else {
- /* in blend mode, we interpolate to the shape key */
- interp_v3_v3v3(eve->co, eve->co, co, blend);
- }
-
- blended= 1;
+ while(qtest()) {
+ short val=0;
+ event= extern_qread(&val);
+ if(val){
+ if(ELEM3(event, PADENTER, LEFTMOUSE, RETKEY)){
+ finished = 1;
}
- }
+ else if (event == MIDDLEMOUSE){
+ fullcopy = 1;
+ }
+ else if (ELEM3(event,ESCKEY,RIGHTMOUSE,RIGHTMOUSE)){
+ canceled = 1;
+ finished = 1;
+ }
+ }
}
}
+ if(!canceled)
+ BIF_undo_push("Copy Blendshape Verts");
+ else
+ for(ev = em->verts.first; ev ; ev = ev->next){
+ if(ev->f & SELECT){
+ VECCOPY(ev->co, odata+(ev->keyindex*3));
+ }
+ }
+ return;
+}
- BKE_mesh_end_editmesh(me, em);
-
- if(!blended)
- return OPERATOR_CANCELLED;
-
- DAG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
- return OPERATOR_FINISHED;
-}
-static EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
-{
- Object *obedit= CTX_data_edit_object(C);
- Mesh *me= (obedit) ? obedit->data : NULL;
- Key *key;
- KeyBlock *kb, *actkb;
- EnumPropertyItem tmp= {0, "", 0, "", ""}, *item= NULL;
- int totitem= 0, a;
-
- if(obedit && obedit->type == OB_MESH) {
- key= me->key;
- actkb= ob_get_keyblock(obedit);
-
- if(key && actkb) {
- for(kb=key->block.first, a=0; kb; kb=kb->next, a++) {
- if(kb != actkb) {
- tmp.value= a;
- tmp.identifier= kb->name;
- tmp.name= kb->name;
- RNA_enum_item_add(&item, &totitem, &tmp);
- }
+void shape_copy_select_from()
+{
+ Mesh* me = (Mesh*)G.obedit->data;
+ EditMesh *em = G.editMesh;
+ EditVert *ev = NULL;
+ int totverts = 0,curshape = G.obedit->shapenr;
+
+ Key* ky = NULL;
+ KeyBlock *kb = NULL,*thisBlock = NULL;
+ int maxlen=32, nr=0, a=0;
+ char *menu;
+
+ if(me->key){
+ ky = me->key;
+ } else {
+ error("Object Has No Key");
+ return;
+ }
+
+ if(ky->block.first){
+ for(kb=ky->block.first;kb;kb = kb->next){
+ maxlen += 40; // Size of a block name
+ if(a == curshape-1){
+ thisBlock = kb;
+ }
+
+ a++;
+ }
+ a=0;
+ menu = MEM_callocN(maxlen, "Copy Shape Menu Text");
+ strcpy(menu, "Copy Vert Positions from Shape %t|");
+ for(kb=ky->block.first;kb;kb = kb->next){
+ if(a != curshape-1){
+ sprintf(menu,"%s %s %cx%d|",menu,kb->name,'%',a);
}
+ a++;
}
+ nr = pupmenu_col(menu, 20);
+ MEM_freeN(menu);
+ } else {
+ error("Object Has No Blendshapes");
+ return;
}
-
- RNA_enum_item_end(&item, &totitem);
- *free= 1;
-
- return item;
-}
-
-void MESH_OT_blend_from_shape(wmOperatorType *ot)
-{
- PropertyRNA *prop;
- static EnumPropertyItem shape_items[]= {{0, NULL, 0, NULL, NULL}};
-
- /* identifiers */
- ot->name= "Blend From Shape";
- ot->description= "Blend in shape from a shape key";
- ot->idname= "MESH_OT_blend_from_shape";
-
- /* api callbacks */
- ot->exec= blend_from_shape_exec;
- ot->invoke= WM_operator_props_popup;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- prop= RNA_def_enum(ot->srna, "shape", shape_items, 0, "Shape", "Shape key to use for blending");
- RNA_def_enum_funcs(prop, shape_itemf);
- RNA_def_float(ot->srna, "blend", 1.0f, -FLT_MAX, FLT_MAX, "Blend", "Blending factor", -2.0f, 2.0f);
- RNA_def_boolean(ot->srna, "add", 0, "Add", "Add rather than blend between shapes");
+
+ a = 0;
+
+ for(kb=ky->block.first;kb;kb = kb->next){
+ if(a == nr){
+
+ for(ev = em->verts.first;ev;ev = ev->next){
+ totverts++;
+ }
+
+ if(me->totvert != totverts){
+ error("Shape Has had Verts Added/Removed, please cycle editmode before copying");
+ return;
+ }
+ shape_copy_from_lerp(thisBlock,kb);
+
+ return;
+ }
+ a++;
+ }
+ return;
}
-/************************ Merge Operator *************************/
-
/* Collection Routines|Currently used by the improved merge code*/
/* buildEdge_collection() creates a list of lists*/
/* these lists are filled with edges that are topologically connected.*/
@@ -5338,51 +6042,51 @@ typedef struct CollectedEdge{
#define MERGELIMIT 0.000001
-static void build_edgecollection(EditMesh *em, ListBase *allcollections)
+static void build_edgecollection(ListBase *allcollections)
{
EditEdge *eed;
Collection *edgecollection, *newcollection;
CollectedEdge *newedge;
-
+
int currtag = 1;
short ebalanced = 0;
short collectionfound = 0;
-
- for (eed=em->edges.first; eed; eed = eed->next){
+
+ for (eed=G.editMesh->edges.first; eed; eed = eed->next){
eed->tmp.l = 0;
eed->v1->tmp.l = 0;
eed->v2->tmp.l = 0;
}
-
+
/*1st pass*/
- for(eed=em->edges.first; eed; eed=eed->next){
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next){
if(eed->f&SELECT){
eed->v1->tmp.l = currtag;
eed->v2->tmp.l = currtag;
currtag +=1;
}
}
-
+
/*2nd pass - Brute force. Loop through selected faces until there are no 'unbalanced' edges left (those with both vertices 'tmp.l' tag matching */
while(ebalanced == 0){
ebalanced = 1;
- for(eed=em->edges.first; eed; eed = eed->next){
+ for(eed=G.editMesh->edges.first; eed; eed = eed->next){
if(eed->f&SELECT){
if(eed->v1->tmp.l != eed->v2->tmp.l) /*unbalanced*/{
- if(eed->v1->tmp.l > eed->v2->tmp.l && eed->v2->tmp.l !=0) eed->v1->tmp.l = eed->v2->tmp.l;
- else if(eed->v1 != 0) eed->v2->tmp.l = eed->v1->tmp.l;
+ if(eed->v1->tmp.l > eed->v2->tmp.l && eed->v2->tmp.l !=0) eed->v1->tmp.l = eed->v2->tmp.l;
+ else if(eed->v1 != 0) eed->v2->tmp.l = eed->v1->tmp.l;
ebalanced = 0;
}
}
}
}
-
+
/*3rd pass, set all the edge flags (unnessecary?)*/
- for(eed=em->edges.first; eed; eed = eed->next){
+ for(eed=G.editMesh->edges.first; eed; eed = eed->next){
if(eed->f&SELECT) eed->tmp.l = eed->v1->tmp.l;
}
-
- for(eed=em->edges.first; eed; eed=eed->next){
+
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next){
if(eed->f&SELECT){
if(allcollections->first){
for(edgecollection = allcollections->first; edgecollection; edgecollection=edgecollection->next){
@@ -5401,30 +6105,30 @@ static void build_edgecollection(EditMesh *em, ListBase *allcollections)
newcollection->index = eed->tmp.l;
newcollection->collectionbase.first = 0;
newcollection->collectionbase.last = 0;
-
+
newedge = MEM_mallocN(sizeof(CollectedEdge), "collected edge");
newedge->eed = eed;
-
+
BLI_addtail(&(newcollection->collectionbase), newedge);
BLI_addtail(allcollections, newcollection);
}
}
-
+
}
}
static void freecollections(ListBase *allcollections)
{
struct Collection *curcollection;
-
+
for(curcollection = allcollections->first; curcollection; curcollection = curcollection->next)
BLI_freelistN(&(curcollection->collectionbase));
BLI_freelistN(allcollections);
}
-/*Begin UV Edge Collapse Code
+/*Begin UV Edge Collapse Code
Like Edge subdivide, Edge Collapse should handle UV's intelligently, but since UV's are a per-face attribute, normal edge collapse will fail
- in areas such as the boundaries of 'UV islands'. So for each edge collection we need to build a set of 'welded' UV vertices and edges for it.
+ in areas such as the boundries of 'UV islands'. So for each edge collection we need to build a set of 'welded' UV vertices and edges for it.
The welded UV edges can then be sorted and collapsed.
*/
typedef struct wUV{
@@ -5452,18 +6156,18 @@ typedef struct wUVEdge{
typedef struct wUVEdgeCollect{ /*used for grouping*/
struct wUVEdgeCollect *next, *prev;
wUVEdge *uved;
- int id;
+ int id;
} wUVEdgeCollect;
-static void append_weldedUV(EditMesh *em, EditFace *efa, EditVert *eve, int tfindex, ListBase *uvverts)
+static void append_weldedUV(EditFace *efa, EditVert *eve, int tfindex, ListBase *uvverts)
{
wUV *curwvert, *newwvert;
wUVNode *newnode;
int found;
- MTFace *tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
+ MTFace *tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
+
found = 0;
-
+
for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){
if(curwvert->eve == eve && curwvert->u == tf->uv[tfindex][0] && curwvert->v == tf->uv[tfindex][1]){
newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node");
@@ -5474,47 +6178,47 @@ static void append_weldedUV(EditMesh *em, EditFace *efa, EditVert *eve, int tfin
break;
}
}
-
+
if(!found){
newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node");
newnode->u = &(tf->uv[tfindex][0]);
newnode->v = &(tf->uv[tfindex][1]);
-
+
newwvert = MEM_callocN(sizeof(wUV), "Welded UV Vert");
newwvert->u = *(newnode->u);
newwvert->v = *(newnode->v);
newwvert->eve = eve;
-
+
BLI_addtail(&(newwvert->nodes), newnode);
BLI_addtail(uvverts, newwvert);
-
+
}
}
-static void build_weldedUVs(EditMesh *em, ListBase *uvverts)
+static void build_weldedUVs(ListBase *uvverts)
{
EditFace *efa;
- for(efa=em->faces.first; efa; efa=efa->next){
- if(efa->v1->f1) append_weldedUV(em, efa, efa->v1, 0, uvverts);
- if(efa->v2->f1) append_weldedUV(em, efa, efa->v2, 1, uvverts);
- if(efa->v3->f1) append_weldedUV(em, efa, efa->v3, 2, uvverts);
- if(efa->v4 && efa->v4->f1) append_weldedUV(em, efa, efa->v4, 3, uvverts);
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
+ if(efa->v1->f1) append_weldedUV(efa, efa->v1, 0, uvverts);
+ if(efa->v2->f1) append_weldedUV(efa, efa->v2, 1, uvverts);
+ if(efa->v3->f1) append_weldedUV(efa, efa->v3, 2, uvverts);
+ if(efa->v4 && efa->v4->f1) append_weldedUV(efa, efa->v4, 3, uvverts);
}
}
-static void append_weldedUVEdge(EditMesh *em, EditFace *efa, EditEdge *eed, ListBase *uvedges)
+static void append_weldedUVEdge(EditFace *efa, EditEdge *eed, ListBase *uvedges)
{
wUVEdge *curwedge, *newwedge;
int v1tfindex, v2tfindex, found;
- MTFace *tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
+ MTFace *tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
+
found = 0;
-
+
if(eed->v1 == efa->v1) v1tfindex = 0;
else if(eed->v1 == efa->v2) v1tfindex = 1;
else if(eed->v1 == efa->v3) v1tfindex = 2;
else /* if(eed->v1 == efa->v4) */ v1tfindex = 3;
-
+
if(eed->v2 == efa->v1) v2tfindex = 0;
else if(eed->v2 == efa->v2) v2tfindex = 1;
else if(eed->v2 == efa->v3) v2tfindex = 2;
@@ -5526,7 +6230,7 @@ static void append_weldedUVEdge(EditMesh *em, EditFace *efa, EditEdge *eed, List
break; //do nothing, we don't need another welded uv edge
}
}
-
+
if(!found){
newwedge = MEM_callocN(sizeof(wUVEdge), "Welded UV Edge");
newwedge->v1uv[0] = tf->uv[v1tfindex][0];
@@ -5534,25 +6238,25 @@ static void append_weldedUVEdge(EditMesh *em, EditFace *efa, EditEdge *eed, List
newwedge->v2uv[0] = tf->uv[v2tfindex][0];
newwedge->v2uv[1] = tf->uv[v2tfindex][1];
newwedge->eed = eed;
-
+
BLI_addtail(uvedges, newwedge);
}
}
-static void build_weldedUVEdges(EditMesh *em, ListBase *uvedges, ListBase *uvverts)
+static void build_weldedUVEdges(ListBase *uvedges, ListBase *uvverts)
{
wUV *curwvert;
wUVEdge *curwedge;
EditFace *efa;
-
- for(efa=em->faces.first; efa; efa=efa->next){
- if(efa->e1->f1) append_weldedUVEdge(em, efa, efa->e1, uvedges);
- if(efa->e2->f1) append_weldedUVEdge(em, efa, efa->e2, uvedges);
- if(efa->e3->f1) append_weldedUVEdge(em, efa, efa->e3, uvedges);
- if(efa->e4 && efa->e4->f1) append_weldedUVEdge(em, efa, efa->e4, uvedges);
+
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
+ if(efa->e1->f1) append_weldedUVEdge(efa, efa->e1, uvedges);
+ if(efa->e2->f1) append_weldedUVEdge(efa, efa->e2, uvedges);
+ if(efa->e3->f1) append_weldedUVEdge(efa, efa->e3, uvedges);
+ if(efa->e4 && efa->e4->f1) append_weldedUVEdge(efa, efa->e4, uvedges);
}
-
-
+
+
//link vertices: for each uvedge, search uvverts to populate v1 and v2 pointers
for(curwedge=uvedges->first; curwedge; curwedge=curwedge->next){
for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){
@@ -5577,7 +6281,7 @@ static void free_weldedUVs(ListBase *uvverts)
BLI_freelistN(uvverts);
}
-static void collapse_edgeuvs(EditMesh *em)
+static void collapse_edgeuvs(void)
{
ListBase uvedges, uvverts, allcollections;
wUVEdge *curwedge;
@@ -5587,22 +6291,22 @@ static void collapse_edgeuvs(EditMesh *em)
int curtag, balanced, collectionfound= 0, vcount;
float avg[2];
- if (!EM_texFaceCheck(em))
+ if (!EM_texFaceCheck())
return;
-
+
uvverts.first = uvverts.last = uvedges.first = uvedges.last = allcollections.first = allcollections.last = NULL;
-
- build_weldedUVs(em, &uvverts);
- build_weldedUVEdges(em, &uvedges, &uvverts);
-
+
+ build_weldedUVs(&uvverts);
+ build_weldedUVEdges(&uvedges, &uvverts);
+
curtag = 0;
-
+
for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){
curwedge->v1->f = curtag;
curwedge->v2->f = curtag;
curtag +=1;
}
-
+
balanced = 0;
while(!balanced){
balanced = 1;
@@ -5614,10 +6318,10 @@ static void collapse_edgeuvs(EditMesh *em)
}
}
}
-
+
for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next) curwedge->f = curwedge->v1->f;
-
-
+
+
for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){
if(allcollections.first){
for(wuvecollection = allcollections.first; wuvecollection; wuvecollection=wuvecollection->next){
@@ -5628,7 +6332,7 @@ static void collapse_edgeuvs(EditMesh *em)
collectionfound = 1;
break;
}
-
+
else collectionfound = 0;
}
}
@@ -5637,32 +6341,32 @@ static void collapse_edgeuvs(EditMesh *em)
newcollection->index = curwedge->f;
newcollection->collectionbase.first = 0;
newcollection->collectionbase.last = 0;
-
+
newcollectedwuve = MEM_callocN(sizeof(wUVEdgeCollect), "Collected Welded UV Edge");
newcollectedwuve->uved = curwedge;
-
+
BLI_addtail(&(newcollection->collectionbase), newcollectedwuve);
BLI_addtail(&allcollections, newcollection);
}
}
-
+
for(wuvecollection=allcollections.first; wuvecollection; wuvecollection=wuvecollection->next){
-
+
vcount = avg[0] = avg[1] = 0;
-
+
for(collectedwuve= wuvecollection->collectionbase.first; collectedwuve; collectedwuve = collectedwuve->next){
avg[0] += collectedwuve->uved->v1uv[0];
avg[1] += collectedwuve->uved->v1uv[1];
-
+
avg[0] += collectedwuve->uved->v2uv[0];
avg[1] += collectedwuve->uved->v2uv[1];
-
+
vcount +=2;
-
+
}
-
+
avg[0] /= vcount; avg[1] /= vcount;
-
+
for(collectedwuve= wuvecollection->collectionbase.first; collectedwuve; collectedwuve = collectedwuve->next){
for(curwnode=collectedwuve->uved->v1->nodes.first; curwnode; curwnode=curwnode->next){
*(curwnode->u) = avg[0];
@@ -5674,7 +6378,7 @@ static void collapse_edgeuvs(EditMesh *em)
}
}
}
-
+
free_weldedUVs(&uvverts);
BLI_freelistN(&uvedges);
freecollections(&allcollections);
@@ -5682,22 +6386,22 @@ static void collapse_edgeuvs(EditMesh *em)
/*End UV Edge collapse code*/
-static void collapseuvs(EditMesh *em, EditVert *mergevert)
+static void collapseuvs(EditVert *mergevert)
{
EditFace *efa;
MTFace *tf;
int uvcount;
float uvav[2];
- if (!EM_texFaceCheck(em))
+ if (!EM_texFaceCheck())
return;
-
+
uvcount = 0;
uvav[0] = 0;
uvav[1] = 0;
-
- for(efa = em->faces.first; efa; efa=efa->next){
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ for(efa = G.editMesh->faces.first; efa; efa=efa->next){
+ tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
if(efa->v1->f1 && ELEM(mergevert, NULL, efa->v1)) {
uvav[0] += tf->uv[0][0];
@@ -5705,7 +6409,7 @@ static void collapseuvs(EditMesh *em, EditVert *mergevert)
uvcount += 1;
}
if(efa->v2->f1 && ELEM(mergevert, NULL, efa->v2)){
- uvav[0] += tf->uv[1][0];
+ uvav[0] += tf->uv[1][0];
uvav[1] += tf->uv[1][1];
uvcount += 1;
}
@@ -5720,20 +6424,20 @@ static void collapseuvs(EditMesh *em, EditVert *mergevert)
uvcount += 1;
}
}
-
+
if(uvcount > 0) {
- uvav[0] /= uvcount;
+ uvav[0] /= uvcount;
uvav[1] /= uvcount;
-
- for(efa = em->faces.first; efa; efa=efa->next){
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ for(efa = G.editMesh->faces.first; efa; efa=efa->next){
+ tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
if(efa->v1->f1){
tf->uv[0][0] = uvav[0];
tf->uv[0][1] = uvav[1];
}
if(efa->v2->f1){
- tf->uv[1][0] = uvav[0];
+ tf->uv[1][0] = uvav[0];
tf->uv[1][1] = uvav[1];
}
if(efa->v3->f1){
@@ -5748,352 +6452,192 @@ static void collapseuvs(EditMesh *em, EditVert *mergevert)
}
}
-static int collapseEdges(EditMesh *em)
+int collapseEdges(void)
{
EditVert *eve;
EditEdge *eed;
-
+
ListBase allcollections;
CollectedEdge *curredge;
Collection *edgecollection;
-
- int totedges, mergecount,vcount /*, groupcount*/;
+
+ int totedges, groupcount, mergecount,vcount;
float avgcount[3];
-
+
allcollections.first = 0;
allcollections.last = 0;
-
+
mergecount = 0;
-
- build_edgecollection(em, &allcollections);
- /*groupcount = BLI_countlist(&allcollections);*/ /*UNUSED*/
-
-
+
+ if(multires_test()) return 0;
+
+ build_edgecollection(&allcollections);
+ groupcount = BLI_countlist(&allcollections);
+
+
for(edgecollection = allcollections.first; edgecollection; edgecollection = edgecollection->next){
totedges = BLI_countlist(&(edgecollection->collectionbase));
mergecount += totedges;
avgcount[0] = 0; avgcount[1] = 0; avgcount[2] = 0;
-
+
vcount = 0;
-
+
for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
avgcount[0] += ((EditEdge*)curredge->eed)->v1->co[0];
avgcount[1] += ((EditEdge*)curredge->eed)->v1->co[1];
avgcount[2] += ((EditEdge*)curredge->eed)->v1->co[2];
-
+
avgcount[0] += ((EditEdge*)curredge->eed)->v2->co[0];
avgcount[1] += ((EditEdge*)curredge->eed)->v2->co[1];
avgcount[2] += ((EditEdge*)curredge->eed)->v2->co[2];
-
+
vcount +=2;
}
-
+
avgcount[0] /= vcount; avgcount[1] /=vcount; avgcount[2] /= vcount;
-
+
for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
VECCOPY(((EditEdge*)curredge->eed)->v1->co,avgcount);
VECCOPY(((EditEdge*)curredge->eed)->v2->co,avgcount);
}
-
- if (EM_texFaceCheck(em)) {
+
+ if (EM_texFaceCheck()) {
/*uv collapse*/
- for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
- for(eed=em->edges.first; eed; eed=eed->next) eed->f1 = 0;
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0;
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0;
for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
curredge->eed->v1->f1 = 1;
curredge->eed->v2->f1 = 1;
curredge->eed->f1 = 1;
}
- collapse_edgeuvs(em);
+ collapse_edgeuvs();
}
-
+
}
freecollections(&allcollections);
- removedoublesflag(em, 1, 0, MERGELIMIT);
-
+ removedoublesflag(1, 0, MERGELIMIT);
+ /*get rid of this!*/
+ countall();
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ if (EM_texFaceCheck())
+ allqueue(REDRAWIMAGE, 0);
return mergecount;
}
-static int merge_firstlast(EditMesh *em, int first, int uvmerge)
+int merge_firstlast(int first, int uvmerge)
{
EditVert *eve,*mergevert;
EditSelection *ese;
-
+
+ if(multires_test()) return 0;
+
/* do sanity check in mergemenu in edit.c ?*/
- if(first == 0){
- ese = em->selected.last;
+ if(first == 0){
+ ese = G.editMesh->selected.last;
mergevert= (EditVert*)ese->data;
}
- else{
- ese = em->selected.first;
+ else{
+ ese = G.editMesh->selected.first;
mergevert = (EditVert*)ese->data;
}
-
+
if(mergevert->f&SELECT){
- for (eve=em->verts.first; eve; eve=eve->next){
+ for (eve=G.editMesh->verts.first; eve; eve=eve->next){
if (eve->f&SELECT)
VECCOPY(eve->co,mergevert->co);
}
}
-
- if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){
-
- for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
- for(eve=em->verts.first; eve; eve=eve->next){
- if(eve->f&SELECT) eve->f1 = 1;
- }
- collapseuvs(em, mergevert);
- }
-
- return removedoublesflag(em, 1, 0, MERGELIMIT);
-}
-
-static void em_snap_to_center(EditMesh *em)
-{
- EditVert *eve;
- float cent[3] = {0.0f, 0.0f, 0.0f};
- int i=0;
-
- for (eve=em->verts.first; eve; eve=eve->next) {
- if (eve->f & SELECT) {
- add_v3_v3(cent, eve->co);
- i++;
- }
- }
-
- if (!i)
- return;
-
- mul_v3_fl(cent, 1.0f / (float)i);
-
- for (eve=em->verts.first; eve; eve=eve->next) {
- if (eve->f & SELECT) {
- VECCOPY(eve->co, cent);
- }
- }
-}
-
-static void em_snap_to_cursor(EditMesh *em, bContext *C)
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob= CTX_data_edit_object(C);
- View3D *v3d = CTX_wm_view3d(C);
- EditVert *eve;
- float co[3], *vco, invmat[4][4];
+
+ if(uvmerge && CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE)){
- invert_m4_m4(invmat, ob->obmat);
-
- vco = give_cursor(scene, v3d);
- VECCOPY(co, vco);
- mul_m4_v3(invmat, co);
-
- for (eve=em->verts.first; eve; eve=eve->next) {
- if (eve->f & SELECT) {
- VECCOPY(eve->co, co);
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0;
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next){
+ if(eve->f&SELECT) eve->f1 = 1;
}
+ collapseuvs(mergevert);
}
+
+ countall();
+ return removedoublesflag(1, 0, MERGELIMIT);
}
-static int merge_target(bContext *C, EditMesh *em, int target, int uvmerge)
+int merge_target(int target, int uvmerge)
{
EditVert *eve;
-
- // XXX not working
- if(target) em_snap_to_cursor(em, C);
- else em_snap_to_center(em);
-
- if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){
- for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
- for(eve=em->verts.first; eve; eve=eve->next){
+
+ if(multires_test()) return 0;
+
+ if(target) snap_sel_to_curs();
+ else snap_to_center();
+
+ if(uvmerge && CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE)){
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0;
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next){
if(eve->f&SELECT) eve->f1 = 1;
}
- collapseuvs(em, NULL);
+ collapseuvs(NULL);
}
-
- return removedoublesflag(em, 1, 0, MERGELIMIT);
-}
-#undef MERGELIMIT
-
-static int merge_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
- int count= 0, uvs= RNA_boolean_get(op->ptr, "uvs");
- EditSelection *ese;
- int totvert= em->totvert, totedge= em->totedge, totface= em->totface;
-
- switch(RNA_enum_get(op->ptr, "type")) {
- case 3:
- count = merge_target(C, em, 0, uvs);
- break;
- case 4:
- count = merge_target(C, em, 1, uvs);
- break;
- case 1:
- ese= (EditSelection *)em->selected.last;
- if(ese && ese->type == EDITVERT) {
- count = merge_firstlast(em, 0, uvs);
- } else {
- BKE_report(op->reports, RPT_WARNING, "no last selected vertex set");
- }
- break;
- case 6:
- ese= (EditSelection *)em->selected.first;
- if(ese && ese->type == EDITVERT) {
- count = merge_firstlast(em, 1, uvs);
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "no last selected vertex set");
- }
- break;
- case 5:
- count = collapseEdges(em);
- break;
- }
-
- if (!(totvert != em->totvert || totedge != em->totedge || totface != em->totface))
- return OPERATOR_CANCELLED;
-
- recalc_editnormals(em);
- BKE_reportf(op->reports, RPT_INFO, "Removed %d vert%s", count, (count==1)?"ex":"ices");
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-static EnumPropertyItem merge_type_items[]= {
- {6, "FIRST", 0, "At First", ""},
- {1, "LAST", 0, "At Last", ""},
- {3, "CENTER", 0, "At Center", ""},
- {4, "CURSOR", 0, "At Cursor", ""},
- {5, "COLLAPSE", 0, "Collapse", ""},
- {0, NULL, 0, NULL, NULL}};
-
-static EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
-{
- Object *obedit= CTX_data_edit_object(C);
- EnumPropertyItem *item= NULL;
- int totitem= 0;
-
- if (C==NULL) {
- return merge_type_items;
- }
-
- if(obedit && obedit->type == OB_MESH) {
- EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
-
- if(em->selectmode & SCE_SELECT_VERTEX) {
- if(em->selected.first && em->selected.last &&
- ((EditSelection*)em->selected.first)->type == EDITVERT && ((EditSelection*)em->selected.last)->type == EDITVERT) {
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
- }
- else if(em->selected.first && ((EditSelection*)em->selected.first)->type == EDITVERT)
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
- else if(em->selected.last && ((EditSelection*)em->selected.last)->type == EDITVERT)
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
- }
-
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 3);
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 4);
- RNA_enum_items_add_value(&item, &totitem, merge_type_items, 5);
- }
-
- RNA_enum_item_end(&item, &totitem);
- *free= 1;
-
- return item;
-}
-
-void MESH_OT_merge(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Merge";
- ot->description= "Merge selected vertices";
- ot->idname= "MESH_OT_merge";
-
- /* api callbacks */
- ot->exec= merge_exec;
- ot->invoke= WM_menu_invoke;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- prop= RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use");
- RNA_def_enum_funcs(prop, merge_type_itemf);
- ot->prop= prop;
- RNA_def_boolean(ot->srna, "uvs", 0, "UVs", "Move UVs according to merge");
+ countall();
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ return removedoublesflag(1, 0, MERGELIMIT);
+
}
+#undef MERGELIMIT
-/************************ Vertex Path Operator *************************/
-
-typedef struct PathNode {
+typedef struct PathNode{
int u;
int visited;
ListBase edges;
} PathNode;
-typedef struct PathEdge {
+typedef struct PathEdge{
struct PathEdge *next, *prev;
int v;
float w;
} PathEdge;
-#define PATH_SELECT_EDGE_LENGTH 0
-#define PATH_SELECT_TOPOLOGICAL 1
-
-static int select_vertex_path_exec(bContext *C, wmOperator *op)
+void pathselect(void)
{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
EditVert *eve, *s, *t;
EditEdge *eed;
+ EditSelection *ese;
PathEdge *newpe, *currpe;
PathNode *currpn;
PathNode *Q;
int v, *previous, pathvert, pnindex; /*pnindex redundant?*/
- int unbalanced, totnodes;
+ int unbalanced, totnodes;
+ short physical;
float *cost;
- int type= RNA_enum_get(op->ptr, "type");
Heap *heap; /*binary heap for sorting pointers to PathNodes based upon a 'cost'*/
-
+
s = t = NULL;
- for(eve=em->verts.first; eve; eve=eve->next) {
- if(eve->f&SELECT) {
- if(s == NULL) s= eve;
- else if(t == NULL) t= eve;
- else {
- /* more than two vertices are selected,
- show warning message and cancel operator */
- s = t = NULL;
- break;
- }
-
- }
-
+
+ countall(); /*paranoid?*/
+
+ ese = ((EditSelection*)G.editMesh->selected.last);
+ if(ese && ese->type == EDITVERT && ese->prev && ese->prev->type == EDITVERT){
+ physical= pupmenu("Distance Method? %t|Edge Length%x1|Topological%x0");
+
+ t = (EditVert*)ese->data;
+ s = (EditVert*)ese->prev->data;
+
/*need to find out if t is actually reachable by s....*/
- eve->f1 = 0;
- }
-
- if(s != NULL && t != NULL) {
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next){
+ eve->f1 = 0;
+ }
+
s->f1 = 1;
-
+
unbalanced = 1;
totnodes = 1;
while(unbalanced){
unbalanced = 0;
- for(eed=em->edges.first; eed; eed=eed->next){
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next){
if(!eed->h){
- if(eed->v1->f1 && !eed->v2->f1){
+ if(eed->v1->f1 && !eed->v2->f1){
eed->v2->f1 = 1;
totnodes++;
unbalanced = 1;
@@ -6106,11 +6650,13 @@ static int select_vertex_path_exec(bContext *C, wmOperator *op)
}
}
}
-
- if(s->f1 && t->f1){ /* t can be reached by s */
+
+
+
+ if(s->f1 && t->f1){ /*t can be reached by s*/
Q = MEM_callocN(sizeof(PathNode)*totnodes, "Path Select Nodes");
totnodes = 0;
- for(eve=em->verts.first; eve; eve=eve->next){
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next){
if(eve->f1){
Q[totnodes].u = totnodes;
Q[totnodes].edges.first = 0;
@@ -6121,27 +6667,27 @@ static int select_vertex_path_exec(bContext *C, wmOperator *op)
}
else eve->tmp.p = NULL;
}
-
- for(eed=em->edges.first; eed; eed=eed->next){
+
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next){
if(!eed->h){
if(eed->v1->f1){
currpn = ((PathNode*)eed->v1->tmp.p);
-
+
newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge");
newpe->v = ((PathNode*)eed->v2->tmp.p)->u;
- if (type == PATH_SELECT_EDGE_LENGTH) {
+ if(physical){
newpe->w = len_v3v3(eed->v1->co, eed->v2->co);
}
else newpe->w = 1;
newpe->next = 0;
newpe->prev = 0;
BLI_addtail(&(currpn->edges), newpe);
- }
+ }
if(eed->v2->f1){
- currpn = ((PathNode*)eed->v2->tmp.p);
+ currpn = ((PathNode*)eed->v2->tmp.p);
newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge");
newpe->v = ((PathNode*)eed->v1->tmp.p)->u;
- if (type == PATH_SELECT_EDGE_LENGTH) {
+ if(physical){
newpe->w = len_v3v3(eed->v1->co, eed->v2->co);
}
else newpe->w = 1;
@@ -6151,28 +6697,28 @@ static int select_vertex_path_exec(bContext *C, wmOperator *op)
}
}
}
-
+
heap = BLI_heap_new();
cost = MEM_callocN(sizeof(float)*totnodes, "Path Select Costs");
previous = MEM_callocN(sizeof(int)*totnodes, "PathNode indices");
-
+
for(v=0; v < totnodes; v++){
cost[v] = 1000000;
previous[v] = -1; /*array of indices*/
}
-
+
pnindex = ((PathNode*)s->tmp.p)->u;
cost[pnindex] = 0;
BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(pnindex));
-
+
while( !BLI_heap_empty(heap) ){
-
+
pnindex = GET_INT_FROM_POINTER(BLI_heap_popmin(heap));
currpn = &(Q[pnindex]);
-
+
if(currpn == (PathNode*)t->tmp.p) /*target has been reached....*/
break;
-
+
for(currpe=currpn->edges.first; currpe; currpe=currpe->next){
if(!Q[currpe->v].visited){
if( cost[currpe->v] > (cost[currpn->u ] + currpe->w) ){
@@ -6184,125 +6730,78 @@ static int select_vertex_path_exec(bContext *C, wmOperator *op)
}
}
}
-
+
pathvert = ((PathNode*)t->tmp.p)->u;
while(pathvert != -1){
- for(eve=em->verts.first; eve; eve=eve->next){
+ for(eve=G.editMesh->verts.first; eve; eve=eve->next){
if(eve->f1){
if( ((PathNode*)eve->tmp.p)->u == pathvert) eve->f |= SELECT;
}
}
pathvert = previous[pathvert];
}
-
+
for(v=0; v < totnodes; v++) BLI_freelistN(&(Q[v].edges));
MEM_freeN(Q);
MEM_freeN(cost);
MEM_freeN(previous);
BLI_heap_free(heap, NULL);
- EM_select_flush(em);
+ EM_select_flush();
+ countall();
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ if (EM_texFaceCheck())
+ allqueue(REDRAWIMAGE, 0);
}
}
- else {
- BKE_mesh_end_editmesh(obedit->data, em);
- BKE_report(op->reports, RPT_WARNING, "Path Selection requires that exactly two vertices be selected");
- return OPERATOR_CANCELLED;
+ else{
+ error("Path Selection requires that exactly two vertices be selected");
+ return;
}
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_vertex_path(wmOperatorType *ot)
-{
- static const EnumPropertyItem type_items[] = {
- {PATH_SELECT_EDGE_LENGTH, "EDGE_LENGTH", 0, "Edge Length", NULL},
- {PATH_SELECT_TOPOLOGICAL, "TOPOLOGICAL", 0, "Topological", NULL},
- {0, NULL, 0, NULL, NULL}};
-
- /* identifiers */
- ot->name= "Select Vertex Path";
- ot->description= "Select shortest path between two vertices by distance type";
- ot->idname= "MESH_OT_select_vertex_path";
-
- /* api callbacks */
- ot->exec= select_vertex_path_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- ot->prop= RNA_def_enum(ot->srna, "type", type_items, PATH_SELECT_EDGE_LENGTH, "Type", "Method to compute distance");
}
-/********************** Region/Loop Operators *************************/
-
-static int region_to_loop(bContext *C, wmOperator *UNUSED(op))
+void region_to_loop(void)
{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
EditEdge *eed;
EditFace *efa;
- int selected= 0;
-
- for(eed=em->edges.first; eed; eed=eed->next) eed->f1 = 0;
-
- for(efa=em->faces.first; efa; efa=efa->next){
- if(efa->f&SELECT){
- efa->e1->f1++;
- efa->e2->f1++;
- efa->e3->f1++;
- if(efa->e4)
- efa->e4->f1++;
-
- selected= 1;
+
+ if(G.totfacesel){
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0;
+
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
+ if(efa->f&SELECT){
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4)
+ efa->e4->f1++;
+ }
}
- }
-
- if(!selected)
- return OPERATOR_CANCELLED;
-
- EM_clear_flag_all(em, SELECT);
+
+ EM_clear_flag_all(SELECT);
+
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next){
+ if(eed->f1 == 1) EM_select_edge(eed, 1);
+ }
+
+ G.scene->selectmode = SCE_SELECT_EDGE;
+ EM_selectmode_set();
+ countall();
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ if (EM_texFaceCheck())
+ allqueue(REDRAWIMAGE, 0);
+ BIF_undo_push("Face Region to Edge Loop");
- for(eed=em->edges.first; eed; eed=eed->next){
- if(eed->f1 == 1) EM_select_edge(eed, 1);
}
-
- em->selectmode = SCE_SELECT_EDGE;
- CTX_data_tool_settings(C)->selectmode= em->selectmode;
- EM_selectmode_set(em);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
}
-void MESH_OT_region_to_loop(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Region to Loop";
- ot->description= "Select a region as a loop of connected edges";
- ot->idname= "MESH_OT_region_to_loop";
-
- /* api callbacks */
- ot->exec= region_to_loop;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int validate_loop(EditMesh *em, Collection *edgecollection)
+static int validate_loop(Collection *edgecollection)
{
EditEdge *eed;
EditFace *efa;
CollectedEdge *curredge;
-
+
/*1st test*/
for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
curredge->eed->v1->f1 = 0;
@@ -6316,10 +6815,10 @@ static int validate_loop(EditMesh *em, Collection *edgecollection)
if(curredge->eed->v1->f1 > 2) return(0); else
if(curredge->eed->v2->f1 > 2) return(0);
}
-
+
/*2nd test*/
- for(eed = em->edges.first; eed; eed=eed->next) eed->f1 = 0;
- for(efa=em->faces.first; efa; efa=efa->next){
+ for(eed = G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0;
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
efa->e1->f1++;
efa->e2->f1++;
efa->e3->f1++;
@@ -6331,22 +6830,22 @@ static int validate_loop(EditMesh *em, Collection *edgecollection)
return(1);
}
-static int loop_bisect(EditMesh *em, Collection *edgecollection){
-
+static int loop_bisect(Collection *edgecollection){
+
EditFace *efa, *sf1, *sf2;
EditEdge *eed, *sed;
CollectedEdge *curredge;
int totsf1, totsf2, unbalanced,balancededges;
-
- for(eed=em->edges.first; eed; eed=eed->next) eed->f1 = eed->f2 = 0;
- for(efa=em->faces.first; efa; efa=efa->next) efa->f1 = 0;
-
+
+ for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = eed->f2 = 0;
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next) efa->f1 = 0;
+
for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next) curredge->eed->f1 = 1;
-
+
sf1 = sf2 = NULL;
sed = ((CollectedEdge*)edgecollection->collectionbase.first)->eed;
-
- for(efa=em->faces.first; efa; efa=efa->next){
+
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
if(sf2) break;
else if(sf1){
if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf2 = efa;
@@ -6355,29 +6854,29 @@ static int loop_bisect(EditMesh *em, Collection *edgecollection){
if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf1 = efa;
}
}
-
+
if(sf1==NULL || sf2==NULL)
return(-1);
-
+
if(!(sf1->e1->f1)) sf1->e1->f2 = 1;
if(!(sf1->e2->f1)) sf1->e2->f2 = 1;
if(!(sf1->e3->f1)) sf1->e3->f2 = 1;
if(sf1->e4 && !(sf1->e4->f1)) sf1->e4->f2 = 1;
sf1->f1 = 1;
totsf1 = 1;
-
+
if(!(sf2->e1->f1)) sf2->e1->f2 = 2;
if(!(sf2->e2->f1)) sf2->e2->f2 = 2;
if(!(sf2->e3->f1)) sf2->e3->f2 = 2;
if(sf2->e4 && !(sf2->e4->f1)) sf2->e4->f2 = 2;
sf2->f1 = 2;
totsf2 = 1;
-
+
/*do sf1*/
unbalanced = 1;
while(unbalanced){
unbalanced = 0;
- for(efa=em->faces.first; efa; efa=efa->next){
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
balancededges = 0;
if(efa->f1 == 0){
if(efa->e1->f2 == 1 || efa->e2->f2 == 1 || efa->e3->f2 == 1 || ( (efa->e4) ? efa->e4->f2 == 1 : 0) ){
@@ -6394,12 +6893,12 @@ static int loop_bisect(EditMesh *em, Collection *edgecollection){
}
}
}
-
+
/*do sf2*/
unbalanced = 1;
while(unbalanced){
unbalanced = 0;
- for(efa=em->faces.first; efa; efa=efa->next){
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
balancededges = 0;
if(efa->f1 == 0){
if(efa->e1->f2 == 2 || efa->e2->f2 == 2 || efa->e3->f2 == 2 || ( (efa->e4) ? efa->e4->f2 == 2 : 0) ){
@@ -6416,28 +6915,24 @@ static int loop_bisect(EditMesh *em, Collection *edgecollection){
}
}
}
-
+
if(totsf1 < totsf2) return(1);
else return(2);
}
-static int loop_to_region(bContext *C, wmOperator *UNUSED(op))
+void loop_to_region(void)
{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
-
EditFace *efa;
ListBase allcollections={NULL,NULL};
Collection *edgecollection;
int testflag;
-
- build_edgecollection(em, &allcollections);
-
+
+ build_edgecollection(&allcollections);
+
for(edgecollection = (Collection *)allcollections.first; edgecollection; edgecollection=edgecollection->next){
- if(validate_loop(em, edgecollection)){
- testflag = loop_bisect(em, edgecollection);
- for(efa=em->faces.first; efa; efa=efa->next){
+ if(validate_loop(edgecollection)){
+ testflag = loop_bisect(edgecollection);
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){
if(efa->f1 == testflag){
if(efa->f&SELECT) EM_select_face(efa, 0);
else EM_select_face(efa,1);
@@ -6445,90 +6940,72 @@ static int loop_to_region(bContext *C, wmOperator *UNUSED(op))
}
}
}
-
- for(efa=em->faces.first; efa; efa=efa->next){ /*fix this*/
+
+ for(efa=G.editMesh->faces.first; efa; efa=efa->next){ /*fix this*/
if(efa->f&SELECT) EM_select_face(efa,1);
}
-
+
+ countall();
freecollections(&allcollections);
- BKE_mesh_end_editmesh(obedit->data, em);
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ if (EM_texFaceCheck())
+ allqueue(REDRAWIMAGE, 0);
+ BIF_undo_push("Edge Loop to Face Region");
}
-void MESH_OT_loop_to_region(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Loop to Region";
- ot->description= "Select a loop of connected edges as a region";
- ot->idname= "MESH_OT_loop_to_region";
- /* api callbacks */
- ot->exec= loop_to_region;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/********************** UV/Color Operators *************************/
-
-// XXX please check if these functions do what you want them to
/* texface and vertex color editmode tools for the face menu */
-static int mesh_rotate_uvs(bContext *C, wmOperator *op)
+void mesh_rotate_uvs(void)
{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
+ EditMesh *em = G.editMesh;
EditFace *efa;
- short change = 0;
+ short change = 0, ccw;
MTFace *tf;
float u1, v1;
- int dir= RNA_enum_get(op->ptr, "direction");
-
- if (!EM_texFaceCheck(em)) {
- BKE_report(op->reports, RPT_WARNING, "Mesh has no uv/image layers");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
+
+ if (!EM_texFaceCheck()) {
+ error("mesh has no uv/image layers");
+ return;
}
-
+
+ ccw = (G.qual == LR_SHIFTKEY);
+
for(efa=em->faces.first; efa; efa=efa->next) {
if (efa->f & SELECT) {
tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
u1= tf->uv[0][0];
v1= tf->uv[0][1];
-
- if (dir == DIRECTION_CCW) {
+
+ if (ccw) {
if(efa->v4) {
tf->uv[0][0]= tf->uv[3][0];
tf->uv[0][1]= tf->uv[3][1];
-
+
tf->uv[3][0]= tf->uv[2][0];
tf->uv[3][1]= tf->uv[2][1];
} else {
tf->uv[0][0]= tf->uv[2][0];
tf->uv[0][1]= tf->uv[2][1];
}
-
+
tf->uv[2][0]= tf->uv[1][0];
tf->uv[2][1]= tf->uv[1][1];
-
+
tf->uv[1][0]= u1;
tf->uv[1][1]= v1;
- } else {
+ } else {
tf->uv[0][0]= tf->uv[1][0];
tf->uv[0][1]= tf->uv[1][1];
-
+
tf->uv[1][0]= tf->uv[2][0];
tf->uv[1][1]= tf->uv[2][1];
-
+
if(efa->v4) {
tf->uv[2][0]= tf->uv[3][0];
tf->uv[2][1]= tf->uv[3][1];
-
+
tf->uv[3][0]= u1;
tf->uv[3][1]= v1;
}
@@ -6540,46 +7017,40 @@ static int mesh_rotate_uvs(bContext *C, wmOperator *op)
change = 1;
}
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- if(!change)
- return OPERATOR_CANCELLED;
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
+
+ if (change) {
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ BIF_undo_push("Rotate UV face");
+ }
}
-static int mesh_mirror_uvs(bContext *C, wmOperator *op)
+void mesh_mirror_uvs(void)
{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
+ EditMesh *em = G.editMesh;
EditFace *efa;
- short change = 0;
+ short change = 0, altaxis;
MTFace *tf;
float u1, v1;
- int axis= RNA_enum_get(op->ptr, "axis");
-
- if (!EM_texFaceCheck(em)) {
- BKE_report(op->reports, RPT_WARNING, "Mesh has no uv/image layers");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
+
+ if (!EM_texFaceCheck()) {
+ error("mesh has no uv/image layers");
+ return;
}
-
+
+ altaxis = (G.qual == LR_SHIFTKEY);
+
for(efa=em->faces.first; efa; efa=efa->next) {
if (efa->f & SELECT) {
tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if (axis == AXIS_Y) {
+ if (altaxis) {
u1= tf->uv[1][0];
v1= tf->uv[1][1];
if(efa->v4) {
-
+
tf->uv[1][0]= tf->uv[2][0];
tf->uv[1][1]= tf->uv[2][1];
-
+
tf->uv[2][0]= u1;
tf->uv[2][1]= v1;
@@ -6588,7 +7059,7 @@ static int mesh_mirror_uvs(bContext *C, wmOperator *op)
tf->uv[3][0]= tf->uv[0][0];
tf->uv[3][1]= tf->uv[0][1];
-
+
tf->uv[0][0]= u1;
tf->uv[0][1]= v1;
}
@@ -6598,15 +7069,15 @@ static int mesh_mirror_uvs(bContext *C, wmOperator *op)
tf->uv[2][0]= u1;
tf->uv[2][1]= v1;
}
-
+
} else {
u1= tf->uv[0][0];
v1= tf->uv[0][1];
if(efa->v4) {
-
+
tf->uv[0][0]= tf->uv[1][0];
tf->uv[0][1]= tf->uv[1][1];
-
+
tf->uv[1][0]= u1;
tf->uv[1][1]= v1;
@@ -6615,7 +7086,7 @@ static int mesh_mirror_uvs(bContext *C, wmOperator *op)
tf->uv[3][0]= tf->uv[2][0];
tf->uv[3][1]= tf->uv[2][1];
-
+
tf->uv[2][0]= u1;
tf->uv[2][1]= v1;
}
@@ -6629,40 +7100,33 @@ static int mesh_mirror_uvs(bContext *C, wmOperator *op)
change = 1;
}
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- if(!change)
- return OPERATOR_CANCELLED;
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
+
+ if (change) {
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ BIF_undo_push("Mirror UV face");
+ }
}
-static int mesh_rotate_colors(bContext *C, wmOperator *op)
+void mesh_rotate_colors(void)
{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
+ EditMesh *em = G.editMesh;
EditFace *efa;
- short change = 0;
+ short change = 0, ccw;
MCol tmpcol, *mcol;
- int dir= RNA_enum_get(op->ptr, "direction");
-
- if (!EM_vertColorCheck(em)) {
- BKE_report(op->reports, RPT_WARNING, "Mesh has no color layers");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
+ if (!EM_vertColorCheck()) {
+ error("mesh has no color layers");
+ return;
}
-
+
+ ccw = (G.qual == LR_SHIFTKEY);
+
for(efa=em->faces.first; efa; efa=efa->next) {
if (efa->f & SELECT) {
mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
tmpcol= mcol[0];
-
- if (dir == DIRECTION_CCW) {
+
+ if (ccw) {
if(efa->v4) {
mcol[0]= mcol[3];
mcol[3]= mcol[2];
@@ -6674,7 +7138,7 @@ static int mesh_rotate_colors(bContext *C, wmOperator *op)
} else {
mcol[0]= mcol[1];
mcol[1]= mcol[2];
-
+
if(efa->v4) {
mcol[2]= mcol[3];
mcol[3]= tmpcol;
@@ -6685,43 +7149,35 @@ static int mesh_rotate_colors(bContext *C, wmOperator *op)
change = 1;
}
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- if(!change)
- return OPERATOR_CANCELLED;
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
+
+ if (change) {
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ BIF_undo_push("Rotate Color face");
+ }
}
-
-static int mesh_mirror_colors(bContext *C, wmOperator *op)
+void mesh_mirror_colors(void)
{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
+ EditMesh *em = G.editMesh;
EditFace *efa;
- short change = 0;
+ short change = 0, altaxis;
MCol tmpcol, *mcol;
- int axis= RNA_enum_get(op->ptr, "axis");
-
- if (!EM_vertColorCheck(em)) {
- BKE_report(op->reports, RPT_WARNING, "Mesh has no color layers");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
+ if (!EM_vertColorCheck()) {
+ error("mesh has no color layers");
+ return;
}
-
+
+ altaxis = (G.qual == LR_SHIFTKEY);
+
for(efa=em->faces.first; efa; efa=efa->next) {
if (efa->f & SELECT) {
mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
- if (axis == AXIS_Y) {
+ if (altaxis) {
tmpcol= mcol[1];
mcol[1]= mcol[2];
mcol[2]= tmpcol;
-
+
if(efa->v4) {
tmpcol= mcol[0];
mcol[0]= mcol[3];
@@ -6731,7 +7187,7 @@ static int mesh_mirror_colors(bContext *C, wmOperator *op)
tmpcol= mcol[0];
mcol[0]= mcol[1];
mcol[1]= tmpcol;
-
+
if(efa->v4) {
tmpcol= mcol[2];
mcol[2]= mcol[3];
@@ -6741,865 +7197,10 @@ static int mesh_mirror_colors(bContext *C, wmOperator *op)
change = 1;
}
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- if(!change)
- return OPERATOR_CANCELLED;
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_uvs_rotate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Rotate UVs";
- ot->description= "Rotate selected UVs";
- ot->idname= "MESH_OT_uvs_rotate";
-
- /* api callbacks */
- ot->exec= mesh_rotate_uvs;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate UVs around");
-}
-
-void MESH_OT_uvs_mirror(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Mirror UVs";
- ot->description= "Mirror selected UVs";
- ot->idname= "MESH_OT_uvs_mirror";
-
- /* api callbacks */
- ot->exec= mesh_mirror_uvs;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "axis", axis_items_xy, DIRECTION_CW, "Axis", "Axis to mirror UVs around");
-}
-
-void MESH_OT_colors_rotate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Rotate Colors";
- ot->description= "Rotate UV/image color layer";
- ot->idname= "MESH_OT_colors_rotate";
-
- /* api callbacks */
- ot->exec= mesh_rotate_colors;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate edge around");
-}
-
-void MESH_OT_colors_mirror(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Mirror Colors";
- ot->description= "Mirror UV/image color layer";
- ot->idname= "MESH_OT_colors_mirror";
-
- /* api callbacks */
- ot->exec= mesh_mirror_colors;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "axis", axis_items_xy, DIRECTION_CW, "Axis", "Axis to mirror colors around");
-}
-
-/********************** Subdivide Operator *************************/
-
-static int subdivide_exec(bContext *C, wmOperator *op)
-{
- ToolSettings *ts= CTX_data_tool_settings(C);
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
- int cuts= RNA_int_get(op->ptr,"number_cuts");
- float smooth= 0.292f*RNA_float_get(op->ptr, "smoothness");
- float fractal= RNA_float_get(op->ptr, "fractal")/100;
- int corner_cut_pattern= RNA_enum_get(op->ptr,"corner_cut_pattern");
- int flag= 0;
-
- if(smooth != 0.0f)
- flag |= B_SMOOTH;
- if(fractal != 0.0f)
- flag |= B_FRACTAL;
-
- esubdivideflag(obedit, em, 1, smooth, fractal, ts->editbutflag|flag, cuts, corner_cut_pattern, 0);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_subdivide(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Subdivide";
- ot->description= "Subdivide selected edges";
- ot->idname= "MESH_OT_subdivide";
-
- /* api callbacks */
- ot->exec= subdivide_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of Cuts", "", 1, 10);
- RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, FLT_MAX, "Smoothness", "Smoothness factor", 0.0f, 1.0f);
- RNA_def_float(ot->srna, "fractal", 0.0, 0.0f, FLT_MAX, "Fractal", "Fractal randomness factor", 0.0f, 1000.0f);
- RNA_def_enum(ot->srna, "corner_cut_pattern", corner_type_items, SUBDIV_CORNER_INNERVERT, "Corner Cut Pattern", "Topology pattern to use to fill a face after cutting across its corner");
-}
-
-/********************** Fill Operators *************************/
-
-/* note; the EM_selectmode_set() calls here illustrate how badly constructed it all is... from before the
-edge/face flags, with very mixed results.... */
-static void beautify_fill(EditMesh *em)
-{
- EditVert *v1, *v2, *v3, *v4;
- EditEdge *eed, *nexted;
- EditEdge dia1, dia2;
- EditFace *efa, *w;
- // void **efaar, **efaa;
- EVPTuple *efaar;
- EVPtr *efaa;
- float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
- int totedge, ok, notbeauty=8, onedone, vindex[4];
-
- /* - all selected edges with two faces
- * - find the faces: store them in edges (using datablock)
- * - per edge: - test convex
- * - test edge: flip?
- * - if true: remedge, addedge, all edges at the edge get new face pointers
- */
-
- EM_selectmode_set(em); // makes sure in selectmode 'face' the edges of selected faces are selected too
-
- totedge = count_selected_edges(em->edges.first);
- if(totedge==0) return;
-
- /* temp block with face pointers */
- efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "beautyfill");
-
- while (notbeauty) {
- notbeauty--;
-
- ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
-
- /* there we go */
- onedone= 0;
-
- eed= em->edges.first;
- while(eed) {
- nexted= eed->next;
-
- /* f2 is set in collect_quadedges() */
- if(eed->f2==2 && eed->h==0) {
-
- efaa = (EVPtr *) eed->tmp.p;
-
- /* none of the faces should be treated before, nor be part of fgon */
- ok= 1;
- efa= efaa[0];
- if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
- if(efa->fgonf) ok= 0;
- efa= efaa[1];
- if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
- if(efa->fgonf) ok= 0;
-
- if(ok) {
- /* test convex */
- givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
- if(v1 && v2 && v3 && v4) {
- if( convex(v1->co, v2->co, v3->co, v4->co) ) {
-
- /* test edges */
- if( (v1) > (v3) ) {
- dia1.v1= v3;
- dia1.v2= v1;
- }
- else {
- dia1.v1= v1;
- dia1.v2= v3;
- }
-
- if( (v2) > (v4) ) {
- dia2.v1= v4;
- dia2.v2= v2;
- }
- else {
- dia2.v1= v2;
- dia2.v2= v4;
- }
-
- /* testing rule:
- * the area divided by the total edge lengths
- */
-
- len1= len_v3v3(v1->co, v2->co);
- len2= len_v3v3(v2->co, v3->co);
- len3= len_v3v3(v3->co, v4->co);
- len4= len_v3v3(v4->co, v1->co);
- len5= len_v3v3(v1->co, v3->co);
- len6= len_v3v3(v2->co, v4->co);
-
- opp1= area_tri_v3(v1->co, v2->co, v3->co);
- opp2= area_tri_v3(v1->co, v3->co, v4->co);
-
- fac1= opp1/(len1+len2+len5) + opp2/(len3+len4+len5);
-
- opp1= area_tri_v3(v2->co, v3->co, v4->co);
- opp2= area_tri_v3(v2->co, v4->co, v1->co);
-
- fac2= opp1/(len2+len3+len6) + opp2/(len4+len1+len6);
-
- ok= 0;
- if(fac1 > fac2) {
- if(dia2.v1==eed->v1 && dia2.v2==eed->v2) {
- eed->f1= 1;
- efa= efaa[0];
- efa->f1= 1;
- efa= efaa[1];
- efa->f1= 1;
-
- w= EM_face_from_faces(em, efaa[0], efaa[1],
- vindex[0], vindex[1], 4+vindex[2], -1);
- w->f |= SELECT;
-
-
- w= EM_face_from_faces(em, efaa[0], efaa[1],
- vindex[0], 4+vindex[2], 4+vindex[3], -1);
- w->f |= SELECT;
-
- onedone= 1;
- }
- }
- else if(fac1 < fac2) {
- if(dia1.v1==eed->v1 && dia1.v2==eed->v2) {
- eed->f1= 1;
- efa= efaa[0];
- efa->f1= 1;
- efa= efaa[1];
- efa->f1= 1;
-
-
- w= EM_face_from_faces(em, efaa[0], efaa[1],
- vindex[1], 4+vindex[2], 4+vindex[3], -1);
- w->f |= SELECT;
-
-
- w= EM_face_from_faces(em, efaa[0], efaa[1],
- vindex[0], 4+vindex[1], 4+vindex[3], -1);
- w->f |= SELECT;
-
- onedone= 1;
- }
- }
- }
- }
- }
-
- }
- eed= nexted;
- }
-
- free_tagged_edges_faces(em, em->edges.first, em->faces.first);
-
- if(onedone==0) break;
-
- EM_selectmode_set(em); // new edges/faces were added
- }
-
- MEM_freeN(efaar);
-
- EM_select_flush(em);
-
-}
-
-/* Got this from scanfill.c. You will need to juggle around the
-* callbacks for the scanfill.c code a bit for this to work. */
-static void fill_mesh(EditMesh *em)
-{
- EditVert *eve,*v1;
- EditEdge *eed,*e1,*nexted;
- EditFace *efa,*nextvl, *efan;
- short ok;
-
- if(em==NULL) return;
- waitcursor(1);
-
- /* copy all selected vertices */
- eve= em->verts.first;
- while(eve) {
- if(eve->f & SELECT) {
- v1= BLI_addfillvert(eve->co);
- eve->tmp.v= v1;
- v1->tmp.v= eve;
- v1->xs= 0; // used for counting edges
- }
- eve= eve->next;
- }
- /* copy all selected edges */
- eed= em->edges.first;
- while(eed) {
- if( (eed->v1->f & SELECT) && (eed->v2->f & SELECT) ) {
- e1= BLI_addfilledge(eed->v1->tmp.v, eed->v2->tmp.v);
- e1->v1->xs++;
- e1->v2->xs++;
- }
- eed= eed->next;
- }
- /* from all selected faces: remove vertices and edges to prevent doubles */
- /* all edges add values, faces subtract,
- then remove edges with vertices ->xs<2 */
- efa= em->faces.first;
- ok= 0;
- while(efa) {
- nextvl= efa->next;
- if( faceselectedAND(efa, 1) ) {
- efa->v1->tmp.v->xs--;
- efa->v2->tmp.v->xs--;
- efa->v3->tmp.v->xs--;
- if(efa->v4) efa->v4->tmp.v->xs--;
- ok= 1;
-
- }
- efa= nextvl;
- }
- if(ok) { /* there are faces selected */
- eed= filledgebase.first;
- while(eed) {
- nexted= eed->next;
- if(eed->v1->xs<2 || eed->v2->xs<2) {
- BLI_remlink(&filledgebase,eed);
- }
- eed= nexted;
- }
- }
-
- if(BLI_edgefill(em->mat_nr)) {
- efa= fillfacebase.first;
- while(efa) {
- /* normals default pointing up */
- efan= addfacelist(em, efa->v3->tmp.v, efa->v2->tmp.v,
- efa->v1->tmp.v, 0, NULL, NULL);
- if(efan) EM_select_face(efan, 1);
- efa= efa->next;
- }
- }
-
- BLI_end_edgefill();
- beautify_fill(em);
-
- WM_cursor_wait(0);
- EM_select_flush(em);
-
-}
-
-static int fill_mesh_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- fill_mesh(em);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-
-}
-
-void MESH_OT_fill(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Fill";
- ot->description= "Create a segment, edge or face";
- ot->idname= "MESH_OT_fill";
-
- /* api callbacks */
- ot->exec= fill_mesh_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int beautify_fill_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- beautify_fill(em);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_beautify_fill(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Beautify Fill";
- ot->description= "Rearrange geometry on a selected surface to avoid skinny faces";
- ot->idname= "MESH_OT_beautify_fill";
-
- /* api callbacks */
- ot->exec= beautify_fill_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/* ********************** SORT FACES ******************* */
-
-static void permutate(void *list, int num, int size, int *index)
-{
- void *buf;
- int len;
- int i;
-
- len = num * size;
-
- buf = MEM_mallocN(len, "permutate");
- memcpy(buf, list, len);
-
- for (i = 0; i < num; i++) {
- memcpy((char *)list + (i * size), (char *)buf + (index[i] * size), size);
- }
- MEM_freeN(buf);
-}
-
-/* sort faces on view axis */
-static float *face_sort_floats;
-static int float_sort(const void *v1, const void *v2)
-{
- float x1, x2;
-
- x1 = face_sort_floats[((int *) v1)[0]];
- x2 = face_sort_floats[((int *) v2)[0]];
-
- if( x1 > x2 ) return 1;
- else if( x1 < x2 ) return -1;
- return 0;
-}
-
-
-static int sort_faces_exec(bContext *C, wmOperator *op)
-{
- RegionView3D *rv3d= ED_view3d_context_rv3d(C);
- View3D *v3d= CTX_wm_view3d(C);
- Object *ob= CTX_data_edit_object(C);
- Scene *scene= CTX_data_scene(C);
- Mesh *me;
- CustomDataLayer *layer;
- int i, *index;
- int event;
- float reverse = 1;
- // XXX int ctrl= 0;
-
- if (!v3d) return OPERATOR_CANCELLED;
-
- /* This operator work in Object Mode, not in edit mode.
- * After talk with Campbell we agree that there is no point to port this to EditMesh right now.
- * so for now, we just exit_editmode and enter_editmode at the end of this function.
- */
- ED_object_exit_editmode(C, EM_FREEDATA);
-
- me= ob->data;
- if(me->totface==0) {
- ED_object_enter_editmode(C, 0);
- return OPERATOR_FINISHED;
- }
-
- event= RNA_enum_get(op->ptr, "type");
-
- // XXX
- //if(ctrl)
- // reverse = -1;
- /* create index list */
- index= (int *)MEM_mallocN(sizeof(int) * me->totface, "sort faces");
- for (i = 0; i < me->totface; i++) {
- index[i] = i;
- }
-
- face_sort_floats = (float *) MEM_mallocN(sizeof(float) * me->totface, "sort faces float");
-
- /* sort index list instead of faces itself
- * and apply this permutation to all face layers
- */
- if (event == 5) {
- /* Random */
- for(i=0; i<me->totface; i++) {
- face_sort_floats[i] = BLI_frand();
- }
- qsort(index, me->totface, sizeof(int), float_sort);
- } else {
- MFace *mf;
- float vec[3];
- float mat[4][4];
- float cur[3];
-
- if (event == 1)
- mul_m4_m4m4(mat, OBACT->obmat, rv3d->viewmat); /* apply the view matrix to the object matrix */
- else if (event == 2) { /* sort from cursor */
- if( v3d && v3d->localvd ) {
- VECCOPY(cur, v3d->cursor);
- } else {
- VECCOPY(cur, scene->cursor);
- }
- invert_m4_m4(mat, OBACT->obmat);
- mul_m4_v3(mat, cur);
- }
-
- mf= me->mface;
-
- for(i=0; i<me->totface; i++, mf++) {
- if (event==3) {
- face_sort_floats[i] = ((float)mf->mat_nr)*reverse;
- } else if (event==4) {
- /*selected first*/
- if (mf->flag & ME_FACE_SEL)
- face_sort_floats[i] = 0.0;
- else
- face_sort_floats[i] = reverse;
- } else {
- /* find the faces center */
- add_v3_v3v3(vec, (me->mvert+mf->v1)->co, (me->mvert+mf->v2)->co);
- if (mf->v4) {
- add_v3_v3(vec, (me->mvert+mf->v3)->co);
- add_v3_v3(vec, (me->mvert+mf->v4)->co);
- mul_v3_fl(vec, 0.25f);
- } else {
- add_v3_v3(vec, (me->mvert+mf->v3)->co);
- mul_v3_fl(vec, 1.0f/3.0f);
- } /* done */
-
- if (event == 1) { /* sort on view axis */
- mul_m4_v3(mat, vec);
- face_sort_floats[i] = vec[2] * reverse;
- } else if(event == 2) { /* distance from cursor*/
- face_sort_floats[i] = len_v3v3(cur, vec) * reverse; /* back to front */
- }
- }
- }
- qsort(index, me->totface, sizeof(int), float_sort);
- }
-
- MEM_freeN(face_sort_floats);
- for(i = 0; i < me->fdata.totlayer; i++) {
- layer = &me->fdata.layers[i];
- permutate(layer->data, me->totface, CustomData_sizeof(layer->type), index);
- }
-
- MEM_freeN(index);
- DAG_id_tag_update(ob->data, 0);
-
- /* Return to editmode. */
- ED_object_enter_editmode(C, 0);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_sort_faces(wmOperatorType *ot)
-{
- static EnumPropertyItem type_items[]= {
- { 1, "VIEW_AXIS", 0, "View Axis", "" },
- { 2, "CURSOR_DISTANCE", 0, "Cursor Distance", "" },
- { 3, "MATERIAL", 0, "Material", "" },
- { 4, "SELECTED", 0, "Selected", "" },
- { 5, "RANDOMIZE", 0, "Randomize", "" },
- { 0, NULL, 0, NULL, NULL }};
-
- /* identifiers */
- ot->name= "Sort Faces"; // XXX (Ctrl to reverse)%t|
- ot->description= "The faces of the active Mesh Object are sorted, based on the current view";
- ot->idname= "MESH_OT_sort_faces";
-
- /* api callbacks */
- ot->invoke= WM_menu_invoke;
- ot->exec= sort_faces_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- ot->prop= RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
-}
-
-/********************** Quad/Tri Operators *************************/
-
-static int quads_convert_to_tris_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- convert_to_triface(em,0);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_quads_convert_to_tris(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Quads to Tris";
- ot->description= "Convert selected quads to triangles";
- ot->idname= "MESH_OT_quads_convert_to_tris";
-
- /* api callbacks */
- ot->exec= quads_convert_to_tris_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int tris_convert_to_quads_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- join_triangles(em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_tris_convert_to_quads(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Tris to Quads";
- ot->description= "Convert selected triangles to quads";
- ot->idname= "MESH_OT_tris_convert_to_quads";
-
- /* api callbacks */
- ot->exec= tris_convert_to_quads_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int edge_flip_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- edge_flip(em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_edge_flip(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Edge Flip";
- ot->description= "Flip selected edge or adjoining faces";
- ot->idname= "MESH_OT_edge_flip";
-
- /* api callbacks */
- ot->exec= edge_flip_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/********************** Smooth/Solid Operators *************************/
-
-static void mesh_set_smooth_faces(EditMesh *em, short smooth)
-{
- EditFace *efa;
-
- if(em==NULL) return;
-
- for(efa= em->faces.first; efa; efa=efa->next) {
- if(efa->f & SELECT) {
- if(smooth) efa->flag |= ME_SMOOTH;
- else efa->flag &= ~ME_SMOOTH;
- }
+ if (change) {
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ BIF_undo_push("Mirror Color face");
}
-
- recalc_editnormals(em);
-}
-
-static int mesh_faces_shade_smooth_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- mesh_set_smooth_faces(em, 1);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
}
-
-void MESH_OT_faces_shade_smooth(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Shade Smooth";
- ot->description= "Display faces 'smooth' (using vertex normals)";
- ot->idname= "MESH_OT_faces_shade_smooth";
-
- /* api callbacks */
- ot->exec= mesh_faces_shade_smooth_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int mesh_faces_shade_flat_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- mesh_set_smooth_faces(em, 0);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_faces_shade_flat(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Shade Flat";
- ot->description= "Display faces 'flat'";
- ot->idname= "MESH_OT_faces_shade_flat";
-
- /* api callbacks */
- ot->exec= mesh_faces_shade_flat_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/* TODO - some way to select on an arbitrary axis */
-static int select_axis_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
-
- int axis= RNA_enum_get(op->ptr, "axis");
- int mode= RNA_enum_get(op->ptr, "mode"); /* -1==aligned, 0==neg, 1==pos*/
-
- EditSelection *ese = em->selected.last;
-
-
- if(ese==NULL)
- return OPERATOR_CANCELLED;
-
- if(ese->type==EDITVERT) {
- EditVert *ev;
- EditVert *act_vert= (EditVert*)ese->data;
- float value= act_vert->co[axis];
- float limit= CTX_data_tool_settings(C)->doublimit; // XXX
-
- if(mode==0) value -= limit;
- else if (mode==1) value += limit;
-
- for(ev=em->verts.first;ev;ev=ev->next) {
- if(!ev->h) {
- switch(mode) {
- case -1: /* aligned */
- if(fabs(ev->co[axis] - value) < limit)
- ev->f |= SELECT;
- break;
- case 0: /* neg */
- if(ev->co[axis] > value)
- ev->f |= SELECT;
- break;
- case 1: /* pos */
- if(ev->co[axis] < value)
- ev->f |= SELECT;
- break;
- }
- }
- }
- }
-
- EM_select_flush(em);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_axis(wmOperatorType *ot)
-{
- static EnumPropertyItem axis_mode_items[] = {
- {0, "POSITIVE", 0, "Positive Axis", ""},
- {1, "NEGATIVE", 0, "Negative Axis", ""},
- {-1, "ALIGNED", 0, "Aligned Axis", ""},
- {0, NULL, 0, NULL, NULL}};
-
- static EnumPropertyItem axis_items_xyz[] = {
- {0, "X_AXIS", 0, "X Axis", ""},
- {1, "Y_AXIS", 0, "Y Axis", ""},
- {2, "Z_AXIS", 0, "Z Axis", ""},
- {0, NULL, 0, NULL, NULL}};
-
- /* identifiers */
- ot->name= "Select Axis";
- ot->description= "Select all data in the mesh on a single axis";
- ot->idname= "MESH_OT_select_axis";
-
- /* api callbacks */
- ot->exec= select_axis_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "mode", axis_mode_items, 0, "Axis Mode", "Axis side to use when selecting");
- RNA_def_enum(ot->srna, "axis", axis_items_xyz, 0, "Axis", "Select the axis to compare each vertex on");
-}
-
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
new file mode 100644
index 00000000000..50d4a1610ca
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -0,0 +1,674 @@
+/**
+ * bmesh_construct.c August 2008
+ *
+ * BM construction functions.
+ *
+ * ***** 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.
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_customdata.h"
+#include "BKE_utildefines.h"
+
+#include "BLI_array.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#define SELECT 1
+
+/*prototypes*/
+static void bm_copy_loop_attributes(BMesh *source_mesh, BMesh *target_mesh,
+ const BMLoop *source_loop, BMLoop *target_loop);
+#if 0
+
+/*
+ * BM_CONSTRUCT.C
+ *
+ * This file contains functions for making and destroying
+ * individual elements like verts, edges and faces.
+ *
+*/
+
+/*
+ * BMESH MAKE VERT
+ *
+ * Creates a new vertex and returns a pointer
+ * to it. If a pointer to an example vertex is
+ * passed in, it's custom data and properties
+ * will be copied to the new vertex.
+ *
+*/
+
+BMVert *BM_Make_Vert(BMesh *bm, float co[3], BMVert *example)
+{
+ BMVert *v = NULL;
+ v = bmesh_mv(bm, co);
+ if(example)
+ CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, example->head.data, &v->head.data);
+ return v;
+}
+
+/*
+ * BMESH MAKE EDGE
+ *
+ * Creates a new edge betweeen two vertices and returns a
+ * pointer to it. If 'nodouble' equals 1, then a check is
+ * is done to make sure that an edge between those two vertices
+ * does not already exist. If it does, that edge is returned instead
+ * of creating a new one.
+ *
+ * If a new edge is created, and a pointer to an example edge is
+ * provided, it's custom data and properties will be copied to the
+ * new edge.
+ *
+*/
+
+BMEdge *BM_Make_Edge(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge *example, int nodouble)
+{
+ BMEdge *e = NULL;
+
+ if(nodouble) /*test if edge already exists.*/
+ e = BM_Edge_Exist(v1, v2);
+
+ if(!e){
+ e = bmesh_me(bm, v1, v2);
+
+ if(example)
+ CustomData_bmesh_copy_data(&bm->edata, &bm->edata, example->head.data, &e->head.data);
+ }
+
+ return e;
+
+}
+#endif
+
+/*
+ * BMESH MAKE QUADTRIANGLE
+ *
+ * Creates a new quad or triangle from
+ * a list of 3 or 4 vertices. If nodouble
+ * equals 1, then a check is done to see
+ * if a face with these vertices already
+ * exists and returns it instead. If a pointer
+ * to an example face is provided, it's custom
+ * data and properties will be copied to the new
+ * face.
+ *
+ * Note that the winding of the face is determined
+ * by the order of the vertices in the vertex array
+ *
+*/
+
+BMFace *BM_Make_QuadTri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3,
+ BMVert *v4, const BMFace *example, int nodouble)
+{
+ BMEdge *edar[4];
+ BMVert *vtar[4];
+
+ edar[0] = BM_Edge_Exist(v1, v2);
+ edar[1] = BM_Edge_Exist(v2, v3);
+ edar[2] = BM_Edge_Exist(v3, v4? v4 : v1);
+ if (v4) edar[3] = BM_Edge_Exist(v4, v1);
+ else edar[3] = NULL;
+
+ if (!edar[0]) edar[0] = BM_Make_Edge(bm, v1, v2, NULL, 0);
+ if (!edar[1]) edar[1] = BM_Make_Edge(bm, v2, v3, NULL, 0);
+ if (!edar[2]) edar[2] = BM_Make_Edge(bm, v3, v4?v4:v1, NULL, 0);
+ if (!edar[0] && v4) edar[0] = BM_Make_Edge(bm, v4, v1, NULL, 0);
+
+ vtar[0] = v1;
+ vtar[1] = v2;
+ vtar[2] = v3;
+ vtar[3] = v4;
+
+ return BM_Make_Quadtriangle(bm, vtar, edar, v4?4:3, example, nodouble);
+}
+
+/*remove the edge array bits from this. Its not really needed?*/
+BMFace *BM_Make_Quadtriangle(BMesh *bm, BMVert **verts, BMEdge **edges, int len, const BMFace *example, int nodouble)
+{
+ BMEdge *edar[4];
+ BMFace *f = NULL;
+ int overlap = 0;
+
+ edar[0] = edar[1] = edar[2] = edar[3] = NULL;
+
+ if(edges){
+ edar[0] = edges[0];
+ edar[1] = edges[1];
+ edar[2] = edges[2];
+ if(len == 4) edar[3] = edges[3];
+ }else{
+ edar[0] = BM_Edge_Exist(verts[0],verts[1]);
+ edar[1] = BM_Edge_Exist(verts[1],verts[2]);
+ if(len == 4){
+ edar[2] = BM_Edge_Exist(verts[2],verts[3]);
+ edar[3] = BM_Edge_Exist(verts[3],verts[0]);
+
+ }else{
+ edar[2] = BM_Edge_Exist(verts[2],verts[0]);
+ }
+ }
+
+ if(nodouble){
+ /*check if face exists or overlaps*/
+ if(len == 4){
+ overlap = BM_Exist_Face_Overlaps(bm, verts, len, &f);
+ }else{
+ overlap = BM_Exist_Face_Overlaps(bm, verts, len, &f);
+ }
+ }
+
+ /*make new face*/
+ if((!f) && (!overlap)){
+ if(!edar[0]) edar[0] = BM_Make_Edge(bm, verts[0], verts[1], NULL, 0);
+ if(!edar[1]) edar[1] = BM_Make_Edge(bm, verts[1], verts[2], NULL, 0);
+ if(len == 4){
+ if(!edar[2]) edar[2] = BM_Make_Edge(bm, verts[2], verts[3], NULL, 0);
+ if(!edar[3]) edar[3] = BM_Make_Edge(bm, verts[3], verts[0], NULL, 0);
+ } else {
+ if(!edar[2]) edar[2] = BM_Make_Edge(bm, verts[2], verts[0], NULL, 0);
+ }
+
+ f = BM_Make_Face(bm, verts, edar, len, 0);
+
+ if(example && f)
+ BM_Copy_Attributes(bm, bm, example, f);
+
+ }
+
+ return f;
+}
+
+
+/*copies face data from shared adjacent faces*/
+void BM_Face_CopyShared(BMesh *bm, BMFace *f) {
+ BMIter iter;
+ BMLoop *l, *l2;
+
+ if (!f) return;
+
+ l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f);
+ for (; l; l=BMIter_Step(&iter)) {
+ l2 = l->radial_next;
+
+ if (l2 && l2 != l) {
+ if (l2->v == l->v) {
+ bm_copy_loop_attributes(bm, bm, l2, l);
+ } else {
+ l2 = l2->next;
+ bm_copy_loop_attributes(bm, bm, l2, l);
+ }
+ }
+ }
+}
+
+/*
+ * BMESH MAKE NGON
+ *
+ * Attempts to make a new Ngon from a list of edges.
+ * If nodouble equals one, a check for overlaps or existing
+ *
+ * The edges are not required to be ordered, simply to to form
+ * a single closed loop as a whole
+ *
+ * Note that while this function will work fine when the edges
+ * are already sorted, if the edges are always going to be sorted,
+ * BM_Make_Face should be considered over this function as it
+ * avoids some unnecessary work.
+*/
+#define VERT_BUF_SIZE 100
+BMFace *BM_Make_Ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble)
+{
+ BMEdge **edges2 = NULL;
+ BLI_array_staticdeclare(edges2, VERT_BUF_SIZE);
+ BMVert **verts = NULL, *v;
+ BLI_array_staticdeclare(verts, VERT_BUF_SIZE);
+ BMFace *f = NULL;
+ BMEdge *e;
+ BMVert *ev1, *ev2;
+ int overlap = 0, i, /* j,*/ v1found, reverse;
+
+ /*this code is hideous, yeek. I'll have to think about ways of
+ cleaning it up. basically, it now combines the old BM_Make_Ngon
+ *and* the old bmesh_mf functions, so its kindof smashed together
+ - joeedh*/
+
+ if (!len || !v1 || !v2 || !edges || !bm)
+ return NULL;
+
+ /*put edges in correct order*/
+ for (i=0; i<len; i++) {
+ bmesh_api_setflag(edges[i], _FLAG_MF);
+ }
+
+ ev1 = edges[0]->v1;
+ ev2 = edges[0]->v2;
+
+ if (v1 == ev2) {
+ /* Swapping here improves performance and consistency of face
+ structure in the special case that the edges are already in
+ the correct order and winding */
+ SWAP(BMVert *, ev1, ev2);
+ }
+
+ BLI_array_append(verts, ev1);
+ v = ev2;
+ e = edges[0];
+ do {
+ BMEdge *e2 = e;
+
+ BLI_array_append(verts, v);
+ BLI_array_append(edges2, e);
+
+ do {
+ e2 = bmesh_disk_nextedge(e2, v);
+ if (e2 != e && bmesh_api_getflag(e2, _FLAG_MF)) {
+ v = BM_OtherEdgeVert(e2, v);
+ break;
+ }
+ } while (e2 != e);
+
+ if (e2 == e)
+ goto err; /*the edges do not form a closed loop*/
+
+ e = e2;
+ } while (e != edges[0]);
+
+ if (BLI_array_count(edges2) != len)
+ goto err; /*we didn't use all edges in forming the boundary loop*/
+
+ /*ok, edges are in correct order, now ensure they are going
+ in the correct direction*/
+ v1found = reverse = 0;
+ for (i=0; i<len; i++) {
+ if (BM_Vert_In_Edge(edges2[i], v1)) {
+ /*see if v1 and v2 are in the same edge*/
+ if (BM_Vert_In_Edge(edges2[i], v2)) {
+ /*if v1 is shared by the *next* edge, then the winding
+ is incorrect*/
+ if (BM_Vert_In_Edge(edges2[(i+1)%len], v1)) {
+ reverse = 1;
+ break;
+ }
+ }
+
+ v1found = 1;
+ }
+
+ if (!v1found && BM_Vert_In_Edge(edges2[i], v2)) {
+ reverse = 1;
+ break;
+ }
+ }
+
+ if (reverse) {
+ for (i=0; i<len/2; i++) {
+ v = verts[i];
+ verts[i] = verts[len-i-1];
+ verts[len-i-1] = v;
+ }
+ }
+
+ for (i=0; i<len; i++) {
+ edges2[i] = BM_Edge_Exist(verts[i], verts[(i+1)%len]);
+ if (!edges2[i])
+ goto err;
+ }
+
+ f = BM_Make_Face(bm, verts, edges2, len, nodouble);
+
+ /*clean up flags*/
+ for (i=0; i<len; i++) {
+ bmesh_api_clearflag(edges2[i], _FLAG_MF);
+ }
+
+ BLI_array_free(verts);
+ BLI_array_free(edges2);
+
+ return f;
+
+err:
+ for (i=0; i<len; i++) {
+ bmesh_api_clearflag(edges[i], _FLAG_MF);
+ }
+
+ BLI_array_free(verts);
+ BLI_array_free(edges2);
+
+ return NULL;
+}
+
+
+/*bmesh_make_face_from_face(BMesh *bm, BMFace *source, BMFace *target) */
+
+
+/*
+ * REMOVE TAGGED XXX
+ *
+ * Called by operators to remove elements that they have marked for
+ * removal.
+ *
+*/
+
+void BM_remove_tagged_faces(BMesh *bm, int flag)
+{
+ BMFace *f;
+ BMIter iter;
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if(BMO_TestFlag(bm, f, flag)) BM_Kill_Face(bm, f);
+ }
+}
+
+void BM_remove_tagged_edges(BMesh *bm, int flag)
+{
+ BMEdge *e;
+ BMIter iter;
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if(BMO_TestFlag(bm, e, flag)) BM_Kill_Edge(bm, e);
+ }
+}
+
+void BM_remove_tagged_verts(BMesh *bm, int flag)
+{
+ BMVert *v;
+ BMIter iter;
+
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if(BMO_TestFlag(bm, v, flag)) BM_Kill_Vert(bm, v);
+ }
+}
+
+static void bm_copy_vert_attributes(BMesh *source_mesh, BMesh *target_mesh, const BMVert *source_vertex, BMVert *target_vertex)
+{
+ if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) {
+ return;
+ }
+ copy_v3_v3(target_vertex->no, source_vertex->no);
+ CustomData_bmesh_free_block(&target_mesh->vdata, &target_vertex->head.data);
+ CustomData_bmesh_copy_data(&source_mesh->vdata, &target_mesh->vdata, source_vertex->head.data, &target_vertex->head.data);
+}
+
+static void bm_copy_edge_attributes(BMesh *source_mesh, BMesh *target_mesh, const BMEdge *source_edge, BMEdge *target_edge)
+{
+ if ((source_mesh == target_mesh) && (source_edge == target_edge)) {
+ return;
+ }
+ CustomData_bmesh_free_block(&target_mesh->edata, &target_edge->head.data);
+ CustomData_bmesh_copy_data(&source_mesh->edata, &target_mesh->edata, source_edge->head.data, &target_edge->head.data);
+}
+
+static void bm_copy_loop_attributes(BMesh *source_mesh, BMesh *target_mesh, const BMLoop *source_loop, BMLoop *target_loop)
+{
+ if ((source_mesh == target_mesh) && (source_loop == target_loop)) {
+ return;
+ }
+ CustomData_bmesh_free_block(&target_mesh->ldata, &target_loop->head.data);
+ CustomData_bmesh_copy_data(&source_mesh->ldata, &target_mesh->ldata, source_loop->head.data, &target_loop->head.data);
+}
+
+static void bm_copy_face_attributes(BMesh *source_mesh, BMesh *target_mesh, const BMFace *source_face, BMFace *target_face)
+{
+ if ((source_mesh == target_mesh) && (source_face == target_face)) {
+ return;
+ }
+ copy_v3_v3(target_face->no, source_face->no);
+ CustomData_bmesh_free_block(&target_mesh->pdata, &target_face->head.data);
+ CustomData_bmesh_copy_data(&source_mesh->pdata, &target_mesh->pdata, source_face->head.data, &target_face->head.data);
+ target_face->mat_nr = source_face->mat_nr;
+}
+
+/*BMESH_TODO: Special handling for hide flags?*/
+
+void BM_Copy_Attributes(BMesh *source_mesh, BMesh *target_mesh, const void *source, void *target)
+{
+ const BMHeader *sheader = source;
+ BMHeader *theader = target;
+
+ if(sheader->type != theader->type)
+ return;
+
+ /*First we copy select*/
+ if(BM_Selected(source_mesh, source)) BM_Select(target_mesh, target, 1);
+
+ /*Now we copy flags*/
+ theader->flag = sheader->flag;
+
+ /*Copy specific attributes*/
+ if(theader->type == BM_VERT)
+ bm_copy_vert_attributes(source_mesh, target_mesh, (const BMVert*)source, (BMVert*)target);
+ else if(theader->type == BM_EDGE)
+ bm_copy_edge_attributes(source_mesh, target_mesh, (const BMEdge*)source, (BMEdge*)target);
+ else if(theader->type == BM_LOOP)
+ bm_copy_loop_attributes(source_mesh, target_mesh, (const BMLoop*)source, (BMLoop*)target);
+ else if(theader->type == BM_FACE)
+ bm_copy_face_attributes(source_mesh, target_mesh, (const BMFace*)source, (BMFace*)target);
+}
+
+BMesh *BM_Copy_Mesh(BMesh *bmold)
+{
+ BMesh *bm;
+ BMVert *v, *v2, **vtable = NULL;
+ BMEdge *e, *e2, **edges = NULL, **etable = NULL;
+ BLI_array_declare(edges);
+ BMLoop *l, /* *l2,*/ **loops = NULL;
+ BLI_array_declare(loops);
+ BMFace *f, *f2, **ftable = NULL;
+ BMEditSelection *ese;
+ BMIter iter, liter;
+ int allocsize[4] = {512,512,2048,512}, numTex, numCol;
+ int i, j;
+
+ /*allocate a bmesh*/
+ bm = BM_Make_Mesh(bmold->ob, allocsize);
+
+ CustomData_copy(&bmold->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bmold->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bmold->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bmold->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+ CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
+
+ /*needed later*/
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ vtable= MEM_mallocN(sizeof(BMVert *) * bmold->totvert, "BM_Copy_Mesh vtable");
+ etable= MEM_mallocN(sizeof(BMEdge *) * bmold->totedge, "BM_Copy_Mesh etable");
+ ftable= MEM_mallocN(sizeof(BMFace *) * bmold->totface, "BM_Copy_Mesh ftable");
+
+ v = BMIter_New(&iter, bmold, BM_VERTS_OF_MESH, NULL);
+ for (i=0; v; v=BMIter_Step(&iter), i++) {
+ v2 = BM_Make_Vert(bm, v->co, NULL); /* copy between meshes so cant use 'example' argument */
+ BM_Copy_Attributes(bmold, bm, v, v2);
+ vtable[i] = v2;
+ BM_SetIndex(v, i);
+ BM_SetIndex(v2, i);
+ }
+ /* safety check */
+ BLI_assert(i == bmold->totvert);
+
+ e = BMIter_New(&iter, bmold, BM_EDGES_OF_MESH, NULL);
+ for (i=0; e; e=BMIter_Step(&iter), i++) {
+ e2 = BM_Make_Edge(bm, vtable[BM_GetIndex(e->v1)],
+ vtable[BM_GetIndex(e->v2)], e, 0);
+
+ BM_Copy_Attributes(bmold, bm, e, e2);
+ etable[i] = e2;
+ BM_SetIndex(e, i);
+ BM_SetIndex(e2, i);
+ }
+ /* safety check */
+ BLI_assert(i == bmold->totedge);
+
+ f = BMIter_New(&iter, bmold, BM_FACES_OF_MESH, NULL);
+ for (i=0; f; f=BMIter_Step(&iter), i++) {
+ BLI_array_empty(loops);
+ BLI_array_empty(edges);
+ l = BMIter_New(&liter, bmold, BM_LOOPS_OF_FACE, f);
+ for (j=0; j<f->len; j++, l = BMIter_Step(&liter)) {
+ BLI_array_growone(loops);
+ BLI_array_growone(edges);
+ loops[j] = l;
+ edges[j] = etable[BM_GetIndex(l->e)];
+ }
+
+ v = vtable[BM_GetIndex(loops[0]->v)];
+ v2 = vtable[BM_GetIndex(loops[1]->v)];
+
+ if (!bmesh_verts_in_edge(v, v2, edges[0])) {
+ v = vtable[BM_GetIndex(loops[BLI_array_count(loops)-1]->v)];
+ v2 = vtable[BM_GetIndex(loops[0]->v)];
+ }
+
+ f2 = BM_Make_Ngon(bm, v, v2, edges, f->len, 0);
+ if (!f2)
+ continue;
+
+ BM_SetIndex(f, i);
+ ftable[i] = f2;
+
+ BM_Copy_Attributes(bmold, bm, f, f2);
+ copy_v3_v3(f2->no, f->no);
+
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f2);
+ for (j=0; j<f->len; j++, l = BMIter_Step(&liter)) {
+ BM_Copy_Attributes(bmold, bm, loops[j], l);
+ }
+
+ if (f == bmold->act_face) bm->act_face = f2;
+ }
+ /* safety check */
+ BLI_assert(i == bmold->totface);
+
+ /*copy over edit selection history*/
+ for (ese=bmold->selected.first; ese; ese=ese->next) {
+ void *ele = NULL;
+
+ if (ese->type == BM_VERT)
+ ele = vtable[BM_GetIndex(ese->data)];
+ else if (ese->type == BM_EDGE)
+ ele = etable[BM_GetIndex(ese->data)];
+ else if (ese->type == BM_FACE) {
+ ele = ftable[BM_GetIndex(ese->data)];
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (ele)
+ BM_store_selection(bm, ele);
+ }
+
+ MEM_freeN(etable);
+ MEM_freeN(vtable);
+ MEM_freeN(ftable);
+
+ BLI_array_free(loops);
+ BLI_array_free(edges);
+
+ return bm;
+}
+
+/*
+ BM FLAGS TO ME FLAGS
+
+ Returns the flags stored in element,
+ which much be either a BMVert, BMEdge,
+ or BMFace, converted to mesh flags.
+*/
+
+int BMFlags_To_MEFlags(void *element) {
+ const short src_type= ((BMHeader *)element)->type;
+ const short src_flag= ((BMHeader *)element)->flag;
+
+ int dst_flag = 0;
+
+ if (src_flag & BM_HIDDEN) dst_flag |= ME_HIDE;
+
+ if (src_type == BM_FACE) {
+ if (src_flag & BM_SELECT) dst_flag |= ME_FACE_SEL;
+ if (src_flag & BM_SMOOTH) dst_flag |= ME_SMOOTH;
+ } else if (src_type == BM_EDGE) {
+ if (src_flag & BM_SELECT) dst_flag |= SELECT;
+ if (src_flag & BM_SEAM) dst_flag |= ME_SEAM;
+ if (src_flag & BM_SHARP) dst_flag |= ME_SHARP;
+ if (BM_Wire_Edge(NULL, element)) dst_flag |= ME_LOOSEEDGE;
+ dst_flag |= ME_EDGEDRAW | ME_EDGERENDER;
+ } else if (src_type == BM_VERT) {
+ if (src_flag & BM_SELECT) dst_flag |= SELECT;
+ }
+
+ return dst_flag;
+}
+
+/*
+ BM FLAGS TO ME FLAGS
+
+ Returns the flags stored in element,
+ which much be either a MVert, MEdge,
+ or MPoly, converted to mesh flags.
+ type must be either BM_VERT, BM_EDGE,
+ or BM_FACE.
+*/
+int MEFlags_To_BMFlags(int flag, int type) {
+ int f = 0;
+
+ if (type == BM_FACE) {
+ if (flag & ME_FACE_SEL) f |= BM_SELECT;
+ if (flag & ME_SMOOTH) f |= BM_SMOOTH;
+ if (flag & ME_HIDE) f |= BM_HIDDEN;
+ } else if (type == BM_EDGE) {
+ if (flag & SELECT) f |= BM_SELECT;
+ if (flag & ME_SEAM) f |= BM_SEAM;
+ if (flag & ME_SHARP) f |= BM_SHARP;
+ if (flag & ME_HIDE) f |= BM_HIDDEN;
+ } else if (type == BM_VERT) {
+ if (flag & SELECT) f |= BM_SELECT;
+ if (flag & ME_HIDE) f |= BM_HIDDEN;
+ }
+
+ return f;
+}
diff --git a/source/blender/bmesh/intern/bmesh_eulers.c b/source/blender/bmesh/intern/bmesh_eulers.c
new file mode 100644
index 00000000000..25b4ee846a0
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_eulers.c
@@ -0,0 +1,1208 @@
+/*some of this may come back, such as split face or split edge, if necassary for speed*/
+
+#if 0
+/**
+ * bmesh_eulers.c jan 2007
+ *
+ * BM Euler construction API.
+ *
+ * $Id: bmesh_eulers.c,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** 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.
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_utildefines.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+
+/*********************************************************
+ * "Euler API" *
+ * *
+ * *
+ * Primitive construction operators for mesh tools. *
+ * *
+ **********************************************************/
+
+
+/*
+ The functions in this file represent the 'primitive' or 'atomic' operators that
+ mesh tools use to manipulate the topology of the structure.* The purpose of these
+ functions is to provide a trusted set of operators to manipulate the mesh topology
+ and which can also be combined together like building blocks to create more
+ sophisticated tools. It needs to be stressed that NO manipulation of an existing
+ mesh structure should be done outside of these functions.
+
+ In the BM system, each euler is named by an ancronym which describes what it actually does.
+ Furthermore each Euler has a logical inverse. An important design criteria of all Eulers is that
+ through a Euler's logical inverse you can 'undo' an operation. (Special note should
+ be taken of bmesh_loop_reverse, which is its own inverse).
+
+ bmesh_MF/KF: Make Face and Kill Face
+ bmesh_ME/KE: Make Edge and Kill Edge
+ bmesh_MV/KV: Make Vert and Kill Vert
+ bmesh_SEMV/JEKV: Split Edge, Make Vert and Join Edge, Kill Vert
+ bmesh_SFME/JFKE: Split Face, Make Edge and Join Face, Kill Edge
+ bmesh_loop_reverse: Reverse a Polygon's loop cycle. (used for flip normals for one)
+
+ Using a combination of these eleven eulers any non-manifold modelling operation can be achieved.
+ Each Euler operator has a detailed explanation of what is does in the comments preceding its
+ code.
+
+ *The term "Euler Operator" is actually a misnomer when referring to a non-manifold
+ data structure. Its use is in keeping with the convention established by others.
+
+ BMESH_TODO:
+ -Make seperate 'debug levels' of validation
+ -Add in the UnglueFaceRegionMakeVert and GlueFaceRegionKillVert eulers.
+
+ NOTE:
+ -The functions in this file are notoriously difficult to debug and even understand sometimes.
+ better code comments would be nice....
+
+*/
+
+
+/*MAKE Eulers*/
+
+/**
+ * bmesh_MV
+ *
+ * MAKE VERT EULER:
+ *
+ * Makes a single loose vertex.
+ *
+ * Returns -
+ * A BMVert pointer.
+ */
+
+BMVert *bmesh_mv(BMesh *bm, float *vec){
+ BMVert *v = bmesh_addvertlist(bm, NULL);
+ VECCOPY(v->co,vec);
+ return v;
+}
+
+/**
+ * bmesh_ME
+ *
+ * MAKE EDGE EULER:
+ *
+ * Makes a single wire edge between two vertices.
+ * If the caller does not want there to be duplicate
+ * edges between the vertices, it is up to them to check
+ * for this condition beforehand.
+ *
+ * Returns -
+ * A BMEdge pointer.
+ */
+
+BMEdge *bmesh_me(BMesh *bm, BMVert *v1, BMVert *v2){
+ BMEdge *e=NULL;
+ BMNode *d1=NULL, *d2=NULL;
+ int valance1=0, valance2=0, edok;
+
+ /*edge must be between two distinct vertices...*/
+ if(v1 == v2) return NULL;
+
+ #ifndef bmesh_FASTEULER
+ /*count valance of v1*/
+ if(v1->e){
+ d1 = bmesh_disk_getpointer(v1->e,v1);
+ if(d1) valance1 = bmesh_cycle_length(d1);
+ else bmesh_error();
+ }
+ if(v2->e){
+ d2 = bmesh_disk_getpointer(v2->e,v2);
+ if(d2) valance2 = bmesh_cycle_length(d2);
+ else bmesh_error();
+ }
+ #endif
+
+ /*go ahead and add*/
+ e = bmesh_addedgelist(bm, v1, v2, NULL);
+ bmesh_disk_append_edge(e, e->v1);
+ bmesh_disk_append_edge(e, e->v2);
+
+ #ifndef bmesh_FASTEULER
+ /*verify disk cycle lengths*/
+ d1 = bmesh_disk_getpointer(e, e->v1);
+ edok = bmesh_cycle_validate(valance1+1, d1);
+ if(!edok) bmesh_error();
+ d2 = bmesh_disk_getpointer(e, e->v2);
+ edok = bmesh_cycle_validate(valance2+1, d2);
+ if(!edok) bmesh_error();
+
+ /*verify that edge actually made it into the cycle*/
+ edok = bmesh_disk_hasedge(v1, e);
+ if(!edok) bmesh_error();
+ edok = bmesh_disk_hasedge(v2, e);
+ if(!edok) bmesh_error();
+ #endif
+ return e;
+}
+
+
+
+/**
+ * bmesh_MF
+ *
+ * MAKE FACE EULER:
+ * Takes a list of edge pointers which form a closed loop and makes a face
+ * from them. The first edge in elist is considered to be the start of the
+ * polygon, and v1 and v2 are its vertices and determine the winding of the face
+ * Other than the first edge, no other assumptions are made about the order of edges
+ * in the elist array. To verify that it is a single closed loop and derive the correct
+ * order a simple series of verifications is done and all elements are visited.
+ *
+ * Returns -
+ * A BMFace pointer
+ */
+
+#define MF_CANDIDATE 1
+#define MF_VISITED 2
+#define MF_TAKEN 4
+
+BMFace *bmesh_mf(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **elist, int len)
+{
+ BMFace *f = NULL;
+ BMEdge *curedge;
+ BMVert *curvert, *tv, **vlist;
+ int i, j, done, cont, edok;
+
+ if(len < 2) return NULL;
+
+ /*make sure that v1 and v2 are in elist[0]*/
+ //if(bmesh_verts_in_edge(v1,v2,elist[0]) == 0)
+ // return NULL;
+
+ /*clear euler flags*/
+ for(i=0;i<len;i++) {
+ BMNode *diskbase;
+ BMEdge *curedge;
+ BMVert *v1;
+ int j;
+
+ for (j=0; j<2; j++) {
+ int a, len=0;
+
+ v1 = j ? elist[i]->v2 : elist[i]->v1;
+ diskbase = bmesh_disk_getpointer(v1->e, v1);
+ len = bmesh_cycle_length(diskbase);
+
+ for(a=0,curedge=v1->e;a<len;a++,curedge = bmesh_disk_nextedge(curedge,v1)){
+ curedge->head.eflag1 = curedge->head.eflag2 = 0;
+ }
+ }
+ }
+
+ for(i=0;i<len;i++){
+ elist[i]->head.eflag1 |= MF_CANDIDATE;
+
+ /*if elist[i] has a loop, count its radial length*/
+ if(elist[i]->loop) elist[i]->head.eflag2 = bmesh_cycle_length(&(elist[i]->l->radial));
+ else elist[i]->head.eflag2 = 0;
+ }
+
+ /* For each vertex in each edge, it must have exactly two MF_CANDIDATE edges attached to it
+ Note that this does not gauruntee that face is a single closed loop. At best it gauruntees
+ that elist contains a finite number of seperate closed loops.
+ */
+// for(i=0; i<len; i++){
+// edok = bmesh_disk_count_edgeflag(elist[i]->v1, MF_CANDIDATE, 0);
+// if(edok != 2) return NULL;
+// edok = bmesh_disk_count_edgeflag(elist[i]->v2, MF_CANDIDATE, 0);
+// if(edok != 2) return NULL;
+// }
+
+ /*set start edge, start vert and target vert for our loop traversal*/
+ curedge = elist[0];
+ tv = v1;
+ curvert = v2;
+
+ if(bm->vtarlen < len){
+ if (bm->vtar) MEM_freeN(bm->vtar);
+ bm->vtar = MEM_callocN(sizeof(BMVert *)* len, "BM Vert pointer array");
+ bm->vtarlen = len;
+ }
+ /*insert tv into vlist since its the first vertex in face*/
+
+ i=0;
+ vlist=bm->vtar;
+ vlist[i] = tv;
+
+ /* Basic procedure: Starting with curv we find the edge in it's disk cycle which hasn't
+ been visited yet. When we do, we put curv in a linked list and find the next MF_CANDIDATE
+ edge, loop until we find TV. We know TV is reachable because of test we did earlier.
+ */
+ done=0;
+ while(!done){
+ /*add curvert to vlist*/
+ /*insert some error cheking here for overflows*/
+ i++;
+ vlist[i] = curvert;
+
+ /*mark curedge as visited*/
+ curedge->head.eflag1 |= MF_VISITED;
+
+ /*find next edge and vert*/
+ curedge = bmesh_disk_next_edgeflag(curedge, curvert, MF_CANDIDATE, 0);
+ curvert = bmesh_edge_getothervert(curedge, curvert);
+ if(curvert == tv){
+ curedge->head.eflag1 |= MF_VISITED;
+ done=1;
+ }
+ }
+
+ /* Verify that all edges have been visited It's possible that we did reach tv
+ from sv, but that several unconnected loops were passed in via elist.
+ */
+ cont=1;
+// for(i=0; i<len; i++){
+// if((elist[i]->head.eflag1 & MF_VISITED) == 0) cont = 0;
+// }
+
+ /*if we get this far, its ok to allocate the face and add the loops*/
+ if(cont){
+ BMLoop *l;
+ BMEdge *e;
+ f = bmesh_addpolylist(bm, NULL);
+ f->len = len;
+ for(i=0;i<len;i++){
+ curvert = vlist[i];
+ l = bmesh_create_loop(bm,curvert,NULL,f,NULL);
+ if(!(f->loopbase)) f->lbase = l;
+ bmesh_cycle_append(f->lbase, l);
+ }
+
+ /*take care of edge pointers and radial cycle*/
+ for(i=0, l = f->loopbase; i<len; i++, l= l->next) {
+ e = NULL;
+ if(l == f->loopbase) e = elist[0]; /*first edge*/
+
+ else{/*search elist for others*/
+ for(j=1; j<len; j++){
+ edok = bmesh_verts_in_edge(l->v, ((l->next))->v, elist[j]);
+ if(edok){
+ e = elist[j];
+ break;
+ }
+ }
+ }
+ l->e = e; /*set pointer*/
+ bmesh_radial_append(e, l); /*append into radial*/
+ }
+
+ f->len = len;
+
+ /*Validation Loop cycle*/
+ edok = bmesh_cycle_validate(len, f->lbase);
+ if(!edok) bmesh_error();
+ for(i=0, l = f->loopbase; i<len; i++, l=((l->next))){
+ /*validate loop vert pointers*/
+ edok = bmesh_verts_in_edge(l->v, ((l->next))->v, l->e);
+ if(!edok) bmesh_error();
+ /*validate the radial cycle of each edge*/
+ edok = bmesh_cycle_length(&(l->radial));
+ if(edok != (l->e->head.eflag2 + 1)) bmesh_error();
+ }
+ }
+
+ for(i=0;i<len;i++) elist[i]->head.eflag1=elist[i]->head.eflag2 = 0;
+ return f;
+}
+
+/* KILL Eulers */
+
+/**
+ * bmesh_KV
+ *
+ * KILL VERT EULER:
+ *
+ * Kills a single loose vertex.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+
+int bmesh_kv(BMesh *bm, BMVert *v){
+ if(v->e == NULL){
+ if (BM_TestHFlag(v, BM_SELECT)) bm->totvertsel--;
+
+ BLI_remlink(&(bm->verts), &(v->head));
+ bmesh_free_vert(bm,v);
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * bmesh_KE
+ *
+ * KILL EDGE EULER:
+ *
+ * Kills a wire edge.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+
+int bmesh_ke(BMesh *bm, BMEdge *e){
+ int edok;
+
+ /*Make sure that no faces!*/
+ if(e->l == NULL){
+ bmesh_disk_remove_edge(e, e->v1);
+ bmesh_disk_remove_edge(e, e->v2);
+
+ /*verify that edge out of disk*/
+ edok = bmesh_disk_hasedge(e->v1, e);
+ if(edok) bmesh_error();
+ edok = bmesh_disk_hasedge(e->v2, e);
+ if(edok) bmesh_error();
+
+ /*remove and deallocate*/
+ if (BM_TestHFlag(e, BM_SELECT)) bm->totedgesel--;
+ BLI_remlink(&(bm->edges), &(e->head));
+ bmesh_free_edge(bm, e);
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * bmesh_KF
+ *
+ * KILL FACE EULER:
+ *
+ * The logical inverse of bmesh_MF.
+ * Kills a face and removes each of its loops from the radial that it belongs to.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+*/
+
+int bmesh_kf(BMesh *bm, BMFace *bply){
+ BMLoop *newbase,*oldbase, *curloop;
+ int i,len=0;
+
+ /*add validation to make sure that radial cycle is cleaned up ok*/
+ /*deal with radial cycle first*/
+ len = bmesh_cycle_length(bply->lbase);
+ for(i=0, curloop=bply->loopbase; i < len; i++, curloop = ((curloop->next)))
+ bmesh_radial_remove_loop(curloop, curloop->e);
+
+ /*now deallocate the editloops*/
+ for(i=0; i < len; i++){
+ newbase = ((bply->lbase->next));
+ oldbase = bply->lbase;
+ bmesh_cycle_remove(oldbase, oldbase);
+ bmesh_free_loop(bm, oldbase);
+ bply->loopbase = newbase;
+ }
+
+ if (BM_TestHFlag(bply, BM_SELECT)) bm->totfacesel--;
+ BLI_remlink(&(bm->polys), &(bply->head));
+ bmesh_free_poly(bm, bply);
+ return 1;
+}
+
+/*SPLIT Eulers*/
+
+/**
+ * bmesh_SEMV
+ *
+ * SPLIT EDGE MAKE VERT:
+ * Takes a given edge and splits it into two, creating a new vert.
+ *
+ *
+ * Before: OV---------TV
+ * After: OV----NV---TV
+ *
+ * Returns -
+ * BMVert pointer.
+ *
+*/
+
+BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **re){
+ BMVert *nv, *ov;
+ BMNode *diskbase;
+ BMEdge *ne;
+ int i, edok, valance1=0, valance2=0;
+
+ if(bmesh_vert_in_edge(e,tv) == 0) return NULL;
+ ov = bmesh_edge_getothervert(e,tv);
+ //v2 = tv;
+
+ /*count valance of v1*/
+ diskbase = bmesh_disk_getpointer(e, ov);
+ valance1 = bmesh_cycle_length(diskbase);
+ /*count valance of v2*/
+ diskbase = bmesh_disk_getpointer(e, tv);
+ valance2 = bmesh_cycle_length(diskbase);
+
+ nv = bmesh_addvertlist(bm, tv);
+ ne = bmesh_addedgelist(bm, nv, tv, e);
+
+ //e->v2 = nv;
+ /*remove e from v2's disk cycle*/
+ bmesh_disk_remove_edge(e, tv);
+ /*swap out tv for nv in e*/
+ bmesh_edge_swapverts(e, tv, nv);
+ /*add e to nv's disk cycle*/
+ bmesh_disk_append_edge(e, nv);
+ /*add ne to nv's disk cycle*/
+ bmesh_disk_append_edge(ne, nv);
+ /*add ne to tv's disk cycle*/
+ bmesh_disk_append_edge(ne, tv);
+ /*verify disk cycles*/
+ diskbase = bmesh_disk_getpointer(ov->e,ov);
+ edok = bmesh_cycle_validate(valance1, diskbase);
+ if(!edok) bmesh_error();
+ diskbase = bmesh_disk_getpointer(tv->e,tv);
+ edok = bmesh_cycle_validate(valance2, diskbase);
+ if(!edok) bmesh_error();
+ diskbase = bmesh_disk_getpointer(nv->e,nv);
+ edok = bmesh_cycle_validate(2, diskbase);
+ if(!edok) bmesh_error();
+
+ /*Split the radial cycle if present*/
+ if(e->l){
+ BMLoop *nl,*l;
+ BMNode *radEBase=NULL, *radNEBase=NULL;
+ int radlen = bmesh_cycle_length(&(e->l->radial));
+ /*Take the next loop. Remove it from radial. Split it. Append to appropriate radials.*/
+ while(e->l){
+ l=e->l;
+ l->f->len++;
+ bmesh_radial_remove_loop(l,e);
+
+ nl = bmesh_create_loop(bm,NULL,NULL,l->f,l);
+ nl->prev = (BMHeader*)l;
+ nl->next = (BMHeader*)(l->next);
+ nl->prev->next = (BMHeader*)nl;
+ nl->next->prev = (BMHeader*)nl;
+ nl->v = nv;
+
+ /*assign the correct edge to the correct loop*/
+ if(bmesh_verts_in_edge(nl->v, ((nl->next))->v, e)){
+ nl->e = e;
+ l->e = ne;
+
+ /*append l into ne's rad cycle*/
+ if(!radNEBase){
+ radNEBase = &(l->radial);
+ radNEBase->next = NULL;
+ radNEBase->prev = NULL;
+ }
+
+ if(!radEBase){
+ radEBase = &(nl->radial);
+ radEBase->next = NULL;
+ radEBase->prev = NULL;
+ }
+
+ bmesh_cycle_append(radEBase,&(nl->radial));
+ bmesh_cycle_append(radNEBase,&(l->radial));
+
+ }
+ else if(bmesh_verts_in_edge(nl->v,((nl->next))->v,ne)){
+ nl->e = ne;
+ l->e = e;
+
+ if(!radNEBase){
+ radNEBase = &(nl->radial);
+ radNEBase->next = NULL;
+ radNEBase->prev = NULL;
+ }
+ if(!radEBase){
+ radEBase = &(l->radial);
+ radEBase->next = NULL;
+ radEBase->prev = NULL;
+ }
+ bmesh_cycle_append(radEBase,&(l->radial));
+ bmesh_cycle_append(radNEBase,&(nl->radial));
+ }
+
+ }
+
+ e->l = radEBase->data;
+ ne->l = radNEBase->data;
+
+ /*verify length of radial cycle*/
+ edok = bmesh_cycle_validate(radlen,&(e->l->radial));
+ if(!edok) bmesh_error();
+ edok = bmesh_cycle_validate(radlen,&(ne->l->radial));
+ if(!edok) bmesh_error();
+
+ /*verify loop->v and loop->next->v pointers for e*/
+ for(i=0,l=e->l; i < radlen; i++, l = l->radial_next){
+ if(!(l->e == e)) bmesh_error();
+ if(!(l->radial.data == l)) bmesh_error();
+ if( ((l->prev))->e != ne && ((l->next))->e != ne) bmesh_error();
+ edok = bmesh_verts_in_edge(l->v, ((l->next))->v, e);
+ if(!edok) bmesh_error();
+ if(l->v == ((l->next))->v) bmesh_error();
+ if(l->e == ((l->next))->e) bmesh_error();
+ /*verify loop cycle for kloop->f*/
+ edok = bmesh_cycle_validate(l->f->len, l->f->lbase);
+ if(!edok) bmesh_error();
+ }
+ /*verify loop->v and loop->next->v pointers for ne*/
+ for(i=0,l=ne->l; i < radlen; i++, l = l->radial_next){
+ if(!(l->e == ne)) bmesh_error();
+ if(!(l->radial.data == l)) bmesh_error();
+ if( ((l->prev))->e != e && ((l->next))->e != e) bmesh_error();
+ edok = bmesh_verts_in_edge(l->v, ((l->next))->v, ne);
+ if(!edok) bmesh_error();
+ if(l->v == ((l->next))->v) bmesh_error();
+ if(l->e == ((l->next))->e) bmesh_error();
+ /*verify loop cycle for kloop->f. Redundant*/
+ edok = bmesh_cycle_validate(l->f->len, l->f->lbase);
+ if(!edok) bmesh_error();
+ }
+ }
+
+ if(re) *re = ne;
+ return nv;
+}
+
+/**
+ * bmesh_SFME
+ *
+ * SPLIT FACE MAKE EDGE:
+ *
+ * Takes as input two vertices in a single face. An edge is created which divides the original face
+ * into two distinct regions. One of the regions is assigned to the original face and it is closed off.
+ * The second region has a new face assigned to it.
+ *
+ * Examples:
+ *
+ * Before: After:
+ * ---------- ----------
+ * | | | |
+ * | | | f1 |
+ * v1 f1 v2 v1======v2
+ * | | | f2 |
+ * | | | |
+ * ---------- ----------
+ *
+ * Note that the input vertices can be part of the same edge. This will result in a two edged face.
+ * This is desirable for advanced construction tools and particularly essential for edge bevel. Because
+ * of this it is up to the caller to decide what to do with the extra edge.
+ *
+ * Note that the tesselator abuses eflag2 while using this euler! (don't ever ever do this....)
+ *
+ * Returns -
+ * A BMFace pointer
+ */
+BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **rl){
+
+ BMFace *f2;
+ BMLoop *v1loop = NULL, *v2loop = NULL, *curloop, *f1loop=NULL, *f2loop=NULL;
+ BMEdge *e;
+ int i, len, f1len, f2len;
+
+
+ /*verify that v1 and v2 are in face.*/
+ len = bmesh_cycle_length(f->lbase);
+ for(i = 0, curloop = f->loopbase; i < len; i++, curloop = ((curloop->next)) ){
+ if(curloop->v == v1) v1loop = curloop;
+ else if(curloop->v == v2) v2loop = curloop;
+ }
+
+ if(!v1loop || !v2loop) return NULL;
+
+ /*allocate new edge between v1 and v2*/
+ e = bmesh_addedgelist(bm, v1, v2,NULL);
+ bmesh_disk_append_edge(e, v1);
+ bmesh_disk_append_edge(e, v2);
+
+ f2 = bmesh_addpolylist(bm,f);
+ f1loop = bmesh_create_loop(bm,v2,e,f,v2loop);
+ f2loop = bmesh_create_loop(bm,v1,e,f2,v1loop);
+
+ f1loop->prev = v2loop->prev;
+ f2loop->prev = v1loop->prev;
+ v2loop->prev->next = (BMHeader*)f1loop;
+ v1loop->prev->next = (BMHeader*)f2loop;
+
+ f1loop->next = (BMHeader*)v1loop;
+ f2loop->next = (BMHeader*)v2loop;
+ v1loop->prev = (BMHeader*)f1loop;
+ v2loop->prev = (BMHeader*)f2loop;
+
+ f2->loopbase = f2loop;
+ f->loopbase = f1loop;
+
+ /*validate both loops*/
+ /*I dont know how many loops are supposed to be in each face at this point! FIXME!*/
+
+ /*go through all of f2's loops and make sure they point to it properly.*/
+ f2len = bmesh_cycle_length(f2->lbase);
+ for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((curloop->next)) ) curloop->f = f2;
+
+ /*link up the new loops into the new edges radial*/
+ bmesh_radial_append(e, f1loop);
+ bmesh_radial_append(e, f2loop);
+
+
+ f2->len = f2len;
+
+ f1len = bmesh_cycle_length(f->lbase);
+ f->len = f1len;
+
+ if(rl) *rl = f2loop;
+ return f2;
+}
+
+
+/**
+ * bmesh_JEKV
+ *
+ * JOIN EDGE KILL VERT:
+ * Takes a an edge and pointer to one of its vertices and collapses
+ * the edge on that vertex.
+ *
+ * Before: OE KE
+ * ------- -------
+ * | || |
+ * OV KV TV
+ *
+ *
+ * After: OE
+ * ---------------
+ * | |
+ * OV TV
+ *
+ *
+ * Restrictions:
+ * KV is a vertex that must have a valance of exactly two. Furthermore
+ * both edges in KV's disk cycle (OE and KE) must be unique (no double
+ * edges).
+ *
+ * It should also be noted that this euler has the possibility of creating
+ * faces with just 2 edges. It is up to the caller to decide what to do with
+ * these faces.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+int bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv)
+{
+ BMEdge *oe;
+ BMVert *ov, *tv;
+ BMNode *diskbase;
+ BMLoop *killoop,*nextl;
+ int len,radlen=0, halt = 0, i, valance1, valance2,edok;
+
+ if(bmesh_vert_in_edge(ke,kv) == 0) return 0;
+ diskbase = bmesh_disk_getpointer(kv->e, kv);
+ len = bmesh_cycle_length(diskbase);
+
+ if(len == 2){
+ oe = bmesh_disk_nextedge(ke, kv);
+ tv = bmesh_edge_getothervert(ke, kv);
+ ov = bmesh_edge_getothervert(oe, kv);
+ halt = bmesh_verts_in_edge(kv, tv, oe); //check for double edges
+
+ if(halt) return 0;
+ else{
+
+ /*For verification later, count valance of ov and tv*/
+ diskbase = bmesh_disk_getpointer(ov->e, ov);
+ valance1 = bmesh_cycle_length(diskbase);
+ diskbase = bmesh_disk_getpointer(tv->e, tv);
+ valance2 = bmesh_cycle_length(diskbase);
+
+ /*remove oe from kv's disk cycle*/
+ bmesh_disk_remove_edge(oe,kv);
+ /*relink oe->kv to be oe->tv*/
+ bmesh_edge_swapverts(oe, kv, tv);
+ /*append oe to tv's disk cycle*/
+ bmesh_disk_append_edge(oe, tv);
+ /*remove ke from tv's disk cycle*/
+ bmesh_disk_remove_edge(ke, tv);
+
+
+
+ /*deal with radial cycle of ke*/
+ if(ke->l){
+ /*first step, fix the neighboring loops of all loops in ke's radial cycle*/
+ radlen = bmesh_cycle_length(&(ke->l->radial));
+ for(i=0,killoop = ke->l; i<radlen; i++, killoop = bmesh_radial_nextloop(killoop)){
+ /*relink loops and fix vertex pointer*/
+ killoop->next->prev = killoop->prev;
+ killoop->prev->next = killoop->next;
+ if( ((killoop->next))->v == kv) ((killoop->next))->v = tv;
+
+ /*fix len attribute of face*/
+ killoop->f->len--;
+ if(killoop->f->loopbase == killoop) killoop->f->lbase = ((killoop->next));
+ }
+ /*second step, remove all the hanging loops attached to ke*/
+ killoop = ke->l;
+ radlen = bmesh_cycle_length(&(ke->l->radial));
+ /*make sure we have enough room in bm->lpar*/
+ if(bm->lparlen < radlen){
+ MEM_freeN(bm->lpar);
+ bm->lpar = MEM_callocN(sizeof(BMLoop *)* radlen, "BM Loop pointer array");
+ bm->lparlen = bm->lparlen * radlen;
+ }
+ /*this should be wrapped into a bme_free_radial function to be used by bmesh_KF as well...*/
+ i=0;
+ while(i<radlen){
+ bm->lpar[i] = killoop;
+ killoop = killoop->radial_next;
+ i++;
+ }
+ i=0;
+ while(i<radlen){
+ bmesh_free_loop(bm,bm->lpar[i]);
+ i++;
+ }
+ /*Validate radial cycle of oe*/
+ edok = bmesh_cycle_validate(radlen,&(oe->l->radial));
+
+ }
+
+
+ /*Validate disk cycles*/
+ diskbase = bmesh_disk_getpointer(ov->e,ov);
+ edok = bmesh_cycle_validate(valance1, diskbase);
+ if(!edok) bmesh_error();
+ diskbase = bmesh_disk_getpointer(tv->e,tv);
+ edok = bmesh_cycle_validate(valance2, diskbase);
+ if(!edok) bmesh_error();
+
+ /*Validate loop cycle of all faces attached to oe*/
+ for(i=0,nextl = oe->l; i<radlen; i++, nextl = bmesh_radial_nextloop(nextl)){
+ edok = bmesh_cycle_validate(nextl->f->len,nextl->f->lbase);
+ if(!edok) bmesh_error();
+ }
+ /*deallocate edge*/
+ BLI_remlink(&(bm->edges), &(ke->head));
+ bmesh_free_edge(bm, ke);
+ /*deallocate vertex*/
+ BLI_remlink(&(bm->verts), &(kv->head));
+ bmesh_free_vert(bm, kv);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * bmesh_loop_reverse
+ *
+ * FLIP FACE EULER
+ *
+ * Changes the winding order of a face from CW to CCW or vice versa.
+ * This euler is a bit peculiar in compairson to others as it is its
+ * own inverse.
+ *
+ * BMESH_TODO: reinsert validation code.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+
+int bmesh_loop_reverse(BMesh *bm, BMFace *f){
+ BMLoop *l = f->loopbase, *curloop, *oldprev, *oldnext;
+ int i, j, edok, len = 0;
+
+ len = bmesh_cycle_length(l);
+ if(bm->edarlen < len){
+ MEM_freeN(bm->edar);
+ bm->edar = MEM_callocN(sizeof(BMEdge *)* len, "BM Edge pointer array");
+ bm->edarlen = len;
+ }
+
+ for(i=0, curloop = l; i< len; i++, curloop= ((curloop->next)) ){
+ curloop->e->head.eflag1 = 0;
+ curloop->e->head.eflag2 = bmesh_cycle_length(&curloop->radial);
+ bmesh_radial_remove_loop(curloop, curloop->e);
+ /*in case of border edges we HAVE to zero out curloop->radial Next/Prev*/
+ curloop->radial.next = curloop->radial.prev = NULL;
+ bm->edar[i] = curloop->e;
+ }
+
+ /*actually reverse the loop. This belongs in bmesh_cycle_reverse!*/
+ for(i=0, curloop = l; i < len; i++){
+ oldnext = ((curloop->next));
+ oldprev = ((curloop->prev));
+ curloop->next = (BMHeader*)oldprev;
+ curloop->prev = (BMHeader*)oldnext;
+ curloop = oldnext;
+ }
+
+ if(len == 2){ //two edged face
+ //do some verification here!
+ l->e = bm->edar[1];
+ ((l->next))->e = bm->edar[0];
+ }
+ else{
+ for(i=0, curloop = l; i < len; i++, curloop = ((curloop->next)) ){
+ edok = 0;
+ for(j=0; j < len; j++){
+ edok = bmesh_verts_in_edge(curloop->v, ((curloop->next))->v, bm->edar[j]);
+ if(edok){
+ curloop->e = bm->edar[j];
+ break;
+ }
+ }
+ }
+ }
+ /*rebuild radial*/
+ for(i=0, curloop = l; i < len; i++, curloop = curloop->next ) bmesh_radial_append(curloop->e, curloop);
+
+ /*validate radial*/
+ for(i=0, curloop = l; i < len; i++, curloop = ((curloop->next)) ){
+ edok = bmesh_cycle_validate(curloop->e->head.eflag2, &(curloop->radial));
+ if(!edok){
+ bmesh_error();
+ }
+ }
+ return 1;
+}
+
+/**
+ * bmesh_JFKE
+ *
+ * JOIN FACE KILL EDGE:
+ *
+ * Takes two faces joined by a single 2-manifold edge and fuses them togather.
+ * The edge shared by the faces must not be connected to any other edges which have
+ * Both faces in its radial cycle
+ *
+ * Examples:
+ *
+ * A B
+ * ---------- ----------
+ * | | | |
+ * | f1 | | f1 |
+ * v1========v2 = Ok! v1==V2==v3 == Wrong!
+ * | f2 | | f2 |
+ * | | | |
+ * ---------- ----------
+ *
+ * In the example A, faces f1 and f2 are joined by a single edge, and the euler can safely be used.
+ * In example B however, f1 and f2 are joined by multiple edges and will produce an error. The caller
+ * in this case should call bmesh_JEKV on the extra edges before attempting to fuse f1 and f2.
+ *
+ * Also note that the order of arguments decides whether or not certain per-face attributes are present
+ * in the resultant face. For instance vertex winding, material index, smooth flags, ect are inherited
+ * from f1, not f2.
+ *
+ * Returns -
+ * A BMFace pointer
+*/
+
+//disregarding f1loop and f2loop, if a vertex appears in a joined face more than once, we cancel
+
+BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
+{
+
+ BMLoop *curloop, *f1loop=NULL, *f2loop=NULL;
+ int loopok = 0, newlen = 0,i, f1len=0, f2len=0, radlen=0, edok, shared;
+
+ if(f1 == f2) return NULL; //can't join a face to itself
+ /*verify that e is in both f1 and f2*/
+ f1len = bmesh_cycle_length(f1->lbase);
+ f2len = bmesh_cycle_length(f2->lbase);
+ for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = ((curloop->next)) ){
+ if(curloop->e == e){
+ f1loop = curloop;
+ break;
+ }
+ }
+ for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((curloop->next)) ){
+ if(curloop->e==e){
+ f2loop = curloop;
+ break;
+ }
+ }
+ if(!(f1loop && f2loop)) return NULL;
+
+ /*validate that edge is 2-manifold edge*/
+ radlen = bmesh_cycle_length(&(f1loop->radial));
+ if(radlen != 2) return NULL;
+
+ /*validate direction of f2's loop cycle is compatible.*/
+ if(f1loop->v == f2loop->v) return NULL;
+
+ /*
+ validate that for each face, each vertex has another edge in its disk cycle that is
+ not e, and not shared.
+ */
+ if(bmesh_radial_find_face( ((f1loop->next))->e,f2)) return NULL;
+ if(bmesh_radial_find_face( ((f1loop->prev))->e,f2)) return NULL;
+ if(bmesh_radial_find_face( ((f2loop->next))->e,f1)) return NULL;
+ if(bmesh_radial_find_face( ((f2loop->prev))->e,f1)) return NULL;
+
+ /*validate only one shared edge*/
+ shared = BM_Face_Sharededges(f1,f2);
+ if(shared > 1) return NULL;
+
+ /*validate no internal joins*/
+ for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = ((curloop->next)) ) curloop->v->head.eflag1 = 0;
+ for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((curloop->next)) ) curloop->v->head.eflag1 = 0;
+
+ for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = ((curloop->next)) ){
+ if(curloop != f1loop)
+ curloop->v->head.eflag1++;
+ }
+ for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((curloop->next)) ){
+ if(curloop != f2loop)
+ curloop->v->head.eflag1++;
+ }
+
+ for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = ((curloop->next)) ){
+ if(curloop->v->head.eflag1 > 1)
+ return NULL;
+ }
+
+ for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = ((curloop->next)) ){
+ if(curloop->v->head.eflag1 > 1)
+ return NULL;
+ }
+
+ /*join the two loops*/
+ f1loop->prev->next = f2loop->next;
+ f2loop->next->prev = f1loop->prev;
+
+ f1loop->next->prev = f2loop->prev;
+ f2loop->prev->next = f1loop->next;
+
+ /*if f1loop was baseloop, give f1loop->next the base.*/
+ if(f1->loopbase == f1loop) f1->lbase = ((f1loop->next));
+
+ /*validate the new loop*/
+ loopok = bmesh_cycle_validate((f1len+f2len)-2, f1->lbase);
+ if(!loopok) bmesh_error();
+
+ /*make sure each loop points to the proper face*/
+ newlen = bmesh_cycle_length(f1->lbase);
+ for(i = 0, curloop = f1->loopbase; i < newlen; i++, curloop = ((curloop->next)) ) curloop->f = f1;
+
+ f1->len = newlen;
+
+ edok = bmesh_cycle_validate(f1->len, f1->lbase);
+ if(!edok) bmesh_error();
+
+ /*remove edge from the disk cycle of its two vertices.*/
+ bmesh_disk_remove_edge(f1loop->e, f1loop->e->v1);
+ bmesh_disk_remove_edge(f1loop->e, f1loop->e->v2);
+
+ /*deallocate edge and its two loops as well as f2*/
+ BLI_remlink(&(bm->edges), &(f1loop->e->head));
+ BLI_remlink(&(bm->polys), &(f2->head));
+ bmesh_free_edge(bm, f1loop->e);
+ bmesh_free_loop(bm, f1loop);
+ bmesh_free_loop(bm, f2loop);
+ bmesh_free_poly(bm, f2);
+ return f1;
+}
+
+/**
+* bmesh_URMV
+*
+* UNGLUE REGION MAKE VERT:
+*
+* Takes a locally manifold disk of face corners and 'unglues' it
+* creating a new vertex
+*
+**/
+
+#define URMV_VISIT 1
+#define URMV_VISIT2 2
+
+BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv)
+{
+ BMVert *nv = NULL;
+ BMLoop *l = NULL, *sl = NULL;
+ BMEdge *curedge = NULL;
+ int numloops = 0, numedges = 0, i, maxedges, maxloops;
+
+
+ /*BMESH_TODO: Validation*/
+ /*validate radial cycle of all collected loops*/
+ /*validate the disk cycle of sv, and nv*/
+ /*validate the face length of all faces? overkill?*/
+ /*validate the l->e pointers of all affected faces, ie: l->v and l->next->v should be equivalent to l->e*/
+
+ /*verify that sv has edges*/
+ if(sv->e == NULL)
+ return NULL;
+
+ /*first verify no wire edges on sv*/
+ curedge = sv->e;
+ do{
+ if(curedge->l == NULL)
+ return NULL;
+ curedge = bmesh_disk_nextedge(curedge, sv);
+ }while(curedge != sv->e);
+
+ /*next verify that sv is in sf*/
+ l = sf->loopbase;
+ do{
+ if(l->v == sv){
+ sl = l;
+ break;
+ }
+ l = (l->next);
+ }while(l != sf->lbase);
+
+ if(sl == NULL)
+ return NULL;
+
+ /*clear euler flags*/
+ sv->head.eflag1 = 0;
+
+ curedge = sv->e;
+ do{
+ curedge->head.eflag1 = 0;
+ l = curedge->l;
+ do{
+ l->head.eflag1 = 0;
+ l->f->head.eflag1 = 0;
+ l = bmesh_radial_nextloop(l);
+ }while(l != curedge->l);
+ curedge = bmesh_disk_nextedge(curedge, sv);
+ }while(curedge != sv->e);
+
+ /*search through face disk and flag elements as we go.*/
+ /*Note, test this to make sure that it works correct on
+ non-manifold faces!
+ */
+ l = sl;
+ l->e->head.eflag1 |= URMV_VISIT;
+ l->f->head.eflag1 |= URMV_VISIT;
+ do{
+ if(l->v == sv)
+ l = bmesh_radial_nextloop((l->prev));
+ else
+ l = bmesh_radial_nextloop((l->next));
+ l->e->head.eflag1 |= URMV_VISIT;
+ l->f->head.eflag1 |= URMV_VISIT;
+ }while(l != sl && (bmesh_cycle_length(&(l->radial)) > 1) );
+
+ /*Verify that all visited edges are at least 1 or 2 manifold*/
+ curedge = sv->e;
+ do{
+ if(curedge->head.eflag1 && (bmesh_cycle_length(&(curedge->l->radial)) > 2) )
+ return NULL;
+ curedge = bmesh_disk_nextedge(curedge, sv);
+ }while(curedge != sv->e);
+
+ /*allocate temp storage - we overallocate here instead of trying to be clever*/
+ maxedges = 0;
+ maxloops = 0;
+ curedge = sv->e;
+ do{
+ if(curedge->l){
+ l = curedge->l;
+ do{
+ maxloops += l->f->len;
+ l = bmesh_radial_nextloop(l);
+ }while(l != curedge->l);
+ }
+ maxedges+= 1;
+ curedge = bmesh_disk_nextedge(curedge,sv);
+ }while(curedge != sv->e);
+
+ if(bm->edarlen < maxedges){
+ MEM_freeN(bm->edar);
+ bm->edar = MEM_callocN(sizeof(BMEdge *) * maxedges, "BM Edge pointer array");
+ bm->edarlen = maxedges;
+ }
+ if(bm->lparlen < maxloops){
+ MEM_freeN(bm->lpar);
+ bm->lpar = MEM_callocN(sizeof(BMLoop *) * maxloops, "BM Loop pointer array");
+ bm->lparlen = maxloops;
+ }
+
+ /*first get loops by looping around edges and loops around that edges faces*/
+ curedge = sv->e;
+ do{
+ if(curedge->l){
+ l = curedge->l;
+ do{
+ if( (l->head.eflag1 & URMV_VISIT) && (!(l->head.eflag1 & URMV_VISIT2)) ){
+ bm->lpar[numloops] = l;
+ l->head.eflag1 |= URMV_VISIT2;
+ numloops++;
+ }
+ l = bmesh_radial_nextloop(l);
+ }while(l != curedge->l);
+ }
+ curedge = bmesh_disk_nextedge(curedge, sv);
+ }while(curedge != sv->e);
+
+ /*now collect edges by looping around edges and looking at visited flags*/
+ curedge = sv->e;
+ do{
+ if(curedge->head.eflag1 & URMV_VISIT){
+ bm->edar[numedges] = curedge;
+ numedges++;
+ }
+ curedge = bmesh_disk_nextedge(curedge, sv);
+ }while(curedge != sv->e);
+
+ /*make new vertex*/
+ nv = bmesh_addvertlist(bm, sv);
+
+ /*go through and relink edges*/
+ for(i = 0; i < numedges; i++){
+ curedge = bm->edar[i];
+ /*remove curedge from sv*/
+ bmesh_disk_remove_edge(curedge, sv);
+ /*swap out sv for nv in curedge*/
+ bmesh_edge_swapverts(curedge, sv, nv);
+ /*add curedge to nv's disk cycle*/
+ bmesh_disk_append_edge(curedge, nv);
+ }
+
+ /*go through and relink loops*/
+ for(i = 0; i < numloops; i ++){
+ l = bm->lpar[i];
+ if(l->v == sv)
+ l->v = nv;
+ }
+ return nv;
+}
+#endif
diff --git a/source/blender/bmesh/intern/bmesh_filters.c b/source/blender/bmesh/intern/bmesh_filters.c
new file mode 100644
index 00000000000..c31139a8f93
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_filters.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "bmesh.h"
+#include "bmesh_private.h"
diff --git a/source/blender/bmesh/intern/bmesh_inline.c b/source/blender/bmesh/intern/bmesh_inline.c
new file mode 100644
index 00000000000..4a549248710
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_inline.c
@@ -0,0 +1,44 @@
+#ifndef BM_INLINE_C
+#define BM_INLINE_C
+
+#include "bmesh.h"
+
+BM_INLINE int BM_TestHFlag(const void *element, const int flag)
+{
+ return ((const BMHeader *)element)->flag & flag;
+}
+
+BM_INLINE void BM_SetHFlag(void *element, const int flag)
+{
+ ((BMHeader *)element)->flag |= flag;
+}
+
+BM_INLINE void BM_ClearHFlag(void *element, const int flag)
+{
+ ((BMHeader *)element)->flag &= ~flag;
+}
+
+BM_INLINE void BM_ToggleHFlag(void *element, const int flag)
+{
+ ((BMHeader *)element)->flag ^= flag;
+}
+
+BM_INLINE void BM_MergeHFlag(void *element_a, void *element_b)
+{
+ ((BMHeader *)element_a)->flag =
+ ((BMHeader *)element_b)->flag = (((BMHeader *)element_a)->flag |
+ ((BMHeader *)element_b)->flag);
+}
+
+BM_INLINE void BM_SetIndex(void *element, const int index)
+{
+ ((BMHeader *)element)->index = index;
+}
+
+BM_INLINE int BM_GetIndex(const void *element)
+{
+ return ((BMHeader *)element)->index;
+}
+
+#endif /*BM_INLINE_C*/
+
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
new file mode 100644
index 00000000000..ab6eb6cff8e
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -0,0 +1,950 @@
+/**
+ * BME_interp.c August 2008
+ *
+ * BM interpolation functions.
+ *
+ * ***** 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.
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_utildefines.h"
+#include "BKE_multires.h"
+
+#include "BLI_array.h"
+#include "BLI_math.h"
+#include "BLI_cellalloc.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+/*
+ * BME_INTERP.C
+ *
+ * Functions for interpolating data across the surface of a mesh.
+ *
+*/
+
+/**
+ * bmesh_data_interp_from_verts
+ *
+ * Interpolates per-vertex data from two sources to a target.
+ *
+ * Returns -
+ * Nothing
+ */
+void BM_Data_Interp_From_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, float fac)
+{
+ void *src[2];
+ float w[2];
+ if (v1->head.data && v2->head.data) {
+ src[0]= v1->head.data;
+ src[1]= v2->head.data;
+ w[0] = 1.0f-fac;
+ w[1] = fac;
+ CustomData_bmesh_interp(&bm->vdata, src, w, NULL, 2, v->head.data);
+ }
+}
+
+/*
+ BM Data Vert Average
+
+ Sets all the customdata (e.g. vert, loop) associated with a vert
+ to the average of the face regions surrounding it.
+*/
+
+
+static void BM_Data_Vert_Average(BMesh *UNUSED(bm), BMFace *UNUSED(f))
+{
+ // BMIter iter;
+}
+
+/**
+ * bmesh_data_facevert_edgeinterp
+ *
+ * Walks around the faces of an edge and interpolates the per-face-edge
+ * data between two sources to a target.
+ *
+ * Returns -
+ * Nothing
+*/
+
+void BM_Data_Facevert_Edgeinterp(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BMVert *v, BMEdge *e1, float fac){
+ void *src[2];
+ float w[2];
+ BMLoop *l=NULL, *v1loop = NULL, *vloop = NULL, *v2loop = NULL;
+
+ w[1] = 1.0f - fac;
+ w[0] = fac;
+
+ if(!e1->l) return;
+ l = e1->l;
+ do{
+ if(l->v == v1){
+ v1loop = l;
+ vloop = v1loop->next;
+ v2loop = vloop->next;
+ }else if(l->v == v){
+ v1loop = l->next;
+ vloop = l;
+ v2loop = l->prev;
+ }
+
+ if (!v1loop || !v2loop)
+ return;
+
+ src[0] = v1loop->head.data;
+ src[1] = v2loop->head.data;
+
+ CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, vloop->head.data);
+ l = l->radial_next;
+ }while(l!=e1->l);
+}
+
+void BM_loops_to_corners(BMesh *bm, Mesh *me, int findex,
+ BMFace *f, int numTex, int numCol)
+{
+ BMLoop *l;
+ BMIter iter;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ int i, j;
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_n(&me->fdata, CD_MTFACE, findex, i);
+ texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
+
+ texface->tpage = texpoly->tpage;
+ texface->flag = texpoly->flag;
+ texface->transp = texpoly->transp;
+ texface->mode = texpoly->mode;
+ texface->tile = texpoly->tile;
+ texface->unwrap = texpoly->unwrap;
+
+ j = 0;
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
+ texface->uv[j][0] = mloopuv->uv[0];
+ texface->uv[j][1] = mloopuv->uv[1];
+
+ j++;
+ }
+
+ }
+
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_get_n(&me->fdata, CD_MCOL, findex, i);
+
+ j = 0;
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+
+ j++;
+ }
+ }
+}
+
+/**
+ * BM_data_interp_from_face
+ *
+ * projects target onto source, and pulls interpolated customdata from
+ * source.
+ *
+ * Returns -
+ * Nothing
+*/
+void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source)
+{
+ BMLoop *l1, *l2;
+ void **blocks=NULL;
+ float (*cos)[3]=NULL, *w=NULL;
+ BLI_array_staticdeclare(cos, 64);
+ BLI_array_staticdeclare(w, 64);
+ BLI_array_staticdeclare(blocks, 64);
+
+ BM_Copy_Attributes(bm, bm, source, target);
+
+ l2 = bm_firstfaceloop(source);
+ do {
+ BLI_array_growone(cos);
+ copy_v3_v3(cos[BLI_array_count(cos)-1], l2->v->co);
+ BLI_array_growone(w);
+ BLI_array_append(blocks, l2->head.data);
+ l2 = l2->next;
+ } while (l2 != bm_firstfaceloop(source));
+
+ l1 = bm_firstfaceloop(target);
+ do {
+ interp_weights_poly_v3(w, cos, source->len, l1->v->co);
+ CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, BLI_array_count(blocks), l1->head.data);
+ l1 = l1->next;
+ } while (l1 != bm_firstfaceloop(target));
+
+ BLI_array_free(cos);
+ BLI_array_free(w);
+ BLI_array_free(blocks);
+}
+
+/****some math stuff for dealing with doubles, put here to
+ avoid merge errors - joeedh ****/
+
+#define VECMUL(a, b) (((a)[0] = (a)[0] * (b)), ((a)[1] = (a)[1] * (b)), ((a)[2] = (a)[2] * (b)))
+#define VECADD2(a, b) (((a)[0] = (a)[0] + (b)[0]), ((a)[1] = (a)[1] + (b)[1]), ((a)[2] = (a)[2] + (b)[2]))
+#define VECSUB2(a, b) (((a)[0] = (a)[0] - (b)[0]), ((a)[1] = (a)[1] - (b)[1]), ((a)[2] = (a)[2] - (b)[2]))
+
+/* find closest point to p on line through l1,l2 and return lambda,
+ * where (0 <= lambda <= 1) when cp is in the line segement l1,l2
+ */
+static double closest_to_line_v3_d(double cp[3], const double p[3], const double l1[3], const double l2[3])
+{
+ double h[3],u[3],lambda;
+ VECSUB(u, l2, l1);
+ VECSUB(h, p, l1);
+ lambda =INPR(u,h)/INPR(u,u);
+ cp[0] = l1[0] + u[0] * lambda;
+ cp[1] = l1[1] + u[1] * lambda;
+ cp[2] = l1[2] + u[2] * lambda;
+ return lambda;
+}
+
+/* point closest to v1 on line v2-v3 in 3D */
+static void closest_to_line_segment_v3_d(double *closest, double v1[3], double v2[3], double v3[3])
+{
+ double lambda, cp[3];
+
+ lambda= closest_to_line_v3_d(cp,v1, v2, v3);
+
+ if(lambda <= 0.0) {
+ VECCOPY(closest, v2);
+ } else if(lambda >= 1.0) {
+ VECCOPY(closest, v3);
+ } else {
+ VECCOPY(closest, cp);
+ }
+}
+
+static double len_v3_d(const double a[3])
+{
+ return sqrt(INPR(a, a));
+}
+
+static double len_v3v3_d(const double a[3], const double b[3])
+{
+ double d[3];
+
+ VECSUB(d, b, a);
+ return sqrt(INPR(d, d));
+}
+
+static void cent_quad_v3_d(double *cent, double *v1, double *v2, double *v3, double *v4)
+{
+ cent[0]= 0.25*(v1[0]+v2[0]+v3[0]+v4[0]);
+ cent[1]= 0.25*(v1[1]+v2[1]+v3[1]+v4[1]);
+ cent[2]= 0.25*(v1[2]+v2[2]+v3[2]+v4[2]);
+}
+
+static void cent_tri_v3_d(double *cent, double *v1, double *v2, double *v3)
+{
+ cent[0]= 0.33333*(v1[0]+v2[0]+v3[0]);
+ cent[1]= 0.33333*(v1[1]+v2[1]+v3[1]);
+ cent[2]= 0.33333*(v1[2]+v2[2]+v3[2]);
+}
+
+static void cross_v3_v3v3_d(double r[3], const double a[3], const double b[3])
+{
+ r[0]= a[1]*b[2] - a[2]*b[1];
+ r[1]= a[2]*b[0] - a[0]*b[2];
+ r[2]= a[0]*b[1] - a[1]*b[0];
+}
+
+/* distance v1 to line-piece v2-v3 */
+static double dist_to_line_segment_v2_d(double v1[3], double v2[3], double v3[3])
+{
+ double labda, rc[2], pt[2], len;
+
+ rc[0]= v3[0]-v2[0];
+ rc[1]= v3[1]-v2[1];
+ len= rc[0]*rc[0]+ rc[1]*rc[1];
+ if(len==0.0) {
+ rc[0]= v1[0]-v2[0];
+ rc[1]= v1[1]-v2[1];
+ return sqrt(rc[0]*rc[0]+ rc[1]*rc[1]);
+ }
+
+ labda= (rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]))/len;
+ if(labda<=0.0) {
+ pt[0]= v2[0];
+ pt[1]= v2[1];
+ }
+ else if(labda>=1.0) {
+ pt[0]= v3[0];
+ pt[1]= v3[1];
+ }
+ else {
+ pt[0]= labda*rc[0]+v2[0];
+ pt[1]= labda*rc[1]+v2[1];
+ }
+
+ rc[0]= pt[0]-v1[0];
+ rc[1]= pt[1]-v1[1];
+ return sqrt(rc[0]*rc[0]+ rc[1]*rc[1]);
+}
+
+
+MINLINE double line_point_side_v2_d(const double *l1, const double *l2, const double *pt)
+{
+ return ((l1[0]-pt[0]) * (l2[1]-pt[1])) -
+ ((l2[0]-pt[0]) * (l1[1]-pt[1]));
+}
+
+/* point in quad - only convex quads */
+static int isect_point_quad_v2_d(double pt[2], double v1[2], double v2[2], double v3[2], double v4[2])
+{
+ if (line_point_side_v2_d(v1,v2,pt)>=0.0) {
+ if (line_point_side_v2_d(v2,v3,pt)>=0.0) {
+ if (line_point_side_v2_d(v3,v4,pt)>=0.0) {
+ if (line_point_side_v2_d(v4,v1,pt)>=0.0) {
+ return 1;
+ }
+ }
+ }
+ } else {
+ if (! (line_point_side_v2_d(v2,v3,pt)>=0.0)) {
+ if (! (line_point_side_v2_d(v3,v4,pt)>=0.0)) {
+ if (! (line_point_side_v2_d(v4,v1,pt)>=0.0)) {
+ return -1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/***** multires interpolation*****
+
+mdisps is a grid of displacements, ordered thus:
+
+ v1/center----v4/next -> x
+ | |
+ | |
+ v2/prev------v3/cur
+ |
+ V
+ y
+*/
+
+static int compute_mdisp_quad(BMLoop *l, double v1[3], double v2[3], double v3[3], double v4[3], double e1[3], double e2[3])
+{
+ double cent[3] = {0.0, 0.0, 0.0}, n[3], p[3];
+ BMLoop *l2;
+
+ /*computer center*/
+ l2 = bm_firstfaceloop(l->f);
+ do {
+ cent[0] += (double)l2->v->co[0];
+ cent[1] += (double)l2->v->co[1];
+ cent[2] += (double)l2->v->co[2];
+ l2 = l2->next;
+ } while (l2 != bm_firstfaceloop(l->f));
+
+ VECMUL(cent, (1.0/(double)l->f->len));
+
+ VECADD(p, l->prev->v->co, l->v->co);
+ VECMUL(p, 0.5);
+ VECADD(n, l->next->v->co, l->v->co);
+ VECMUL(n, 0.5);
+
+ VECCOPY(v1, cent);
+ VECCOPY(v2, p);
+ VECCOPY(v3, l->v->co);
+ VECCOPY(v4, n);
+
+ VECSUB(e1, v2, v1);
+ VECSUB(e2, v3, v4);
+
+ return 1;
+}
+
+/*funnily enough, I think this is identical to face_to_crn_interp, heh*/
+static double quad_coord(double aa[3], double bb[3], double cc[3], double dd[3], int a1, int a2)
+{
+ double x, y, z, f1;
+
+ x = aa[a1]*cc[a2]-cc[a1]*aa[a2];
+ y = aa[a1]*dd[a2]+bb[a1]*cc[a2]-cc[a1]*bb[a2]-dd[a1]*aa[a2];
+ z = bb[a1]*dd[a2]-dd[a1]*bb[a2];
+
+ if (fabs(2*(x-y+z)) > DBL_EPSILON*10.0) {
+ double f2;
+
+ f1 = (sqrt(y*y-4.0*x*z) - y + 2.0*z) / (2.0*(x-y+z));
+ f2 = (-sqrt(y*y-4.0*x*z) - y + 2.0*z) / (2.0*(x-y+z));
+
+ f1= fabs(f1);
+ f2= fabs(f2);
+ f1 = MIN2(f1, f2);
+ CLAMP(f1, 0.0, 1.0+DBL_EPSILON);
+ } else {
+ f1 = -z/(y - 2*z);
+ CLAMP(f1, 0.0, 1.0+DBL_EPSILON);
+
+ if (isnan(f1) || f1 > 1.0 || f1 < 0.0) {
+ int i;
+
+ for (i=0; i<2; i++) {
+ if (fabsf(aa[i]) < FLT_EPSILON*100)
+ return aa[(i+1)%2] / fabs(bb[(i+1)%2] - aa[(i+1)%2]);
+ if (fabsf(cc[i]) < FLT_EPSILON*100)
+ return cc[(i+1)%2] / fabs(dd[(i+1)%2] - cc[(i+1)%2]);
+ }
+ }
+ }
+
+ return f1;
+}
+
+static int quad_co(double *x, double *y, double v1[3], double v2[3], double v3[3], double v4[3], double p[3], float n[3])
+{
+ float projverts[5][3], n2[3];
+ double dprojverts[4][3], origin[3]={0.0f, 0.0f, 0.0f};
+ int i;
+
+ /*project points into 2d along normal*/
+ VECCOPY(projverts[0], v1);
+ VECCOPY(projverts[1], v2);
+ VECCOPY(projverts[2], v3);
+ VECCOPY(projverts[3], v4);
+ VECCOPY(projverts[4], p);
+
+ normal_quad_v3(n2, projverts[0], projverts[1], projverts[2], projverts[3]);
+
+ if (INPR(n, n2) < -FLT_EPSILON)
+ return 0;
+
+ /*rotate*/
+ poly_rotate_plane(n, projverts, 5);
+
+ /*flatten*/
+ for (i=0; i<5; i++) projverts[i][2] = 0.0f;
+
+ /*subtract origin*/
+ for (i=0; i<4; i++) {
+ VECSUB2(projverts[i], projverts[4]);
+ }
+
+ VECCOPY(dprojverts[0], projverts[0]);
+ VECCOPY(dprojverts[1], projverts[1]);
+ VECCOPY(dprojverts[2], projverts[2]);
+ VECCOPY(dprojverts[3], projverts[3]);
+
+ if (!isect_point_quad_v2_d(origin, dprojverts[0], dprojverts[1], dprojverts[2], dprojverts[3]))
+ return 0;
+
+ *y = quad_coord(dprojverts[1], dprojverts[0], dprojverts[2], dprojverts[3], 0, 1);
+ *x = quad_coord(dprojverts[2], dprojverts[1], dprojverts[3], dprojverts[0], 0, 1);
+
+ return 1;
+}
+
+
+/*tl is loop to project onto, l is loop whose internal displacement, co, is being
+ projected. x and y are location in loop's mdisps grid of point co.*/
+static int mdisp_in_mdispquad(BMesh *bm, BMLoop *l, BMLoop *tl, double p[3], double *x, double *y, int res)
+{
+ double v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3];
+ double eps = FLT_EPSILON*4000;
+
+ if (len_v3(l->v->no) == 0.0f)
+ BM_Vert_UpdateAllNormals(bm, l->v);
+ if (len_v3(tl->v->no) == 0.0f)
+ BM_Vert_UpdateAllNormals(bm, tl->v);
+
+ compute_mdisp_quad(tl, v1, v2, v3, v4, e1, e2);
+
+ /*expand quad a bit*/
+ cent_quad_v3_d(c, v1, v2, v3, v4);
+
+ VECSUB2(v1, c); VECSUB2(v2, c);
+ VECSUB2(v3, c); VECSUB2(v4, c);
+ VECMUL(v1, 1.0+eps); VECMUL(v2, 1.0+eps);
+ VECMUL(v3, 1.0+eps); VECMUL(v4, 1.0+eps);
+ VECADD2(v1, c); VECADD2(v2, c);
+ VECADD2(v3, c); VECADD2(v4, c);
+
+ if (!quad_co(x, y, v1, v2, v3, v4, p, l->v->no))
+ return 0;
+
+ *x *= res-1;
+ *y *= res-1;
+
+ return 1;
+}
+
+static void bmesh_loop_interp_mdisps(BMesh *bm, BMLoop *target, BMFace *source)
+{
+ MDisps *mdisps;
+ BMLoop *l2;
+ double x, y, d, v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3];
+ int ix, iy, res;
+
+ /*ignore 2-edged faces*/
+ if (target->f->len < 3)
+ return;
+
+ if (!CustomData_has_layer(&bm->ldata, CD_MDISPS))
+ return;
+
+ mdisps = CustomData_bmesh_get(&bm->ldata, target->head.data, CD_MDISPS);
+ compute_mdisp_quad(target, v1, v2, v3, v4, e1, e2);
+
+ /*if no disps data allocate a new grid, the size of the first grid in source.*/
+ if (!mdisps->totdisp) {
+ MDisps *md2 = CustomData_bmesh_get(&bm->ldata, bm_firstfaceloop(source)->head.data, CD_MDISPS);
+
+ mdisps->totdisp = md2->totdisp;
+ if (mdisps->totdisp)
+ mdisps->disps = BLI_cellalloc_calloc(sizeof(float)*3*mdisps->totdisp, "mdisp->disps in bmesh_loop_intern_mdisps");
+ else
+ return;
+ }
+
+ res = (int)sqrt(mdisps->totdisp);
+ d = 1.0/(double)(res-1);
+ for (x=0.0f, ix=0; ix<res; x += d, ix++) {
+ for (y=0.0f, iy=0; iy<res; y+= d, iy++) {
+ double co1[3], co2[3], co[3];
+ double xx, yy;
+
+ VECCOPY(co1, e1);
+
+ if (!iy) yy = y + (double)FLT_EPSILON*20;
+ else yy = y - (double)FLT_EPSILON*20;
+
+ VECMUL(co1, y);
+ VECADD2(co1, v1);
+
+ VECCOPY(co2, e2);
+ VECMUL(co2, y);
+ VECADD2(co2, v4);
+
+ if (!ix) xx = x + (double)FLT_EPSILON*20;
+ else xx = x - (double)FLT_EPSILON*20;
+
+ VECSUB(co, co2, co1);
+ VECMUL(co, x);
+ VECADD2(co, co1);
+
+ l2 = bm_firstfaceloop(source);
+ do {
+ double x2, y2;
+ int ix2, iy2;
+ MDisps *md1, *md2;
+
+ md1 = CustomData_bmesh_get(&bm->ldata, target->head.data, CD_MDISPS);
+ md2 = CustomData_bmesh_get(&bm->ldata, l2->head.data, CD_MDISPS);
+
+ if (mdisp_in_mdispquad(bm, target, l2, co, &x2, &y2, res)) {
+ ix2 = (int)x2;
+ iy2 = (int)y2;
+
+ old_mdisps_bilinear(md1->disps[iy*res+ix], md2->disps, res, (float)x2, (float)y2);
+ }
+ l2 = l2->next;
+ } while (l2 != bm_firstfaceloop(source));
+ }
+ }
+}
+
+void BM_multires_smooth_bounds(BMesh *bm, BMFace *f)
+{
+ BMLoop *l;
+ BMIter liter;
+
+ if (!CustomData_has_layer(&bm->ldata, CD_MDISPS))
+ return;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ MDisps *mdp = CustomData_bmesh_get(&bm->ldata, l->prev->head.data, CD_MDISPS);
+ MDisps *mdl = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MDISPS);
+ MDisps *mdn = CustomData_bmesh_get(&bm->ldata, l->next->head.data, CD_MDISPS);
+ float co1[3];
+ int sides;
+ int y;
+
+ /*****
+ mdisps is a grid of displacements, ordered thus:
+
+ v4/next
+ |
+ | v1/cent-----mid2 ---> x
+ | | |
+ | | |
+ v2/prev---mid1-----v3/cur
+ |
+ V
+ y
+ *****/
+
+ sides = sqrt(mdp->totdisp);
+ for (y=0; y<sides; y++) {
+ add_v3_v3v3(co1, mdn->disps[y*sides], mdl->disps[y]);
+ mul_v3_fl(co1, 0.5);
+
+ copy_v3_v3(mdn->disps[y*sides], co1);
+ copy_v3_v3(mdl->disps[y], co1);
+ }
+ }
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ MDisps *mdl1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MDISPS);
+ MDisps *mdl2;
+ float co1[3], co2[3], co[3];
+ int sides;
+ int y;
+
+ /*****
+ mdisps is a grid of displacements, ordered thus:
+
+ v4/next
+ |
+ | v1/cent-----mid2 ---> x
+ | | |
+ | | |
+ v2/prev---mid1-----v3/cur
+ |
+ V
+ y
+ *****/
+
+ if (l->radial_next == l)
+ continue;
+
+ if (l->radial_next->v == l->v)
+ mdl2 = CustomData_bmesh_get(&bm->ldata, l->radial_next->head.data, CD_MDISPS);
+ else
+ mdl2 = CustomData_bmesh_get(&bm->ldata, l->radial_next->next->head.data, CD_MDISPS);
+
+ sides = sqrt(mdl1->totdisp);
+ for (y=0; y<sides; y++) {
+ int a1, a2, o1, o2;
+
+ if (l->v != l->radial_next->v) {
+ a1 = sides*y + sides-2;
+ a2 = (sides-2)*sides + y;
+
+ o1 = sides*y + sides-1;
+ o2 = (sides-1)*sides + y;
+ } else {
+ a1 = sides*y + sides-2;
+ a2 = sides*y + sides-2;
+ o1 = sides*y + sides-1;
+ o2 = sides*y + sides-1;
+ }
+
+ /*magic blending numbers, hardcoded!*/
+ add_v3_v3v3(co1, mdl1->disps[a1], mdl2->disps[a2]);
+ mul_v3_fl(co1, 0.18);
+
+ add_v3_v3v3(co2, mdl1->disps[o1], mdl2->disps[o2]);
+ mul_v3_fl(co2, 0.32);
+
+ add_v3_v3v3(co, co1, co2);
+
+ copy_v3_v3(mdl1->disps[o1], co);
+ copy_v3_v3(mdl2->disps[o2], co); //*/
+ }
+ }
+}
+
+void BM_loop_interp_multires(BMesh *bm, BMLoop *target, BMFace *source)
+{
+ bmesh_loop_interp_mdisps(bm, target, source);
+}
+
+void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
+ int do_vertex, int do_multires)
+{
+ BMLoop *l;
+ void **blocks=NULL;
+ void **vblocks=NULL;
+ float (*cos)[3]=NULL, co[3], *w=NULL, cent[3] = {0.0f, 0.0f, 0.0f};
+ BLI_array_staticdeclare(cos, 64);
+ BLI_array_staticdeclare(w, 64);
+ BLI_array_staticdeclare(blocks, 64);
+ BLI_array_staticdeclare(vblocks, 64);
+ int i, xn, yn, zn, ax, ay;
+
+ BM_Copy_Attributes(bm, bm, source, target->f);
+
+ l = bm_firstfaceloop(source);
+ do {
+ BLI_array_growone(cos);
+ copy_v3_v3(cos[BLI_array_count(cos)-1], l->v->co);
+ add_v3_v3(cent, cos[BLI_array_count(cos)-1]);
+
+ BLI_array_append(w, 0.0f);
+ BLI_array_append(blocks, l->head.data);
+
+ if (do_vertex)
+ BLI_array_append(vblocks, l->v->head.data);
+
+ l = l->next;
+ } while (l != bm_firstfaceloop(source));
+
+ /* find best projection of face XY, XZ or YZ: barycentric weights of
+ the 2d projected coords are the same and faster to compute */
+ xn= (float)fabs(source->no[0]);
+ yn= (float)fabs(source->no[1]);
+ zn= (float)fabs(source->no[2]);
+ if(zn>=xn && zn>=yn) {ax= 0; ay= 1;}
+ else if(yn>=xn && yn>=zn) {ax= 0; ay= 2;}
+ else {ax= 1; ay= 2;}
+
+ /* scale source face coordinates a bit, so points sitting directonly on an
+ edge will work.*/
+ mul_v3_fl(cent, 1.0f/(float)source->len);
+ for (i=0; i<source->len; i++) {
+ float vec[3], tmp[3];
+ sub_v3_v3v3(vec, cent, cos[i]);
+ mul_v3_fl(vec, 0.001);
+ add_v3_v3(cos[i], vec);
+
+ copy_v3_v3(tmp, cos[i]);
+ cos[i][0] = tmp[ax];
+ cos[i][1] = tmp[ay];
+ cos[i][2] = 0.0;
+ }
+
+
+ /*interpolate*/
+ co[0] = target->v->co[ax];
+ co[1] = target->v->co[ay];
+ co[2] = 0.0f;
+
+ interp_weights_poly_v3(w, cos, source->len, co);
+ CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, source->len, target->head.data);
+ if (do_vertex) {
+ CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, source->len, target->v->head.data);
+ BLI_array_free(vblocks);
+ }
+
+ BLI_array_free(cos);
+ BLI_array_free(w);
+ BLI_array_free(blocks);
+
+ if (do_multires) {
+ if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
+ bmesh_loop_interp_mdisps(bm, target, source);
+ }
+ }
+}
+
+
+void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source)
+{
+ BMLoop *l;
+ void **blocks=NULL;
+ float (*cos)[3]=NULL, *w=NULL, cent[3] = {0.0f, 0.0f, 0.0f};
+ BLI_array_staticdeclare(cos, 64);
+ BLI_array_staticdeclare(w, 64);
+ BLI_array_staticdeclare(blocks, 64);
+ int i;
+
+ l = bm_firstfaceloop(source);
+ do {
+ BLI_array_growone(cos);
+ copy_v3_v3(cos[BLI_array_count(cos)-1], l->v->co);
+ add_v3_v3(cent, cos[BLI_array_count(cos)-1]);
+
+ BLI_array_append(w, 0.0f);
+ BLI_array_append(blocks, l->v->head.data);
+ l = l->next;
+ } while (l != bm_firstfaceloop(source));
+
+ /*scale source face coordinates a bit, so points sitting directonly on an
+ edge will work.*/
+ mul_v3_fl(cent, 1.0f/(float)source->len);
+ for (i=0; i<source->len; i++) {
+ float vec[3];
+ sub_v3_v3v3(vec, cent, cos[i]);
+ mul_v3_fl(vec, 0.01);
+ add_v3_v3(cos[i], vec);
+ }
+
+ /*interpolate*/
+ interp_weights_poly_v3(w, cos, source->len, v->co);
+ CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, source->len, v->head.data);
+
+ BLI_array_free(cos);
+ BLI_array_free(w);
+ BLI_array_free(blocks);
+}
+
+static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
+{
+ BMIter iter;
+ BLI_mempool *oldpool = olddata->pool;
+ void *block;
+
+ CustomData_bmesh_init_pool(data, data==&bm->ldata ? 2048 : 512);
+
+ if (data == &bm->vdata) {
+ BMVert *eve;
+
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ block = NULL;
+ CustomData_bmesh_set_default(data, &block);
+ CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block);
+ CustomData_bmesh_free_block(olddata, &eve->head.data);
+ eve->head.data= block;
+ }
+ }
+ else if (data == &bm->edata) {
+ BMEdge *eed;
+
+ BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ block = NULL;
+ CustomData_bmesh_set_default(data, &block);
+ CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block);
+ CustomData_bmesh_free_block(olddata, &eed->head.data);
+ eed->head.data= block;
+ }
+ }
+ else if (data == &bm->pdata || data == &bm->ldata) {
+ BMIter liter;
+ BMFace *efa;
+ BMLoop *l;
+
+ BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if (data == &bm->pdata) {
+ block = NULL;
+ CustomData_bmesh_set_default(data, &block);
+ CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block);
+ CustomData_bmesh_free_block(olddata, &efa->head.data);
+ efa->head.data= block;
+ }
+
+ if (data == &bm->ldata) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
+ block = NULL;
+ CustomData_bmesh_set_default(data, &block);
+ CustomData_bmesh_copy_data(olddata, data, l->head.data, &block);
+ CustomData_bmesh_free_block(olddata, &l->head.data);
+ l->head.data= block;
+ }
+ }
+ }
+ }
+
+ if (oldpool) {
+ /* this should never happen but can when dissolve fails - [#28960] */
+ BLI_assert(data->pool != oldpool);
+
+ BLI_mempool_destroy(oldpool);
+ }
+}
+
+
+void BM_add_data_layer(BMesh *bm, CustomData *data, int type)
+{
+ CustomData olddata;
+
+ olddata= *data;
+ olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
+ CustomData_add_layer(data, type, CD_DEFAULT, NULL, 0);
+
+ update_data_blocks(bm, &olddata, data);
+ if (olddata.layers) MEM_freeN(olddata.layers);
+}
+
+void BM_add_data_layer_named(BMesh *bm, CustomData *data, int type, char *name)
+{
+ CustomData olddata;
+
+ olddata= *data;
+ olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
+ CustomData_add_layer_named(data, type, CD_DEFAULT, NULL, 0, name);
+
+ update_data_blocks(bm, &olddata, data);
+ if (olddata.layers) MEM_freeN(olddata.layers);
+}
+
+void BM_free_data_layer(BMesh *bm, CustomData *data, int type)
+{
+ CustomData olddata;
+
+ olddata= *data;
+ olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
+ CustomData_free_layer_active(data, type, 0);
+
+ update_data_blocks(bm, &olddata, data);
+ if (olddata.layers) MEM_freeN(olddata.layers);
+}
+
+void BM_free_data_layer_n(BMesh *bm, CustomData *data, int type, int n)
+{
+ CustomData olddata;
+
+ olddata= *data;
+ olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
+ CustomData_free_layer(data, type, 0, CustomData_get_layer_index_n(data, type, n));
+
+ update_data_blocks(bm, &olddata, data);
+ if (olddata.layers) MEM_freeN(olddata.layers);
+}
+
+float BM_GetCDf(CustomData *cd, void *element, int type)
+{
+ if (CustomData_has_layer(cd, type)) {
+ float *f = CustomData_bmesh_get(cd, ((BMHeader*)element)->data, type);
+ return *f;
+ }
+
+ return 0.0;
+}
+
+void BM_SetCDf(CustomData *cd, void *element, int type, float val)
+{
+ if (CustomData_has_layer(cd, type)) {
+ float *f = CustomData_bmesh_get(cd, ((BMHeader*)element)->data, type);
+ *f = val;
+ }
+
+ return;
+}
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
new file mode 100644
index 00000000000..e2b9f6eab10
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -0,0 +1,464 @@
+#include <string.h>
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+
+void *BMIter_AtIndex(struct BMesh *bm, int type, void *data, int index)
+{
+ BMIter iter;
+ void *val;
+ int i;
+
+ /*sanity check*/
+ if (index < 0) return NULL;
+
+ val=BMIter_New(&iter, bm, type, data);
+
+ i = 0;
+ while (i < index) {
+ val=BMIter_Step(&iter);
+ i++;
+ }
+
+ return val;
+}
+
+/*
+ * BMESH ITERATOR STEP
+ *
+ * Calls an iterators step fucntion to return
+ * the next element.
+*/
+
+void *BMIter_Step(BMIter *iter)
+{
+ return iter->step(iter);
+}
+
+/*
+ * INIT ITERATOR
+ *
+ * Clears the internal state of an iterator
+ * For begin() callbacks.
+ *
+*/
+
+static void init_iterator(BMIter *iter)
+{
+ iter->firstvert = iter->nextvert = NULL;
+ iter->firstedge = iter->nextedge = NULL;
+ iter->firstloop = iter->nextloop = NULL;
+ iter->firstpoly = iter->nextpoly = NULL;
+ iter->ldata = NULL;
+}
+
+/*
+ * Notes on iterator implementation:
+ *
+ * Iterators keep track of the next element
+ * in a sequence. When a step() callback is
+ * invoked the current value of 'next' is stored
+ * to be returned later and the next variable is
+ * incremented.
+ *
+ * When the end of a sequence is
+ * reached, next should always equal NULL
+ *
+*/
+
+/*
+ * VERT OF MESH CALLBACKS
+ *
+*/
+
+static void vert_of_mesh_begin(BMIter *iter)
+{
+ BLI_mempool_iternew(iter->bm->vpool, &iter->pooliter);
+}
+
+static void *vert_of_mesh_step(BMIter *iter)
+{
+ return BLI_mempool_iterstep(&iter->pooliter);
+
+}
+
+static void edge_of_mesh_begin(BMIter *iter)
+{
+ BLI_mempool_iternew(iter->bm->epool, &iter->pooliter);
+}
+
+static void *edge_of_mesh_step(BMIter *iter)
+{
+ return BLI_mempool_iterstep(&iter->pooliter);
+
+}
+
+static void face_of_mesh_begin(BMIter *iter)
+{
+ BLI_mempool_iternew(iter->bm->fpool, &iter->pooliter);
+}
+
+static void *face_of_mesh_step(BMIter *iter)
+{
+ return BLI_mempool_iterstep(&iter->pooliter);
+
+}
+
+/*
+ * EDGE OF VERT CALLBACKS
+ *
+*/
+
+static void edge_of_vert_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ if(iter->vdata->e){
+ iter->firstedge = iter->vdata->e;
+ iter->nextedge = iter->vdata->e;
+ }
+}
+
+static void *edge_of_vert_step(BMIter *iter)
+{
+ BMEdge *current = iter->nextedge;
+
+ if(iter->nextedge)
+ iter->nextedge = bmesh_disk_nextedge(iter->nextedge, iter->vdata);
+
+ if(iter->nextedge == iter->firstedge) iter->nextedge = NULL;
+
+ return current;
+}
+
+/*
+ * FACE OF VERT CALLBACKS
+ *
+*/
+
+static void face_of_vert_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ iter->count = 0;
+ if(iter->vdata->e)
+ iter->count = bmesh_disk_count_facevert(iter->vdata);
+ if(iter->count){
+ iter->firstedge = bmesh_disk_find_first_faceedge(iter->vdata->e, iter->vdata);
+ iter->nextedge = iter->firstedge;
+ iter->firstloop = bmesh_radial_find_first_facevert(iter->firstedge->l, iter->vdata);
+ iter->nextloop = iter->firstloop;
+ }
+}
+static void *face_of_vert_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->count && iter->nextloop) {
+ iter->count--;
+ iter->nextloop = bmesh_radial_find_next_facevert(iter->nextloop, iter->vdata);
+ if(iter->nextloop == iter->firstloop){
+ iter->nextedge = bmesh_disk_find_next_faceedge(iter->nextedge, iter->vdata);
+ iter->firstloop = bmesh_radial_find_first_facevert(iter->nextedge->l, iter->vdata);
+ iter->nextloop = iter->firstloop;
+ }
+ }
+
+ if(!iter->count) iter->nextloop = NULL;
+
+
+ if(current) return current->f;
+ return NULL;
+}
+
+
+/*
+ * LOOP OF VERT CALLBACKS
+ *
+*/
+
+static void loop_of_vert_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ iter->count = 0;
+ if(iter->vdata->e)
+ iter->count = bmesh_disk_count_facevert(iter->vdata);
+ if(iter->count){
+ iter->firstedge = bmesh_disk_find_first_faceedge(iter->vdata->e, iter->vdata);
+ iter->nextedge = iter->firstedge;
+ iter->firstloop = bmesh_radial_find_first_facevert(iter->firstedge->l, iter->vdata);
+ iter->nextloop = iter->firstloop;
+ }
+}
+static void *loop_of_vert_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->count){
+ iter->count--;
+ iter->nextloop = bmesh_radial_find_next_facevert(iter->nextloop, iter->vdata);
+ if(iter->nextloop == iter->firstloop){
+ iter->nextedge = bmesh_disk_find_next_faceedge(iter->nextedge, iter->vdata);
+ iter->firstloop = bmesh_radial_find_first_facevert(iter->nextedge->l, iter->vdata);
+ iter->nextloop = iter->firstloop;
+ }
+ }
+
+ if(!iter->count) iter->nextloop = NULL;
+
+
+ if(current) return current;
+ return NULL;
+}
+
+
+static void loops_of_edge_begin(BMIter *iter)
+{
+ BMLoop *l;
+
+ l = iter->edata->l;
+
+ /*note sure why this sets ldata. . .*/
+ init_iterator(iter);
+
+ iter->firstloop = iter->nextloop = l;
+}
+
+static void *loops_of_edge_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->nextloop)
+ iter->nextloop = bmesh_radial_nextloop(iter->nextloop);
+
+ if(iter->nextloop == iter->firstloop)
+ iter->nextloop = NULL;
+
+ if(current) return current;
+ return NULL;
+}
+
+static void loops_of_loop_begin(BMIter *iter)
+{
+ BMLoop *l;
+
+ l = iter->ldata;
+
+ /*note sure why this sets ldata. . .*/
+ init_iterator(iter);
+
+ iter->firstloop = l;
+ iter->nextloop = bmesh_radial_nextloop(iter->firstloop);
+
+ if (iter->nextloop == iter->firstloop)
+ iter->nextloop = NULL;
+}
+
+static void *loops_of_loop_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->nextloop) iter->nextloop = bmesh_radial_nextloop(iter->nextloop);
+
+ if(iter->nextloop == iter->firstloop) iter->nextloop = NULL;
+ if(current) return current;
+ return NULL;
+}
+
+/*
+ * FACE OF EDGE CALLBACKS
+ *
+*/
+
+static void face_of_edge_begin(BMIter *iter)
+{
+ init_iterator(iter);
+
+ if(iter->edata->l){
+ iter->firstloop = iter->edata->l;
+ iter->nextloop = iter->edata->l;
+ }
+}
+
+static void *face_of_edge_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->nextloop) iter->nextloop = bmesh_radial_nextloop(iter->nextloop);
+
+ if(iter->nextloop == iter->firstloop) iter->nextloop = NULL;
+ if(current) return current->f;
+ return NULL;
+}
+
+/*
+ * VERT OF FACE CALLBACKS
+ *
+*/
+
+static void vert_of_face_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ iter->firstloop = iter->nextloop = ((BMLoopList*)iter->pdata->loops.first)->first;
+}
+
+static void *vert_of_face_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->nextloop) iter->nextloop = iter->nextloop->next;
+ if(iter->nextloop == iter->firstloop) iter->nextloop = NULL;
+
+ if(current) return current->v;
+ return NULL;
+}
+
+/*
+ * EDGE OF FACE CALLBACKS
+ *
+*/
+
+static void edge_of_face_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ iter->firstloop = iter->nextloop = ((BMLoopList*)iter->pdata->loops.first)->first;
+}
+
+static void *edge_of_face_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->nextloop) iter->nextloop = iter->nextloop->next;
+ if(iter->nextloop == iter->firstloop) iter->nextloop = NULL;
+
+ if(current) return current->e;
+ return NULL;
+}
+
+/*
+ * LOOP OF FACE CALLBACKS
+ *
+*/
+
+static void loop_of_face_begin(BMIter *iter)
+{
+ init_iterator(iter);
+ iter->firstloop = iter->nextloop = bm_firstfaceloop(iter->pdata);
+}
+
+static void *loop_of_face_step(BMIter *iter)
+{
+ BMLoop *current = iter->nextloop;
+
+ if(iter->nextloop) iter->nextloop = iter->nextloop->next;
+ if(iter->nextloop == iter->firstloop) iter->nextloop = NULL;
+
+ return current;
+}
+
+/*
+ * BMESH ITERATOR INIT
+ *
+ * Takes a bmesh iterator structure and fills
+ * it with the appropriate function pointers based
+ * upon its type and then calls BMeshIter_step()
+ * to return the first element of the iterator.
+ *
+*/
+void *BMIter_New(BMIter *iter, BMesh *bm, int type, void *data)
+{
+ /* int argtype; */
+ iter->type = type;
+ iter->bm = bm;
+
+ switch(type){
+ case BM_VERTS_OF_MESH:
+ iter->begin = vert_of_mesh_begin;
+ iter->step = vert_of_mesh_step;
+ break;
+ case BM_EDGES_OF_MESH:
+ iter->begin = edge_of_mesh_begin;
+ iter->step = edge_of_mesh_step;
+ break;
+ case BM_FACES_OF_MESH:
+ iter->begin = face_of_mesh_begin;
+ iter->step = face_of_mesh_step;
+ break;
+ case BM_EDGES_OF_VERT:
+ if (!data)
+ return NULL;
+
+ iter->begin = edge_of_vert_begin;
+ iter->step = edge_of_vert_step;
+ iter->vdata = data;
+ break;
+ case BM_FACES_OF_VERT:
+ if (!data)
+ return NULL;
+
+ iter->begin = face_of_vert_begin;
+ iter->step = face_of_vert_step;
+ iter->vdata = data;
+ break;
+ case BM_LOOPS_OF_VERT:
+ if (!data)
+ return NULL;
+
+ iter->begin = loop_of_vert_begin;
+ iter->step = loop_of_vert_step;
+ iter->vdata = data;
+ break;
+ case BM_FACES_OF_EDGE:
+ if (!data)
+ return NULL;
+
+ iter->begin = face_of_edge_begin;
+ iter->step = face_of_edge_step;
+ iter->edata = data;
+ break;
+ case BM_VERTS_OF_FACE:
+ if (!data)
+ return NULL;
+
+ iter->begin = vert_of_face_begin;
+ iter->step = vert_of_face_step;
+ iter->pdata = data;
+ break;
+ case BM_EDGES_OF_FACE:
+ if (!data)
+ return NULL;
+
+ iter->begin = edge_of_face_begin;
+ iter->step = edge_of_face_step;
+ iter->pdata = data;
+ break;
+ case BM_LOOPS_OF_FACE:
+ if (!data)
+ return NULL;
+
+ iter->begin = loop_of_face_begin;
+ iter->step = loop_of_face_step;
+ iter->pdata = data;
+ break;
+ case BM_LOOPS_OF_LOOP:
+ if (!data)
+ return NULL;
+
+ iter->begin = loops_of_loop_begin;
+ iter->step = loops_of_loop_step;
+ iter->ldata = data;
+ break;
+ case BM_LOOPS_OF_EDGE:
+ if (!data)
+ return NULL;
+
+ iter->begin = loops_of_edge_begin;
+ iter->step = loops_of_edge_step;
+ iter->edata = data;
+ break;
+ default:
+ break;
+ }
+
+ iter->begin(iter);
+ return BMIter_Step(iter);
+}
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
new file mode 100644
index 00000000000..2c08f2b9866
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -0,0 +1,729 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_array.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include <string.h>
+
+/*
+ * BM_MARK.C
+ *
+ * Selection routines for bmesh structures.
+ * This is actually all old code ripped from
+ * editmesh_lib.c and slightly modified to work
+ * for bmesh's. This also means that it has some
+ * of the same problems.... something that
+ * that should be addressed eventually.
+ *
+*/
+
+/*
+ * BMESH SELECTMODE FLUSH
+ *
+ * Makes sure to flush selections
+ * 'upwards' (ie: all verts of an edge
+ * selects the edge and so on). This
+ * should only be called by system and not
+ * tool authors.
+ *
+*/
+
+static void recount_totsels(BMesh *bm)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+ int *tots[3];
+ int i;
+
+ /*recount tot*sel variables*/
+ bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
+ tots[0] = &bm->totvertsel;
+ tots[1] = &bm->totedgesel;
+ tots[2] = &bm->totfacesel;
+
+ for (i=0; i<3; i++) {
+ ele = BMIter_New(&iter, bm, types[i], NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(ele, BM_SELECT)) *tots[i] += 1;
+ }
+ }
+}
+
+void BM_SelectMode_Flush(BMesh *bm)
+{
+ BMEdge *e;
+ BMLoop *l;
+ BMFace *f;
+
+ BMIter edges;
+ BMIter faces;
+
+ int totsel;
+
+ if(bm->selectmode & SCE_SELECT_VERTEX) {
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges)) {
+ if(BM_TestHFlag(e->v1, BM_SELECT) && BM_TestHFlag(e->v2, BM_SELECT) && !BM_TestHFlag(e, BM_HIDDEN)) {
+ BM_SetHFlag(e, BM_SELECT);
+ }
+ else {
+ BM_ClearHFlag(e, BM_SELECT);
+ }
+ }
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)) {
+ totsel = 0;
+ l=(BMLoop*) bm_firstfaceloop(f);
+ do{
+ if(BM_TestHFlag(l->v, BM_SELECT))
+ totsel++;
+ l = l->next;
+ } while(l != bm_firstfaceloop(f));
+
+ if(totsel == f->len && !BM_TestHFlag(f, BM_HIDDEN)) {
+ BM_SetHFlag(f, BM_SELECT);
+ }
+ else {
+ BM_ClearHFlag(f, BM_SELECT);
+ }
+ }
+ }
+ else if(bm->selectmode & SCE_SELECT_EDGE) {
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)) {
+ totsel = 0;
+ l = bm_firstfaceloop(f);
+ do{
+ if(BM_TestHFlag(&(l->e->head), BM_SELECT))
+ totsel++;
+ l = l->next;
+ }while(l!=bm_firstfaceloop(f));
+
+ if(totsel == f->len && !BM_TestHFlag(f, BM_HIDDEN)) {
+ BM_SetHFlag(f, BM_SELECT);
+ }
+ else {
+ BM_ClearHFlag(f, BM_SELECT);
+ }
+ }
+ }
+
+ /*Remove any deselected elements from the BMEditSelection*/
+ BM_validate_selections(bm);
+
+ recount_totsels(bm);
+}
+
+/*
+ * BMESH SELECT VERT
+ *
+ * Changes selection state of a single vertex
+ * in a mesh
+ *
+*/
+
+void BM_Select_Vert(BMesh *bm, BMVert *v, int select)
+{
+ /* BMIter iter; */
+ /* BMEdge *e; */
+
+ if (BM_TestHFlag(v, BM_HIDDEN)) {
+ return;
+ }
+
+ if(select) {
+ if (!BM_TestHFlag(v, BM_SELECT)) {
+ bm->totvertsel += 1;
+ BM_SetHFlag(v, BM_SELECT);
+ }
+ } else {
+ if (BM_TestHFlag(v, BM_SELECT)) {
+ bm->totvertsel -= 1;
+ BM_ClearHFlag(v, BM_SELECT);
+ }
+ }
+}
+
+/*
+ * BMESH SELECT EDGE
+ *
+ * Changes selection state of a single edge
+ * in a mesh.
+ *
+*/
+
+void BM_Select_Edge(BMesh *bm, BMEdge *e, int select)
+{
+ if (BM_TestHFlag(e, BM_HIDDEN)) {
+ return;
+ }
+
+ if(select){
+ if (!BM_TestHFlag(e, BM_SELECT)) bm->totedgesel += 1;
+
+ BM_SetHFlag(&(e->head), BM_SELECT);
+ BM_Select(bm, e->v1, 1);
+ BM_Select(bm, e->v2, 1);
+ }else{
+ if (BM_TestHFlag(e, BM_SELECT)) bm->totedgesel -= 1;
+ BM_ClearHFlag(&(e->head), BM_SELECT);
+
+ if(
+ bm->selectmode == SCE_SELECT_EDGE ||
+ bm->selectmode == SCE_SELECT_FACE ||
+ bm->selectmode == (SCE_SELECT_EDGE | SCE_SELECT_FACE)){
+
+ BMIter iter;
+ BMVert *verts[2] = {e->v1, e->v2};
+ BMEdge *e2;
+ int i;
+
+ for(i = 0; i < 2; i++){
+ int deselect = 1;
+
+ for(e2 = BMIter_New(&iter, bm, BM_EDGES_OF_VERT, verts[i]);
+ e2; e2 = BMIter_Step(&iter)){
+ if(e2 == e){
+ continue;
+ }
+
+ if (BM_TestHFlag(e2, BM_SELECT)){
+ deselect = 0;
+ break;
+ }
+ }
+
+ if(deselect) BM_Select_Vert(bm, verts[i], 0);
+ }
+ }else{
+ BM_Select(bm, e->v1, 0);
+ BM_Select(bm, e->v2, 0);
+ }
+
+ }
+}
+
+/*
+ *
+ * BMESH SELECT FACE
+ *
+ * Changes selection state of a single
+ * face in a mesh.
+ *
+*/
+
+void BM_Select_Face(BMesh *bm, BMFace *f, int select)
+{
+ BMLoop *l;
+
+ if (BM_TestHFlag(f, BM_HIDDEN)) {
+ return;
+ }
+
+ if(select){
+ if (!BM_TestHFlag(f, BM_SELECT)) bm->totfacesel += 1;
+
+ BM_SetHFlag(&(f->head), BM_SELECT);
+ l=(BMLoop*) bm_firstfaceloop(f);
+ do{
+ BM_Select_Vert(bm, l->v, 1);
+ BM_Select_Edge(bm, l->e, 1);
+ l = l->next;
+ }while(l != bm_firstfaceloop(f));
+ }
+ else{
+ BMIter liter;
+ BMLoop *l;
+
+ if (BM_TestHFlag(f, BM_SELECT)) bm->totfacesel -= 1;
+ BM_ClearHFlag(&(f->head), BM_SELECT);
+
+ /*flush down to edges*/
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BMIter fiter;
+ BMFace *f2;
+ BM_ITER(f2, &fiter, bm, BM_FACES_OF_EDGE, l->e) {
+ if (BM_TestHFlag(f2, BM_SELECT))
+ break;
+ }
+
+ if (!f2)
+ {
+ BM_Select(bm, l->e, 0);
+ }
+ }
+
+ /*flush down to verts*/
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BMIter eiter;
+ BMEdge *e;
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, l->v) {
+ if (BM_TestHFlag(e, BM_SELECT))
+ break;
+ }
+
+ if (!e)
+ {
+ BM_Select(bm, l->v, 0);
+ }
+ }
+ }
+}
+
+/*
+ * BMESH SELECTMODE SET
+ *
+ * Sets the selection mode for the bmesh
+ *
+*/
+
+void BM_Selectmode_Set(BMesh *bm, int selectmode)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ bm->selectmode = selectmode;
+
+ if(bm->selectmode & SCE_SELECT_VERTEX) {
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges))
+ BM_ClearHFlag(e, 0);
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces))
+ BM_ClearHFlag(f, 0);
+ BM_SelectMode_Flush(bm);
+ }
+ else if(bm->selectmode & SCE_SELECT_EDGE) {
+ for(v= BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm ); v; v= BMIter_Step(&verts))
+ BM_ClearHFlag(v, 0);
+ for(e= BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges)){
+ if(BM_TestHFlag(&(e->head), BM_SELECT))
+ BM_Select_Edge(bm, e, 1);
+ }
+ BM_SelectMode_Flush(bm);
+ }
+ else if(bm->selectmode & SCE_SELECT_FACE) {
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e= BMIter_Step(&edges))
+ BM_ClearHFlag(e, 0);
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f= BMIter_Step(&faces)){
+ if(BM_TestHFlag(&(f->head), BM_SELECT))
+ BM_Select_Face(bm, f, 1);
+ }
+ BM_SelectMode_Flush(bm);
+ }
+}
+
+
+int BM_CountFlag(struct BMesh *bm, int type, int flag, int respecthide)
+{
+ BMHeader *head;
+ BMIter iter;
+ int tot = 0;
+
+ if (type & BM_VERT) {
+ for (head = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
+ if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
+ if (head->flag & flag) tot++;
+ }
+ }
+ if (type & BM_EDGE) {
+ for (head = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
+ if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
+ if (head->flag & flag) tot++;
+ }
+ }
+ if (type & BM_FACE) {
+ for (head = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); head; head=BMIter_Step(&iter)) {
+ if (respecthide && BM_TestHFlag(head, BM_HIDDEN)) continue;
+ if (head->flag & flag) tot++;
+ }
+ }
+
+ return tot;
+}
+
+/*note: by design, this will not touch the editselection history stuff*/
+void BM_Select(struct BMesh *bm, void *element, int select)
+{
+ BMHeader *head = element;
+
+ if(head->type == BM_VERT) BM_Select_Vert(bm, (BMVert*)element, select);
+ else if(head->type == BM_EDGE) BM_Select_Edge(bm, (BMEdge*)element, select);
+ else if(head->type == BM_FACE) BM_Select_Face(bm, (BMFace*)element, select);
+}
+
+int BM_Selected(BMesh *UNUSED(bm), const void *element)
+{
+ const BMHeader *head = element;
+ int selected = BM_TestHFlag(head, BM_SELECT);
+ BLI_assert(!selected || !BM_TestHFlag(head, BM_HIDDEN));
+ return selected;
+}
+
+/* this replaces the active flag used in uv/face mode */
+void BM_set_actFace(BMesh *bm, BMFace *efa)
+{
+ bm->act_face = efa;
+}
+
+BMFace *BM_get_actFace(BMesh *bm, int sloppy)
+{
+ if (bm->act_face) {
+ return bm->act_face;
+ } else if (sloppy) {
+ BMIter iter;
+ BMFace *f= NULL;
+ BMEditSelection *ese;
+
+ /* Find the latest non-hidden face from the BMEditSelection */
+ ese = bm->selected.last;
+ for (; ese; ese=ese->prev){
+ if(ese->type == BM_FACE) {
+ f = (BMFace *)ese->data;
+
+ if (BM_TestHFlag(f, BM_HIDDEN)) {
+ f= NULL;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ /* Last attempt: try to find any selected face */
+ if (f==NULL) {
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(f, BM_SELECT)) {
+ break;
+ }
+ }
+ }
+ return f; /* can still be null */
+ }
+ return NULL;
+}
+
+/* generic way to get data from an EditSelection type
+These functions were written to be used by the Modifier widget when in Rotate about active mode,
+but can be used anywhere.
+EM_editselection_center
+EM_editselection_normal
+EM_editselection_plane
+*/
+void BM_editselection_center(BMesh *bm, float *center, BMEditSelection *ese)
+{
+ if (ese->type==BM_VERT) {
+ BMVert *eve= ese->data;
+ copy_v3_v3(center, eve->co);
+ } else if (ese->type==BM_EDGE) {
+ BMEdge *eed= ese->data;
+ add_v3_v3v3(center, eed->v1->co, eed->v2->co);
+ mul_v3_fl(center, 0.5);
+ } else if (ese->type==BM_FACE) {
+ BMFace *efa= ese->data;
+ BM_Compute_Face_Center(bm, efa, center);
+ }
+}
+
+void BM_editselection_normal(float *normal, BMEditSelection *ese)
+{
+ if (ese->type==BM_VERT) {
+ BMVert *eve= ese->data;
+ copy_v3_v3(normal, eve->no);
+ } else if (ese->type==BM_EDGE) {
+ BMEdge *eed= ese->data;
+ float plane[3]; /* need a plane to correct the normal */
+ float vec[3]; /* temp vec storage */
+
+ add_v3_v3v3(normal, eed->v1->no, eed->v2->no);
+ sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
+
+ /* the 2 vertex normals will be close but not at rightangles to the edge
+ for rotate about edge we want them to be at right angles, so we need to
+ do some extra colculation to correct the vert normals,
+ we need the plane for this */
+ cross_v3_v3v3(vec, normal, plane);
+ cross_v3_v3v3(normal, plane, vec);
+ normalize_v3(normal);
+
+ } else if (ese->type==BM_FACE) {
+ BMFace *efa= ese->data;
+ copy_v3_v3(normal, efa->no);
+ }
+}
+
+/* Calculate a plane that is rightangles to the edge/vert/faces normal
+also make the plane run along an axis that is related to the geometry,
+because this is used for the manipulators Y axis.*/
+void BM_editselection_plane(BMesh *bm, float *plane, BMEditSelection *ese)
+{
+ if (ese->type==BM_VERT) {
+ BMVert *eve= ese->data;
+ float vec[3]={0,0,0};
+
+ if (ese->prev) { /*use previously selected data to make a useful vertex plane */
+ BM_editselection_center(bm, vec, ese->prev);
+ sub_v3_v3v3(plane, vec, eve->co);
+ } else {
+ /* make a fake plane thats at rightangles to the normal
+ we cant make a crossvec from a vec thats the same as the vec
+ unlikely but possible, so make sure if the normal is (0,0,1)
+ that vec isnt the same or in the same direction even.*/
+ if (eve->no[0] < 0.5f) vec[0]= 1.0f;
+ else if (eve->no[1] < 0.5f) vec[1]= 1.0f;
+ else vec[2]= 1.0f;
+ cross_v3_v3v3(plane, eve->no, vec);
+ }
+ } else if (ese->type==BM_EDGE) {
+ BMEdge *eed= ese->data;
+
+ /* the plane is simple, it runs along the edge
+ however selecting different edges can swap the direction of the y axis.
+ this makes it less likely for the y axis of the manipulator
+ (running along the edge).. to flip less often.
+ at least its more pradictable */
+ if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */
+ sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
+ else
+ sub_v3_v3v3(plane, eed->v1->co, eed->v2->co);
+
+ } else if (ese->type==BM_FACE) {
+ BMFace *efa= ese->data;
+ float vec[3] = {0.0f, 0.0f, 0.0f};
+
+ /*for now, use face normal*/
+
+ /* make a fake plane thats at rightangles to the normal
+ we cant make a crossvec from a vec thats the same as the vec
+ unlikely but possible, so make sure if the normal is (0,0,1)
+ that vec isnt the same or in the same direction even.*/
+ if (efa->no[0] < 0.5f) vec[0]= 1.0f;
+ else if (efa->no[1] < 0.5f) vec[1]= 1.0f;
+ else vec[2]= 1.0f;
+ cross_v3_v3v3(plane, efa->no, vec);
+#if 0 //BMESH_TODO
+
+ if (efa->v4) { /*if its a quad- set the plane along the 2 longest edges.*/
+ float vecA[3], vecB[3];
+ sub_v3_v3v3(vecA, efa->v4->co, efa->v3->co);
+ sub_v3_v3v3(vecB, efa->v1->co, efa->v2->co);
+ add_v3_v3v3(plane, vecA, vecB);
+
+ sub_v3_v3v3(vecA, efa->v1->co, efa->v4->co);
+ sub_v3_v3v3(vecB, efa->v2->co, efa->v3->co);
+ add_v3_v3v3(vec, vecA, vecB);
+ /*use the biggest edge length*/
+ if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
+ copy_v3_v3(plane, vec);
+ } else {
+ /*start with v1-2 */
+ sub_v3_v3v3(plane, efa->v1->co, efa->v2->co);
+
+ /*test the edge between v2-3, use if longer */
+ sub_v3_v3v3(vec, efa->v2->co, efa->v3->co);
+ if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
+ copy_v3_v3(plane, vec);
+
+ /*test the edge between v1-3, use if longer */
+ sub_v3_v3v3(vec, efa->v3->co, efa->v1->co);
+ if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
+ copy_v3_v3(plane, vec);
+ }
+#endif
+ }
+ normalize_v3(plane);
+}
+
+static int BM_check_selection(BMesh *bm, void *data)
+{
+ BMEditSelection *ese;
+
+ for(ese = bm->selected.first; ese; ese = ese->next){
+ if(ese->data == data) return 1;
+ }
+
+ return 0;
+}
+
+void BM_remove_selection(BMesh *bm, void *data)
+{
+ BMEditSelection *ese;
+ for(ese=bm->selected.first; ese; ese = ese->next){
+ if(ese->data == data){
+ BLI_freelinkN(&(bm->selected),ese);
+ break;
+ }
+ }
+}
+
+void BM_clear_selection_history(BMesh *bm)
+{
+ BLI_freelistN(&bm->selected);
+ bm->selected.first = bm->selected.last = NULL;
+}
+
+void BM_store_selection(BMesh *bm, void *data)
+{
+ BMEditSelection *ese;
+ if(!BM_check_selection(bm, data)){
+ ese = (BMEditSelection*) MEM_callocN( sizeof(BMEditSelection), "BMEdit Selection");
+ ese->type = ((BMHeader*)data)->type;
+ ese->data = data;
+ BLI_addtail(&(bm->selected),ese);
+ }
+}
+
+void BM_validate_selections(BMesh *bm)
+{
+ BMEditSelection *ese, *nextese;
+
+ ese = bm->selected.first;
+
+ while(ese) {
+ nextese = ese->next;
+ if (!BM_TestHFlag(ese->data, BM_SELECT)) {
+ BLI_freelinkN(&(bm->selected), ese);
+ }
+ ese = nextese;
+ }
+}
+
+void BM_clear_flag_all(BMesh *bm, int flag)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int i, type;
+
+ if (flag & BM_SELECT)
+ BM_clear_selection_history(bm);
+
+ for (i=0; i<3; i++) {
+ switch (i) {
+ case 0:
+ type = BM_VERTS_OF_MESH;
+ break;
+ case 1:
+ type = BM_EDGES_OF_MESH;
+ break;
+ case 2:
+ type = BM_FACES_OF_MESH;
+ break;
+ }
+
+ ele = BMIter_New(&iter, bm, type, NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ if (flag & BM_SELECT) BM_Select(bm, ele, 0);
+ BM_ClearHFlag(ele, flag);
+ }
+ }
+}
+
+
+/***************** Mesh Hiding stuff *************/
+
+#define SETHIDE(ele) hide ? BM_SetHFlag(ele, BM_HIDDEN) : BM_ClearHFlag(ele, BM_HIDDEN);
+
+static void vert_flush_hide(BMesh *bm, BMVert *v) {
+ BMIter iter;
+ BMEdge *e;
+ int hide = 1;
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
+ hide = hide && BM_TestHFlag(e, BM_HIDDEN);
+ }
+
+ SETHIDE(v);
+}
+
+static void edge_flush_hide(BMesh *bm, BMEdge *e) {
+ BMIter iter;
+ BMFace *f;
+ int hide = 1;
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_EDGE, e) {
+ hide = hide && BM_TestHFlag(f, BM_HIDDEN);
+ }
+
+ SETHIDE(e);
+}
+
+void BM_Hide_Vert(BMesh *bm, BMVert *v, int hide)
+{
+ /*vert hiding: vert + surrounding edges and faces*/
+ BMIter iter, fiter;
+ BMEdge *e;
+ BMFace *f;
+
+ SETHIDE(v);
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
+ SETHIDE(e);
+
+ BM_ITER(f, &fiter, bm, BM_FACES_OF_EDGE, e) {
+ SETHIDE(f);
+ }
+ }
+}
+
+void BM_Hide_Edge(BMesh *bm, BMEdge *e, int hide)
+{
+ BMIter iter;
+ BMFace *f;
+ /* BMVert *v; */
+
+ /*edge hiding: faces around the edge*/
+ BM_ITER(f, &iter, bm, BM_FACES_OF_EDGE, e) {
+ SETHIDE(f);
+ }
+
+ SETHIDE(e);
+
+ /*hide vertices if necassary*/
+ vert_flush_hide(bm, e->v1);
+ vert_flush_hide(bm, e->v2);
+}
+
+void BM_Hide_Face(BMesh *bm, BMFace *f, int hide)
+{
+ BMIter iter;
+ BMLoop *l;
+
+ /**/
+ SETHIDE(f);
+
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ edge_flush_hide(bm, l->e);
+ }
+
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ vert_flush_hide(bm, l->v);
+ }
+}
+
+void BM_Hide(BMesh *bm, void *element, int hide)
+{
+ BMHeader *h = element;
+
+ /*Follow convention of always deselecting before
+ hiding an element*/
+ if (hide)
+ BM_Select(bm, element, 0);
+
+ switch (h->type) {
+ case BM_VERT:
+ BM_Hide_Vert(bm, element, hide);
+ break;
+ case BM_EDGE:
+ BM_Hide_Edge(bm, element, hide);
+ break;
+ case BM_FACE:
+ BM_Hide_Face(bm, element, hide);
+ break;
+ }
+}
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
new file mode 100644
index 00000000000..fd01b9273e8
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -0,0 +1,412 @@
+/**
+ * BME_mesh.c jan 2007
+ *
+ * BM mesh level functions.
+ *
+ * $Id: BME_eulers.c,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** 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.
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_object_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+#include "BLI_cellalloc.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_tessmesh.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_multires.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+void BME_error(void);
+
+/*bmesh_error stub*/
+void bmesh_error(void)
+{
+ printf("BM modelling error!");
+}
+
+/*
+ * BMESH MAKE MESH
+ *
+ * Allocates a new BMesh structure.
+ * Returns -
+ * Pointer to a BM
+ *
+*/
+
+BMesh *BM_Make_Mesh(struct Object *ob, int allocsize[4])
+{
+ /*allocate the structure*/
+ BMesh *bm = MEM_callocN(sizeof(BMesh),"BM");
+ int vsize, esize, lsize, fsize, lstsize;
+
+ vsize = sizeof(BMVert);
+ esize = sizeof(BMEdge);
+ lsize = sizeof(BMLoop);
+ fsize = sizeof(BMFace);
+ lstsize = sizeof(BMLoopList);
+
+ bm->ob = ob;
+
+/*allocate the memory pools for the mesh elements*/
+ bm->vpool = BLI_mempool_create(vsize, allocsize[0], allocsize[0], 0, 1);
+ bm->epool = BLI_mempool_create(esize, allocsize[1], allocsize[1], 0, 1);
+ bm->lpool = BLI_mempool_create(lsize, allocsize[2], allocsize[2], 0, 0);
+ bm->looplistpool = BLI_mempool_create(lstsize, allocsize[3], allocsize[3], 0, 0);
+ bm->fpool = BLI_mempool_create(fsize, allocsize[3], allocsize[3], 0, 1);
+
+ /*allocate one flag pool that we dont get rid of.*/
+ bm->toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), 512, 512, 0, 0);
+ bm->stackdepth = 1;
+ bm->totflags = 1;
+
+ return bm;
+}
+
+/*
+ * BMESH FREE MESH
+ *
+ * Frees a BMesh structure.
+*/
+
+void BM_Free_Mesh_Data(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMLoop *l;
+ BMFace *f;
+
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+ BMIter loops;
+
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm ); v; v = BMIter_Step(&verts)) CustomData_bmesh_free_block( &(bm->vdata), &(v->head.data) );
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm ); e; e = BMIter_Step(&edges)) CustomData_bmesh_free_block( &(bm->edata), &(e->head.data) );
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm ); f; f = BMIter_Step(&faces)){
+ CustomData_bmesh_free_block( &(bm->pdata), &(f->head.data) );
+ for(l = BMIter_New(&loops, bm, BM_LOOPS_OF_FACE, f ); l; l = BMIter_Step(&loops)) CustomData_bmesh_free_block( &(bm->ldata), &(l->head.data) );
+ }
+
+ /*Free custom data pools, This should probably go in CustomData_free?*/
+ if(bm->vdata.totlayer) BLI_mempool_destroy(bm->vdata.pool);
+ if(bm->edata.totlayer) BLI_mempool_destroy(bm->edata.pool);
+ if(bm->ldata.totlayer) BLI_mempool_destroy(bm->ldata.pool);
+ if(bm->pdata.totlayer) BLI_mempool_destroy(bm->pdata.pool);
+
+ /*free custom data*/
+ CustomData_free(&bm->vdata,0);
+ CustomData_free(&bm->edata,0);
+ CustomData_free(&bm->ldata,0);
+ CustomData_free(&bm->pdata,0);
+
+ /*destroy element pools*/
+ BLI_mempool_destroy(bm->vpool);
+ BLI_mempool_destroy(bm->epool);
+ BLI_mempool_destroy(bm->lpool);
+ BLI_mempool_destroy(bm->fpool);
+
+ /*destroy flag pool*/
+ BLI_mempool_destroy(bm->toolflagpool);
+ BLI_mempool_destroy(bm->looplistpool);
+
+ BLI_freelistN(&bm->selected);
+
+ BMO_ClearStack(bm);
+}
+
+void BM_Free_Mesh(BMesh *bm)
+{
+ BM_Free_Mesh_Data(bm);
+ MEM_freeN(bm);
+}
+
+/*
+ * BMESH COMPUTE NORMALS
+ *
+ * Updates the normals of a mesh.
+ * Note that this can only be called
+ *
+*/
+
+void BM_Compute_Normals(BMesh *bm)
+{
+ BMVert *v;
+ BMFace *f;
+ BMLoop *l;
+ BMEdge *e;
+ BMIter verts;
+ BMIter faces;
+ BMIter loops;
+ BMIter edges;
+ unsigned int maxlength = 0;
+ int index;
+ float (*projectverts)[3];
+ float (*edgevec)[3];
+
+ /*first, find out the largest face in mesh*/
+ BM_ITER(f, &faces, bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(f, BM_HIDDEN))
+ continue;
+
+ if(f->len > maxlength) maxlength = f->len;
+ }
+
+ /*make sure we actually have something to do*/
+ if(maxlength < 3) return;
+
+ /*allocate projectverts array*/
+ projectverts = MEM_callocN(sizeof(float) * maxlength * 3, "BM normal computation array");
+
+ /*calculate all face normals*/
+ BM_ITER(f, &faces, bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(f, BM_HIDDEN))
+ continue;
+ if (f->head.flag & BM_NONORMCALC)
+ continue;
+
+ bmesh_update_face_normal(bm, f, projectverts);
+ }
+
+ /*Zero out vertex normals*/
+ BM_ITER(v, &verts, bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(v, BM_HIDDEN))
+ continue;
+
+ zero_v3(v->no);
+ }
+
+ /* compute normalized direction vectors for each edge. directions will be
+ used below for calculating the weights of the face normals on the vertex
+ normals */
+ index = 0;
+ edgevec = MEM_callocN(sizeof(float) * 3 * bm->totedge, "BM normal computation array");
+ BM_ITER(e, &edges, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!e->l) {
+ /* the edge vector will not be needed when the edge has no radial */
+ continue;
+ }
+ BM_SetIndex(e, index);
+ sub_v3_v3v3(edgevec[index], e->v2->co, e->v1->co);
+ normalize_v3(edgevec[index]);
+ index++;
+ }
+
+ /*add weighted face normals to vertices*/
+ BM_ITER(f, &faces, bm, BM_FACES_OF_MESH, NULL) {
+
+ if (BM_TestHFlag(f, BM_HIDDEN))
+ continue;
+
+ BM_ITER(l, &loops, bm, BM_LOOPS_OF_FACE, f) {
+ float *e1diff, *e2diff;
+ float dotprod;
+ float fac;
+
+ /* calculate the dot product of the two edges that
+ meet at the loop's vertex */
+ e1diff = edgevec[BM_GetIndex(l->prev->e)];
+ e2diff = edgevec[BM_GetIndex(l->e)];
+ dotprod = dot_v3v3(e1diff, e2diff);
+
+ /* edge vectors are calculated from e->v1 to e->v2, so
+ adjust the dot product if one but not both loops
+ actually runs from from e->v2 to e->v1 */
+ if ((l->prev->e->v1 == l->prev->v) ^ (l->e->v1 == l->v)) {
+ dotprod *= -1.0f;
+ }
+
+ fac = saacos(-dotprod);
+
+ /* accumulate weighted face normal into the vertex's normal */
+ madd_v3_v3fl(l->v->no, f->no, fac);
+ }
+ }
+
+ /* normalize the accumulated vertex normals */
+ BM_ITER(v, &verts, bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(v, BM_HIDDEN))
+ continue;
+
+ if (normalize_v3(v->no) == 0.0f) {
+ copy_v3_v3(v->no, v->co);
+ normalize_v3(v->no);
+ }
+ }
+
+ MEM_freeN(edgevec);
+ MEM_freeN(projectverts);
+}
+
+/*
+ This function ensures correct normals for the mesh, but
+ sets the flag BM_FLIPPED in flipped faces, to allow restoration
+ of original normals.
+
+ if undo is 0: calculate right normals
+ if undo is 1: restore original normals
+*/
+//keep in sycn with utils.c!
+#define FACE_FLIP 8
+static void bmesh_rationalize_normals(BMesh *bm, int undo) {
+ BMOperator bmop;
+ BMFace *f;
+ BMIter iter;
+
+ if (undo) {
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(f, BM_FLIPPED)) {
+ BM_flip_normal(bm, f);
+ }
+ BM_ClearHFlag(f, BM_FLIPPED);
+ }
+
+ return;
+ }
+
+ BMO_InitOpf(bm, &bmop, "righthandfaces faces=%af doflip=%d", 0);
+
+ BMO_push(bm, &bmop);
+ bmesh_righthandfaces_exec(bm, &bmop);
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, f, FACE_FLIP))
+ BM_SetHFlag(f, BM_FLIPPED);
+ else BM_ClearHFlag(f, BM_FLIPPED);
+ }
+
+ BMO_pop(bm);
+ BMO_Finish_Op(bm, &bmop);
+}
+
+static void bmesh_set_mdisps_space(BMesh *bm, int from, int to)
+{
+ /*switch multires data out of tangent space*/
+ if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
+ Object *ob = bm->ob;
+ BMEditMesh *em = BMEdit_Create(bm);
+ DerivedMesh *dm = CDDM_from_BMEditMesh(em, NULL, 1);
+ MDisps *mdisps;
+ BMFace *f;
+ BMIter iter;
+ // int i= 0; // UNUSED
+
+ multires_set_space(dm, ob, from, to);
+
+ mdisps = CustomData_get_layer(&dm->loopData, CD_MDISPS);
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ BMLoop *l;
+ BMIter liter;
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ MDisps *lmd = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MDISPS);
+
+ if (!lmd->disps) {
+ printf("eck!\n");
+ }
+
+ if (lmd->disps && lmd->totdisp == mdisps->totdisp) {
+ memcpy(lmd->disps, mdisps->disps, sizeof(float)*3*lmd->totdisp);
+ } else if (mdisps->disps) {
+ if (lmd->disps)
+ BLI_cellalloc_free(lmd->disps);
+
+ lmd->disps = BLI_cellalloc_dupalloc(mdisps->disps);
+ lmd->totdisp = mdisps->totdisp;
+ }
+
+ mdisps++;
+ // i += 1;
+ }
+ }
+
+ dm->needsFree = 1;
+ dm->release(dm);
+
+ /*setting this to NULL prevents BMEdit_Free from freeing it*/
+ em->bm = NULL;
+ BMEdit_Free(em);
+ MEM_freeN(em);
+ }
+}
+
+/*
+ * BMESH BEGIN/END EDIT
+ *
+ * Functions for setting up a mesh for editing and cleaning up after
+ * the editing operations are done. These are called by the tools/operator
+ * API for each time a tool is executed.
+ *
+ * Returns -
+ * Nothing
+ *
+*/
+void bmesh_begin_edit(BMesh *bm, int flag) {
+ bm->opflag = flag;
+
+ /*switch multires data out of tangent space*/
+ if ((flag & BMOP_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
+ bmesh_set_mdisps_space(bm, MULTIRES_SPACE_TANGENT, MULTIRES_SPACE_ABSOLUTE);
+
+ /*ensure correct normals, if possible*/
+ bmesh_rationalize_normals(bm, 0);
+ BM_Compute_Normals(bm);
+ } else if (flag & BMOP_RATIONALIZE_NORMALS) {
+ bmesh_rationalize_normals(bm, 0);
+ }
+}
+
+void bmesh_end_edit(BMesh *bm, int flag){
+ /*switch multires data into tangent space*/
+ if ((flag & BMOP_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
+ /*set normals to their previous winding*/
+ bmesh_rationalize_normals(bm, 1);
+ bmesh_set_mdisps_space(bm, MULTIRES_SPACE_ABSOLUTE, MULTIRES_SPACE_TANGENT);
+ } else if (flag & BMOP_RATIONALIZE_NORMALS) {
+ bmesh_rationalize_normals(bm, 1);
+ }
+
+ bm->opflag = 0;
+
+ /*compute normals, clear temp flags and flush selections*/
+ BM_Compute_Normals(bm);
+ BM_SelectMode_Flush(bm);
+}
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
new file mode 100644
index 00000000000..c6ac65b9733
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -0,0 +1,729 @@
+#include <limits.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+#include "BLI_ghash.h"
+#include "BLI_math.h"
+#include "BLI_array.h"
+#include "BLI_utildefines.h"
+#include "BLI_smallhash.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * BME_MODS.C
+ *
+ * This file contains functions for locally modifying
+ * the topology of existing mesh data. (split, join, flip etc).
+ *
+*/
+
+/**
+ * bmesh_dissolve_disk
+ *
+ * Turns the face region surrounding a manifold vertex into
+ * A single polygon.
+ *
+ *
+ * Example:
+ *
+ * |=========| |=========|
+ * | \ / | | |
+ * Before: | V | After: | |
+ * | / \ | | |
+ * |=========| |=========|
+ *
+ *
+ */
+#if 1
+int BM_Dissolve_Vert(BMesh *bm, BMVert *v) {
+ BMIter iter;
+ BMEdge *e;
+ int len=0;
+
+ if (!v) return 0;
+
+ e = BMIter_New(&iter, bm, BM_EDGES_OF_VERT, v);
+ for (; e; e=BMIter_Step(&iter)) {
+ len++;
+ }
+
+ if (len == 1) {
+ if (v->e)
+ BM_Kill_Edge(bm, v->e);
+ BM_Kill_Vert(bm, v);
+ return 1;
+ }
+
+ if(BM_Nonmanifold_Vert(bm, v)) {
+ if (!v->e) BM_Kill_Vert(bm, v);
+ else if (!v->e->l) {
+ BM_Kill_Edge(bm, v->e);
+ BM_Kill_Vert(bm, v);
+ } else return 0;
+
+ return 1;
+ }
+
+ return BM_Dissolve_Disk(bm, v);
+}
+
+int BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
+ BMFace *f, *f2;
+ BMEdge *e, *keepedge=NULL, *baseedge=NULL;
+ BMLoop *loop;
+ int done, len= 0;
+
+ if(BM_Nonmanifold_Vert(bm, v)) {
+ return 0;
+ }
+
+ if(v->e){
+ /*v->e we keep, what else?*/
+ e = v->e;
+ do{
+ e = bmesh_disk_nextedge(e,v);
+ if(!(BM_Edge_Share_Faces(e, v->e))){
+ keepedge = e;
+ baseedge = v->e;
+ break;
+ }
+ len++;
+ }while(e != v->e);
+ }
+
+ /*this code for handling 2 and 3-valence verts
+ may be totally bad.*/
+ if (keepedge == NULL && len == 3) {
+ /*handle specific case for three-valence. solve it by
+ increasing valence to four. this may be hackish. . .*/
+ loop = e->l;
+ if (loop->v == v) loop = loop->next;
+ if (!BM_Split_Face(bm, loop->f, v, loop->v, NULL, NULL))
+ return 0;
+
+ if (!BM_Dissolve_Disk(bm, v)) {
+ return 0;
+ }
+ return 1;
+ } else if (keepedge == NULL && len == 2) {
+ /*collapse the vertex*/
+ e = BM_Collapse_Vert(bm, v->e, v, 1.0);
+
+ if (!e) {
+ return 0;
+ }
+
+ /*handle two-valence*/
+ f = e->l->f;
+ f2 = e->l->radial_next->f;
+
+ if (f != f2 && !BM_Join_TwoFaces(bm, f, f2, NULL))
+ return 0;
+
+ return 1;
+ }
+
+ if(keepedge){
+ done = 0;
+ while(!done){
+ done = 1;
+ e = v->e;
+ do{
+ f = NULL;
+ len = bmesh_radial_length(e->l);
+ if(len == 2 && (e!=baseedge) && (e!=keepedge)) {
+ f = BM_Join_TwoFaces(bm, e->l->f, e->l->radial_next->f, e);
+ /*return if couldn't join faces in manifold
+ conditions.*/
+ //!disabled for testing why bad things happen
+ if (!f) return 0;
+ }
+
+ if(f){
+ done = 0;
+ break;
+ }
+ e = bmesh_disk_nextedge(e, v);
+ }while(e != v->e);
+ }
+
+ /*collapse the vertex*/
+ e = BM_Collapse_Vert(bm, baseedge, v, 1.0);
+
+ if (!e) {
+ return 0;
+ }
+
+ /*get remaining two faces*/
+ f = e->l->f;
+ f2 = e->l->radial_next->f;
+
+ if (f != f2) {
+ /*join two remaining faces*/
+ if (!BM_Join_TwoFaces(bm, f, f2, NULL)) {
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+#else
+void BM_Dissolve_Disk(BMesh *bm, BMVert *v){
+ BMFace *f;
+ BMEdge *e;
+ BMIter iter;
+ int done, len;
+
+ if(v->e){
+ done = 0;
+ while(!done){
+ done = 1;
+
+ /*loop the edges looking for an edge to dissolve*/
+ for (e=BMIter_New(&iter, bm, BM_EDGES_OF_VERT, v); e;
+ e = BMIter_Step(&iter)) {
+ f = NULL;
+ len = bmesh_cycle_length(&(e->l->radial));
+ if(len == 2){
+ f = BM_Join_TwoFaces(bm,e->l->f,((BMLoop*)
+ (e->l->radial_next))->f,
+ e);
+ }
+ if(f){
+ done = 0;
+ break;
+ }
+ };
+ }
+ BM_Collapse_Vert(bm, v->e, v, 1.0);
+ }
+}
+#endif
+
+/**
+ * BM_Join_TwoFaces
+ *
+ * Joins two adjacenct faces togather.
+ *
+ * Because this method calls to BM_Join_Faces to do its work, ff a pair
+ * of faces share multiple edges, the pair of faces will be joined at
+ * every edge (not just edge e). This part of the functionality might need
+ * to be reconsidered.
+ *
+ * If the windings do not match the winding of the new face will follow
+ * f1's winding (i.e. f2 will be reversed before the join).
+ *
+ * Returns:
+ * pointer to the combined face
+ */
+
+BMFace *BM_Join_TwoFaces(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
+{
+ BMLoop *l1, *l2;
+ BMEdge *jed=NULL;
+ BMFace *faces[2] = {f1, f2};
+
+ jed = e;
+ if(!jed){
+ /*search for an edge that has both these faces in its radial cycle*/
+ l1 = bm_firstfaceloop(f1);
+ do{
+ if(l1->radial_next->f == f2 ) {
+ jed = l1->e;
+ break;
+ }
+ l1 = l1->next;
+ }while(l1!=bm_firstfaceloop(f1));
+ }
+
+ if (!jed) {
+ bmesh_error();
+ return NULL;
+ }
+
+ l1 = jed->l;
+
+ if (!l1) {
+ bmesh_error();
+ return NULL;
+ }
+
+ l2 = l1->radial_next;
+ if (l1->v == l2->v) {
+ bmesh_loop_reverse(bm, f2);
+ }
+
+ f1 = BM_Join_Faces(bm, faces, 2);
+
+ return f1;
+}
+
+/*connects two verts together, automatically (if very naively) finding the
+ face they both share (if there is one) and splittling it. use this at your
+ own risk, as it doesn't handle the many complex cases it should (like zero-area faces,
+ multiple faces, etc).
+
+ this is really only meant for cases where you don't know before hand the face
+ the two verts belong to for splitting (e.g. the subdivision operator).
+*/
+
+BMEdge *BM_Connect_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) {
+ BMIter iter, iter2;
+ BMVert *v;
+ BMLoop *nl;
+ BMFace *face;
+
+ /*be warned: this can do weird things in some ngon situation, see BM_LegalSplits*/
+ for (face = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v1); face; face=BMIter_Step(&iter)) {
+ for (v=BMIter_New(&iter2, bm, BM_VERTS_OF_FACE, face); v; v=BMIter_Step(&iter2)) {
+ if (v == v2) {
+ face = BM_Split_Face(bm, face, v1, v2, &nl, NULL);
+
+ if (nf) *nf = face;
+ return nl->e;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * BM_Split_Face
+ *
+ * Splits a single face into two.
+ *
+ * f - the original face
+ * v1 & v2 - vertices which define the split edge, must be different
+ * nl - pointer which will receive the BMLoop for the split edge in the new face
+ *
+ * Notes: the
+
+ * Returns -
+ * Pointer to the newly created face representing one side of the split
+ * if the split is successful (and the original original face will be the
+ * other side). NULL if the split fails.
+ *
+ */
+
+BMFace *BM_Split_Face(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **nl, BMEdge *UNUSED(example))
+{
+ BMFace *nf, *of;
+
+ /*do we have a multires layer?*/
+ if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
+ of = BM_Copy_Face(bm, f, 0, 0);
+ }
+
+ nf = bmesh_sfme(bm, f, v1, v2, nl, NULL);
+
+ if (nf) {
+ BM_Copy_Attributes(bm, bm, f, nf);
+ copy_v3_v3(nf->no, f->no);
+
+ /*handle multires update*/
+ if (nf != f && CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
+ BMLoop *l;
+
+ l = bm_firstfaceloop(f);
+ do {
+ BM_loop_interp_from_face(bm, l, of, 0, 1);
+ l = l->next;
+ } while (l != bm_firstfaceloop(f));
+
+ l = bm_firstfaceloop(nf);
+ do {
+ BM_loop_interp_from_face(bm, l, of, 0, 1);
+ l = l->next;
+ } while (l != bm_firstfaceloop(nf));
+
+ BM_Kill_Face(bm, of);
+
+ BM_multires_smooth_bounds(bm, f);
+ BM_multires_smooth_bounds(bm, nf);
+ }
+ }
+
+ return nf;
+}
+
+/**
+ * bmesh_collapse_vert
+ *
+ * Collapses a vertex that has only two manifold edges
+ * onto a vertex it shares an edge with. Fac defines
+ * the amount of interpolation for Custom Data.
+ *
+ * Note that this is not a general edge collapse function.
+ *
+ * BMESH_TODO:
+ * Insert error checking for KV valance.
+ *
+ * Returns -
+ * Nothing
+ */
+
+BMEdge* BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac){
+ BMFace **faces = NULL, *f;
+ BLI_array_staticdeclare(faces, 8);
+ BMIter iter;
+ BMLoop *l=NULL, *kvloop=NULL, *tvloop=NULL;
+ BMEdge *ne = NULL;
+ BMVert *tv = bmesh_edge_getothervert(ke,kv);
+ void *src[2];
+ float w[2];
+
+ /* Only intended to be called for 2-valence vertices */
+ BLI_assert(bmesh_disk_count(kv) <= 2);
+
+ w[0] = 1.0f - fac;
+ w[1] = fac;
+
+ if(ke->l){
+ l = ke->l;
+ do{
+ if(l->v == tv && l->next->v == kv) {
+ tvloop = l;
+ kvloop = l->next;
+
+ src[0] = kvloop->head.data;
+ src[1] = tvloop->head.data;
+ CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, kvloop->head.data);
+ }
+ l=l->radial_next;
+ }while(l!=ke->l);
+ }
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_VERT, kv) {
+ BLI_array_append(faces, f);
+ }
+
+ BM_Data_Interp_From_Verts(bm, kv, tv, kv, fac);
+
+ //bmesh_jekv(bm,ke,kv);
+ if (faces && BLI_array_count(faces) > 1) {
+ BMFace *f2;
+ BMEdge *e2;
+ BMVert *tv2;
+
+ e2 = bmesh_disk_nextedge(ke, kv);
+ tv2 = BM_OtherEdgeVert(e2, kv);
+
+ f2 = BM_Join_Faces(bm, faces, BLI_array_count(faces));
+ if (f2) {
+ BMLoop *nl = NULL;
+ if (BM_Split_Face(bm, f2, tv, tv2, &nl, NULL)) {
+ ne = nl->e;
+ }
+ }
+ } else if (faces && BLI_array_count(faces) == 1) {
+ BMLoop **loops = NULL;
+ BMVert **verts = NULL;
+ BMEdge **edges = NULL;
+ BMFace *f2;
+ BLI_array_staticdeclare(verts, 64);
+ BLI_array_staticdeclare(edges, 64);
+ BLI_array_staticdeclare(loops, 64);
+ int i;
+
+ /*create new face excluding kv*/
+ f = *faces;
+ l = bm_firstfaceloop(f);
+ i = 0;
+ do {
+ if (l->v != kv) {
+ BLI_array_append(verts, l->v);
+
+ if (l->e != ke && !BM_Vert_In_Edge(l->e, kv)) {
+ BLI_array_append(edges, l->e);
+ } else {
+ BMVert *v2;
+
+ /* Create a single edge to replace the two edges incident on kv */
+
+ if (BM_Vert_In_Edge(l->next->e, kv))
+ v2 = BM_OtherEdgeVert(l->next->e, kv);
+ else
+ v2 = BM_OtherEdgeVert(l->prev->e, kv);
+
+ /* Only one new edge should be created */
+ BLI_assert(ne == NULL);
+
+ ne = BM_Make_Edge(bm, BM_OtherEdgeVert(l->e, kv), v2, l->e, 1);
+ BLI_array_append(edges, ne);
+ }
+
+ BLI_array_append(loops, l);
+ i++;
+ }
+
+ l = l->next;
+ } while (l != bm_firstfaceloop(f));
+
+ f2 = BM_Make_Face(bm, verts, edges, BLI_array_count(verts), 0);
+ l = bm_firstfaceloop(f2);
+ i = 0;
+ do {
+ BM_Copy_Attributes(bm, bm, loops[i], l);
+ BM_loop_interp_multires(bm, loops[i], l->f);
+ i++;
+ l = l->next;
+ } while (l != bm_firstfaceloop(f2));
+
+ BM_Copy_Attributes(bm, bm, f, f2);
+ BM_Kill_Face(bm, f);
+ BM_Kill_Vert(bm, kv);
+ } else {
+ BMVert *tv2;
+ BMEdge *e2;
+
+ /*ok, no faces, means we have a wire edge*/
+ e2 = bmesh_disk_nextedge(ke, kv);
+ tv2 = BM_OtherEdgeVert(e2, kv);
+
+ ne = BM_Make_Edge(bm, tv, tv2, ke, 0);
+
+ BM_Kill_Edge(bm, ke);
+ BM_Kill_Edge(bm, e2);
+ BM_Kill_Vert(bm, kv);
+ }
+
+ BLI_array_free(faces);
+ return ne;
+}
+
+/**
+ * BM_split_edge
+ *
+ * Splits an edge. v should be one of the vertices in e and
+ * defines the direction of the splitting operation for interpolation
+ * purposes.
+ *
+ * Returns -
+ * the new vert
+ */
+
+BMVert *BM_Split_Edge(BMesh *bm, BMVert *v, BMEdge *e, BMEdge **ne, float percent) {
+ BMVert *nv, *v2;
+ BMFace **oldfaces = NULL;
+ BMEdge *dummy;
+ BLI_array_staticdeclare(oldfaces, 32);
+ SmallHash hash;
+
+ /*we need this for handling multires*/
+ if (!ne)
+ ne = &dummy;
+
+ /*do we have a multires layer?*/
+ if (CustomData_has_layer(&bm->ldata, CD_MDISPS) && e->l) {
+ BMLoop *l;
+ int i;
+
+ l = e->l;
+ do {
+ BLI_array_append(oldfaces, l->f);
+ l = l->radial_next;
+ } while (l != e->l);
+
+ /*create a hash so we can differentiate oldfaces from new faces*/
+ BLI_smallhash_init(&hash);
+
+ for (i=0; i<BLI_array_count(oldfaces); i++) {
+ oldfaces[i] = BM_Copy_Face(bm, oldfaces[i], 1, 1);
+ BLI_smallhash_insert(&hash, (intptr_t)oldfaces[i], NULL);
+ }
+ }
+
+ v2 = bmesh_edge_getothervert(e,v);
+ nv = bmesh_semv(bm,v,e,ne);
+ if (nv == NULL) return NULL;
+
+ sub_v3_v3v3(nv->co,v2->co,v->co);
+ VECADDFAC(nv->co,v->co,nv->co,percent);
+
+ if (ne) {
+ (*ne)->head.flag = e->head.flag;
+ BM_Copy_Attributes(bm, bm, e, *ne);
+ }
+
+ /*v->nv->v2*/
+ BM_Data_Facevert_Edgeinterp(bm, v2, v, nv, e, percent);
+ BM_Data_Interp_From_Verts(bm, v, v2, nv, percent);
+
+ if (CustomData_has_layer(&bm->ldata, CD_MDISPS) && e->l && nv) {
+ int i, j;
+
+ /*interpolate new/changed loop data from copied old faces*/
+ for (j=0; j<2; j++) {
+ for (i=0; i<BLI_array_count(oldfaces); i++) {
+ BMEdge *e1 = j ? *ne : e;
+ BMLoop *l, *l2;
+
+ l = e1->l;
+ if (!l) {
+ bmesh_error();
+ break;
+ }
+
+ do {
+ if (!BLI_smallhash_haskey(&hash, (intptr_t)l->f)) {
+ l2 = bm_firstfaceloop(l->f);
+ do {
+ BM_loop_interp_multires(bm, l2, oldfaces[i]);
+ l2 = l2->next;
+ } while (l2 != bm_firstfaceloop(l->f));
+ }
+ l = l->radial_next;
+ } while (l != e1->l);
+ }
+ }
+
+ /*destroy the old faces*/
+ for (i=0; i<BLI_array_count(oldfaces); i++) {
+ BM_Kill_Face_Verts(bm, oldfaces[i]);
+ }
+
+ /*fix boundaries a bit, doesn't work too well quite yet*/
+#if 0
+ for (j=0; j<2; j++) {
+ BMEdge *e1 = j ? *ne : e;
+ BMLoop *l, *l2;
+
+ l = e1->l;
+ if (!l) {
+ bmesh_error();
+ break;
+ }
+
+ do {
+ BM_multires_smooth_bounds(bm, l->f);
+ l = l->radial_next;
+ } while (l != e1->l);
+ }
+#endif
+
+ BLI_array_free(oldfaces);
+ BLI_smallhash_release(&hash);
+ }
+
+ return nv;
+}
+
+BMVert *BM_Split_Edge_Multi(BMesh *bm, BMEdge *e, int numcuts)
+{
+ int i;
+ float percent;
+ BMVert *nv = NULL;
+
+ for(i=0; i < numcuts; i++){
+ percent = 1.0f / (float)(numcuts + 1 - i);
+ nv = BM_Split_Edge(bm, e->v2, e, NULL, percent);
+ }
+ return nv;
+}
+
+int BM_Validate_Face(BMesh *bm, BMFace *face, FILE *err)
+{
+ BMIter iter;
+ BLI_array_declare(verts);
+ BMVert **verts = NULL;
+ BMLoop *l;
+ int ret = 1, i, j;
+
+ if (face->len == 2) {
+ fprintf(err, "warning: found two-edged face. face ptr: %p\n", face);
+ fflush(err);
+ }
+
+ for (l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, face);l;l=BMIter_Step(&iter)) {
+ BLI_array_growone(verts);
+ verts[BLI_array_count(verts)-1] = l->v;
+
+ if (l->e->v1 == l->e->v2) {
+ fprintf(err, "Found bmesh edge with identical verts!\n");
+ fprintf(err, " edge ptr: %p, vert: %p\n", l->e, l->e->v1);
+ fflush(err);
+ ret = 0;
+ }
+ }
+
+ for (i=0; i<BLI_array_count(verts); i++) {
+ for (j=0; j<BLI_array_count(verts); j++) {
+ if (j == i) continue;
+ if (verts[i] == verts[j]) {
+ fprintf(err, "Found duplicate verts in bmesh face!\n");
+ fprintf(err, " face ptr: %p, vert: %p\n", face, verts[i]);
+ fflush(err);
+ ret = 0;
+ }
+ }
+ }
+
+ BLI_array_free(verts);
+ return ret;
+}
+
+/*
+ BM Rotate Edge
+
+ Spins an edge topologically, either counter-clockwise or clockwise.
+ If ccw is true, the edge is spun counter-clockwise, otherwise it is
+ spun clockwise.
+
+ Returns the spun edge. Note that this works by dissolving the edge
+ then re-creating it, so the returned edge won't have the same pointer
+ address as the original one.
+
+ Returns NULL on error (e.g., if the edge isn't surrounded by exactly
+ two faces).
+*/
+BMEdge *BM_Rotate_Edge(BMesh *bm, BMEdge *e, int ccw)
+{
+ BMVert *v1, *v2;
+ BMLoop *l, *l1, *l2, *nl;
+ BMFace *f;
+ BMIter liter;
+
+ v1 = e->v1;
+ v2 = e->v2;
+
+ if (BM_Edge_FaceCount(e) != 2)
+ return NULL;
+
+ f = BM_Join_TwoFaces(bm, e->l->f, e->l->radial_next->f, e);
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ if (l->v == v1)
+ l1 = l;
+ else if (l->v == v2)
+ l2 = l;
+ }
+
+ if (ccw) {
+ l1 = l1->prev;
+ l2 = l2->prev;
+ } else {
+ l1 = l1->next;
+ l2 = l2->next;
+ }
+
+ if (!BM_Split_Face(bm, f, l1->v, l2->v, &nl, NULL))
+ return NULL;
+
+ return nl->e;
+}
+
+BMVert *BM_Rip_Vertex ( BMesh *bm, BMFace *sf, BMVert *sv)
+{
+ return bmesh_urmv(bm, sf, sv);
+}
diff --git a/source/blender/bmesh/intern/bmesh_newcore.c b/source/blender/bmesh/intern/bmesh_newcore.c
new file mode 100644
index 00000000000..c49d2faa395
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_newcore.c
@@ -0,0 +1,1805 @@
+#include <limits.h>
+
+#include "BLI_math_vector.h"
+
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+#include "BLI_listbase.h"
+#include "BLI_mempool.h"
+#include "BLI_ghash.h"
+#include "BLI_array.h"
+
+#include "DNA_listBase.h"
+
+#include "bmesh_class.h"
+
+#include "bmesh_iterators.h"
+#include "bmesh_private.h"
+
+BMVert *BM_Make_Vert(BMesh *bm, float co[3], const struct BMVert *example) {
+ BMVert *v = BLI_mempool_calloc(bm->vpool);
+
+ bm->totvert += 1;
+
+ v->head.type = BM_VERT;
+
+ /* 'v->no' is handled by BM_Copy_Attributes */
+ if (co) copy_v3_v3(v->co, co);
+
+ /*allocate flags*/
+ v->head.flags = BLI_mempool_calloc(bm->toolflagpool);
+
+ CustomData_bmesh_set_default(&bm->vdata, &v->head.data);
+
+ if (example) {
+ BM_Copy_Attributes(bm, bm, (BMVert*)example, (BMVert*)v);
+ }
+
+ CHECK_ELEMENT(bm, v);
+
+ return (BMVert*) v;
+}
+
+/**
+ * BMESH EDGE EXIST
+ *
+ * Finds out if two vertices already have an edge
+ * connecting them. Note that multiple edges may
+ * exist between any two vertices, and therefore
+ * This function only returns the first one found.
+ *
+ * Returns -
+ * BMEdge pointer
+ */
+BMEdge *BM_Edge_Exist(BMVert *v1, BMVert *v2)
+{
+ BMIter iter;
+ BMEdge *e;
+
+ BM_ITER(e, &iter, NULL, BM_EDGES_OF_VERT, v1) {
+ if (e->v1 == v2 || e->v2 == v2)
+ return e;
+ }
+
+ return NULL;
+}
+
+BMEdge *BM_Make_Edge(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble) {
+ BMEdge *e;
+
+ if (nodouble && (e= BM_Edge_Exist(v1, v2)))
+ return (BMEdge*)e;
+
+ e = BLI_mempool_calloc(bm->epool);
+ bm->totedge += 1;
+ e->head.type = BM_EDGE;
+
+ /*allocate flags*/
+ e->head.flags = BLI_mempool_calloc(bm->toolflagpool);
+
+ e->v1 = (BMVert*) v1;
+ e->v2 = (BMVert*) v2;
+
+
+ CustomData_bmesh_set_default(&bm->edata, &e->head.data);
+
+ bmesh_disk_append_edge(e, e->v1);
+ bmesh_disk_append_edge(e, e->v2);
+
+ if (example)
+ BM_Copy_Attributes(bm, bm, (BMEdge*)example, (BMEdge*)e);
+
+ CHECK_ELEMENT(bm, e);
+
+ return (BMEdge*) e;
+}
+
+static BMLoop *bmesh_create_loop(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, const BMLoop *example){
+ BMLoop *l=NULL;
+
+ l = BLI_mempool_calloc(bm->lpool);
+ l->next = l->prev = NULL;
+ l->v = v;
+ l->e = e;
+ l->f = f;
+ l->radial_next = l->radial_prev = NULL;
+ l->head.data = NULL;
+ l->head.type = BM_LOOP;
+
+ bm->totloop++;
+
+ if(example)
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data);
+ else
+ CustomData_bmesh_set_default(&bm->ldata, &l->head.data);
+
+ return l;
+}
+
+static BMLoop *BM_Add_FaceBoundary(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte) {
+ BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool);
+ BMLoop *l = bmesh_create_loop(bm, startv, starte, f, NULL);
+
+ bmesh_radial_append(starte, l);
+
+ lst->first = lst->last = l;
+ BLI_addtail(&f->loops, lst);
+
+ l->f = f;
+
+ return l;
+}
+
+BMFace *BM_Copy_Face(BMesh *bm, BMFace *f, int copyedges, int copyverts)
+{
+ BMEdge **edges = NULL;
+ BMVert **verts = NULL;
+ BLI_array_staticdeclare(edges, 256);
+ BLI_array_staticdeclare(verts, 256);
+ BMLoop *l, *l2;
+ BMFace *f2;
+ int i;
+
+ l = bm_firstfaceloop(f);
+ do {
+ if (copyverts) {
+ BMVert *v = BM_Make_Vert(bm, l->v->co, l->v);
+ BLI_array_append(verts, v);
+ } else {
+ BLI_array_append(verts, l->v);
+ }
+ l = l->next;
+ } while (l != bm_firstfaceloop(f));
+
+ l = bm_firstfaceloop(f);
+ i = 0;
+ do {
+ if (copyedges) {
+ BMEdge *e;
+ BMVert *v1, *v2;
+
+ if (l->e->v1 == verts[i]) {
+ v1 = verts[i];
+ v2 = verts[(i+1)%f->len];
+ } else {
+ v2 = verts[i];
+ v1 = verts[(i+1)%f->len];
+ }
+
+ e = BM_Make_Edge(bm, v1, v2, l->e, 0);
+ BLI_array_append(edges, e);
+ } else {
+ BLI_array_append(edges, l->e);
+ }
+
+ i++;
+ l = l->next;
+ } while (l != bm_firstfaceloop(f));
+
+ f2 = BM_Make_Face(bm, verts, edges, f->len, 0);
+
+ BM_Copy_Attributes(bm, bm, f, f2);
+
+ l = bm_firstfaceloop(f);
+ l2 = bm_firstfaceloop(f2);
+ do {
+ BM_Copy_Attributes(bm, bm, l, l2);
+ l = l->next;
+ l2 = l2->next;
+ } while (l != bm_firstfaceloop(f));
+
+ return f2;
+}
+
+BMFace *BM_Make_Face(BMesh *bm, BMVert **verts, BMEdge **edges, int len, int nodouble) {
+ BMFace *f = NULL;
+ BMLoop *l, *startl, *lastl;
+ int i, overlap;
+
+ if (len == 0) {
+ /*just return NULL for now*/
+ return NULL;
+ }
+
+ if (nodouble) {
+ /* Check if face already exists */
+ overlap = BM_Face_Exists(bm, verts, len, &f);
+ if (overlap) {
+ return f;
+ }
+ else {
+ BLI_assert(f == NULL);
+ }
+ }
+
+ f = BLI_mempool_calloc(bm->fpool);
+ bm->totface += 1;
+ f->head.type = BM_FACE;
+
+ startl = lastl = BM_Add_FaceBoundary(bm, (BMFace*)f, verts[0], edges[0]);
+
+ startl->v = (BMVert*) verts[0];
+ startl->e = (BMEdge*) edges[0];
+ for (i=1; i<len; i++) {
+ l = bmesh_create_loop(bm, verts[i], edges[i], (BMFace *)f, edges[i]->l);
+
+ l->f = (BMFace*) f;
+ bmesh_radial_append(edges[i], l);
+
+ l->prev = lastl;
+ lastl->next = l;
+ lastl = l;
+ }
+
+ /*allocate flags*/
+ f->head.flags = BLI_mempool_calloc(bm->toolflagpool);
+
+ CustomData_bmesh_set_default(&bm->pdata, &f->head.data);
+
+ startl->prev = lastl;
+ lastl->next = startl;
+
+ f->len = len;
+ f->totbounds = 0;
+
+ CHECK_ELEMENT(bm, f);
+
+ return (BMFace*) f;
+}
+
+int bmesh_check_element(BMesh *UNUSED(bm), void *element, int type) {
+ BMHeader *head = element;
+ int err = 0;
+
+ if (!element)
+ return 1;
+
+ if (head->type != type)
+ return 2;
+
+ switch (type) {
+ case BM_VERT: {
+ BMVert *v = element;
+ if (v->e && v->e->head.type != BM_EDGE) {
+ err |= 4;
+ }
+ break;
+ }
+ case BM_EDGE: {
+ BMEdge *e = element;
+ if (e->l && e->l->head.type != BM_LOOP)
+ err |= 8;
+ if (e->l && e->l->f->head.type != BM_FACE)
+ err |= 16;
+ if (e->dlink1.prev == NULL || e->dlink2.prev == NULL || e->dlink1.next == NULL || e->dlink2.next == NULL)
+ err |= 32;
+ if (e->l && (e->l->radial_next == NULL || e->l->radial_prev == NULL))
+ err |= 64;
+ if (e->l && e->l->f->len <= 0)
+ err |= 128;
+ break;
+ }
+ case BM_LOOP: {
+ BMLoop *l = element, *l2;
+ int i;
+
+ if (l->f->head.type != BM_FACE)
+ err |= 256;
+ if (l->e->head.type != BM_EDGE)
+ err |= 512;
+ if (l->v->head.type != BM_VERT)
+ err |= 1024;
+ if (!BM_Vert_In_Edge(l->e, l->v)) {
+ fprintf(stderr, "%s: fatal bmesh error (vert not in edge)! (bmesh internal error)\n", __func__);
+ err |= 2048;
+ }
+
+ if (l->radial_next == NULL || l->radial_prev == NULL)
+ err |= (1<<12);
+ if (l->f->len <= 0)
+ err |= (1<<13);
+
+ /*validate boundary loop--invalid for hole loops, of course,
+ but we won't be allowing those for a while yet*/
+ l2 = l;
+ i = 0;
+ do {
+ if (i >= 9999999)
+ break;
+
+ i++;
+ l2 = l2->next;
+ } while (l2 != l);
+
+ if (i != l->f->len || l2 != l)
+ err |= (1<<14);
+
+ if (!bmesh_radial_validate(bmesh_radial_length(l), l))
+ err |= (1<<15);
+
+ break;
+ }
+ case BM_FACE: {
+ BMFace *f = element;
+ BMLoop *l;
+ int len=0;
+
+ if (!f->loops.first)
+ err |= (1<<16);
+ l = bm_firstfaceloop(f);
+ do {
+ if (l->f != f) {
+ fprintf(stderr, "%s: loop inside one face points to another! (bmesh internal error)\n", __func__);
+ err |= (1<<17);
+ }
+
+ if (!l->e)
+ err |= (1<<18);
+ if (!l->v)
+ err |= (1<<19);
+ if (!BM_Vert_In_Edge(l->e, l->v) || !BM_Vert_In_Edge(l->e, l->next->v)) {
+ err |= (1<<20);
+ }
+
+ if (!bmesh_radial_validate(bmesh_radial_length(l), l))
+ err |= (1<<21);
+
+ if (!bmesh_disk_count(l->v) || !bmesh_disk_count(l->next->v))
+ err |= (1<<22);
+
+ len++;
+ l = l->next;
+ } while (l != bm_firstfaceloop(f));
+
+ if (len != f->len)
+ err |= (1<<23);
+ }
+ }
+
+ if (err) {
+ bmesh_error();
+ }
+
+ return err;
+}
+
+static void bmesh_kill_loop(BMesh *bm, BMLoop *l) {
+ bm->totloop--;
+ if (l->head.data)
+ CustomData_bmesh_free_block(&bm->ldata, &l->head.data);
+
+ if (l->head.flags)
+ BLI_mempool_free(bm->toolflagpool, l->head.flags);
+ BLI_mempool_free(bm->lpool, l);
+}
+
+void BM_Kill_Face_Edges(BMesh *bm, BMFace *f) {
+ BMEdge **edges = NULL;
+ BLI_array_staticdeclare(edges, 256);
+ BMLoop *l;
+ int i;
+
+ l = bm_firstfaceloop(f);
+ do {
+ BLI_array_append(edges, l->e);
+ l = l->next;
+ } while (l != bm_firstfaceloop(f));
+
+ for (i=0; i<BLI_array_count(edges); i++) {
+ BM_Kill_Edge(bm, edges[i]);
+ }
+
+ BLI_array_free(edges);
+}
+
+void BM_Kill_Face_Verts(BMesh *bm, BMFace *f) {
+ BMVert**verts = NULL;
+ BLI_array_staticdeclare(verts, 256);
+ BMLoop *l;
+ int i;
+
+ l = bm_firstfaceloop(f);
+ do {
+ BLI_array_append(verts, l->v);
+ l = l->next;
+ } while (l != bm_firstfaceloop(f));
+
+ for (i=0; i<BLI_array_count(verts); i++) {
+ BM_Kill_Vert(bm, verts[i]);
+ }
+
+ BLI_array_free(verts);
+}
+
+void BM_Kill_Face(BMesh *bm, BMFace *f) {
+ BMLoopList *ls, *lsnext;
+
+ CHECK_ELEMENT(bm, f);
+
+ for (ls=f->loops.first; ls; ls=lsnext) {
+ BMLoop *l, *lnext;
+
+ lsnext = ls->next;
+ l = ls->first;
+ do {
+ lnext = l->next;
+
+ bmesh_radial_remove_loop(l, l->e);
+ bmesh_kill_loop(bm, l);
+
+ l = lnext;
+ } while (l != ls->first);
+
+ BLI_mempool_free(bm->looplistpool, ls);
+ }
+
+ if (bm->act_face == f)
+ bm->act_face = NULL;
+
+ bm->totface--;
+ BM_remove_selection(bm, f);
+ if (f->head.data)
+ CustomData_bmesh_free_block(&bm->pdata, &f->head.data);
+
+ BLI_mempool_free(bm->toolflagpool, f->head.flags);
+
+ BLI_mempool_free(bm->fpool, f);
+}
+
+void BM_Kill_Edge(BMesh *bm, BMEdge *e) {
+
+ bmesh_disk_remove_edge(e, e->v1);
+ bmesh_disk_remove_edge(e, e->v2);
+
+ if (e->l) {
+ BMLoop *l = e->l, *lnext, *startl=e->l;
+
+ do {
+ lnext = l->radial_next;
+ if (lnext->f == l->f) {
+ BM_Kill_Face(bm, l->f);
+ break;
+ }
+
+ BM_Kill_Face(bm, l->f);
+
+ if (l == lnext)
+ break;
+ l = lnext;
+ } while (l != startl);
+ }
+
+ bm->totedge--;
+ BM_remove_selection(bm, e);
+ if (e->head.data)
+ CustomData_bmesh_free_block(&bm->edata, &e->head.data);
+
+ BLI_mempool_free(bm->toolflagpool, e->head.flags);
+ BLI_mempool_free(bm->epool, e);
+}
+
+void BM_Kill_Vert(BMesh *bm, BMVert *v) {
+ if (v->e) {
+ BMEdge *e, *nexte;
+
+ e = v->e;
+ while (v->e) {
+ nexte=bmesh_disk_nextedge(e, v);
+ BM_Kill_Edge(bm, e);
+ e = nexte;
+ }
+ }
+
+ bm->totvert--;
+ BM_remove_selection(bm, v);
+ if (v->head.data)
+ CustomData_bmesh_free_block(&bm->vdata, &v->head.data);
+
+ BLI_mempool_free(bm->toolflagpool, v->head.flags);
+ BLI_mempool_free(bm->vpool, v);
+}
+
+/********** private disk and radial cycle functions ************/
+
+/**
+ * bmesh_loop_reverse
+ *
+ * FLIP FACE EULER
+ *
+ * Changes the winding order of a face from CW to CCW or vice versa.
+ * This euler is a bit peculiar in compairson to others as it is its
+ * own inverse.
+ *
+ * BMESH_TODO: reinsert validation code.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+
+static int bmesh_loop_length(BMLoop *l)
+{
+ BMLoop *ol = l;
+ int i = 0;
+
+ do {
+ l = l->next;
+ i++;
+ } while (l != ol);
+
+ return i;
+}
+
+static int bmesh_loop_reverse_loop(BMesh *bm, BMFace *f, BMLoopList *lst){
+ BMLoop *l = lst->first, *curloop, *oldprev, *oldnext;
+ BMEdge **edar = NULL;
+ MDisps *md;
+ BLI_array_staticdeclare(edar, 64);
+ int i, j, edok, len = 0, do_disps = CustomData_has_layer(&bm->ldata, CD_MDISPS);
+
+ len = bmesh_loop_length(l);
+
+ for(i=0, curloop = l; i< len; i++, curloop= curloop->next) {
+ BMEdge *curedge = curloop->e;
+ bmesh_radial_remove_loop(curloop, curedge);
+ BLI_array_append(edar, curedge);
+ }
+
+ /*actually reverse the loop.*/
+ for(i=0, curloop = l; i < len; i++){
+ oldnext = curloop->next;
+ oldprev = curloop->prev;
+ curloop->next = oldprev;
+ curloop->prev = oldnext;
+ curloop = oldnext;
+
+ if (do_disps) {
+ float (*co)[3];
+ int x, y, sides;
+
+ md = CustomData_bmesh_get(&bm->ldata, curloop->head.data, CD_MDISPS);
+ if (!md->totdisp || !md->disps)
+ continue;
+
+ sides=sqrt(md->totdisp);
+ co = md->disps;
+
+ for (x=0; x<sides; x++) {
+ for (y=0; y<x; y++) {
+ swap_v3_v3(co[y*sides+x], co[sides*x + y]);
+ }
+ }
+ }
+ }
+
+ if(len == 2){ //two edged face
+ //do some verification here!
+ l->e = edar[1];
+ l->next->e = edar[0];
+ }
+ else{
+ for(i=0, curloop = l; i < len; i++, curloop = curloop->next) {
+ edok = 0;
+ for(j=0; j < len; j++){
+ edok = bmesh_verts_in_edge(curloop->v, curloop->next->v, edar[j]);
+ if(edok){
+ curloop->e = edar[j];
+ break;
+ }
+ }
+ }
+ }
+ /*rebuild radial*/
+ for(i=0, curloop = l; i < len; i++, curloop = curloop->next)
+ bmesh_radial_append(curloop->e, curloop);
+
+ /*validate radial*/
+ for(i=0, curloop = l; i < len; i++, curloop = curloop->next) {
+ CHECK_ELEMENT(bm, curloop);
+ CHECK_ELEMENT(bm, curloop->e);
+ CHECK_ELEMENT(bm, curloop->v);
+ CHECK_ELEMENT(bm, curloop->f);
+ }
+
+ BLI_array_free(edar);
+
+ CHECK_ELEMENT(bm, f);
+
+ return 1;
+}
+
+int bmesh_loop_reverse(BMesh *bm, BMFace *f)
+{
+ return bmesh_loop_reverse_loop(bm, f, f->loops.first);
+}
+
+static void bmesh_systag_elements(BMesh *UNUSED(bm), void *veles, int tot, int flag)
+{
+ BMHeader **eles = veles;
+ int i;
+
+ for (i=0; i<tot; i++) {
+ bmesh_api_setflag(eles[i], flag);
+ }
+}
+
+static void bmesh_clear_systag_elements(BMesh *UNUSED(bm), void *veles, int tot, int flag)
+{
+ BMHeader **eles = veles;
+ int i;
+
+ for (i=0; i<tot; i++) {
+ bmesh_api_clearflag(eles[i], flag);
+ }
+}
+
+#define FACE_MARK (1<<10)
+
+static int count_flagged_radial(BMesh *bm, BMLoop *l, int flag)
+{
+ BMLoop *l2 = l;
+ int i = 0, c=0;
+
+ do {
+ if (!l2) {
+ bmesh_error();
+ goto error;
+ }
+
+ i += bmesh_api_getflag(l2->f, flag) ? 1 : 0;
+ l2 = bmesh_radial_nextloop(l2);
+ if (c >= 800000) {
+ bmesh_error();
+ goto error;
+ }
+ c++;
+ } while (l2 != l);
+
+ return i;
+
+error:
+ BMO_RaiseError(bm, bm->currentop, BMERR_MESH_ERROR, NULL);
+ return 0;
+}
+
+static int count_flagged_disk(BMVert *v, int flag)
+{
+ BMEdge *e = v->e;
+ int i=0;
+
+ if (!e)
+ return 0;
+
+ do {
+ i += bmesh_api_getflag(e, flag) ? 1 : 0;
+ e = bmesh_disk_nextedge(e, v);
+ } while (e != v->e);
+
+ return i;
+}
+
+static int disk_is_flagged(BMVert *v, int flag)
+{
+ BMEdge *e = v->e;
+
+ if (!e)
+ return 0;
+
+ do {
+ BMLoop *l = e->l;
+
+ if (!l) {
+ return 0;
+ }
+
+ if (bmesh_radial_length(l) == 1)
+ return 0;
+
+ do {
+ if (!bmesh_api_getflag(l->f, flag))
+ return 0;
+
+ l = l->radial_next;
+ } while (l != e->l);
+
+ e = bmesh_disk_nextedge(e, v);
+ } while (e != v->e);
+
+ return 1;
+}
+
+/* Midlevel Topology Manipulation Functions */
+
+/*
+ * BM_Join_Faces
+ *
+ * Joins a collected group of faces into one. Only restriction on
+ * the input data is that the faces must be connected to each other.
+ *
+ * If a pair of faces share multiple edges, the pair of
+ * faces will be joined at every edge.
+ *
+ * Returns a pointer to the combined face.
+ */
+BMFace *BM_Join_Faces(BMesh *bm, BMFace **faces, int totface)
+{
+ BMFace *f, *newf;
+ BMLoopList *lst;
+ BMLoop *l;
+ BMEdge **edges = NULL;
+ BMEdge **deledges = NULL;
+ BMVert **delverts = NULL;
+ BLI_array_staticdeclare(edges, 64);
+ BLI_array_staticdeclare(deledges, 64);
+ BLI_array_staticdeclare(delverts, 64);
+ BMVert *v1=NULL, *v2=NULL;
+ ListBase holes = {NULL, NULL};
+ const char *err = NULL;
+ int i, tote=0;
+
+ if (!totface) {
+ bmesh_error();
+ return NULL;
+ }
+
+ if (totface == 1)
+ return faces[0];
+
+ bmesh_systag_elements(bm, faces, totface, _FLAG_JF);
+
+ for (i=0; i<totface; i++) {
+ f = faces[i];
+ l = bm_firstfaceloop(f);
+ do {
+ int rlen = count_flagged_radial(bm, l, _FLAG_JF);
+
+ if (rlen > 2) {
+ err = "Input faces do not form a contiguous manifold region";
+ goto error;
+ } else if (rlen == 1) {
+ BLI_array_append(edges, l->e);
+
+ if (!v1) {
+ v1 = l->v;
+ v2 = BM_OtherEdgeVert(l->e, l->v);
+ }
+ tote++;
+ } else if (rlen == 2) {
+ int d1, d2;
+
+ d1 = disk_is_flagged(l->e->v1, _FLAG_JF);
+ d2 = disk_is_flagged(l->e->v2, _FLAG_JF);
+
+ if (!d1 && !d2 && !bmesh_api_getflag(l->e, _FLAG_JF)) {
+ BLI_array_append(deledges, l->e);
+ bmesh_api_setflag(l->e, _FLAG_JF);
+ } else {
+ if (d1 && !bmesh_api_getflag(l->e->v1, _FLAG_JF)) {
+ BLI_array_append(delverts, l->e->v1);
+ bmesh_api_setflag(l->e->v1, _FLAG_JF);
+ }
+
+ if (d2 && !bmesh_api_getflag(l->e->v2, _FLAG_JF)) {
+ BLI_array_append(delverts, l->e->v2);
+ bmesh_api_setflag(l->e->v2, _FLAG_JF);
+ }
+ }
+ }
+
+ l = l->next;
+ } while (l != bm_firstfaceloop(f));
+
+ for (lst=f->loops.first; lst; lst=lst->next) {
+ if (lst == f->loops.first) continue;
+
+ BLI_remlink(&f->loops, lst);
+ BLI_addtail(&holes, lst);
+ }
+ }
+
+ /*create region face*/
+ newf = BM_Make_Ngon(bm, v1, v2, edges, tote, 0);
+ if (!newf || BMO_HasError(bm)) {
+ if (!BMO_HasError(bm))
+ err = "Invalid boundary region to join faces";
+ goto error;
+ }
+
+ /*copy over loop data*/
+ l = bm_firstfaceloop(newf);
+ do {
+ BMLoop *l2 = l->radial_next;
+
+ do {
+ if (bmesh_api_getflag(l2->f, _FLAG_JF))
+ break;
+ l2 = l2->radial_next;
+ } while (l2 != l);
+
+ if (l2 != l) {
+ /*I think this is correct?*/
+ if (l2->v != l->v) {
+ l2 = l2->next;
+ }
+
+ BM_Copy_Attributes(bm, bm, l2, l);
+ }
+
+ l = l->next;
+ } while (l != bm_firstfaceloop(newf));
+
+ BM_Copy_Attributes(bm, bm, faces[0], newf);
+
+ /*add holes*/
+ BLI_movelisttolist(&newf->loops, &holes);
+
+ /*update loop face pointers*/
+ for (lst=newf->loops.first; lst; lst=lst->next) {
+ l = lst->first;
+ do {
+ l->f = newf;
+ l = l->next;
+ } while (l != lst->first);
+ }
+
+ bmesh_clear_systag_elements(bm, faces, totface, _FLAG_JF);
+ bmesh_api_clearflag(newf, _FLAG_JF);
+
+ /* handle multires data*/
+ if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
+ l = bm_firstfaceloop(newf);
+ do {
+ for (i=0; i<totface; i++) {
+ BM_loop_interp_multires(bm, l, faces[i]);
+ }
+
+ l = l->next;
+ } while (l != bm_firstfaceloop(newf));
+ }
+
+ /*delete old geometry*/
+ for (i=0; i<BLI_array_count(deledges); i++) {
+ BM_Kill_Edge(bm, deledges[i]);
+ }
+
+ for (i=0; i<BLI_array_count(delverts); i++) {
+ BM_Kill_Vert(bm, delverts[i]);
+ }
+
+ BLI_array_free(edges);
+ BLI_array_free(deledges);
+ BLI_array_free(delverts);
+
+ CHECK_ELEMENT(bm, newf);
+ return newf;
+error:
+ bmesh_clear_systag_elements(bm, faces, totface, _FLAG_JF);
+ BLI_array_free(edges);
+ BLI_array_free(deledges);
+ BLI_array_free(delverts);
+
+ if (err) {
+ BMO_RaiseError(bm, bm->currentop, BMERR_DISSOLVEFACES_FAILED, err);
+ }
+ return NULL;
+}
+
+static BMFace *bmesh_addpolylist(BMesh *bm, BMFace *UNUSED(example)) {
+ BMFace *f;
+ BMLoopList *lst;
+
+ f = BLI_mempool_calloc(bm->fpool);
+ lst = BLI_mempool_calloc(bm->looplistpool);
+
+ f->head.type = BM_FACE;
+ BLI_addtail(&f->loops, lst);
+ bm->totface++;
+
+ /*allocate flags*/
+ f->head.flags = BLI_mempool_calloc(bm->toolflagpool);
+
+ CustomData_bmesh_set_default(&bm->pdata, &f->head.data);
+
+ f->len = 0;
+ f->totbounds = 1;
+
+ return (BMFace*) f;
+}
+
+/**
+ * bmesh_SFME
+ *
+ * SPLIT FACE MAKE EDGE:
+ *
+ * Takes as input two vertices in a single face. An edge is created which divides the original face
+ * into two distinct regions. One of the regions is assigned to the original face and it is closed off.
+ * The second region has a new face assigned to it.
+ *
+ * Examples:
+ *
+ * Before: After:
+ * ---------- ----------
+ * | | | |
+ * | | | f1 |
+ * v1 f1 v2 v1======v2
+ * | | | f2 |
+ * | | | |
+ * ---------- ----------
+ *
+ * Note that the input vertices can be part of the same edge. This will
+ * result in a two edged face. This is desirable for advanced construction
+ * tools and particularly essential for edge bevel. Because of this it is
+ * up to the caller to decide what to do with the extra edge.
+ *
+ * If holes is NULL, then both faces will lose
+ * all holes from the original face. Also, you cannot split between
+ * a hole vert and a boundary vert; that case is handled by higher-
+ * level wrapping functions (when holes are fully implemented, anyway).
+ *
+ * Note that holes represents which holes goes to the new face, and of
+ * course this requires removing them from the exitsing face first, since
+ * you cannot have linked list links inside multiple lists.
+ *
+ * Returns -
+ * A BMFace pointer
+ */
+BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
+ BMLoop **rl, ListBase *holes)
+{
+
+ BMFace *f2;
+ BMLoop *v1loop = NULL, *v2loop = NULL, *curloop, *f1loop=NULL, *f2loop=NULL;
+ BMEdge *e;
+ BMLoopList *lst, *lst2;
+ int i, len, f1len, f2len;
+
+ /*verify that v1 and v2 are in face.*/
+ len = f->len;
+ for(i = 0, curloop = bm_firstfaceloop(f); i < len; i++, curloop = curloop->next) {
+ if(curloop->v == v1) v1loop = curloop;
+ else if(curloop->v == v2) v2loop = curloop;
+ }
+
+ if(!v1loop || !v2loop) return NULL;
+
+ /*allocate new edge between v1 and v2*/
+ e = BM_Make_Edge(bm, v1, v2, NULL, 0);
+
+ f2 = bmesh_addpolylist(bm,f);
+ f1loop = bmesh_create_loop(bm,v2,e,f,v2loop);
+ f2loop = bmesh_create_loop(bm,v1,e,f2,v1loop);
+
+ f1loop->prev = v2loop->prev;
+ f2loop->prev = v1loop->prev;
+ v2loop->prev->next = f1loop;
+ v1loop->prev->next = f2loop;
+
+ f1loop->next = v1loop;
+ f2loop->next = v2loop;
+ v1loop->prev = f1loop;
+ v2loop->prev = f2loop;
+
+ lst = f->loops.first;
+ lst2 = f2->loops.first;
+
+ lst2->first = lst2->last = f2loop;
+ lst->first = lst->last = f1loop;
+
+ /*validate both loops*/
+ /*I dont know how many loops are supposed to be in each face at this point! FIXME!*/
+
+ /*go through all of f2's loops and make sure they point to it properly.*/
+ curloop = lst2->first;
+ f2len = 0;
+ do {
+ curloop->f = f2;
+
+ curloop = curloop->next;
+ f2len++;
+ } while (curloop != lst2->first);
+
+ /*link up the new loops into the new edges radial*/
+ bmesh_radial_append(e, f1loop);
+ bmesh_radial_append(e, f2loop);
+
+ f2->len = f2len;
+
+ f1len = 0;
+ curloop = lst->first;
+ do {
+ f1len++;
+ curloop = curloop->next;
+ } while (curloop != lst->first);
+
+ f->len = f1len;
+
+ if(rl) *rl = f2loop;
+
+ if (holes) {
+ BLI_movelisttolist(&f2->loops, holes);
+ } else {
+ /*this code is not significant until holes actually work ;) */
+ //printf("warning: call to split face euler without holes argument; holes will be tossed.\n");
+ for (lst=f->loops.last; lst != f->loops.first; lst=lst2) {
+ lst2 = lst->prev;
+ BLI_mempool_free(bm->looplistpool, lst);
+ }
+ }
+
+ CHECK_ELEMENT(bm, e);
+ CHECK_ELEMENT(bm, f);
+ CHECK_ELEMENT(bm, f2);
+
+ return f2;
+}
+
+/**
+ * bmesh_SEMV
+ *
+ * SPLIT EDGE MAKE VERT:
+ * Takes a given edge and splits it into two, creating a new vert.
+ *
+ *
+ * Before: OV---------TV
+ * After: OV----NV---TV
+ *
+ * Returns -
+ * BMVert pointer.
+ *
+*/
+
+BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **re){
+ BMLoop *nextl;
+ BMEdge *ne;
+ BMVert *nv, *ov;
+ int i, edok, valence1=0, valence2=0;
+
+ if(bmesh_vert_in_edge(e,tv) == 0) return NULL;
+ ov = bmesh_edge_getothervert(e,tv);
+
+ /*count valence of v1*/
+ valence1 = bmesh_disk_count(ov);
+
+ /*count valence of v2*/
+ valence2 = bmesh_disk_count(tv);
+
+ nv = BM_Make_Vert(bm, tv->co, tv);
+ ne = BM_Make_Edge(bm, nv, tv, e, 0);
+
+ bmesh_disk_remove_edge(ne, tv);
+ bmesh_disk_remove_edge(ne, nv);
+
+ /*remove e from v2's disk cycle*/
+ bmesh_disk_remove_edge(e, tv);
+
+ /*swap out tv for nv in e*/
+ bmesh_edge_swapverts(e, tv, nv);
+
+ /*add e to nv's disk cycle*/
+ bmesh_disk_append_edge(e, nv);
+
+ /*add ne to nv's disk cycle*/
+ bmesh_disk_append_edge(ne, nv);
+
+ /*add ne to tv's disk cycle*/
+ bmesh_disk_append_edge(ne, tv);
+
+ /*verify disk cycles*/
+ edok = bmesh_disk_validate(valence1, ov->e, ov);
+ if(!edok) bmesh_error();
+ edok = bmesh_disk_validate(valence2, tv->e, tv);
+ if(!edok) bmesh_error();
+ edok = bmesh_disk_validate(2, nv->e, nv);
+ if(!edok) bmesh_error();
+
+ /*Split the radial cycle if present*/
+ nextl = e->l;
+ e->l = NULL;
+ if(nextl) {
+ BMLoop *nl, *l;
+ int radlen = bmesh_radial_length(nextl);
+ int first1=0, first2=0;
+
+ /*Take the next loop. Remove it from radial. Split it. Append to appropriate radials.*/
+ while(nextl) {
+ l=nextl;
+ l->f->len++;
+ nextl = nextl!=nextl->radial_next ? nextl->radial_next : NULL;
+ bmesh_radial_remove_loop(l, NULL);
+
+ nl = bmesh_create_loop(bm,NULL,NULL,l->f,l);
+ nl->prev = l;
+ nl->next = (l->next);
+ nl->prev->next = nl;
+ nl->next->prev = nl;
+ nl->v = nv;
+
+ /*assign the correct edge to the correct loop*/
+ if(bmesh_verts_in_edge(nl->v, nl->next->v, e)) {
+ nl->e = e;
+ l->e = ne;
+
+ /*append l into ne's rad cycle*/
+ if(!first1) {
+ first1 = 1;
+ l->radial_next = l->radial_prev = NULL;
+ }
+
+ if(!first2) {
+ first2 = 1;
+ l->radial_next = l->radial_prev = NULL;
+ }
+
+ bmesh_radial_append(nl->e, nl);
+ bmesh_radial_append(l->e, l);
+ }
+ else if(bmesh_verts_in_edge(nl->v, nl->next->v, ne)){
+ nl->e = ne;
+ l->e = e;
+
+ /*append l into ne's rad cycle*/
+ if(!first1) {
+ first1 = 1;
+ l->radial_next = l->radial_prev = NULL;
+ }
+
+ if(!first2) {
+ first2 = 1;
+ l->radial_next = l->radial_prev = NULL;
+ }
+
+ bmesh_radial_append(nl->e, nl);
+ bmesh_radial_append(l->e, l);
+ }
+
+ }
+
+ /*verify length of radial cycle*/
+ edok = bmesh_radial_validate(radlen, e->l);
+ if(!edok) bmesh_error();
+ edok = bmesh_radial_validate(radlen, ne->l);
+ if(!edok) bmesh_error();
+
+ /*verify loop->v and loop->next->v pointers for e*/
+ for(i=0,l=e->l; i < radlen; i++, l = l->radial_next){
+ if(!(l->e == e)) bmesh_error();
+ //if(!(l->radial_next == l)) bmesh_error();
+ if(l->prev->e != ne && l->next->e != ne) bmesh_error();
+ edok = bmesh_verts_in_edge(l->v, l->next->v, e);
+ if(!edok) bmesh_error();
+ if(l->v == l->next->v) bmesh_error();
+ if(l->e == l->next->e) bmesh_error();
+
+ /*verify loop cycle for kloop->f*/
+ CHECK_ELEMENT(bm, l);
+ CHECK_ELEMENT(bm, l->v);
+ CHECK_ELEMENT(bm, l->e);
+ CHECK_ELEMENT(bm, l->f);
+ }
+ /*verify loop->v and loop->next->v pointers for ne*/
+ for(i=0,l=ne->l; i < radlen; i++, l = l->radial_next){
+ if(!(l->e == ne)) bmesh_error();
+ //if(!(l->radial_next == l)) bmesh_error();
+ if( l->prev->e != e && l->next->e != e) bmesh_error();
+ edok = bmesh_verts_in_edge(l->v, l->next->v, ne);
+ if(!edok) bmesh_error();
+ if(l->v == l->next->v) bmesh_error();
+ if(l->e == l->next->e) bmesh_error();
+
+ CHECK_ELEMENT(bm, l);
+ CHECK_ELEMENT(bm, l->v);
+ CHECK_ELEMENT(bm, l->e);
+ CHECK_ELEMENT(bm, l->f);
+ }
+ }
+
+ CHECK_ELEMENT(bm, ne);
+ CHECK_ELEMENT(bm, nv);
+ CHECK_ELEMENT(bm, ov);
+ CHECK_ELEMENT(bm, e);
+ CHECK_ELEMENT(bm, tv);
+
+ if(re) *re = ne;
+ return nv;
+}
+
+/**
+ * bmesh_JEKV
+ *
+ * JOIN EDGE KILL VERT:
+ * Takes a an edge and pointer to one of its vertices and collapses
+ * the edge on that vertex.
+ *
+ * Before: OE KE
+ * ------- -------
+ * | || |
+ * OV KV TV
+ *
+ *
+ * After: OE
+ * ---------------
+ * | |
+ * OV TV
+ *
+ *
+ * Restrictions:
+ * KV is a vertex that must have a valance of exactly two. Furthermore
+ * both edges in KV's disk cycle (OE and KE) must be unique (no double
+ * edges).
+ *
+ * It should also be noted that this euler has the possibility of creating
+ * faces with just 2 edges. It is up to the caller to decide what to do with
+ * these faces.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+int bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv)
+{
+ BMEdge *oe;
+ BMVert *ov, *tv;
+ BMLoop *killoop, *l;
+ int len,radlen=0, halt = 0, i, valence1, valence2,edok;
+ BMLoop **loops = NULL;
+ BLI_array_staticdeclare(loops, 256);
+
+ if(bmesh_vert_in_edge(ke,kv) == 0) return 0;
+ len = bmesh_disk_count(kv);
+
+ if(len == 2){
+ oe = bmesh_disk_nextedge(ke, kv);
+ tv = bmesh_edge_getothervert(ke, kv);
+ ov = bmesh_edge_getothervert(oe, kv);
+ halt = bmesh_verts_in_edge(kv, tv, oe); /*check for double edges*/
+
+ if(halt) return 0;
+ else{
+ /*For verification later, count valence of ov and tv*/
+ valence1 = bmesh_disk_count(ov);
+ valence2 = bmesh_disk_count(tv);
+
+ /*remove oe from kv's disk cycle*/
+ bmesh_disk_remove_edge(oe,kv);
+ /*relink oe->kv to be oe->tv*/
+ bmesh_edge_swapverts(oe, kv, tv);
+ /*append oe to tv's disk cycle*/
+ bmesh_disk_append_edge(oe, tv);
+ /*remove ke from tv's disk cycle*/
+ bmesh_disk_remove_edge(ke, tv);
+
+ /*deal with radial cycle of ke*/
+ radlen = bmesh_radial_length(ke->l);
+ if(ke->l){
+ /*first step, fix the neighboring loops of all loops in ke's radial cycle*/
+ for(i=0,killoop = ke->l; i<radlen; i++, killoop = bmesh_radial_nextloop(killoop)){
+ /*relink loops and fix vertex pointer*/
+ if( killoop->next->v == kv ) killoop->next->v = tv;
+
+ killoop->next->prev = killoop->prev;
+ killoop->prev->next = killoop->next;
+ if (bm_firstfaceloop(killoop->f) == killoop)
+ bm_firstfaceloop(killoop->f) = killoop->next;
+ killoop->next = NULL;
+ killoop->prev = NULL;
+
+ /*fix len attribute of face*/
+ killoop->f->len--;
+ }
+ /*second step, remove all the hanging loops attached to ke*/
+ killoop = ke->l;
+ radlen = bmesh_radial_length(ke->l);
+ /*this should be wrapped into a bme_free_radial function to be used by bmesh_KF as well...*/
+ for (i=0;i<radlen;i++) {
+ BLI_array_growone(loops);
+ loops[BLI_array_count(loops)-1] = killoop;
+ killoop = bmesh_radial_nextloop(killoop);
+ }
+ for (i=0;i<radlen;i++) {
+ bm->totloop--;
+ BLI_mempool_free(bm->lpool, loops[i]);
+ }
+ /*Validate radial cycle of oe*/
+ edok = bmesh_radial_validate(radlen,oe->l);
+ if(!edok) bmesh_error();
+ }
+
+ /*deallocate edge*/
+ BM_remove_selection(bm, ke);
+ BLI_mempool_free(bm->toolflagpool, ke->head.flags);
+ BLI_mempool_free(bm->epool, ke);
+ bm->totedge--;
+ /*deallocate vertex*/
+ BM_remove_selection(bm, kv);
+ BLI_mempool_free(bm->toolflagpool, kv->head.flags);
+ BLI_mempool_free(bm->vpool, kv);
+ bm->totvert--;
+
+ /*Validate disk cycle lengths of ov,tv are unchanged*/
+ edok = bmesh_disk_validate(valence1, ov->e, ov);
+ if(!edok) bmesh_error();
+ edok = bmesh_disk_validate(valence2, tv->e, tv);
+ if(!edok) bmesh_error();
+
+ /*Validate loop cycle of all faces attached to oe*/
+ for(i=0,l = oe->l; i<radlen; i++, l = bmesh_radial_nextloop(l)){
+ if(l->e != oe) bmesh_error();
+ edok = bmesh_verts_in_edge(l->v, l->next->v, oe);
+ if(!edok) bmesh_error();
+ edok = bmesh_loop_validate(l->f);
+ if(!edok) bmesh_error();
+
+ CHECK_ELEMENT(bm, l);
+ CHECK_ELEMENT(bm, l->v);
+ CHECK_ELEMENT(bm, l->e);
+ CHECK_ELEMENT(bm, l->f);
+ }
+
+ CHECK_ELEMENT(bm, ov);
+ CHECK_ELEMENT(bm, tv);
+ CHECK_ELEMENT(bm, oe);
+
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * bmesh_JFKE
+ *
+ * JOIN FACE KILL EDGE:
+ *
+ * Takes two faces joined by a single 2-manifold edge and fuses them togather.
+ * The edge shared by the faces must not be connected to any other edges which have
+ * Both faces in its radial cycle
+ *
+ * Examples:
+ *
+ * A B
+ * ---------- ----------
+ * | | | |
+ * | f1 | | f1 |
+ * v1========v2 = Ok! v1==V2==v3 == Wrong!
+ * | f2 | | f2 |
+ * | | | |
+ * ---------- ----------
+ *
+ * In the example A, faces f1 and f2 are joined by a single edge, and the euler can safely be used.
+ * In example B however, f1 and f2 are joined by multiple edges and will produce an error. The caller
+ * in this case should call bmesh_JEKV on the extra edges before attempting to fuse f1 and f2.
+ *
+ * Also note that the order of arguments decides whether or not certain per-face attributes are present
+ * in the resultant face. For instance vertex winding, material index, smooth flags, ect are inherited
+ * from f1, not f2.
+ *
+ * Returns -
+ * A BMFace pointer
+*/
+BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
+{
+ BMLoop *curloop, *f1loop=NULL, *f2loop=NULL;
+ int loopok = 0, newlen = 0,i, f1len=0, f2len=0, radlen=0, edok, shared;
+ BMIter iter;
+
+ /*can't join a face to itself*/
+ if(f1 == f2) return NULL;
+ /*verify that e is in both f1 and f2*/
+ f1len = f1->len;
+ f2len = f2->len;
+ BM_ITER(curloop, &iter, bm, BM_LOOPS_OF_FACE, f1) {
+ if(curloop->e == e){
+ f1loop = curloop;
+ break;
+ }
+ }
+ BM_ITER(curloop, &iter, bm, BM_LOOPS_OF_FACE, f2) {
+ if(curloop->e == e){
+ f2loop = curloop;
+ break;
+ }
+ }
+ if (!(f1loop && f2loop)) return NULL;
+
+ /*validate that edge is 2-manifold edge*/
+ radlen = bmesh_radial_length(f1loop);
+ if(radlen != 2) return NULL;
+
+ /*validate direction of f2's loop cycle is compatible.*/
+ if(f1loop->v == f2loop->v) return NULL;
+
+ /*
+ validate that for each face, each vertex has another edge in its disk cycle that is
+ not e, and not shared.
+ */
+ if(bmesh_radial_find_face(f1loop->next->e,f2)) return NULL;
+ if(bmesh_radial_find_face(f1loop->prev->e,f2)) return NULL;
+ if(bmesh_radial_find_face(f2loop->next->e,f1)) return NULL;
+ if(bmesh_radial_find_face(f2loop->prev->e,f1)) return NULL;
+
+ /*validate only one shared edge*/
+ shared = BM_Face_Sharededges(f1,f2);
+ if(shared > 1) return NULL;
+
+ /*validate no internal joins*/
+ for(i=0, curloop = bm_firstfaceloop(f1); i < f1len; i++, curloop = curloop->next)
+ bmesh_api_setindex(curloop->v, 0);
+ for(i=0, curloop = bm_firstfaceloop(f2); i < f2len; i++, curloop = curloop->next)
+ bmesh_api_setindex(curloop->v, 0);
+
+ for(i=0, curloop = bm_firstfaceloop(f1); i < f1len; i++, curloop = curloop->next) {
+ if (curloop != f1loop)
+ bmesh_api_setindex(curloop->v, bmesh_api_getindex(curloop->v) + 1);
+ }
+ for(i=0, curloop = bm_firstfaceloop(f2); i < f2len; i++, curloop = curloop->next) {
+ if (curloop != f2loop)
+ bmesh_api_setindex(curloop->v, bmesh_api_getindex(curloop->v) + 1);
+ }
+
+ for(i=0, curloop = bm_firstfaceloop(f1); i < f1len; i++, curloop = curloop->next) {
+ if (bmesh_api_getindex(curloop->v) > 1)
+ return NULL;
+ }
+
+ for(i=0, curloop = bm_firstfaceloop(f2); i < f2len; i++, curloop = curloop->next) {
+ if (bmesh_api_getindex(curloop->v) > 1)
+ return NULL;
+ }
+
+ /*join the two loops*/
+ f1loop->prev->next = f2loop->next;
+ f2loop->next->prev = f1loop->prev;
+
+ f1loop->next->prev = f2loop->prev;
+ f2loop->prev->next = f1loop->next;
+
+ /*if f1loop was baseloop, make f1loop->next the base.*/
+ if(bm_firstfaceloop(f1) == f1loop)
+ bm_firstfaceloop(f1) = f1loop->next;
+
+ /*increase length of f1*/
+ f1->len += (f2->len - 2);
+
+ /*make sure each loop points to the proper face*/
+ newlen = f1->len;
+ for(i = 0, curloop = bm_firstfaceloop(f1); i < newlen; i++, curloop = curloop->next)
+ curloop->f = f1;
+
+ /*remove edge from the disk cycle of its two vertices.*/
+ bmesh_disk_remove_edge(f1loop->e, f1loop->e->v1);
+ bmesh_disk_remove_edge(f1loop->e, f1loop->e->v2);
+
+ /*deallocate edge and its two loops as well as f2*/
+ BLI_mempool_free(bm->toolflagpool, f1loop->e->head.flags);
+ BLI_mempool_free(bm->epool, f1loop->e);
+ bm->totedge--;
+ BLI_mempool_free(bm->lpool, f1loop);
+ bm->totloop--;
+ BLI_mempool_free(bm->lpool, f2loop);
+ bm->totloop--;
+ BLI_mempool_free(bm->toolflagpool, f2->head.flags);
+ BLI_mempool_free(bm->fpool, f2);
+ bm->totface--;
+
+ CHECK_ELEMENT(bm, f1);
+
+ /*validate the new loop cycle*/
+ edok = bmesh_loop_validate(f1);
+ if(!edok) bmesh_error();
+
+ return f1;
+}
+
+/*
+ * BMESH SPLICE VERT
+ *
+ * merges two verts into one (v into vtarget).
+ */
+static int bmesh_splicevert(BMesh *bm, BMVert *v, BMVert *vtarget)
+{
+ BMEdge *e;
+ BMLoop *l;
+ BMIter liter;
+
+ /* verts already spliced */
+ if (v == vtarget) {
+ return 0;
+ }
+
+ /* retarget all the loops of v to vtarget */
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_VERT, v) {
+ l->v = vtarget;
+ }
+
+ /* move all the edges from v's disk to vtarget's disk */
+ e = v->e;
+ while (e != NULL) {
+ bmesh_disk_remove_edge(e, v);
+ bmesh_edge_swapverts(e, v, vtarget);
+ bmesh_disk_append_edge(e, vtarget);
+ e = v->e;
+ }
+
+ CHECK_ELEMENT(bm, v);
+ CHECK_ELEMENT(bm, vtarget);
+
+ /* v is unused now, and can be killed */
+ BM_Kill_Vert(bm, v);
+
+ return 1;
+}
+
+/* BMESH CUT VERT
+ *
+ * cut all disjoint fans that meet at a vertex, making a unique
+ * vertex for each region. returns an array of all resulting
+ * vertices.
+ */
+static int bmesh_cutvert(BMesh *bm, BMVert *v, BMVert ***vout, int *len)
+{
+ BMEdge **stack = NULL;
+ BLI_array_declare(stack);
+ BMVert **verts = NULL;
+ GHash *visithash;
+ BMIter eiter, liter;
+ BMLoop *l;
+ BMEdge *e;
+ int i, maxindex;
+ BMLoop *nl;
+
+ visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh_cutvert visithash");
+
+ maxindex = 0;
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ if (BLI_ghash_haskey(visithash, e)) {
+ continue;
+ }
+
+ /* Prime the stack with this unvisited edge */
+ BLI_array_append(stack, e);
+
+ /* Considering only edges and faces incident on vertex v, walk
+ the edges & faces and assign an index to each connected set */
+ while ((e = BLI_array_pop(stack))) {
+ BLI_ghash_insert(visithash, e, SET_INT_IN_POINTER(maxindex));
+ BM_SetIndex(e, maxindex);
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_EDGE, e) {
+ nl = (l->v == v) ? l->prev : l->next;
+ if (!BLI_ghash_haskey(visithash, nl->e)) {
+ BLI_array_append(stack, nl->e);
+ }
+ }
+ }
+
+ maxindex++;
+ }
+
+ /* Make enough verts to split v for each group */
+ verts = MEM_callocN(sizeof(BMVert *) * maxindex, "bmesh_cutvert");
+ verts[0] = v;
+ for (i = 1; i < maxindex; i++) {
+ verts[i] = BM_Make_Vert(bm, v->co, v);
+ }
+
+ /* Replace v with the new verts in each group */
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_VERT, v) {
+ i = GET_INT_FROM_POINTER(BLI_ghash_lookup(visithash, l->e));
+ if (i == 0) {
+ continue;
+ }
+
+ /* Loops here should alway refer to an edge that has v as an
+ endpoint. For each appearance of this vert in a face, there
+ will actually be two iterations: one for the loop heading
+ towards vertex v, and another for the loop heading out from
+ vertex v. Only need to swap the vertex on one of those times,
+ on the outgoing loop. */
+ if (l->v == v) {
+ l->v = verts[i];
+ }
+ }
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ i = GET_INT_FROM_POINTER(BLI_ghash_lookup(visithash, e));
+ if (i == 0) {
+ continue;
+ }
+
+ BLI_assert(e->v1 == v || e->v2 == v);
+ bmesh_disk_remove_edge(e, v);
+ bmesh_edge_swapverts(e, v, verts[i]);
+ bmesh_disk_append_edge(e, verts[i]);
+ }
+
+ BLI_ghash_free(visithash, NULL, NULL);
+ BLI_array_free(stack);
+
+ for (i = 0; i < maxindex; i++) {
+ CHECK_ELEMENT(bm, verts[i]);
+ }
+
+ if (len != NULL) {
+ *len = maxindex;
+ }
+
+ if (vout != NULL) {
+ *vout = verts;
+ }
+ else {
+ MEM_freeN(verts);
+ }
+
+ return 1;
+}
+
+/* BMESH SPLICE EDGE
+ *
+ * splice two unique edges which share the same two vertices into one edge.
+ *
+ * edges must already have the same vertices
+ */
+static int bmesh_spliceedge(BMesh *bm, BMEdge *e, BMEdge *etarget)
+{
+ BMLoop *l;
+
+ if (!BM_Vert_In_Edge(e, etarget->v1) || !BM_Vert_In_Edge(e, etarget->v2)) {
+ /* not the same vertices can't splice */
+ return 0;
+ }
+
+ while (e->l) {
+ l = e->l;
+ BLI_assert(BM_Vert_In_Edge(etarget, l->v));
+ BLI_assert(BM_Vert_In_Edge(etarget, l->next->v));
+ bmesh_radial_remove_loop(l, e);
+ bmesh_radial_append(etarget, l);
+ }
+
+ BLI_assert(bmesh_radial_length(e->l) == 0);
+
+ CHECK_ELEMENT(bm, e);
+ CHECK_ELEMENT(bm, etarget);
+
+ BM_Kill_Edge(bm, e);
+
+ return 1;
+}
+
+/*
+ * BMESH CUT EDGE
+ *
+ * Cuts a single edge into two edge: the original edge and
+ * a new edge that has only "cutl" in its radial.
+ *
+ * Does nothing if cutl is already the only loop in the
+ * edge radial.
+ */
+static int bmesh_cutedge(BMesh *bm, BMEdge *e, BMLoop *cutl)
+{
+ BMEdge *ne;
+ int radlen;
+
+ BLI_assert(cutl->e == e);
+ BLI_assert(e->l);
+
+ radlen = bmesh_radial_length(e->l);
+ if (radlen < 2) {
+ /* no cut required */
+ return 1;
+ }
+
+ if (cutl == e->l) {
+ e->l = cutl->radial_next;
+ }
+
+ ne = BM_Make_Edge(bm, e->v1, e->v2, e, 0);
+ bmesh_radial_remove_loop(cutl, e);
+ bmesh_radial_append(ne, cutl);
+ cutl->e = ne;
+
+ BLI_assert(bmesh_radial_length(e->l) == radlen - 1);
+ BLI_assert(bmesh_radial_length(ne->l) == 1);
+
+ CHECK_ELEMENT(bm, ne);
+ CHECK_ELEMENT(bm, e);
+
+ return 1;
+}
+
+/*
+ * BMESH UNGLUE REGION MAKE VERT
+ *
+ * Disconnects a face from its vertex fan at loop sl.
+ */
+static BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl)
+{
+ BMVert **vtar;
+ int len, i;
+ BMVert *nv = NULL;
+ BMVert *sv = sl->v;
+
+ /* peel the face from the edge radials on both sides of the
+ loop vert, disconnecting the face from its fan */
+ bmesh_cutedge(bm, sl->e, sl);
+ bmesh_cutedge(bm, sl->prev->e, sl->prev);
+
+ if (bmesh_disk_count(sv) == 2) {
+ /* If there are still only two edges out of sv, then
+ this whole URMV was just a no-op, so exit now. */
+ return sv;
+ }
+
+ /* Update the disk start, so that v->e points to an edge
+ not touching the split loop. This is so that bmesh_cutvert
+ will leave the original sv on some *other* fan (not the
+ one-face fan that holds the unglue face). */
+ while (sv->e == sl->e || sv->e == sl->prev->e) {
+ sv->e = bmesh_disk_nextedge(sv->e, sv);
+ }
+
+ /* Split all fans connected to the vert, duplicating it for
+ each fans. */
+ bmesh_cutvert(bm, sv, &vtar, &len);
+
+ /* There should have been at least two fans cut apart here,
+ otherwise the early exit would have kicked in. */
+ BLI_assert(len >= 2);
+
+ nv = sl->v;
+
+ /* Desired result here is that a new vert should always be
+ created for the unglue face. This is so we can glue any
+ extras back into the original vert. */
+ BLI_assert(nv != sv);
+ BLI_assert(sv == vtar[0]);
+
+ /* If there are more than two verts as a result, glue together
+ all the verts except the one this URMV intended to create */
+ if (len > 2) {
+ for (i = 0; i < len; i++) {
+ if (vtar[i] == nv) {
+ break;
+ }
+ }
+
+ if (i != len) {
+ /* Swap the single vert that was needed for the
+ unglue into the last array slot */
+ SWAP(BMVert *, vtar[i], vtar[len - 1]);
+
+ /* And then glue the rest back together */
+ for (i = 1; i < len - 1; i++) {
+ bmesh_splicevert(bm, vtar[i], vtar[0]);
+ }
+ }
+ }
+
+ MEM_freeN(vtar);
+
+ return nv;
+}
+
+/*
+ * BMESH UNGLUE REGION MAKE VERT
+ *
+ * Disconnects sf from the vertex fan at sv
+ */
+BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv)
+{
+ BMLoop *hl, *sl;
+
+ hl = sl = bm_firstfaceloop(sf);
+ do {
+ if (sl->v == sv) break;
+ sl = sl->next;
+ } while (sl != hl);
+
+ if (sl->v != sv) {
+ /* sv is not part of sf */
+ return NULL;
+ }
+
+ return bmesh_urmv_loop(bm, sl);
+}
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
new file mode 100644
index 00000000000..381684c1349
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -0,0 +1,1108 @@
+#include "bmesh.h"
+#include "bmesh_private.h"
+#include <stdio.h>
+
+/*
+This file defines (and documents) all bmesh operators (bmops).
+
+Do not rename any operator or slot names! otherwise you must go
+through the code and find all references to them!
+
+A word on slot names:
+
+For geometry input slots, the following are valid names:
+* verts
+* edges
+* faces
+* edgefacein
+* vertfacein
+* vertedgein
+* vertfacein
+* geom
+
+The basic rules are, for single-type geometry slots, use the plural of the
+type name (e.g. edges). for double-type slots, use the two type names plus
+"in" (e.g. edgefacein). for three-type slots, use geom.
+
+for output slots, for single-type geometry slots, use the type name plus "out",
+(e.g. vertout), for double-type slots, use the two type names plus "out",
+(e.g. vertfaceout), for three-type slots, use geom. note that you can also
+use more esohteric names (e.g. skirtout) so long as the comment next to the
+slot definition tells you what types of elements are in it.
+
+*/
+
+/*
+ok, I'm going to write a little docgen script. so all
+bmop comments must conform to the following template/rules:
+
+template (py quotes used because nested comments don't work
+on all C compilers):
+
+"""
+Region Extend.
+
+paragraph1, Extends bleh bleh bleh.
+Bleh Bleh bleh.
+
+Another paragraph.
+
+Another paragraph.
+"""
+
+so the first line is the "title" of the bmop.
+subsequent line blocks seperated by blank lines
+are paragraphs. individual descriptions of slots
+would be extracted from comments
+next to them, e.g.
+
+{BMOP_OPSLOT_ELEMENT_BUF, "geomout"}, //output slot, boundary region
+
+the doc generator would automatically detect the presence of "output slot"
+and flag the slot as an output. the same happens for "input slot". also
+note that "edges", "faces", "verts", "loops", and "geometry" are valid
+substitutions for "slot".
+
+note that slots default to being input slots.
+*/
+
+/*
+ Vertex Smooth
+
+ Smoothes vertices by using a basic vertex averaging scheme.
+*/
+static BMOpDefine def_vertexsmooth = {
+ "vertexsmooth",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {BMOP_OPSLOT_INT, "mirror_clip_x"}, //set vertices close to the x axis before the operation to 0
+ {BMOP_OPSLOT_INT, "mirror_clip_y"}, //set vertices close to the y axis before the operation to 0
+ {BMOP_OPSLOT_INT, "mirror_clip_z"}, //set vertices close to the z axis before the operation to 0
+ {BMOP_OPSLOT_FLT, "clipdist"}, //clipping threshod for the above three slots
+ {0} /*null-terminating sentinel*/,
+ },
+ bmesh_vertexsmooth_exec,
+ 0
+};
+
+/*
+ Right-Hand Faces
+
+ Computes an "outside" normal for the specified input faces.
+*/
+
+static BMOpDefine def_righthandfaces = {
+ "righthandfaces",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"},
+ {BMOP_OPSLOT_INT, "doflip"}, //internal flag, used by bmesh_rationalize_normals
+ {0} /*null-terminating sentinel*/,
+ },
+ bmesh_righthandfaces_exec,
+ BMOP_UNTAN_MULTIRES,
+};
+
+/*
+ Region Extend
+
+ used to implement the select more/less tools.
+ this puts some geometry surrounding regions of
+ geometry in geom into geomout.
+
+ if usefaces is 0 then geomout spits out verts and edges,
+ otherwise it spits out faces.
+ */
+static BMOpDefine def_regionextend = {
+ "regionextend",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"}, //input geometry
+ {BMOP_OPSLOT_ELEMENT_BUF, "geomout"}, //output slot, computed boundary geometry.
+ {BMOP_OPSLOT_INT, "constrict"}, //find boundary inside the regions, not outside.
+ {BMOP_OPSLOT_INT, "usefaces"}, //extend from faces instead of edges
+ {0} /*null-terminating sentinel*/,
+ },
+ bmesh_regionextend_exec,
+ 0
+};
+
+/*
+ Edge Rotate
+
+ Rotates edges topologically. Also known as "spin edge" to some people.
+ Simple example: [/] becomes [|] then [\].
+*/
+static BMOpDefine def_edgerotate = {
+ "edgerotate",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, //input edges
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"}, //newly spun edges
+ {BMOP_OPSLOT_INT, "ccw"}, //rotate edge counter-clockwise if true, othewise clockwise
+ {0} /*null-terminating sentinel*/,
+ },
+ bmesh_edgerotate_exec,
+ BMOP_UNTAN_MULTIRES
+};
+
+/*
+ Reverse Faces
+
+ Reverses the winding (vertex order) of faces. This has the effect of
+ flipping the normal.
+*/
+static BMOpDefine def_reversefaces = {
+ "reversefaces",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, //input faces
+ {0} /*null-terminating sentinel*/,
+ },
+ bmesh_reversefaces_exec,
+ BMOP_UNTAN_MULTIRES,
+};
+
+/*
+ Edge Bisect
+
+ Splits input edges (but doesn't do anything else).
+ This creates a 2-valence vert.
+*/
+static BMOpDefine def_edgebisect = {
+ "edgebisect",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, //input edges
+ {BMOP_OPSLOT_INT, "numcuts"}, //number of cuts
+ {BMOP_OPSLOT_ELEMENT_BUF, "outsplit"}, //newly created vertices and edges
+ {0} /*null-terminating sentinel*/,
+ },
+ esplit_exec,
+ BMOP_UNTAN_MULTIRES
+};
+
+/*
+ Mirror
+
+ Mirrors geometry along an axis. The resulting geometry is welded on using
+ mergedist. Pairs of original/mirrored vertices are welded using the mergedist
+ parameter (which defines the minimum distance for welding to happen).
+*/
+
+static BMOpDefine def_mirror = {
+ "mirror",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"}, //input geometry
+ {BMOP_OPSLOT_MAT, "mat"}, //matrix defining the mirror transformation
+ {BMOP_OPSLOT_FLT, "mergedist"}, //maximum distance for merging. does no merging if 0.
+ {BMOP_OPSLOT_ELEMENT_BUF, "newout"}, //output geometry, mirrored
+ {BMOP_OPSLOT_INT, "axis"}, //the axis to use, 0, 1, or 2 for x, y, z
+ {BMOP_OPSLOT_INT, "mirror_u"}, //mirror UVs across the u axis
+ {BMOP_OPSLOT_INT, "mirror_v"}, //mirror UVs across the v axis
+ {0, /*null-terminating sentinel*/}},
+ bmesh_mirror_exec,
+ 0,
+};
+
+/*
+ Find Doubles
+
+ Takes input verts and find vertices they should weld to. Outputs a
+ mapping slot suitable for use with the weld verts bmop.
+*/
+static BMOpDefine def_finddoubles = {
+ "finddoubles",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {BMOP_OPSLOT_ELEMENT_BUF, "keepverts"}, //list of verts to keep
+ {BMOP_OPSLOT_FLT, "dist"}, //minimum distance
+ {BMOP_OPSLOT_MAPPING, "targetmapout"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_finddoubles_exec,
+ 0,
+};
+
+/*
+ Remove Doubles
+
+ Finds groups of vertices closer then dist and merges them together,
+ using the weld verts bmop.
+*/
+static BMOpDefine def_removedoubles = {
+ "removedoubles",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input verts
+ {BMOP_OPSLOT_FLT, "dist"}, //minimum distance
+ {0, /*null-terminating sentinel*/}},
+ bmesh_removedoubles_exec,
+ BMOP_UNTAN_MULTIRES,
+};
+
+/*
+ Auto Merge
+
+ Finds groups of vertices closer then dist and merges them together,
+ using the weld verts bmop. The merges must go from a vert not in
+ verts to one in verts.
+*/
+static BMOpDefine def_automerge = {
+ "automerge",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input verts
+ {BMOP_OPSLOT_FLT, "dist"}, //minimum distance
+ {0, /*null-terminating sentinel*/}},
+ bmesh_automerge_exec,
+ BMOP_UNTAN_MULTIRES,
+};
+
+/*
+ Collapse Connected
+
+ Collapses connected vertices
+*/
+static BMOpDefine def_collapse = {
+ "collapse",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /*input edges*/
+ {0, /*null-terminating sentinel*/}},
+ bmesh_collapse_exec,
+ BMOP_UNTAN_MULTIRES,
+};
+
+
+/*
+ Facedata point Merge
+
+ Merge uv/vcols at a specific vertex.
+*/
+static BMOpDefine def_pointmerge_facedata = {
+ "pointmerge_facedata",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /*input vertices*/
+ {BMOP_OPSLOT_ELEMENT_BUF, "snapv"}, /*snap vertex*/
+ {0, /*null-terminating sentinel*/}},
+ bmesh_pointmerge_facedata_exec,
+ 0,
+};
+
+/*
+ Average Vertices Facevert Data
+
+ Merge uv/vcols associated with the input vertices at
+ the bounding box center. (I know, it's not averaging but
+ the vert_snap_to_bb_center is just too long).
+*/
+static BMOpDefine def_vert_average_facedata = {
+ "vert_average_facedata",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /*input vertices*/
+ {0, /*null-terminating sentinel*/}},
+ bmesh_vert_average_facedata_exec,
+ 0,
+};
+
+/*
+ Point Merge
+
+ Merge verts together at a point.
+*/
+static BMOpDefine def_pointmerge = {
+ "pointmerge",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /*input vertices*/
+ {BMOP_OPSLOT_VEC, "mergeco"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_pointmerge_exec,
+ BMOP_UNTAN_MULTIRES,
+};
+
+/*
+ Collapse Connected UVs
+
+ Collapses connected UV vertices.
+*/
+static BMOpDefine def_collapse_uvs = {
+ "collapse_uvs",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /*input edges*/
+ {0, /*null-terminating sentinel*/}},
+ bmesh_collapsecon_exec,
+ 0,
+};
+
+/*
+ Weld Verts
+
+ Welds verts together (kindof like remove doubles, merge, etc, all of which
+ use or will use this bmop). You pass in mappings from vertices to the vertices
+ they weld with.
+*/
+static BMOpDefine def_weldverts = {
+ "weldverts",
+ {{BMOP_OPSLOT_MAPPING, "targetmap"}, /*maps welded vertices to verts they should weld to.*/
+ {0, /*null-terminating sentinel*/}},
+ bmesh_weldverts_exec,
+ BMOP_UNTAN_MULTIRES,
+};
+
+/*
+ Make Vertex
+
+ Creates a single vertex; this bmop was necassary
+ for click-create-vertex.
+*/
+static BMOpDefine def_makevert = {
+ "makevert",
+ {{BMOP_OPSLOT_VEC, "co"}, //the coordinate of the new vert
+ {BMOP_OPSLOT_ELEMENT_BUF, "newvertout"}, //the new vert
+ {0, /*null-terminating sentinel*/}},
+ bmesh_makevert_exec,
+ 0,
+};
+
+/*
+ Join Triangles
+
+ Tries to intelligently join triangles according
+ to various settings and stuff.
+
+ */
+static BMOpDefine def_join_triangles= {
+ "join_triangles",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, //input geometry.
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, //joined faces
+ {BMOP_OPSLOT_INT, "compare_sharp"},
+ {BMOP_OPSLOT_INT, "compare_uvs"},
+ {BMOP_OPSLOT_INT, "compare_vcols"},
+ {BMOP_OPSLOT_INT, "compare_materials"},
+ {BMOP_OPSLOT_FLT, "limit"},
+ {0, /*null-terminating sentinel*/}},
+ bmesh_jointriangles_exec,
+ BMOP_UNTAN_MULTIRES,
+};
+
+/*
+ Contextual Create
+
+ This is basically fkey, it creates
+ new faces from vertices, makes stuff from edge nets,
+ makes wire edges, etc. It also dissolves
+ faces.
+
+ Three verts become a triangle, four become a quad. Two
+ become a wire edge.
+ */
+static BMOpDefine def_contextual_create= {
+ "contextual_create",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"}, //input geometry.
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, //newly-made face(s)
+ {0, /*null-terminating sentinel*/}},
+ bmesh_contextual_create_exec,
+ BMOP_UNTAN_MULTIRES,
+};
+
+/*
+
+ Bridge edge loops with faces
+*/
+static BMOpDefine def_bridge_loops= {
+ "bridge_loops",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /*input edges*/
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, /*new faces*/
+ {0, /*null-terminating sentinel*/}},
+ bmesh_bridge_loops_exec,
+ 0,
+};
+
+static BMOpDefine def_edgenet_fill= {
+ "edgenet_fill",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /*input edges*/
+ {BMOP_OPSLOT_MAPPING, "restrict"}, /*restricts edges to groups. maps edges to integers*/
+ {BMOP_OPSLOT_INT, "use_restrict"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "excludefaces"}, /*list of faces to ignore for manifold checks*/
+ {BMOP_OPSLOT_MAPPING, "faceout_groupmap"}, /*maps new faces to the group numbers they came from*/
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, /*new faces*/
+ {0, /*null-terminating sentinel*/}},
+ bmesh_edgenet_fill_exec,
+ 0,
+};
+
+/*
+ Edgenet Prepare
+
+ Identifies several useful edge loop cases and modifies them so
+ they'll become a face when edgenet_fill is called. The cases covered are:
+
+ * One single loop; an edge is added to connect the ends
+ * Two loops; two edges are added to connect the endpoints (based on the
+ shortest distance between each endpont).
+*/
+static BMOpDefine def_edgenet_prepare= {
+ "edgenet_prepare",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, //input edges
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"}, //new edges
+ {0, /*null-terminating sentinel*/}},
+ bmesh_edgenet_prepare,
+ 0,
+};
+
+/*
+ Rotate
+
+ Rotate vertices around a center, using a 3x3 rotation
+ matrix. Equivilent of the old rotateflag function.
+*/
+static BMOpDefine def_rotate = {
+ "rotate",
+ {{BMOP_OPSLOT_VEC, "cent"}, //center of rotation
+ {BMOP_OPSLOT_MAT, "mat"}, //matrix defining rotation
+ {BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {0, /*null-terminating sentinel*/}},
+ bmesh_rotate_exec,
+ 0,
+};
+
+/*
+ Translate
+
+ Translate vertices by an offset. Equivelent of the
+ old translateflag function.
+*/
+static BMOpDefine def_translate= {
+ "translate",
+ {{BMOP_OPSLOT_VEC, "vec"}, //translation offset
+ {BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {0, /*null-terminating sentinel*/}},
+ bmesh_translate_exec,
+ 0,
+};
+
+/*
+ Scale
+
+ Scales vertices by an offset.
+*/
+static BMOpDefine def_scale= {
+ "scale",
+ {{BMOP_OPSLOT_VEC, "vec"}, //scale factor
+ {BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {0, /*null-terminating sentinel*/}},
+ bmesh_scale_exec,
+ 0,
+};
+
+
+/*
+ Transform
+
+ Transforms a set of vertices by a matrix. Multiplies
+ the vertex coordinates with the matrix.
+*/
+static BMOpDefine def_transform = {
+ "transform",
+ {{BMOP_OPSLOT_MAT, "mat"}, //transform matrix
+ {BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {0, /*null-terminating sentinel*/}},
+ bmesh_transform_exec,
+ 0,
+};
+
+/*
+ Object Load BMesh
+
+ Loads a bmesh into an object/mesh. This is a "private"
+ bmop.
+*/
+static BMOpDefine def_object_load_bmesh = {
+ "object_load_bmesh",
+ {{BMOP_OPSLOT_PNT, "scene"},
+ {BMOP_OPSLOT_PNT, "object"},
+ {0, /*null-terminating sentinel*/}},
+ object_load_bmesh_exec,
+ 0,
+};
+
+
+/*
+ BMesh to Mesh
+
+ Converts a bmesh to a Mesh. This is reserved for exiting editmode.
+*/
+static BMOpDefine def_bmesh_to_mesh = {
+ "bmesh_to_mesh",
+ {{BMOP_OPSLOT_PNT, "mesh"}, //pointer to a mesh structure to fill in
+ {BMOP_OPSLOT_PNT, "object"}, //pointer to an object structure
+ {BMOP_OPSLOT_INT, "notesselation"}, //don't calculate mfaces
+ {0, /*null-terminating sentinel*/}},
+ bmesh_to_mesh_exec,
+ 0,
+};
+
+/*
+ Mesh to BMesh
+
+ Load the contents of a mesh into the bmesh. this bmop is private, it's
+ reserved exclusively for entering editmode.
+*/
+static BMOpDefine def_mesh_to_bmesh = {
+ "mesh_to_bmesh",
+ {{BMOP_OPSLOT_PNT, "mesh"}, //pointer to a Mesh structure
+ {BMOP_OPSLOT_PNT, "object"}, //pointer to an Object structure
+ {BMOP_OPSLOT_INT, "set_shapekey"}, //load active shapekey coordinates into verts
+ {0, /*null-terminating sentinel*/}},
+ mesh_to_bmesh_exec,
+ 0
+};
+
+/*
+ Individual Face Extrude
+
+ Extrudes faces individually.
+*/
+static BMOpDefine def_extrude_indivface = {
+ "extrude_face_indiv",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, //input faces
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, //output faces
+ {BMOP_OPSLOT_ELEMENT_BUF, "skirtout"}, //output skirt geometry, faces and edges
+ {0} /*null-terminating sentinel*/},
+ bmesh_extrude_face_indiv_exec,
+ 0
+};
+
+/*
+ Extrude Only Edges
+
+ Extrudes Edges into faces, note that this is very simple, there's no fancy
+ winged extrusion.
+*/
+static BMOpDefine def_extrude_onlyedge = {
+ "extrude_edge_only",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, //input vertices
+ {BMOP_OPSLOT_ELEMENT_BUF, "geomout"}, //output geometry
+ {0} /*null-terminating sentinel*/},
+ bmesh_extrude_onlyedge_exec,
+ 0
+};
+
+/*
+ Individual Vertex Extrude
+
+ Extrudes wire edges from vertices.
+*/
+static BMOpDefine def_extrudeverts_indiv = {
+ "extrude_vert_indiv",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, //input vertices
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"}, //output wire edges
+ {BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output vertices
+ {0} /*null-terminating sentinel*/},
+ extrude_vert_indiv_exec,
+ 0
+};
+
+static BMOpDefine def_connectverts = {
+ "connectverts",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"},
+ {0} /*null-terminating sentinel*/},
+ connectverts_exec,
+ BMOP_UNTAN_MULTIRES
+};
+
+static BMOpDefine def_extrudefaceregion = {
+ "extrudefaceregion",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edgefacein"},
+ {BMOP_OPSLOT_MAPPING, "exclude"},
+ {BMOP_OPSLOT_INT, "alwayskeeporig"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "geomout"},
+ {0} /*null-terminating sentinel*/},
+ extrude_edge_context_exec,
+ 0
+};
+
+static BMOpDefine def_dissolvevertsop = {
+ "dissolveverts",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
+ {0} /*null-terminating sentinel*/},
+ dissolveverts_exec,
+ BMOP_UNTAN_MULTIRES
+};
+
+static BMOpDefine def_dissolveedgessop = {
+ "dissolveedges",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "regionout"},
+ {0} /*null-terminating sentinel*/},
+ dissolveedges_exec,
+ BMOP_UNTAN_MULTIRES
+};
+
+static BMOpDefine def_dissolveedgeloopsop = {
+ "dissolveedgeloop",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "regionout"},
+ {0} /*null-terminating sentinel*/},
+ dissolve_edgeloop_exec,
+ BMOP_UNTAN_MULTIRES
+};
+
+static BMOpDefine def_dissolvefacesop = {
+ "dissolvefaces",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "regionout"},
+ {0} /*null-terminating sentinel*/},
+ dissolvefaces_exec,
+ BMOP_UNTAN_MULTIRES
+};
+
+
+static BMOpDefine def_triangop = {
+ "triangulate",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"},
+ {BMOP_OPSLOT_MAPPING, "facemap"},
+ {0} /*null-terminating sentinel*/},
+ triangulate_exec,
+ BMOP_UNTAN_MULTIRES
+};
+
+static BMOpDefine def_subdop = {
+ "esubd",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
+ {BMOP_OPSLOT_INT, "numcuts"},
+ {BMOP_OPSLOT_FLT, "smooth"},
+ {BMOP_OPSLOT_FLT, "fractal"},
+ {BMOP_OPSLOT_INT, "beauty"},
+ {BMOP_OPSLOT_INT, "seed"},
+ {BMOP_OPSLOT_MAPPING, "custompatterns"},
+ {BMOP_OPSLOT_MAPPING, "edgepercents"},
+
+ /*these next three can have multiple types of elements in them.*/
+ {BMOP_OPSLOT_ELEMENT_BUF, "outinner"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "outsplit"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "geomout"}, /*contains all output geometry*/
+
+ {BMOP_OPSLOT_INT, "quadcornertype"}, //quad corner type, see bmesh_operators.h
+ {BMOP_OPSLOT_INT, "gridfill"}, //fill in fully-selected faces with a grid
+ {BMOP_OPSLOT_INT, "singleedge"}, //tesselate the case of one edge selected in a quad or triangle
+
+ {0} /*null-terminating sentinel*/,
+ },
+ esubdivide_exec,
+ BMOP_UNTAN_MULTIRES
+};
+
+static BMOpDefine def_delop = {
+ "del",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"}, {BMOP_OPSLOT_INT, "context"},
+ {0} /*null-terminating sentinel*/},
+ delop_exec,
+ 0
+};
+
+static BMOpDefine def_dupeop = {
+ "dupe",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "origout"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "newout"},
+ /*facemap maps from source faces to dupe
+ faces, and from dupe faces to source faces.*/
+ {BMOP_OPSLOT_MAPPING, "facemap"},
+ {BMOP_OPSLOT_MAPPING, "boundarymap"},
+ {BMOP_OPSLOT_MAPPING, "isovertmap"},
+ {BMOP_OPSLOT_PNT, "dest"}, /*destination bmesh, if NULL will use current one*/
+ {0} /*null-terminating sentinel*/},
+ dupeop_exec,
+ 0
+};
+
+static BMOpDefine def_splitop = {
+ "split",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "geomout"},
+ {BMOP_OPSLOT_MAPPING, "boundarymap"},
+ {BMOP_OPSLOT_MAPPING, "isovertmap"},
+ {BMOP_OPSLOT_PNT, "dest"}, /*destination bmesh, if NULL will use current one*/
+ {0} /*null-terminating sentinel*/},
+ splitop_exec,
+ 0
+};
+
+/*
+ Spin
+
+ Extrude or duplicate geometry a number of times,
+ rotating and possibly translating after each step
+*/
+static BMOpDefine def_spinop = {
+ "spin",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "lastout"}, /* result of last step */
+ {BMOP_OPSLOT_VEC, "cent"}, /* rotation center */
+ {BMOP_OPSLOT_VEC, "axis"}, /* rotation axis */
+ {BMOP_OPSLOT_VEC, "dvec"}, /* translation delta per step */
+ {BMOP_OPSLOT_FLT, "ang"}, /* total rotation angle (degrees) */
+ {BMOP_OPSLOT_INT, "steps"}, /* number of steps */
+ {BMOP_OPSLOT_INT, "dupli"}, /* duplicate or extrude? */
+ {0} /*null-terminating sentinel*/},
+ spinop_exec,
+ 0
+};
+
+
+/*
+ Similar faces search
+
+ Find similar faces (area/material/perimeter....).
+*/
+static BMOpDefine def_similarfaces = {
+ "similarfaces",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, /* output faces */
+ {BMOP_OPSLOT_INT, "type"}, /* type of selection */
+ {BMOP_OPSLOT_FLT, "thresh"}, /* threshold of selection */
+ {0} /*null-terminating sentinel*/},
+ bmesh_similarfaces_exec,
+ 0
+};
+
+/*
+ Similar edges search
+
+ Find similar edges (length, direction, edge, seam,....).
+*/
+static BMOpDefine def_similaredges = {
+ "similaredges",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /* input edges */
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"}, /* output edges */
+ {BMOP_OPSLOT_INT, "type"}, /* type of selection */
+ {BMOP_OPSLOT_FLT, "thresh"}, /* threshold of selection */
+ {0} /*null-terminating sentinel*/},
+ bmesh_similaredges_exec,
+ 0
+};
+
+/*
+ Similar vertices search
+
+ Find similar vertices (normal, face, vertex group,....).
+*/
+static BMOpDefine def_similarverts = {
+ "similarverts",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /* input vertices */
+ {BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, /* output vertices */
+ {BMOP_OPSLOT_INT, "type"}, /* type of selection */
+ {BMOP_OPSLOT_FLT, "thresh"}, /* threshold of selection */
+ {0} /*null-terminating sentinel*/},
+ bmesh_similarverts_exec,
+ 0
+};
+
+/*
+** uv rotation
+** cycle the uvs
+*/
+static BMOpDefine def_meshrotateuvs = {
+ "meshrotateuvs",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {BMOP_OPSLOT_INT, "dir"}, /* direction */
+ {0} /*null-terminating sentinel*/},
+ bmesh_rotateuvs_exec,
+ 0
+};
+
+/*
+** uv reverse
+** reverse the uvs
+*/
+static BMOpDefine def_meshreverseuvs = {
+ "meshreverseuvs",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {0} /*null-terminating sentinel*/},
+ bmesh_reverseuvs_exec,
+ 0
+};
+
+/*
+** color rotation
+** cycle the colors
+*/
+static BMOpDefine def_meshrotatecolors = {
+ "meshrotatecolors",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {BMOP_OPSLOT_INT, "dir"}, /* direction */
+ {0} /*null-terminating sentinel*/},
+ bmesh_rotatecolors_exec,
+ 0
+};
+
+/*
+** color reverse
+** reverse the colors
+*/
+static BMOpDefine def_meshreversecolors = {
+ "meshreversecolors",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {0} /*null-terminating sentinel*/},
+ bmesh_reversecolors_exec,
+ 0
+};
+
+/*
+ Similar vertices search
+
+ Find similar vertices (normal, face, vertex group,....).
+*/
+static BMOpDefine def_vertexshortestpath = {
+ "vertexshortestpath",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "startv"}, /* start vertex */
+ {BMOP_OPSLOT_ELEMENT_BUF, "endv"}, /* end vertex */
+ {BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, /* output vertices */
+ {BMOP_OPSLOT_INT, "type"}, /* type of selection */
+ {0} /*null-terminating sentinel*/},
+ bmesh_vertexshortestpath_exec,
+ 0
+};
+
+/*
+ Edge Split
+
+ Disconnects faces along input edges.
+ */
+static BMOpDefine def_edgesplit = {
+ "edgesplit",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /* input edges */
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout1"}, /* old output disconnected edges */
+ {BMOP_OPSLOT_ELEMENT_BUF, "edgeout2"}, /* new output disconnected edges */
+ {0} /*null-terminating sentinel*/},
+ bmesh_edgesplitop_exec,
+ BMOP_UNTAN_MULTIRES
+};
+
+/*
+ Create Grid
+
+ Creates a grid with a variable number of subdivisions
+*/
+static BMOpDefine def_create_grid = {
+ "create_grid",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output verts
+ {BMOP_OPSLOT_INT, "xsegments"}, //number of x segments
+ {BMOP_OPSLOT_INT, "ysegments"}, //number of y segments
+ {BMOP_OPSLOT_FLT, "size"}, //size of the grid
+ {BMOP_OPSLOT_MAT, "mat"}, //matrix to multiply the new geometry with
+ {0, /*null-terminating sentinel*/}},
+ bmesh_create_grid_exec,
+ 0,
+};
+
+/*
+ Create UV Sphere
+
+ Creates a grid with a variable number of subdivisions
+*/
+static BMOpDefine def_create_uvsphere = {
+ "create_uvsphere",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output verts
+ {BMOP_OPSLOT_INT, "segments"}, //number of u segments
+ {BMOP_OPSLOT_INT, "revolutions"}, //number of v segment
+ {BMOP_OPSLOT_FLT, "diameter"}, //diameter
+ {BMOP_OPSLOT_MAT, "mat"}, //matrix to multiply the new geometry with--
+ {0, /*null-terminating sentinel*/}},
+ bmesh_create_uvsphere_exec,
+ 0,
+};
+
+/*
+ Create Ico Sphere
+
+ Creates a grid with a variable number of subdivisions
+*/
+static BMOpDefine def_create_icosphere = {
+ "create_icosphere",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output verts
+ {BMOP_OPSLOT_INT, "subdivisions"}, //how many times to recursively subdivide the sphere
+ {BMOP_OPSLOT_FLT, "diameter"}, //diameter
+ {BMOP_OPSLOT_MAT, "mat"}, //matrix to multiply the new geometry with
+ {0, /*null-terminating sentinel*/}},
+ bmesh_create_icosphere_exec,
+ 0,
+};
+
+/*
+ Create Suzanne
+
+ Creates a monkey. Be wary.
+*/
+static BMOpDefine def_create_monkey = {
+ "create_monkey",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output verts
+ {BMOP_OPSLOT_MAT, "mat"}, //matrix to multiply the new geometry with--
+ {0, /*null-terminating sentinel*/}},
+ bmesh_create_monkey_exec,
+ 0,
+};
+
+/*
+ Create Cone
+
+ Creates a cone with variable depth at both ends
+*/
+static BMOpDefine def_create_cone = {
+ "create_cone",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output verts
+ {BMOP_OPSLOT_INT, "cap_ends"}, //wheter or not to fill in the ends with faces
+ {BMOP_OPSLOT_INT, "cap_tris"}, //fill ends with triangles instead of ngons
+ {BMOP_OPSLOT_INT, "segments"},
+ {BMOP_OPSLOT_FLT, "diameter1"}, //diameter of one end
+ {BMOP_OPSLOT_FLT, "diameter2"}, //diameter of the opposite
+ {BMOP_OPSLOT_FLT, "depth"}, //distance between ends
+ {BMOP_OPSLOT_MAT, "mat"}, //matrix to multiply the new geometry with--
+ {0, /*null-terminating sentinel*/}},
+ bmesh_create_cone_exec,
+ 0,
+};
+
+/*
+Creates a circle
+*/
+static BMOpDefine def_create_circle = {
+ "create_circle",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output verts
+ {BMOP_OPSLOT_INT, "cap_ends"}, //wheter or not to fill in the ends with faces
+ {BMOP_OPSLOT_INT, "cap_tris"}, //fill ends with triangles instead of ngons
+ {BMOP_OPSLOT_INT, "segments"},
+ {BMOP_OPSLOT_FLT, "diameter"}, //diameter of one end
+ {BMOP_OPSLOT_MAT, "mat"}, //matrix to multiply the new geometry with--
+ {0, /*null-terminating sentinel*/}},
+ bmesh_create_circle_exec,
+ 0,
+};
+
+/*
+ Create Cone
+
+ Creates a cone with variable depth at both ends
+*/
+static BMOpDefine def_create_cube = {
+ "create_cube",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output verts
+ {BMOP_OPSLOT_FLT, "size"}, //size of the cube
+ {BMOP_OPSLOT_MAT, "mat"}, //matrix to multiply the new geometry with--
+ {0, /*null-terminating sentinel*/}},
+ bmesh_create_cube_exec,
+ 0,
+};
+
+/*
+ Bevel
+
+ Bevels edges and vertices
+ */
+static BMOpDefine def_bevel = {
+ "bevel",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */
+ {BMOP_OPSLOT_ELEMENT_BUF, "face_spans"}, /* new geometry */
+ {BMOP_OPSLOT_ELEMENT_BUF, "face_holes"}, /* new geometry */
+ {BMOP_OPSLOT_INT, "uselengths"}, /* grab edge lengths from a PROP_FLT customdata layer*/
+ {BMOP_OPSLOT_INT, "lengthlayer"}, /* which PROP_FLT layer to use*/
+ {BMOP_OPSLOT_FLT, "percent"}, /* percentage to expand bevelled edges*/
+ {0} /*null-terminating sentinel*/},
+ bmesh_bevel_exec,
+ BMOP_UNTAN_MULTIRES
+};
+
+/*
+ Beautify Fill
+
+ Makes triangle a bit nicer
+ */
+static BMOpDefine def_beautify_fill = {
+"beautify_fill",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {BMOP_OPSLOT_ELEMENT_BUF, "constrain_edges"}, /* edges that can't be flipped */
+ {BMOP_OPSLOT_ELEMENT_BUF, "geomout"}, /* new flipped faces and edges */
+ {0} /*null-terminating sentinel*/},
+ bmesh_beautify_fill_exec,
+ BMOP_UNTAN_MULTIRES
+};
+
+/*
+ Triangle Fill
+
+ Fill edges with triangles
+ */
+static BMOpDefine def_triangle_fill = {
+ "triangle_fill",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /* input edges */
+ {BMOP_OPSLOT_ELEMENT_BUF, "geomout"}, /* new faces and edges */
+ {0} /*null-terminating sentinel*/},
+ bmesh_triangle_fill_exec,
+ BMOP_UNTAN_MULTIRES
+};
+
+/*
+ Solidify
+
+ Turns a mesh into a shell with thickness
+*/
+static BMOpDefine def_solidify = {
+ "solidify",
+ {{BMOP_OPSLOT_ELEMENT_BUF, "geom"},
+ {BMOP_OPSLOT_FLT, "thickness"},
+ {BMOP_OPSLOT_ELEMENT_BUF, "geomout"},
+ {0}},
+ bmesh_solidify_face_region_exec,
+ 0
+};
+
+BMOpDefine *opdefines[] = {
+ &def_splitop,
+ &def_spinop,
+ &def_dupeop,
+ &def_delop,
+ &def_subdop,
+ &def_triangop,
+ &def_dissolvefacesop,
+ &def_dissolveedgessop,
+ &def_dissolveedgeloopsop,
+ &def_dissolvevertsop,
+ &def_extrudefaceregion,
+ &def_connectverts,
+ //&def_makeprim,
+ &def_extrudeverts_indiv,
+ &def_mesh_to_bmesh,
+ &def_object_load_bmesh,
+ &def_transform,
+ &def_translate,
+ &def_rotate,
+ &def_edgenet_fill,
+ &def_contextual_create,
+ &def_makevert,
+ &def_weldverts,
+ &def_removedoubles,
+ &def_finddoubles,
+ &def_mirror,
+ &def_edgebisect,
+ &def_reversefaces,
+ &def_edgerotate,
+ &def_regionextend,
+ &def_righthandfaces,
+ &def_vertexsmooth,
+ &def_extrude_onlyedge,
+ &def_extrude_indivface,
+ &def_collapse_uvs,
+ &def_pointmerge,
+ &def_collapse,
+ &def_similarfaces,
+ &def_similaredges,
+ &def_similarverts,
+ &def_pointmerge_facedata,
+ &def_vert_average_facedata,
+ &def_meshrotateuvs,
+ &def_bmesh_to_mesh,
+ &def_meshreverseuvs,
+ &def_edgenet_prepare,
+ &def_meshrotatecolors,
+ &def_meshreversecolors,
+ &def_vertexshortestpath,
+ &def_scale,
+ &def_edgesplit,
+ &def_automerge,
+ &def_create_uvsphere,
+ &def_create_grid,
+ &def_create_icosphere,
+ &def_create_monkey,
+ &def_create_cube,
+ &def_create_circle,
+ &def_create_cone,
+ &def_join_triangles,
+ &def_bevel,
+ &def_beautify_fill,
+ &def_triangle_fill,
+ &def_bridge_loops,
+ &def_solidify,
+};
+
+int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*));
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
new file mode 100644
index 00000000000..9a5193f4811
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -0,0 +1,1383 @@
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
+#include "BLI_mempool.h"
+#include "BLI_blenlib.h"
+#include "BLI_array.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+#include "stdarg.h"
+
+#include <string.h>
+
+/*forward declarations*/
+static void alloc_flag_layer(BMesh *bm);
+static void free_flag_layer(BMesh *bm);
+static void clear_flag_layer(BMesh *bm);
+static int bmesh_name_to_slotcode(BMOpDefine *def, const char *name);
+static int bmesh_name_to_slotcode_check(BMOpDefine *def, const char *name);
+static int bmesh_opname_to_opcode(const char *opname);
+
+static const char *bmop_error_messages[] = {
+ 0,
+ "Self intersection error",
+ "Could not dissolve vert",
+ "Could not connect vertices",
+ "Could not traverse mesh",
+ "Could not dissolve faces",
+ "Could not dissolve vertices",
+ "Tesselation error",
+ "Can not deal with non-manifold geometry",
+ "Invalid selection",
+ "Internal mesh error",
+};
+
+
+/*operator slot type information - size of one element of the type given.*/
+const int BMOP_OPSLOT_TYPEINFO[] = {
+ 0,
+ sizeof(int),
+ sizeof(float),
+ sizeof(void*),
+ 0, /* unused */
+ 0, /* unused */
+ 0, /* unused */
+ sizeof(void*), /* pointer buffer */
+ sizeof(element_mapping)
+};
+
+/* Dummy slot so there is something to return when slot name lookup fails */
+static BMOpSlot BMOpEmptySlot = { 0 };
+
+void BMO_Set_OpFlag(BMesh *UNUSED(bm), BMOperator *op, int flag)
+{
+ op->flag |= flag;
+}
+
+void BMO_Clear_OpFlag(BMesh *UNUSED(bm), BMOperator *op, int flag)
+{
+ op->flag &= ~flag;
+}
+
+/*
+ * BMESH OPSTACK PUSH
+ *
+ * Pushes the opstack down one level
+ * and allocates a new flag layer if
+ * appropriate.
+ *
+*/
+
+void BMO_push(BMesh *bm, BMOperator *UNUSED(op))
+{
+ bm->stackdepth++;
+
+ /*add flag layer, if appropriate*/
+ if (bm->stackdepth > 1)
+ alloc_flag_layer(bm);
+ else
+ clear_flag_layer(bm);
+}
+
+/*
+ * BMESH OPSTACK POP
+ *
+ * Pops the opstack one level
+ * and frees a flag layer if appropriate
+ * BMESH_TODO: investigate NOT freeing flag
+ * layers.
+ *
+*/
+void BMO_pop(BMesh *bm)
+{
+ if(bm->stackdepth > 1)
+ free_flag_layer(bm);
+
+ bm->stackdepth--;
+}
+
+/*
+ * BMESH OPSTACK INIT OP
+ *
+ * Initializes an operator structure
+ * to a certain type
+ *
+*/
+
+void BMO_Init_Op(BMOperator *op, const char *opname)
+{
+ int i, opcode = bmesh_opname_to_opcode(opname);
+
+ memset(op, 0, sizeof(BMOperator));
+ op->type = opcode;
+ op->flag = opdefines[opcode]->flag;
+
+ /*initialize the operator slot types*/
+ for(i = 0; opdefines[opcode]->slottypes[i].type; i++) {
+ op->slots[i].slottype = opdefines[opcode]->slottypes[i].type;
+ op->slots[i].index = i;
+ }
+
+ /*callback*/
+ op->exec = opdefines[opcode]->exec;
+
+ /*memarena, used for operator's slot buffers*/
+ op->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "bmesh operator");
+ BLI_memarena_use_calloc (op->arena);
+}
+
+/*
+ * BMESH OPSTACK EXEC OP
+ *
+ * Executes a passed in operator. This handles
+ * the allocation and freeing of temporary flag
+ * layers and starting/stopping the modelling
+ * loop. Can be called from other operators
+ * exec callbacks as well.
+ *
+*/
+
+void BMO_Exec_Op(BMesh *bm, BMOperator *op)
+{
+
+ BMO_push(bm, op);
+
+ if(bm->stackdepth == 2)
+ bmesh_begin_edit(bm, op->flag);
+ op->exec(bm, op);
+
+ if(bm->stackdepth == 2)
+ bmesh_end_edit(bm, op->flag);
+
+ BMO_pop(bm);
+}
+
+/*
+ * BMESH OPSTACK FINISH OP
+ *
+ * Does housekeeping chores related to finishing
+ * up an operator.
+ *
+*/
+
+void BMO_Finish_Op(BMesh *UNUSED(bm), BMOperator *op)
+{
+ BMOpSlot *slot;
+ int i;
+
+ for (i=0; opdefines[op->type]->slottypes[i].type; i++) {
+ slot = &op->slots[i];
+ if (slot->slottype == BMOP_OPSLOT_MAPPING) {
+ if (slot->data.ghash)
+ BLI_ghash_free(slot->data.ghash, NULL, NULL);
+ }
+ }
+
+ BLI_memarena_free(op->arena);
+}
+
+/*
+ * BMESH OPSTACK HAS SLOT
+ *
+ * Returns 1 if the named slot exists on the given operator,
+ * otherwise returns 0.
+ *
+*/
+
+int BMO_HasSlot(BMOperator *op, const char *slotname)
+{
+ int slotcode = bmesh_name_to_slotcode(opdefines[op->type], slotname);
+ return (slotcode >= 0);
+}
+
+/*
+ * BMESH OPSTACK GET SLOT
+ *
+ * Returns a pointer to the slot of
+ * type 'slotcode'
+ *
+*/
+
+BMOpSlot *BMO_GetSlot(BMOperator *op, const char *slotname)
+{
+ int slotcode = bmesh_name_to_slotcode_check(opdefines[op->type], slotname);
+
+ if (slotcode < 0) {
+ return &BMOpEmptySlot;
+ }
+
+ return &(op->slots[slotcode]);
+}
+
+/*
+ * BMESH OPSTACK COPY SLOT
+ *
+ * Copies data from one slot to another
+ *
+*/
+
+void BMO_CopySlot(BMOperator *source_op, BMOperator *dest_op, const char *src, const char *dst)
+{
+ BMOpSlot *source_slot = BMO_GetSlot(source_op, src);
+ BMOpSlot *dest_slot = BMO_GetSlot(dest_op, dst);
+
+ if(source_slot == dest_slot)
+ return;
+
+ if(source_slot->slottype != dest_slot->slottype)
+ return;
+
+ if (dest_slot->slottype > BMOP_OPSLOT_VEC) {
+ if (dest_slot->slottype != BMOP_OPSLOT_MAPPING) {
+ /*do buffer copy*/
+ dest_slot->data.buf = NULL;
+ dest_slot->len = source_slot->len;
+ if(dest_slot->len){
+ dest_slot->data.buf = BLI_memarena_alloc(dest_op->arena, BMOP_OPSLOT_TYPEINFO[dest_slot->slottype] * dest_slot->len);
+ memcpy(dest_slot->data.buf, source_slot->data.buf, BMOP_OPSLOT_TYPEINFO[dest_slot->slottype] * dest_slot->len);
+ }
+ } else {
+ GHashIterator it;
+ element_mapping *srcmap, *dstmap;
+
+ /*sanity check*/
+ if (!source_slot->data.ghash) return;
+
+ if (!dest_slot->data.ghash) {
+ dest_slot->data.ghash =
+ BLI_ghash_new(BLI_ghashutil_ptrhash,
+ BLI_ghashutil_ptrcmp, "bmesh operator 2");
+ }
+
+ BLI_ghashIterator_init(&it, source_slot->data.ghash);
+ for (; (srcmap=BLI_ghashIterator_getValue(&it));
+ BLI_ghashIterator_step(&it))
+ {
+ dstmap = BLI_memarena_alloc(dest_op->arena,
+ sizeof(*dstmap) + srcmap->len);
+
+ dstmap->element = srcmap->element;
+ dstmap->len = srcmap->len;
+ memcpy(dstmap+1, srcmap+1, srcmap->len);
+
+ BLI_ghash_insert(dest_slot->data.ghash,
+ dstmap->element, dstmap);
+ }
+ }
+ } else {
+ dest_slot->data = source_slot->data;
+ }
+}
+
+/*
+ * BMESH OPSTACK SET XXX
+ *
+ * Sets the value of a slot depending on it's type
+ *
+*/
+
+
+void BMO_Set_Float(BMOperator *op, const char *slotname, float f)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_FLT) )
+ return;
+
+ slot->data.f = f;
+}
+
+void BMO_Set_Int(BMOperator *op, const char *slotname, int i)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_INT) )
+ return;
+
+ slot->data.i = i;
+}
+
+/*only supports square mats*/
+void BMO_Set_Mat(struct BMOperator *op, const char *slotname, float *mat, int size)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_MAT) )
+ return;
+
+ slot->len = 4;
+ slot->data.p = BLI_memarena_alloc(op->arena, sizeof(float)*4*4);
+
+ if (size == 4) {
+ memcpy(slot->data.p, mat, sizeof(float)*4*4);
+ } else if (size == 3) {
+ copy_m4_m3(slot->data.p, (float (*)[3])mat);
+ } else {
+ fprintf(stderr, "%s: invalid size argument %d (bmesh internal error)\n", __func__, size);
+
+ memset(slot->data.p, 0, sizeof(float)*4*4);
+ return;
+ }
+}
+
+void BMO_Get_Mat4(struct BMOperator *op, const char *slotname, float mat[4][4])
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_MAT) )
+ return;
+
+ memcpy(mat, slot->data.p, sizeof(float)*4*4);
+}
+
+void BMO_Get_Mat3(struct BMOperator *op, const char *slotname, float mat[3][3])
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_MAT) )
+ return;
+
+ copy_m3_m4(mat, slot->data.p);
+}
+
+void BMO_Set_Pnt(BMOperator *op, const char *slotname, void *p)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_PNT) )
+ return;
+
+ slot->data.p = p;
+}
+
+void BMO_Set_Vec(BMOperator *op, const char *slotname, float *vec)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_VEC) )
+ return;
+
+ copy_v3_v3(slot->data.vec, vec);
+}
+
+
+float BMO_Get_Float(BMOperator *op, const char *slotname)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_FLT) )
+ return 0.0f;
+
+ return slot->data.f;
+}
+
+int BMO_Get_Int(BMOperator *op, const char *slotname)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_INT) )
+ return 0;
+
+ return slot->data.i;
+}
+
+
+void *BMO_Get_Pnt(BMOperator *op, const char *slotname)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_PNT) )
+ return NULL;
+
+ return slot->data.p;
+}
+
+void BMO_Get_Vec(BMOperator *op, const char *slotname, float *vec_out)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ if( !(slot->slottype == BMOP_OPSLOT_VEC) )
+ return;
+
+ copy_v3_v3(vec_out, slot->data.vec);
+}
+
+/*
+ * BMO_COUNTFLAG
+ *
+ * Counts the number of elements of a certain type that
+ * have a specific flag set.
+ *
+*/
+
+int BMO_CountFlag(BMesh *bm, int flag, int type)
+{
+ BMIter elements;
+ BMHeader *e;
+ int count = 0;
+
+ if(type & BM_VERT){
+ for(e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)){
+ if(BMO_TestFlag(bm, e, flag))
+ count++;
+ }
+ }
+ if(type & BM_EDGE){
+ for(e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)){
+ if(BMO_TestFlag(bm, e, flag))
+ count++;
+ }
+ }
+ if(type & BM_FACE){
+ for(e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)){
+ if(BMO_TestFlag(bm, e, flag))
+ count++;
+ }
+ }
+
+ return count;
+}
+
+void BMO_Clear_Flag_All(BMesh *bm, BMOperator *UNUSED(op), int type, int flag) {
+ BMIter iter;
+ BMHeader *ele;
+ int i=0, types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+
+ for (i=0; i<3; i++) {
+ if (i==0 && !(type & BM_VERT))
+ continue;
+ if (i==1 && !(type & BM_EDGE))
+ continue;
+ if (i==2 && !(type & BM_FACE))
+ continue;
+
+ BM_ITER(ele, &iter, bm, types[i], NULL) {
+ BMO_ClearFlag(bm, ele, flag);
+ }
+ }
+}
+
+int BMO_CountSlotBuf(struct BMesh *UNUSED(bm), struct BMOperator *op, const char *slotname)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ /*check if its actually a buffer*/
+ if( !(slot->slottype > BMOP_OPSLOT_VEC) )
+ return 0;
+
+ return slot->len;
+}
+
+int BMO_CountSlotMap(BMesh *UNUSED(bm), BMOperator *op, const char *slotname)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ /*check if its actually a buffer*/
+ if( !(slot->slottype == BMOP_OPSLOT_MAPPING) )
+ return 0;
+
+ return slot->data.ghash ? BLI_ghash_size(slot->data.ghash) : 0;
+}
+
+#if 0
+void *BMO_Grow_Array(BMesh *bm, BMOperator *op, int slotcode, int totadd) {
+ BMOpSlot *slot = &op->slots[slotcode];
+ void *tmp;
+
+ /*check if its actually a buffer*/
+ if( !(slot->slottype > BMOP_OPSLOT_VEC) )
+ return NULL;
+
+ if (slot->flag & BMOS_DYNAMIC_ARRAY) {
+ if (slot->len >= slot->size) {
+ slot->size = (slot->size+1+totadd)*2;
+
+ tmp = slot->data.buf;
+ slot->data.buf = MEM_callocN(BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->size, "opslot dynamic array");
+ memcpy(slot->data.buf, tmp, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->size);
+ MEM_freeN(tmp);
+ }
+
+ slot->len += totadd;
+ } else {
+ slot->flag |= BMOS_DYNAMIC_ARRAY;
+ slot->len += totadd;
+ slot->size = slot->len+2;
+ tmp = slot->data.buf;
+ slot->data.buf = MEM_callocN(BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->len, "opslot dynamic array");
+ memcpy(slot->data.buf, tmp, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->len);
+ }
+
+ return slot->data.buf;
+}
+#endif
+
+void BMO_Mapping_To_Flag(struct BMesh *bm, struct BMOperator *op,
+ const char *slotname, int flag)
+{
+ GHashIterator it;
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader *ele;
+
+ /*sanity check*/
+ if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
+ if (!slot->data.ghash) return;
+
+ BLI_ghashIterator_init(&it, slot->data.ghash);
+ for ( ; (ele=BLI_ghashIterator_getKey(&it)); BLI_ghashIterator_step(&it)) {
+ BMO_SetFlag(bm, ele, flag);
+ }
+}
+
+static void *alloc_slot_buffer(BMOperator *op, const char *slotname, int len){
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ /*check if its actually a buffer*/
+ if( !(slot->slottype > BMOP_OPSLOT_VEC) )
+ return NULL;
+
+ slot->len = len;
+ if(len)
+ slot->data.buf = BLI_memarena_alloc(op->arena, BMOP_OPSLOT_TYPEINFO[slot->slottype] * len);
+ return slot->data.buf;
+}
+
+
+/*
+ *
+ * BMO_ALL_TO_SLOT
+ *
+ * Copies all elements of a certain type into an operator slot.
+ *
+*/
+
+static void BMO_All_To_Slot(BMesh *bm, BMOperator *op, const char *slotname, int type)
+{
+ BMIter elements;
+ BMHeader *e;
+ BMOpSlot *output = BMO_GetSlot(op, slotname);
+ int totelement=0, i=0;
+
+ if (type & BM_VERT) totelement += bm->totvert;
+ if (type & BM_EDGE) totelement += bm->totedge;
+ if (type & BM_FACE) totelement += bm->totface;
+
+ if(totelement){
+ alloc_slot_buffer(op, slotname, totelement);
+
+ if (type & BM_VERT) {
+ for (e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+
+ if (type & BM_EDGE) {
+ for (e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+
+ if (type & BM_FACE) {
+ for (e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+}
+
+/*
+ *
+ * BMO_HEADERFLAG_TO_SLOT
+ *
+ * Copies elements of a certain type, which have a certain header flag set
+ * into a slot for an operator.
+ *
+*/
+
+void BMO_HeaderFlag_To_Slot(BMesh *bm, BMOperator *op, const char *slotname, int flag, int type)
+{
+ BMIter elements;
+ BMHeader *e;
+ BMOpSlot *output = BMO_GetSlot(op, slotname);
+ int totelement=0, i=0;
+
+ totelement = BM_CountFlag(bm, type, flag, 1);
+
+ if(totelement){
+ alloc_slot_buffer(op, slotname, totelement);
+
+ if (type & BM_VERT) {
+ for (e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ if(!BM_TestHFlag(e, BM_HIDDEN) && BM_TestHFlag(e, flag)) {
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+
+ if (type & BM_EDGE) {
+ for (e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ if(!BM_TestHFlag(e, BM_HIDDEN) && BM_TestHFlag(e, flag)) {
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+
+ if (type & BM_FACE) {
+ for (e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ if(!BM_TestHFlag(e, BM_HIDDEN) && BM_TestHFlag(e, flag)) {
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+ } else {
+ output->len = 0;
+ }
+}
+
+/*
+ *
+ * BMO_FLAG_TO_SLOT
+ *
+ * Copies elements of a certain type, which have a certain flag set
+ * into an output slot for an operator.
+ *
+*/
+void BMO_Flag_To_Slot(BMesh *bm, BMOperator *op, const char *slotname, int flag, int type)
+{
+ BMIter elements;
+ BMHeader *e;
+ BMOpSlot *output = BMO_GetSlot(op, slotname);
+ int totelement = BMO_CountFlag(bm, flag, type), i=0;
+
+ if(totelement){
+ alloc_slot_buffer(op, slotname, totelement);
+
+ if (type & BM_VERT) {
+ for (e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ if(BMO_TestFlag(bm, e, flag)){
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+
+ if (type & BM_EDGE) {
+ for (e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ if(BMO_TestFlag(bm, e, flag)){
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+
+ if (type & BM_FACE) {
+ for (e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
+ if(BMO_TestFlag(bm, e, flag)){
+ ((BMHeader**)output->data.p)[i] = e;
+ i++;
+ }
+ }
+ }
+ } else {
+ output->len = 0;
+ }
+}
+
+/*
+ *
+ * BMO_FLAG_BUFFER
+ *
+ * Header Flags elements in a slots buffer, automatically
+ * using the selection API where appropriate.
+ *
+*/
+
+void BMO_HeaderFlag_Buffer(BMesh *bm, BMOperator *op, const char *slotname, int flag, int type)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader **data = slot->data.p;
+ int i;
+
+ for(i = 0; i < slot->len; i++) {
+ if (!(type & data[i]->type))
+ continue;
+
+ if (flag & BM_SELECT) {
+ BM_Select(bm, data[i], 1);
+ }
+ BM_SetHFlag(data[i], flag);
+ }
+}
+
+/*
+ *
+ * BMO_FLAG_BUFFER
+ *
+ * Removes flags from elements in a slots buffer, automatically
+ * using the selection API where appropriate.
+ *
+*/
+
+void BMO_UnHeaderFlag_Buffer(BMesh *bm, BMOperator *op, const char *slotname, int flag, int type)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader **data = slot->data.p;
+ int i;
+
+ for(i = 0; i < slot->len; i++) {
+ if (!(type & data[i]->type))
+ continue;
+
+ if (flag & BM_SELECT)
+ BM_Select(bm, data[i], 0);
+ BM_ClearHFlag(data[i], flag);
+ }
+}
+
+int BMO_Vert_CountEdgeFlags(BMesh *bm, BMVert *v, int toolflag)
+{
+ BMEdge *curedge;
+ int i, len=0, count=0;
+
+ if(v->e) {
+ len = bmesh_disk_count(v);
+
+ for(i = 0, curedge=v->e; i<len; i++){
+ if (BMO_TestFlag(bm, curedge, toolflag))
+ count++;
+ curedge = bmesh_disk_nextedge(curedge, v);
+ }
+ }
+
+ return count;
+}
+
+/*
+ *
+ * BMO_FLAG_BUFFER
+ *
+ * Flags elements in a slots buffer
+ *
+*/
+
+void BMO_Flag_Buffer(BMesh *bm, BMOperator *op, const char *slotname, int flag, int type)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader **data = slot->data.p;
+ int i;
+
+ for(i = 0; i < slot->len; i++) {
+ if (!(type & data[i]->type))
+ continue;
+
+ BMO_SetFlag(bm, data[i], flag);
+ }
+}
+
+/*
+ *
+ * BMO_FLAG_BUFFER
+ *
+ * Removes flags from elements in a slots buffer
+ *
+*/
+
+void BMO_Unflag_Buffer(BMesh *bm, BMOperator *op, const char *slotname, int flag, int type)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+ BMHeader **data = slot->data.p;
+ int i;
+
+ for(i = 0; i < slot->len; i++) {
+ if (!(type & data[i]->type))
+ continue;
+
+ BMO_ClearFlag(bm, data[i], flag);
+ }
+}
+
+
+/*
+ *
+ * ALLOC/FREE FLAG LAYER
+ *
+ * Used by operator stack to free/allocate
+ * private flag data. This is allocated
+ * using a mempool so the allocation/frees
+ * should be quite fast.
+ *
+ * BMESH_TODO:
+ * Investigate not freeing flag layers until
+ * all operators have been executed. This would
+ * save a lot of realloc potentially.
+ *
+*/
+
+static void alloc_flag_layer(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+ BLI_mempool *oldpool = bm->toolflagpool; /*old flag pool*/
+ void *oldflags;
+
+ bm->totflags++;
+
+ /*allocate new flag pool*/
+ bm->toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer)*bm->totflags, 512, 512, 0, 0);
+
+ /*now go through and memcpy all the flags. Loops don't get a flag layer at this time...*/
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
+ oldflags = v->head.flags;
+ v->head.flags = BLI_mempool_calloc(bm->toolflagpool);
+ memcpy(v->head.flags, oldflags, sizeof(BMFlagLayer)*(bm->totflags-1));
+ }
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
+ oldflags = e->head.flags;
+ e->head.flags = BLI_mempool_calloc(bm->toolflagpool);
+ memcpy(e->head.flags, oldflags, sizeof(BMFlagLayer)*(bm->totflags-1));
+ }
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
+ oldflags = f->head.flags;
+ f->head.flags = BLI_mempool_calloc(bm->toolflagpool);
+ memcpy(f->head.flags, oldflags, sizeof(BMFlagLayer)*(bm->totflags-1));
+ }
+
+ BLI_mempool_destroy(oldpool);
+}
+
+static void free_flag_layer(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+ BLI_mempool *oldpool = bm->toolflagpool;
+ void *oldflags;
+
+ /*de-increment the totflags first...*/
+ bm->totflags--;
+ /*allocate new flag pool*/
+ bm->toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer)*bm->totflags, 512, 512, 1, 0);
+
+ /*now go through and memcpy all the flags*/
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
+ oldflags = v->head.flags;
+ v->head.flags = BLI_mempool_calloc(bm->toolflagpool);
+ memcpy(v->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags); /*correct?*/
+ }
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
+ oldflags = e->head.flags;
+ e->head.flags = BLI_mempool_calloc(bm->toolflagpool);
+ memcpy(e->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags);
+ }
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
+ oldflags = f->head.flags;
+ f->head.flags = BLI_mempool_calloc(bm->toolflagpool);
+ memcpy(f->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags);
+ }
+
+ BLI_mempool_destroy(oldpool);
+}
+
+static void clear_flag_layer(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ /*now go through and memcpy all the flags*/
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
+ memset(v->head.flags+(bm->totflags-1), 0, sizeof(BMFlagLayer));
+ }
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
+ memset(e->head.flags+(bm->totflags-1), 0, sizeof(BMFlagLayer));
+ }
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
+ memset(f->head.flags+(bm->totflags-1), 0, sizeof(BMFlagLayer));
+ }
+}
+
+void *BMO_FirstElem(BMOperator *op, const char *slotname)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ if (slot->slottype != BMOP_OPSLOT_ELEMENT_BUF)
+ return NULL;
+
+ return slot->data.buf ? *(void**)slot->data.buf : NULL;
+}
+
+void *BMO_IterNew(BMOIter *iter, BMesh *UNUSED(bm), BMOperator *op,
+ const char *slotname, int restrictmask)
+{
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ memset(iter, 0, sizeof(BMOIter));
+
+ iter->slot = slot;
+ iter->cur = 0;
+ iter->restrictmask = restrictmask;
+
+ if (iter->slot->slottype == BMOP_OPSLOT_MAPPING) {
+ if (iter->slot->data.ghash)
+ BLI_ghashIterator_init(&iter->giter, slot->data.ghash);
+ else return NULL;
+ }
+
+ return BMO_IterStep(iter);
+}
+
+void *BMO_IterStep(BMOIter *iter)
+{
+ if (iter->slot->slottype == BMOP_OPSLOT_ELEMENT_BUF) {
+ BMHeader *h;
+
+ if (iter->cur >= iter->slot->len) return NULL;
+
+ h = ((void**)iter->slot->data.buf)[iter->cur++];
+ while (!(iter->restrictmask & h->type)) {
+ if (iter->cur >= iter->slot->len) return NULL;
+ h = ((void**)iter->slot->data.buf)[iter->cur++];
+ }
+
+ return h;
+ } else if (iter->slot->slottype == BMOP_OPSLOT_MAPPING) {
+ struct element_mapping *map;
+ void *ret = BLI_ghashIterator_getKey(&iter->giter);
+ map = BLI_ghashIterator_getValue(&iter->giter);
+
+ iter->val = map + 1;
+
+ BLI_ghashIterator_step(&iter->giter);
+
+ return ret;
+ }
+
+ return NULL;
+}
+
+/*used for iterating over mappings*/
+void *BMO_IterMapVal(BMOIter *iter)
+{
+ return iter->val;
+}
+
+void *BMO_IterMapValp(BMOIter *iter)
+{
+ return *((void**)iter->val);
+}
+
+float BMO_IterMapValf(BMOIter *iter)
+{
+ return *((float*)iter->val);
+}
+
+/*error system*/
+typedef struct bmop_error {
+ struct bmop_error *next, *prev;
+ int errorcode;
+ BMOperator *op;
+ const char *msg;
+} bmop_error;
+
+void BMO_ClearStack(BMesh *bm)
+{
+ while (BMO_PopError(bm, NULL, NULL));
+}
+
+void BMO_RaiseError(BMesh *bm, BMOperator *owner, int errcode, const char *msg)
+{
+ bmop_error *err = MEM_callocN(sizeof(bmop_error), "bmop_error");
+
+ err->errorcode = errcode;
+ if (!msg) msg = bmop_error_messages[errcode];
+ err->msg = msg;
+ err->op = owner;
+
+ BLI_addhead(&bm->errorstack, err);
+}
+
+int BMO_HasError(BMesh *bm)
+{
+ return bm->errorstack.first != NULL;
+}
+
+/*returns error code or 0 if no error*/
+int BMO_GetError(BMesh *bm, const char **msg, BMOperator **op)
+{
+ bmop_error *err = bm->errorstack.first;
+ if (!err) return 0;
+
+ if (msg) *msg = err->msg;
+ if (op) *op = err->op;
+
+ return err->errorcode;
+}
+
+int BMO_PopError(BMesh *bm, const char **msg, BMOperator **op)
+{
+ int errorcode = BMO_GetError(bm, msg, op);
+
+ if (errorcode) {
+ bmop_error *err = bm->errorstack.first;
+
+ BLI_remlink(&bm->errorstack, bm->errorstack.first);
+ MEM_freeN(err);
+ }
+
+ return errorcode;
+}
+
+/*
+typedef struct bflag {
+ const char *str;
+ int flag;
+} bflag;
+
+#define b(f) {#f, f},
+static const char *bmesh_flags = {
+ b(BM_SELECT);
+ b(BM_SEAM);
+ b(BM_FGON);
+ b(BM_HIDDEN);
+ b(BM_SHARP);
+ b(BM_SMOOTH);
+ {NULL, 0};
+};
+
+int bmesh_str_to_flag(const char *str)
+{
+ int i;
+
+ while (bmesh_flags[i]->name) {
+ if (!strcmp(bmesh_flags[i]->name, str))
+ return bmesh_flags[i]->flag;
+ }
+
+ return -1;
+}
+*/
+
+//example:
+//BMO_CallOp(bm, "del %d %hv", DEL_ONLYFACES, BM_SELECT);
+/*
+ d - int
+ i - int
+ f - float
+ hv - header flagged verts
+ he - header flagged edges
+ hf - header flagged faces
+ fv - flagged verts
+ fe - flagged edges
+ ff - flagged faces
+
+*/
+
+#define nextc(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0)
+
+static int bmesh_name_to_slotcode(BMOpDefine *def, const char *name)
+{
+ int i;
+
+ for (i=0; def->slottypes[i].type; i++) {
+ if (!strcmp(name, def->slottypes[i].name)) return i;
+ }
+
+ return -1;
+}
+
+static int bmesh_name_to_slotcode_check(BMOpDefine *def, const char *name)
+{
+ int i = bmesh_name_to_slotcode(def, name);
+ if (i < 0) {
+ fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, name);
+ }
+
+ return i;
+}
+
+static int bmesh_opname_to_opcode(const char *opname) {
+ int i;
+
+ for (i=0; i<bmesh_total_ops; i++) {
+ if (!strcmp(opname, opdefines[i]->name)) break;
+ }
+
+ if (i == bmesh_total_ops) {
+ fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname);
+ return 0;
+ }
+
+ return i;
+}
+
+int BMO_VInitOpf(BMesh *bm, BMOperator *op, const char *_fmt, va_list vlist)
+{
+ BMOpDefine *def;
+ char *opname, *ofmt, *fmt = (char*)_fmt;
+ char slotname[64] = {0};
+ int i /*, n=strlen(fmt) */, stop /*, slotcode = -1 */, ret, type, state, c;
+ int noslot=0;
+
+ /*we muck around in here, so dup it*/
+ fmt = ofmt = strdup(fmt);
+
+ /*find operator name*/
+ i = strcspn(fmt, " \t");
+
+ opname = fmt;
+ if (!opname[i]) noslot = 1;
+ opname[i] = 0;
+
+ fmt += i + (noslot ? 0 : 1);
+
+ for (i=0; i<bmesh_total_ops; i++) {
+ if (!strcmp(opname, opdefines[i]->name)) break;
+ }
+
+ if (i == bmesh_total_ops) return 0;
+
+ BMO_Init_Op(op, opname);
+ def = opdefines[i];
+
+ i = 0;
+ state = 1; //0: not inside slotcode name, 1: inside slotcode name
+ c = 0;
+
+ while (*fmt) {
+ if (state) {
+ /*jump past leading whitespace*/
+ i = strspn(fmt, " \t");
+ fmt += i;
+
+ /*ignore trailing whitespace*/
+ if (!fmt[i])
+ break;
+
+ /*find end of slot name. currently this is
+ a little flexible, allowing "slot=%f",
+ "slot %f", "slot%f", and "slot\t%f". */
+ i = strcspn(fmt, "= \t%");
+ if (!fmt[i]) goto error;
+
+ fmt[i] = 0;
+
+ if (bmesh_name_to_slotcode_check(def, fmt) < 0) goto error;
+
+ strcpy(slotname, fmt);
+
+ state = 0;
+ fmt += i;
+ } else {
+ switch (*fmt) {
+ case ' ':
+ case '\t':
+ case '=':
+ case '%':
+ break;
+ case 'm': {
+ int size, c;
+
+ c = nextc(fmt);
+ fmt++;
+
+ if (c == '3') size = 3;
+ else if (c == '4') size = 4;
+ else goto error;
+
+ BMO_Set_Mat(op, slotname, va_arg(vlist, void*), size);
+ state = 1;
+ break;
+ }
+ case 'v': {
+ BMO_Set_Vec(op, slotname, va_arg(vlist, float*));
+ state = 1;
+ break;
+ }
+ case 'e': {
+ BMHeader *ele = va_arg(vlist, void*);
+ BMOpSlot *slot = BMO_GetSlot(op, slotname);
+
+ slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void*)*4);
+ slot->len = 1;
+ *((void**)slot->data.buf) = ele;
+
+ state = 1;
+ break;
+ }
+ case 's': {
+ BMOperator *op2 = va_arg(vlist, void*);
+ const char *slotname2 = va_arg(vlist, char*);
+
+ BMO_CopySlot(op2, op, slotname2, slotname);
+ state = 1;
+ break;
+ }
+ case 'i':
+ case 'd':
+ BMO_Set_Int(op, slotname, va_arg(vlist, int));
+ state = 1;
+ break;
+ case 'p':
+ BMO_Set_Pnt(op, slotname, va_arg(vlist, void*));
+ state = 1;
+ break;
+ case 'f':
+ case 'h':
+ case 'a':
+ type = *fmt;
+
+ if (nextc(fmt) == ' ' || nextc(fmt) == '\t' ||
+ nextc(fmt)==0)
+ {
+ BMO_Set_Float(op,slotname,va_arg(vlist,double));
+ } else {
+ ret = 0;
+ stop = 0;
+ while (1) {
+ switch (nextc(fmt)) {
+ case 'f': ret |= BM_FACE;break;
+ case 'e': ret |= BM_EDGE;break;
+ case 'v': ret |= BM_VERT;break;
+ default:
+ stop = 1;
+ break;
+ }
+ if (stop) break;
+ fmt++;
+ }
+
+ if (type == 'h')
+ BMO_HeaderFlag_To_Slot(bm, op,
+ slotname, va_arg(vlist, int), ret);
+ else if (type == 'a')
+ BMO_All_To_Slot(bm, op, slotname, ret);
+ else
+ BMO_Flag_To_Slot(bm, op, slotname,
+ va_arg(vlist, int), ret);
+ }
+
+ state = 1;
+ break;
+ default:
+ printf("unrecognized bmop format char: %c\n", *fmt);
+ break;
+ }
+ }
+ fmt++;
+ }
+
+ free(ofmt);
+ return 1;
+error:
+ BMO_Finish_Op(bm, op);
+ return 0;
+}
+
+
+int BMO_InitOpf(BMesh *bm, BMOperator *op, const char *fmt, ...) {
+ va_list list;
+
+ va_start(list, fmt);
+ if (!BMO_VInitOpf(bm, op, fmt, list)) {
+ printf("BMO_InitOpf failed\n");
+ va_end(list);
+ return 0;
+ }
+ va_end(list);
+
+ return 1;
+}
+
+int BMO_CallOpf(BMesh *bm, const char *fmt, ...) {
+ va_list list;
+ BMOperator op;
+
+ va_start(list, fmt);
+ if (!BMO_VInitOpf(bm, &op, fmt, list)) {
+ printf("BMO_CallOpf failed, format is:\n \"%s\"\n", fmt);
+ va_end(list);
+ return 0;
+ }
+
+ BMO_Exec_Op(bm, &op);
+ BMO_Finish_Op(bm, &op);
+
+ va_end(list);
+ return 1;
+}
+
+/*
+ * BMO_TOGGLEFLAG
+ *
+ * Toggles a flag for a certain element
+ *
+*/
+#ifdef BMO_ToggleFlag
+#undef BMO_ToggleFlag
+#endif
+static void BMO_ToggleFlag(BMesh *bm, void *element, int flag)
+{
+ BMHeader *head = element;
+ head->flags[bm->stackdepth-1].f ^= flag;
+}
+
+/*
+ * BMO_SETFLAG
+ *
+ * Sets a flag for a certain element
+ *
+*/
+#ifdef BMO_SetFlag
+#undef BMO_SetFlag
+#endif
+static void BMO_SetFlag(BMesh *bm, void *element, int flag)
+{
+ BMHeader *head = element;
+ head->flags[bm->stackdepth-1].f |= flag;
+}
+
+/*
+ * BMO_CLEARFLAG
+ *
+ * Clears a specific flag from a given element
+ *
+*/
+
+#ifdef BMO_ClearFlag
+#undef BMO_ClearFlag
+#endif
+static void BMO_ClearFlag(BMesh *bm, void *element, int flag)
+{
+ BMHeader *head = element;
+ head->flags[bm->stackdepth-1].f &= ~flag;
+}
+
+/*
+ * BMO_TESTFLAG
+ *
+ * Tests whether or not a flag is set for a specific element
+ *
+ *
+*/
+
+#ifdef BMO_TestFlag
+#undef BMO_TestFlag
+#endif
+static int BMO_TestFlag(BMesh *bm, void *element, int flag)
+{
+ BMHeader *head = element;
+ if(head->flags[bm->stackdepth-1].f & flag)
+ return 1;
+ return 0;
+}
diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h
new file mode 100644
index 00000000000..562eb44f3a6
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_operators_private.h
@@ -0,0 +1,79 @@
+#ifndef BM_OPERATORS_PRIVATE_H
+#define BM_OPERATORS_PRIVATE_H
+
+struct BMesh;
+struct BMOperator;
+
+void BMO_push(BMesh *bm, BMOperator *op);
+void BMO_pop(BMesh *bm);
+
+void splitop_exec(BMesh *bm, BMOperator *op);
+void spinop_exec(BMesh *bm, BMOperator *op);
+void dupeop_exec(BMesh *bm, BMOperator *op);
+void delop_exec(BMesh *bm, BMOperator *op);
+void esubdivide_exec(BMesh *bmesh, BMOperator *op);
+void edit2bmesh_exec(BMesh *bmesh, BMOperator *op);
+void bmesh2edit_exec(BMesh *bmesh, BMOperator *op);
+void triangulate_exec(BMesh *bmesh, BMOperator *op);
+void dissolvefaces_exec(BMesh *bmesh, BMOperator *op);
+void dissolveverts_exec(BMesh *bmesh, BMOperator *op);
+void bmesh_make_fgons_exec(BMesh *bmesh, BMOperator *op);
+void extrude_edge_context_exec(BMesh *bm, BMOperator *op);
+void connectverts_exec(BMesh *bm, BMOperator *op);
+void makeprim_exec(BMesh *bm, BMOperator *op);
+void extrude_vert_indiv_exec(BMesh *bm, BMOperator *op);
+void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op);
+void bmesh_to_mesh_exec(BMesh *bm, BMOperator *op);
+void bmesh_translate_exec(BMesh *bm, BMOperator *op);
+void bmesh_transform_exec(BMesh *bm, BMOperator *op);
+void bmesh_contextual_create_exec(BMesh *bm, BMOperator *op);
+void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op);
+void bmesh_rotate_exec(BMesh *bm, BMOperator *op);
+void bmesh_makevert_exec(BMesh *bm, BMOperator *op);
+void dissolveedges_exec(BMesh *bm, BMOperator *op);
+void dissolve_edgeloop_exec(BMesh *bm, BMOperator *op);
+void bmesh_weldverts_exec(BMesh *bm, BMOperator *op);
+void bmesh_removedoubles_exec(BMesh *bm, BMOperator *op);
+void bmesh_finddoubles_exec(BMesh *bm, BMOperator *op);
+void bmesh_mirror_exec(BMesh *bm, BMOperator *op);
+void esplit_exec(BMesh *bm, BMOperator *op);
+void bmesh_reversefaces_exec(BMesh *bm, BMOperator *op);
+void bmesh_edgerotate_exec(BMesh *bm, BMOperator *op);
+void bmesh_regionextend_exec(BMesh *bm, BMOperator *op);
+void bmesh_righthandfaces_exec(BMesh *bm, BMOperator *op);
+void bmesh_vertexsmooth_exec(BMesh *bm, BMOperator *op);
+void bmesh_extrude_onlyedge_exec(BMesh *bm, BMOperator *op);
+void bmesh_extrude_face_indiv_exec(BMesh *bm, BMOperator *op);
+void bmesh_collapsecon_exec(BMesh *bm, BMOperator *op);
+void bmesh_pointmerge_exec(BMesh *bm, BMOperator *op);
+void bmesh_collapse_exec(BMesh *bm, BMOperator *op);
+void bmesh_similarfaces_exec(BMesh *bm, BMOperator *op);
+void bmesh_similaredges_exec(BMesh *bm, BMOperator *op);
+void bmesh_similarverts_exec(BMesh *bm, BMOperator *op);
+void bmesh_pointmerge_facedata_exec(BMesh *bm, BMOperator *op);
+void bmesh_vert_average_facedata_exec(BMesh *bm, BMOperator *op);
+void bmesh_rotateuvs_exec(BMesh *bm, BMOperator *op);
+void object_load_bmesh_exec(BMesh *bm, BMOperator *op);
+void bmesh_reverseuvs_exec(BMesh *bm, BMOperator *op);
+void bmesh_edgenet_prepare(BMesh *bm, BMOperator *op);
+void bmesh_rotatecolors_exec(BMesh *bm, BMOperator *op);
+void bmesh_reversecolors_exec(BMesh *bm, BMOperator *op);
+void bmesh_vertexshortestpath_exec(BMesh *bm, BMOperator *op);
+void bmesh_scale_exec(BMesh *bm, BMOperator *op);
+void bmesh_edgesplitop_exec(BMesh *bm, BMOperator *op);
+void bmesh_automerge_exec(BMesh *bm, BMOperator *op);
+void bmesh_create_cone_exec(BMesh *bm, BMOperator *op);
+void bmesh_create_monkey_exec(BMesh *bm, BMOperator *op);
+void bmesh_create_icosphere_exec(BMesh *bm, BMOperator *op);
+void bmesh_create_uvsphere_exec(BMesh *bm, BMOperator *op);
+void bmesh_create_grid_exec(BMesh *bm, BMOperator *op);
+void bmesh_create_cube_exec(BMesh *bm, BMOperator *op);
+void bmesh_jointriangles_exec(BMesh *bm, BMOperator *op);
+void bmesh_bevel_exec(BMesh *bm, BMOperator *op);
+void bmesh_beautify_fill_exec(BMesh *bm, BMOperator *op);
+void bmesh_triangle_fill_exec(BMesh *bm, BMOperator *op);
+void bmesh_create_circle_exec(BMesh *bm, BMOperator *op);
+void bmesh_bridge_loops_exec(BMesh *bm, BMOperator *op);
+void bmesh_solidify_face_region_exec(BMesh *bm, BMOperator *op);
+
+#endif
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
new file mode 100644
index 00000000000..3c155844259
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -0,0 +1,968 @@
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "BKE_utildefines.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_array.h"
+#include "BLI_utildefines.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+/*
+ *
+ * BME POLYGON.C
+ *
+ * This file contains code for dealing
+ * with polygons (normal/area calculation,
+ * tesselation, ect)
+ *
+ * BMESH_TODO:
+ * -Add in Tesselator frontend that creates
+ * BMTriangles from copied faces
+ * -Add in Function that checks for and flags
+ * degenerate faces.
+ *
+*/
+
+/*
+ * TEST EDGE SIDE and POINT IN TRIANGLE
+ *
+ * Point in triangle tests stolen from scanfill.c.
+ * Used for tesselator
+ *
+*/
+
+static short testedgeside(double *v1, double *v2, double *v3)
+/* is v3 to the right of v1-v2 ? With exception: v3==v1 || v3==v2 */
+{
+ double inp;
+
+ //inp= (v2[cox]-v1[cox])*(v1[coy]-v3[coy]) +(v1[coy]-v2[coy])*(v1[cox]-v3[cox]);
+ inp= (v2[0]-v1[0])*(v1[1]-v3[1]) +(v1[1]-v2[1])*(v1[0]-v3[0]);
+
+ if(inp<0.0) return 0;
+ else if(inp==0) {
+ if(v1[0]==v3[0] && v1[1]==v3[1]) return 0;
+ if(v2[0]==v3[0] && v2[1]==v3[1]) return 0;
+ }
+ return 1;
+}
+
+static short testedgesidef(float *v1, float *v2, float *v3)
+/* is v3 to the right of v1-v2 ? With exception: v3==v1 || v3==v2 */
+{
+ double inp;
+
+ //inp= (v2[cox]-v1[cox])*(v1[coy]-v3[coy]) +(v1[coy]-v2[coy])*(v1[cox]-v3[cox]);
+ inp= (v2[0]-v1[0])*(v1[1]-v3[1]) +(v1[1]-v2[1])*(v1[0]-v3[0]);
+
+ if(inp<0.0) return 0;
+ else if(inp==0) {
+ if(v1[0]==v3[0] && v1[1]==v3[1]) return 0;
+ if(v2[0]==v3[0] && v2[1]==v3[1]) return 0;
+ }
+ return 1;
+}
+
+static int point_in_triangle(double *v1, double *v2, double *v3, double *pt)
+{
+ if(testedgeside(v1,v2,pt) && testedgeside(v2,v3,pt) && testedgeside(v3,v1,pt))
+ return 1;
+ return 0;
+}
+
+/*
+ * COMPUTE POLY NORMAL
+ *
+ * Computes the normal of a planar
+ * polygon See Graphics Gems for
+ * computing newell normal.
+ *
+*/
+#define FEQ(f1, f2) (ABS((double)(f1)-(double)(f2)) < 0.1)
+
+static void compute_poly_normal(float normal[3], float (*verts)[3], int nverts)
+{
+
+ float u[3], v[3], w[3];/*, *w, v1[3], v2[3];*/
+ float n[3]/*, l, v1[3], v2[3] */;
+ /* double l2; */
+ int i /*, s=0 */;
+
+ zero_v3(n);
+
+ /*this fixes some weird numerical error*/
+ add_v3_fl(verts[0], 0.0001f);
+
+ for(i = 0; i < nverts; i++){
+ copy_v3_v3(u, verts[i]);
+ copy_v3_v3(v, verts[(i+1) % nverts]);
+ copy_v3_v3(w, verts[(i+2) % nverts]);
+
+#if 0
+ VECSUB(v1, w, v);
+ VECSUB(v2, v, u);
+ Normalize_d(v1);
+ Normalize_d(v2);
+
+ l = INPR(v1, v2);
+ if (ABS(l-1.0) < 0.1)
+ continue;
+#endif
+ /* newell's method
+
+ so thats?:
+ (a[1] - b[1]) * (a[2] + b[2]);
+ a[1]*b[2] - b[1]*a[2] - b[1]*b[2] + a[1]*a[2]
+
+ odd. half of that is the cross product. . .what's the
+ other half?
+
+ also could be like a[1]*(b[2] + a[2]) - b[1]*(a[2] - b[2])
+ */
+
+ n[0] += (u[1] - v[1]) * (u[2] + v[2]);
+ n[1] += (u[2] - v[2]) * (u[0] + v[0]);
+ n[2] += (u[0] - v[0]) * (u[1] + v[1]);
+ }
+
+ if(normalize_v3_v3(normal, n) == 0.0f) {
+ normal[2] = 1.0f; /* other axis set to 0.0 */
+ }
+
+#if 0
+ l = len_v3(n);
+ /*fast square root, newton/babylonian method:
+ l2 = l*0.1;
+
+ l2 = (l/l2 + l2)*0.5;
+ l2 = (l/l2 + l2)*0.5;
+ l2 = (l/l2 + l2)*0.5;
+ */
+
+ if (l == 0.0) {
+ normal[0] = 0.0f;
+ normal[1] = 0.0f;
+ normal[2] = 1.0f;
+
+ return;
+ } else l = 1.0f / l;
+
+ mul_v3_fl(n, l);
+
+ copy_v3_v3(normal, n);
+#endif
+}
+
+/*
+ * COMPUTE POLY CENTER
+ *
+ * Computes the centroid and
+ * area of a polygon in the X/Y
+ * plane.
+ *
+*/
+
+static int compute_poly_center(float center[3], float *area, float (*verts)[3], int nverts)
+{
+ int i, j;
+ float atmp = 0.0, xtmp = 0.0, ytmp = 0.0, ai;
+
+ zero_v3(center);
+
+ if(nverts < 3)
+ return 0;
+
+ i = nverts-1;
+ j = 0;
+
+ while(j < nverts){
+ ai = verts[i][0] * verts[j][1] - verts[j][0] * verts[i][1];
+ atmp += ai;
+ xtmp += (verts[j][0] + verts[i][0]) * ai;
+ ytmp += (verts[j][1] + verts[i][1]) * ai;
+ i = j;
+ j += 1;
+ }
+
+ if(area)
+ *area = atmp / 2.0f;
+
+ if (atmp != 0){
+ center[0] = xtmp / (3.0f * atmp);
+ center[1] = xtmp / (3.0f * atmp);
+ return 1;
+ }
+ return 0;
+}
+
+float BM_face_area(BMFace *f)
+{
+ BMLoop *l;
+ BMIter iter;
+ float (*verts)[3], stackv[100][3];
+ float area, center[3];
+ int i;
+
+ if (f->len <= 100)
+ verts = stackv;
+ else verts = MEM_callocN(sizeof(float)*f->len*3, "bm_face_area tmp");
+
+ i = 0;
+ BM_ITER(l, &iter, NULL, BM_LOOPS_OF_FACE, f) {
+ copy_v3_v3(verts[i], l->v->co);
+ i++;
+ }
+
+ compute_poly_center(center, &area, verts, f->len);
+
+ if (f->len > 100)
+ MEM_freeN(verts);
+
+ return area;
+}
+/*
+computes center of face in 3d. uses center of bounding box.
+*/
+
+int BM_Compute_Face_Center(BMesh *bm, BMFace *f, float center[3])
+{
+ BMIter iter;
+ BMLoop *l;
+ float min[3], max[3];
+ int i;
+
+ INIT_MINMAX(min, max);
+ l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f);
+ for (i=0; l; l=BMIter_Step(&iter), i++) {
+ DO_MINMAX(l->v->co, min, max);
+ }
+
+ mid_v3_v3v3(center, min, max);
+
+ return 0;
+}
+
+/*
+ * COMPUTE POLY PLANE
+ *
+ * Projects a set polygon's vertices to
+ * a plane defined by the average
+ * of its edges cross products
+ *
+*/
+
+void compute_poly_plane(float (*verts)[3], int nverts)
+{
+
+ float avgc[3], norm[3], mag, avgn[3];
+ float *v1, *v2, *v3;
+ int i;
+
+ if(nverts < 3)
+ return;
+
+ zero_v3(avgn);
+ zero_v3(avgc);
+
+ for(i = 0; i < nverts; i++){
+ v1 = verts[i];
+ v2 = verts[(i+1) % nverts];
+ v3 = verts[(i+2) % nverts];
+ normal_tri_v3( norm,v1, v2, v3);
+
+ add_v3_v3(avgn, norm);
+ }
+
+ /*what was this bit for?*/
+ if (is_zero_v3(avgn)) {
+ avgn[0] = 0.0f;
+ avgn[1] = 0.0f;
+ avgn[2] = 1.0f;
+ } else {
+ /* XXX, why is this being divided and _then_ normalized
+ * division could be removed? - campbell */
+ avgn[0] /= nverts;
+ avgn[1] /= nverts;
+ avgn[2] /= nverts;
+ normalize_v3(avgn);
+ }
+
+ for(i = 0; i < nverts; i++){
+ v1 = verts[i];
+ mag = dot_v3v3(v1, avgn);
+ madd_v3_v3fl(v1, avgn, -mag);
+ }
+}
+
+/*
+ BM LEGAL EDGES
+
+ takes in a face and a list of edges, and sets to NULL any edge in
+ the list that bridges a concave region of the face or intersects
+ any of the faces's edges.
+*/
+#if 0 /* needs BLI math double versions of these functions */
+static void shrink_edged(double *v1, double *v2, double fac)
+{
+ double mid[3];
+
+ mid_v3_v3v3(mid, v1, v2);
+
+ sub_v3_v3v3(v1, v1, mid);
+ sub_v3_v3v3(v2, v2, mid);
+
+ mul_v3_fl(v1, fac);
+ mul_v3_fl(v2, fac);
+
+ add_v3_v3v3(v1, v1, mid);
+ add_v3_v3v3(v2, v2, mid);
+}
+#endif
+
+static void shrink_edgef(float *v1, float *v2, float fac)
+{
+ float mid[3];
+
+ mid_v3_v3v3(mid, v1, v2);
+
+ sub_v3_v3v3(v1, v1, mid);
+ sub_v3_v3v3(v2, v2, mid);
+
+ mul_v3_fl(v1, fac);
+ mul_v3_fl(v2, fac);
+
+ add_v3_v3v3(v1, v1, mid);
+ add_v3_v3v3(v2, v2, mid);
+}
+
+
+/*
+ * POLY ROTATE PLANE
+ *
+ * Rotates a polygon so that it's
+ * normal is pointing towards the mesh Z axis
+ *
+*/
+
+void poly_rotate_plane(float normal[3], float (*verts)[3], int nverts)
+{
+
+ float up[3] = {0.0f,0.0f,1.0f}, axis[3], q[4];
+ float mat[3][3];
+ double angle;
+ int i;
+
+ cross_v3_v3v3(axis, normal, up);
+
+ angle = saacos(dot_v3v3(normal, up));
+
+ if (angle == 0.0) return;
+
+ axis_angle_to_quat(q, axis, (float)angle);
+ quat_to_mat3(mat, q);
+
+ for(i = 0; i < nverts; i++)
+ mul_m3_v3(mat, verts[i]);
+}
+
+/*
+ * BMESH UPDATE FACE NORMAL
+ *
+ * Updates the stored normal for the
+ * given face. Requires that a buffer
+ * of sufficient length to store projected
+ * coordinates for all of the face's vertices
+ * is passed in as well.
+ *
+*/
+
+void BM_Face_UpdateNormal(BMesh *bm, BMFace *f)
+{
+ float projverts[200][3];
+ float (*proj)[3] = f->len < 200 ? projverts : MEM_mallocN(sizeof(float)*f->len*3, "projvertsn");
+ BMIter iter;
+ BMLoop *l;
+ int i=0;
+
+ if (f->len < 3) return;
+
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ copy_v3_v3(proj[i], l->v->co);
+ i += 1;
+ }
+
+ bmesh_update_face_normal(bm, f, proj);
+
+ if (projverts != proj) MEM_freeN(proj);
+}
+
+void BM_Edge_UpdateNormals(BMesh *bm, BMEdge *e)
+{
+ BMIter iter;
+ BMFace *f;
+
+ f = BMIter_New(&iter, bm, BM_FACES_OF_EDGE, e);
+ for (; f; f=BMIter_Step(&iter)) {
+ BM_Face_UpdateNormal(bm, f);
+ }
+
+ BM_Vert_UpdateNormal(bm, e->v1);
+ BM_Vert_UpdateNormal(bm, e->v2);
+}
+
+void BM_Vert_UpdateNormal(BMesh *bm, BMVert *v)
+{
+ BMIter eiter, liter;
+ BMEdge *e;
+ BMLoop *l;
+ float vec1[3], vec2[3], fac;
+ int len=0;
+
+ zero_v3(v->no);
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_EDGE, e) {
+ if (l->v == v) {
+ /* Same calculation used in BM_Compute_Normals */
+ sub_v3_v3v3(vec1, l->v->co, l->prev->v->co);
+ sub_v3_v3v3(vec2, l->next->v->co, l->v->co);
+ normalize_v3(vec1);
+ normalize_v3(vec2);
+
+ fac = saacos(-dot_v3v3(vec1, vec2));
+
+ madd_v3_v3fl(v->no, l->f->no, fac);
+
+ len++;
+ }
+ }
+ }
+
+ if (len) {
+ normalize_v3(v->no);
+ }
+}
+
+void BM_Vert_UpdateAllNormals(BMesh *bm, BMVert *v)
+{
+ BMIter iter;
+ BMFace *f;
+ int len=0;
+
+ f = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v);
+ for (; f; f=BMIter_Step(&iter), len++) {
+ BM_Face_UpdateNormal(bm, f);
+ }
+
+ BM_Vert_UpdateNormal(bm, v);
+}
+
+void bmesh_update_face_normal(BMesh *bm, BMFace *f, float (*projectverts)[3])
+{
+ BMIter iter;
+ BMLoop *l;
+ int i;
+
+ if(f->len > 4) {
+ i = 0;
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ copy_v3_v3(projectverts[i], l->v->co);
+ l = l->next;
+ i += 1;
+ }
+
+ compute_poly_normal(f->no, projectverts, f->len);
+ }
+ else if(f->len == 3){
+ BMVert *v1, *v2, *v3;
+ v1 = bm_firstfaceloop(f)->v;
+ v2 = bm_firstfaceloop(f)->next->v;
+ v3 = bm_firstfaceloop(f)->next->next->v;
+ normal_tri_v3( f->no,v1->co, v2->co, v3->co);
+ }
+ else if(f->len == 4){
+ BMVert *v1, *v2, *v3, *v4;
+ v1 = bm_firstfaceloop(f)->v;
+ v2 = bm_firstfaceloop(f)->next->v;
+ v3 = bm_firstfaceloop(f)->next->next->v;
+ v4 = bm_firstfaceloop(f)->prev->v;
+ normal_quad_v3( f->no,v1->co, v2->co, v3->co, v4->co);
+ }
+ else{ /*horrible, two sided face!*/
+ zero_v3(f->no);
+ }
+
+}
+
+
+/*
+ * BMESH FLIP NORMAL
+ *
+ * Reverses the winding of a face.
+ * Note that this updates the calculated
+ * normal.
+*/
+void BM_flip_normal(BMesh *bm, BMFace *f)
+{
+ bmesh_loop_reverse(bm, f);
+ mul_v3_fl(f->no, -1.0f);
+}
+
+/* detects if two line segments cross each other (intersects).
+ note, there could be more winding cases then there needs to be. */
+static int linecrosses(double *v1, double *v2, double *v3, double *v4)
+{
+ int w1, w2, w3, w4, w5;
+
+ /*w1 = winding(v1, v3, v4);
+ w2 = winding(v2, v3, v4);
+ w3 = winding(v3, v1, v2);
+ w4 = winding(v4, v1, v2);
+
+ return (w1 == w2) && (w3 == w4);*/
+
+ w1 = testedgeside(v1, v3, v2);
+ w2 = testedgeside(v2, v4, v1);
+ w3 = !testedgeside(v1, v2, v3);
+ w4 = testedgeside(v3, v2, v4);
+ w5 = !testedgeside(v3, v1, v4);
+ return w1 == w2 && w2 == w3 && w3 == w4 && w4==w5;
+}
+
+/* detects if two line segments cross each other (intersects).
+ note, there could be more winding cases then there needs to be. */
+static int linecrossesf(float *v1, float *v2, float *v3, float *v4)
+{
+ int w1, w2, w3, w4, w5 /*, ret*/;
+ float mv1[2], mv2[2], mv3[2], mv4[2];
+
+ /*now test winding*/
+ w1 = testedgesidef(v1, v3, v2);
+ w2 = testedgesidef(v2, v4, v1);
+ w3 = !testedgesidef(v1, v2, v3);
+ w4 = testedgesidef(v3, v2, v4);
+ w5 = !testedgesidef(v3, v1, v4);
+
+ if (w1 == w2 && w2 == w3 && w3 == w4 && w4==w5)
+ return 1;
+
+#define GETMIN2_AXIS(a, b, ma, mb, axis) ma[axis] = MIN2(a[axis], b[axis]), mb[axis] = MAX2(a[axis], b[axis])
+#define GETMIN2(a, b, ma, mb) GETMIN2_AXIS(a, b, ma, mb, 0); GETMIN2_AXIS(a, b, ma, mb, 1);
+
+ GETMIN2(v1, v2, mv1, mv2);
+ GETMIN2(v3, v4, mv3, mv4);
+
+ /*do an interval test on the x and y axes*/
+ /*first do x axis*/
+ #define T FLT_EPSILON*15
+ if (ABS(v1[1]-v2[1]) < T && ABS(v3[1]-v4[1]) < T &&
+ ABS(v1[1]-v3[1]) < T)
+ {
+ return (mv4[0] >= mv1[0] && mv3[0] <= mv2[0]);
+ }
+
+ /*now do y axis*/
+ if (ABS(v1[0]-v2[0]) < T && ABS(v3[0]-v4[0]) < T &&
+ ABS(v1[0]-v3[0]) < T)
+ {
+ return (mv4[1] >= mv1[1] && mv3[1] <= mv2[1]);
+ }
+
+ return 0;
+}
+
+/*
+ BM POINT IN FACE
+
+ Projects co onto face f, and returns true if it is inside
+ the face bounds. Note that this uses a best-axis projection
+ test, instead of projecting co directly into f's orientation
+ space, so there might be accuracy issues.
+*/
+int BM_Point_In_Face(BMesh *bm, BMFace *f, float co[3])
+{
+ int xn, yn, zn, ax, ay;
+ float co2[3], cent[3] = {0.0f, 0.0f, 0.0f}, out[3] = {FLT_MAX*0.5f, FLT_MAX*0.5f, 0};
+ BMLoop *l;
+ int crosses = 0;
+ float eps = 1.0f+(float)FLT_EPSILON*150.0f;
+
+ if (dot_v3v3(f->no, f->no) <= FLT_EPSILON*10)
+ BM_Face_UpdateNormal(bm, f);
+
+ /* find best projection of face XY, XZ or YZ: barycentric weights of
+ the 2d projected coords are the same and faster to compute
+
+ this probably isn't all that accurate, but it has the advantage of
+ being fast (especially compared to projecting into the face orientation)
+ */
+ xn= (float)fabs(f->no[0]);
+ yn= (float)fabs(f->no[1]);
+ zn= (float)fabs(f->no[2]);
+ if(zn>=xn && zn>=yn) {ax= 0; ay= 1;}
+ else if(yn>=xn && yn>=zn) {ax= 0; ay= 2;}
+ else {ax= 1; ay= 2;}
+
+ co2[0] = co[ax];
+ co2[1] = co[ay];
+ co2[2] = 0;
+
+ l = bm_firstfaceloop(f);
+ do {
+ cent[0] += l->v->co[ax];
+ cent[1] += l->v->co[ay];
+ l = l->next;
+ } while (l != bm_firstfaceloop(f));
+
+ mul_v2_fl(cent, 1.0f/(float)f->len);
+
+ l = bm_firstfaceloop(f);
+ do {
+ float v1[3], v2[3];
+
+ v1[0] = (l->prev->v->co[ax] - cent[ax])*eps + cent[ax];
+ v1[1] = (l->prev->v->co[ay] - cent[ay])*eps + cent[ay];
+ v1[2] = 0.0f;
+
+ v2[0] = (l->v->co[ax] - cent[ax])*eps + cent[ax];
+ v2[1] = (l->v->co[ay] - cent[ay])*eps + cent[ay];
+ v2[2] = 0.0f;
+
+ crosses += linecrossesf(v1, v2, co2, out) != 0;
+
+ l = l->next;
+ } while (l != bm_firstfaceloop(f));
+
+ return crosses%2 != 0;
+}
+
+static int goodline(float (*projectverts)[3], BMFace *f, int v1i,
+ int v2i, int v3i, int UNUSED(nvert)) {
+ BMLoop *l = bm_firstfaceloop(f);
+ double v1[3], v2[3], v3[3], pv1[3], pv2[3];
+ int i;
+
+ VECCOPY(v1, projectverts[v1i]);
+ VECCOPY(v2, projectverts[v2i]);
+ VECCOPY(v3, projectverts[v3i]);
+
+ if (testedgeside(v1, v2, v3)) return 0;
+
+ //for (i=0; i<nvert; i++) {
+ do {
+ i = BM_GetIndex(l->v);
+ if (i == v1i || i == v2i || i == v3i) {
+ l = l->next;
+ continue;
+ }
+
+ VECCOPY(pv1, projectverts[BM_GetIndex(l->v)]);
+ VECCOPY(pv2, projectverts[BM_GetIndex(l->next->v)]);
+
+ //if (linecrosses(pv1, pv2, v1, v3)) return 0;
+ if (point_in_triangle(v1, v2, v3, pv1)) return 0;
+ if (point_in_triangle(v3, v2, v1, pv1)) return 0;
+
+ l = l->next;
+ } while (l != bm_firstfaceloop(f));
+ return 1;
+}
+/*
+ * FIND EAR
+ *
+ * Used by tesselator to find
+ * the next triangle to 'clip off'
+ * of a polygon while tesselating.
+ *
+*/
+
+static BMLoop *find_ear(BMesh *UNUSED(bm), BMFace *f, float (*verts)[3],
+ int nvert)
+{
+ BMVert *v1, *v2, *v3;
+ BMLoop *bestear = NULL, *l;
+ /*float angle, bestangle = 180.0f;*/
+ int isear /*, i=0*/;
+
+ l = bm_firstfaceloop(f);
+ do {
+ isear = 1;
+
+ v1 = l->prev->v;
+ v2 = l->v;
+ v3 = l->next->v;
+
+ if (BM_Edge_Exist(v1, v3)) isear = 0;
+
+ if (isear && !goodline(verts, f, BM_GetIndex(v1), BM_GetIndex(v2),
+ BM_GetIndex(v3), nvert))
+ isear = 0;
+
+ if(isear) {
+ /*angle = angle_v3v3v3(verts[v1->head.eflag2], verts[v2->head.eflag2], verts[v3->head.eflag2]);
+ if(!bestear || ABS(angle-45.0f) < bestangle) {
+ bestear = l;
+ bestangle = ABS(45.0f-angle);
+ }
+
+ if (angle > 20 && angle < 90) break;
+ if (angle < 100 && i > 5) break;
+ i += 1;*/
+ bestear = l;
+ break;
+ }
+ l = l->next;
+ }
+ while(l != bm_firstfaceloop(f));
+
+ return bestear;
+}
+
+/*
+ * BMESH TRIANGULATE FACE
+ *
+ * Triangulates a face using a
+ * simple 'ear clipping' algorithm
+ * that tries to favor non-skinny
+ * triangles (angles less than
+ * 90 degrees). If the triangulator
+ * has bits left over (or cannot
+ * triangulate at all) it uses a
+ * simple fan triangulation
+ *
+ * newfaces, if non-null, must be an array of BMFace pointers,
+ * with a length equal to f->len. it will be filled with the new
+ * triangles, and will be NULL-terminated.
+*/
+void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3],
+ int newedgeflag, int newfaceflag, BMFace **newfaces)
+{
+ int i, done, nvert, nf_i = 0;
+ BMLoop *l, *newl, *nextloop;
+ BMVert *v;
+
+ /*copy vertex coordinates to vertspace array*/
+ i = 0;
+ l = bm_firstfaceloop(f);
+ do{
+ copy_v3_v3(projectverts[i], l->v->co);
+ BM_SetIndex(l->v, i);
+ i++;
+ l = l->next;
+ }while(l != bm_firstfaceloop(f));
+
+ ///bmesh_update_face_normal(bm, f, projectverts);
+
+ compute_poly_normal(f->no, projectverts, f->len);
+ poly_rotate_plane(f->no, projectverts, i);
+
+ nvert = f->len;
+
+ //compute_poly_plane(projectverts, i);
+ for (i=0; i<nvert; i++) {
+ projectverts[i][2] = 0.0f;
+ }
+
+ done = 0;
+ while(!done && f->len > 3){
+ done = 1;
+ l = find_ear(bm, f, projectverts, nvert);
+ if(l) {
+ done = 0;
+ v = l->v;
+ f = BM_Split_Face(bm, l->f, l->prev->v,
+ l->next->v,
+ &newl, NULL);
+ copy_v3_v3(f->no, l->f->no);
+
+ if (!f) {
+ fprintf(stderr, "%s: triangulator failed to split face! (bmesh internal error)\n", __func__);
+ break;
+ }
+
+ BMO_SetFlag(bm, newl->e, newedgeflag);
+ BMO_SetFlag(bm, f, newfaceflag);
+
+ if (newfaces) newfaces[nf_i++] = f;
+
+ /*l = f->loopbase;
+ do {
+ if (l->v == v) {
+ f->loopbase = l;
+ break;
+ }
+ l = l->next;
+ } while (l != f->loopbase);*/
+ }
+ }
+
+ if (f->len > 3){
+ l = bm_firstfaceloop(f);
+ while (l->f->len > 3){
+ nextloop = l->next->next;
+ f = BM_Split_Face(bm, l->f, l->v, nextloop->v,
+ &newl, NULL);
+ if (!f) {
+ printf("triangle fan step of triangulator failed.\n");
+
+ /*NULL-terminate*/
+ if (newfaces) newfaces[nf_i] = NULL;
+ return;
+ }
+
+ if (newfaces) newfaces[nf_i++] = f;
+
+ BMO_SetFlag(bm, newl->e, newedgeflag);
+ BMO_SetFlag(bm, f, newfaceflag);
+ l = nextloop;
+ }
+ }
+
+ /*NULL-terminate*/
+ if (newfaces) newfaces[nf_i] = NULL;
+}
+
+/*each pair of loops defines a new edge, a split. this function goes
+ through and sets pairs that are geometrically invalid to null. a
+ split is invalid, if it forms a concave angle or it intersects other
+ edges in the face, or it intersects another split. in the case of
+ intersecting splits, only the first of the set of intersecting
+ splits survives.*/
+void BM_LegalSplits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
+{
+ BMIter iter;
+ BMLoop *l;
+ float v1[3], v2[3], v3[3]/*, v4[3]*/, no[3], mid[3], *p1, *p2, *p3, *p4;
+ float out[3] = {-234324.0f, -234324.0f, 0.0f};
+ float projectverts[100][3];
+ float edgevertsstack[200][3];
+ float (*projverts)[3] = projectverts;
+ float (*edgeverts)[3] = edgevertsstack;
+ float fac1 = 1.0000001f, fac2 = 0.9f; //9999f; //0.999f;
+ int i, j, a=0, clen;
+
+ if (f->len > 100) projverts = MEM_mallocN(sizeof(float)*3*f->len, "projvertsb");
+ if (len > 100) edgeverts = MEM_mallocN(sizeof(float)*3*2*len, "edgevertsb");
+
+ i = 0;
+ l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f);
+ for (; l; l=BMIter_Step(&iter)) {
+ BM_SetIndex(l, i);
+ copy_v3_v3(projverts[i], l->v->co);
+ i++;
+ }
+
+ for (i=0; i<len; i++) {
+ copy_v3_v3(v1, loops[i][0]->v->co);
+ copy_v3_v3(v2, loops[i][1]->v->co);
+
+ shrink_edgef(v1, v2, fac2);
+
+ copy_v3_v3(edgeverts[a], v1);
+ a++;
+ copy_v3_v3(edgeverts[a], v2);
+ a++;
+ }
+
+ compute_poly_normal(no, projverts, f->len);
+ poly_rotate_plane(no, projverts, f->len);
+ poly_rotate_plane(no, edgeverts, len*2);
+
+ l = bm_firstfaceloop(f);
+ for (i=0; i<f->len; i++) {
+ p1 = projverts[i];
+ out[0] = MAX2(out[0], p1[0]) + 0.01f;
+ out[1] = MAX2(out[1], p1[1]) + 0.01f;
+ out[2] = 0.0f;
+ p1[2] = 0.0f;
+
+ //copy_v3_v3(l->v->co, p1);
+
+ l = l->next;
+ }
+
+ for (i=0; i<len; i++) {
+ edgeverts[i*2][2] = 0.0f;
+ edgeverts[i*2+1][2] = 0.0f;
+ }
+
+ /*do convexity test*/
+ for (i=0; i<len; i++) {
+ copy_v3_v3(v2, edgeverts[i*2]);
+ copy_v3_v3(v3, edgeverts[i*2+1]);
+
+ mid_v3_v3v3(mid, v2, v3);
+
+ clen = 0;
+ for (j=0; j<f->len; j++) {
+ p1 = projverts[j];
+ p2 = projverts[(j+1)%f->len];
+
+ copy_v3_v3(v1, p1);
+ copy_v3_v3(v2, p2);
+
+ shrink_edgef(v1, v2, fac1);
+
+ if (linecrossesf(p1, p2, mid, out)) clen++;
+ }
+
+ if (clen%2 == 0) {
+ loops[i][0] = NULL;
+ }
+ }
+
+ /*do line crossing tests*/
+ for (i=0; i<f->len; i++) {
+ p1 = projverts[i];
+ p2 = projverts[(i+1)%f->len];
+
+ copy_v3_v3(v1, p1);
+ copy_v3_v3(v2, p2);
+
+ shrink_edgef(v1, v2, fac1);
+
+ for (j=0; j<len; j++) {
+ if (!loops[j][0]) continue;
+
+ p3 = edgeverts[j*2];
+ p4 = edgeverts[j*2+1];
+
+ if (linecrossesf(v1, v2, p3, p4))
+ {
+ loops[j][0] = NULL;
+ }
+ }
+ }
+
+ for (i=0; i<len; i++) {
+ for (j=0; j<len; j++) {
+ if (j == i) continue;
+ if (!loops[i][0]) continue;
+ if (!loops[j][0]) continue;
+
+ p1 = edgeverts[i*2];
+ p2 = edgeverts[i*2+1];
+ p3 = edgeverts[j*2];
+ p4 = edgeverts[j*2+1];
+
+ copy_v3_v3(v1, p1);
+ copy_v3_v3(v2, p2);
+
+ shrink_edgef(v1, v2, fac1);
+
+ if (linecrossesf(v1, v2, p3, p4)) {
+ loops[i][0]=NULL;
+ }
+ }
+ }
+
+ if (projverts != projectverts) MEM_freeN(projverts);
+ if (edgeverts != edgevertsstack) MEM_freeN(edgeverts);
+}
diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h
new file mode 100644
index 00000000000..0986c491817
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_private.h
@@ -0,0 +1,98 @@
+/**
+ * bmesh_private.h jan 2007
+ *
+ * Private function prototypes for bmesh public API.
+ * This file is a grab-bag of functions from various
+ * parts of the bmesh internals.
+ *
+ *
+ * $Id: BKE_bmesh.h,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BMESH_PRIVATE_H
+#define BMESH_PRIVATE_H
+
+#include "bmesh.h"
+struct Link;
+struct BMLoop;
+
+/*returns positive nonzero on error*/
+int bmesh_check_element(BMesh *bm, void *element, int type);
+
+#define CHECK_ELEMENT(bm, el) \
+if (bmesh_check_element(bm, el, ((BMHeader*)el)->type))\
+ printf("check_element failure, with code %i on line %i in file\n \"%s\"\n\n", bmesh_check_element(bm, el, ((BMHeader*)el)->type), __LINE__, __FILE__);
+
+#define bm_get_edge_link(e, v) (((v) == ((BMEdge*)(e))->v1) ? (Link*)&(((BMEdge*)(e))->dlink1) : (Link*)&(((BMEdge*)(e))->dlink2))
+
+int bmesh_radial_length(struct BMLoop *l);
+int bmesh_disk_count(BMVert *v);
+
+/*internal selection flushing*/
+void bmesh_selectmode_flush(struct BMesh *bm);
+
+/*internal filter API*/
+void *bmesh_get_filter_callback(int type);
+int bmesh_get_filter_argtype(int type);
+
+/*NOTE: ensure different parts of the API do not conflict
+ on using these internal flags!*/
+#define _FLAG_JF 1 /*join faces*/
+#define _FLAG_SF 2 /*split faces*/
+#define _FLAG_MF 4 /*make face*/
+
+#define bmesh_api_setflag(element, f) (((BMHeader*)(element))->flags[0].pflag |= (f))
+#define bmesh_api_getflag(element, f) (((BMHeader*)(element))->flags[0].pflag & (f))
+#define bmesh_api_clearflag(element, f) (((BMHeader*)(element))->flags[0].pflag &= ~(f))
+#define bmesh_api_setindex(element, i) (((BMHeader*)(element))->flags[0].index = (i))
+#define bmesh_api_getindex(element) (((BMHeader*)(element))->flags[0].index + 0)
+
+/*Polygon Utilities ? FIXME... where do these each go?*/
+/*newedgeflag sets a flag layer flag, obviously not the header flag.*/
+void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3],
+ int newedgeflag, int newfaceflag, BMFace **newfaces);
+void bmesh_update_face_normal(struct BMesh *bm, struct BMFace *f,
+ float (*projectverts)[3]);
+void compute_poly_plane(float (*verts)[3], int nverts);
+void poly_rotate_plane(float normal[3], float (*verts)[3], int nverts);
+void bmesh_flip_normal(struct BMesh *bm, struct BMFace *f);
+
+/*Error reporting. Shouldnt be called by tools ever.*/
+void BME_error(void);
+
+BMEdge *bmesh_disk_next(BMEdge *e, BMVert *v);
+BMEdge *bmesh_disk_prev(BMEdge *e, BMVert *v);
+
+/*include the rest of our private declarations*/
+#include "bmesh_structure.h"
+#include "bmesh_operators_private.h"
+
+#endif
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
new file mode 100644
index 00000000000..2e71f61de00
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -0,0 +1,540 @@
+#include <string.h>
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_math.h"
+#include "BLI_array.h"
+#include "BLI_utildefines.h"
+
+#define BM_OVERLAP (1<<13)
+
+/*
+ * BM_QUERIES.C
+ *
+ * This file contains functions for answering common
+ * Topological and geometric queries about a mesh, such
+ * as, "What is the angle between these two faces?" or,
+ * "How many faces are incident upon this vertex?" Tool
+ * authors should use the functions in this file instead
+ * of inspecting the mesh structure directly.
+ *
+*/
+
+/*
+ * BMESH COUNT ELEMENT
+ *
+ * Return the amount of element of
+ * type 'type' in a given bmesh.
+ *
+ *
+*/
+
+int BM_Count_Element(BMesh *bm, int type)
+{
+ if(type == BM_VERT) return bm->totvert;
+ else if(type == BM_EDGE) return bm->totedge;
+ else if(type == BM_FACE) return bm->totface;
+
+ return 0;
+}
+
+
+/*
+ * BMESH VERT IN EDGE
+ *
+ * Returns whether or not a given vertex is
+ * is part of a given edge.
+ *
+*/
+
+int BM_Vert_In_Edge(BMEdge *e, BMVert *v)
+{
+ return bmesh_vert_in_edge(e, v);
+}
+
+/*
+ * BMESH OTHER EDGE IN FACE SHARING A VERTEX
+ *
+ * Returns an opposing loop that shares the same face.
+ *
+*/
+
+BMLoop *BM_OtherFaceLoop(BMEdge *e, BMFace *f, BMVert *v)
+{
+ BMLoop *l = bm_firstfaceloop(f) /*, *l2, *l3*/;
+ int found = 0;
+
+ do {
+ if (l->e == e) break;
+ found = 1;
+ l = l->next;
+ } while (l != bm_firstfaceloop(f));
+
+ return l->v == v ? l->prev : l->next;
+}
+
+/*
+ * BMESH VERT IN FACE
+ *
+ * Returns whether or not a given vertex is
+ * is part of a given face.
+ *
+*/
+
+int BM_Vert_In_Face(BMFace *f, BMVert *v)
+{
+ BMLoopList *lst;
+ BMLoop *l;
+
+ for (lst=f->loops.first; lst; lst=lst->next) {
+ l = lst->first;
+ do {
+ if(l->v == v) return 1;
+ l = l->next;
+ } while (l != lst->first);
+ }
+
+ return 0;
+}
+
+/*
+ * BMESH VERTS IN FACE
+ *
+ * Compares the number of vertices in an array
+ * that appear in a given face
+ *
+*/
+int BM_Verts_In_Face(BMesh *bm, BMFace *f, BMVert **varr, int len)
+{
+ BMLoopList *lst;
+ BMLoop *curloop = NULL;
+ int i, count = 0;
+
+ for(i=0; i < len; i++) BMO_SetFlag(bm, varr[i], BM_OVERLAP);
+
+ for (lst=f->loops.first; lst; lst=lst->next) {
+ curloop = lst->first;
+
+ do {
+ if(BMO_TestFlag(bm, curloop->v, BM_OVERLAP))
+ count++;
+
+ curloop = curloop->next;
+ } while (curloop != lst->first);
+ }
+
+ for(i=0; i < len; i++) BMO_ClearFlag(bm, varr[i], BM_OVERLAP);
+
+ return count;
+}
+
+/*
+ * BMESH EDGE IN FACE
+ *
+ * Returns whether or not a given edge is
+ * is part of a given face.
+ *
+*/
+
+int BM_Edge_In_Face(BMFace *f, BMEdge *e)
+{
+ BMLoop *l;
+
+ l = bm_firstfaceloop(f);
+ do{
+
+ if(l->e == e) return 1;
+ l = l->next;
+ }while(l != bm_firstfaceloop(f));
+
+ return 0;
+}
+
+/*
+ * BMESH VERTS IN EDGE
+ *
+ * Returns whether or not two vertices are in
+ * a given edge
+ *
+*/
+
+int BM_Verts_In_Edge(BMVert *v1, BMVert *v2, BMEdge *e)
+{
+ return bmesh_verts_in_edge(v1,v2,e);
+}
+
+/*
+ * BMESH GET OTHER EDGEVERT
+ *
+ * Given a edge and one of its vertices, returns
+ * the other vertex.
+ *
+*/
+
+BMVert *BM_OtherEdgeVert(BMEdge *e, BMVert *v)
+{
+ return bmesh_edge_getothervert(e,v);
+}
+
+/*
+ * BMESH VERT EDGECOUNT
+ *
+ * Returns the number of edges around this vertex.
+ */
+
+int BM_Vert_EdgeCount(BMVert *v)
+{
+ return bmesh_disk_count(v);
+}
+
+/**
+ * BMESH EDGE FACECOUNT
+ *
+ * Returns the number of faces around this edge
+*/
+
+int BM_Edge_FaceCount(BMEdge *e)
+{
+ int count = 0;
+ BMLoop *curloop = NULL;
+
+ if(e->l){
+ curloop = e->l;
+ do{
+ count++;
+ curloop = bmesh_radial_nextloop(curloop);
+ }while(curloop != e->l);
+ }
+
+ return count;
+}
+
+/**
+ * BMESH VERT FACECOUNT
+ *
+ * Returns the number of faces around this vert
+*/
+
+int BM_Vert_FaceCount(BMVert *v){
+ int count = 0;
+ BMLoop *l;
+ BMIter iter;
+
+ BM_ITER(l, &iter, NULL, BM_LOOPS_OF_VERT, v)
+ count++;
+
+ return count;
+#if 0 //this code isn't working
+ BMEdge *curedge = NULL;
+
+ if(v->e){
+ curedge = v->e;
+ do{
+ if(curedge->l) count += BM_Edge_FaceCount(curedge);
+ curedge = bmesh_disk_nextedge(curedge,v);
+ }while(curedge != v->e);
+ }
+ return count;
+#endif
+}
+
+/**
+ * BMESH WIRE VERT
+ *
+ * Tests whether or not the vertex is part of a wire edge.
+ * (ie: has no faces attached to it)
+ *
+ * Returns -
+ * 1 for true, 0 for false.
+ */
+
+int BM_Wire_Vert(BMesh *UNUSED(bm), BMVert *v)
+{
+ BMEdge *curedge;
+
+ if(!(v->e)) return 0;
+
+ curedge = v->e;
+ do{
+ if(curedge->l) return 0;
+ curedge = bmesh_disk_nextedge(curedge, v);
+ }while(curedge != v->e);
+
+ return 1;
+}
+
+/**
+ * BMESH WIRE EDGE
+ *
+ * Tests whether or not the edge is part of a wire.
+ * (ie: has no faces attached to it)
+ *
+ * Returns -
+ * 1 for true, 0 for false.
+ */
+
+int BM_Wire_Edge(BMesh *UNUSED(bm), BMEdge *e)
+{
+ if(e->l) return 0;
+ return 1;
+}
+
+/**
+ * BMESH NONMANIFOLD VERT
+ *
+ * A vertex is non-manifold if it meets the following conditions:
+ * 1: Loose - (has no edges/faces incident upon it)
+ * 2: Joins two distinct regions - (two pyramids joined at the tip)
+ * 3: Is part of a non-manifold edge (edge with more than 2 faces)
+ * 4: Is part of a wire edge
+ *
+ * Returns -
+ * 1 for true, 0 for false.
+ */
+
+int BM_Nonmanifold_Vert(BMesh *UNUSED(bm), BMVert *v) {
+ BMEdge *e, *oe;
+ BMLoop *l;
+ int len, count, flag;
+
+ if (v->e == NULL) {
+ /* loose vert */
+ return 1;
+ }
+
+ /* count edges while looking for non-manifold edges */
+ oe = v->e;
+ for (len=0,e=v->e; e != oe || (e == oe && len == 0); len++,e=bmesh_disk_nextedge(e,v)) {
+ if (e->l == NULL) {
+ /* loose edge */
+ return 1;
+ }
+
+ if (bmesh_radial_length(e->l) > 2) {
+ /* edge shared by more than two faces */
+ return 1;
+ }
+ }
+
+ count = 1;
+ flag = 1;
+ e = NULL;
+ oe = v->e;
+ l = oe->l;
+ while(e != oe) {
+ l = (l->v == v) ? l->prev : l->next;
+ e = l->e;
+ count++; /* count the edges */
+
+ if (flag && l->radial_next == l) {
+ /* we've hit the edge of an open mesh, reset once */
+ flag = 0;
+ count = 1;
+ oe = e;
+ e = NULL;
+ l = oe->l;
+ }
+ else if (l->radial_next == l) {
+ /* break the loop */
+ e = oe;
+ }
+ else {
+ l = l->radial_next;
+ }
+ }
+
+ if (count < len) {
+ /* vert shared by multiple regions */
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * BMESH NONMANIFOLD EDGE
+ *
+ * Tests whether or not this edge is manifold.
+ * A manifold edge either has 1 or 2 faces attached
+ * to it.
+ *
+ * Returns -
+ * 1 for true, 0 for false.
+ */
+
+int BM_Nonmanifold_Edge(BMesh *UNUSED(bm), BMEdge *e)
+{
+ int count = BM_Edge_FaceCount(e);
+ if(count != 2 && count != 1) return 1;
+ return 0;
+}
+
+/**
+ * BMESH BOUNDARY EDGE
+ *
+ * Tests whether or not an edge is on the boundary
+ * of a shell (has one face associated with it)
+ *
+ * Returns -
+ * 1 for true, 0 for false.
+ */
+
+int BM_Boundary_Edge(BMEdge *e)
+{
+ int count = BM_Edge_FaceCount(e);
+ if(count == 1) return 1;
+ return 0;
+}
+
+/**
+ * BMESH FACE SHAREDEDGES
+ *
+ * Counts the number of edges two faces share (if any)
+ *
+ * BMESH_TODO:
+ * Move this to structure, and wrap.
+ *
+ * Returns -
+ * Integer
+ */
+
+int BM_Face_Sharededges(BMFace *f1, BMFace *f2){
+ BMLoop *l;
+ int count = 0;
+
+ l = bm_firstfaceloop(f1);
+ do{
+ if(bmesh_radial_find_face(l->e,f2)) count++;
+ l = l->next;
+ }while(l != bm_firstfaceloop(f1));
+
+ return count;
+}
+
+/**
+ *
+ * BMESH EDGE SHARE FACES
+ *
+ * Tests to see if e1 shares any faces with e2
+ *
+*/
+
+int BM_Edge_Share_Faces(BMEdge *e1, BMEdge *e2)
+{
+ BMLoop *l;
+ BMFace *f;
+
+ if(e1->l && e2->l){
+ l = e1->l;
+ do{
+ f = l->f;
+ if(bmesh_radial_find_face(e2,f)){
+ return 1;
+ }
+ l = l->radial_next;
+ }while(l != e1->l);
+ }
+ return 0;
+}
+
+
+
+/**
+ * BMESH FACE ANGLE
+ *
+ * Calculates the angle between two faces. Assumes
+ * That face normals are correct.
+ *
+ * Returns -
+ * Float.
+ */
+
+float BM_Face_Angle(BMesh *UNUSED(bm), BMEdge *e)
+{
+ BMLoop *l1, *l2;
+ int radlen;
+ float edge_angle_cos = 0.0;
+
+ radlen = BM_Edge_FaceCount(e);
+ if(radlen == 2){
+ l1 = e->l;
+ l2 = e->l->radial_next;
+ edge_angle_cos = INPR(l1->f->no, l2->f->no);
+ }
+ return acos(edge_angle_cos);
+
+}
+
+/*
+ * BMESH EXIST FACE OVERLAPS
+ *
+ * Given a set of vertices (varr), find out if
+ * all those vertices overlap an existing face.
+ *
+ * Returns:
+ * 0 for no overlap
+ * 1 for overlap
+ *
+ *
+*/
+
+int BM_Exist_Face_Overlaps(BMesh *bm, BMVert **varr, int len, BMFace **overlapface)
+{
+ BMIter vertfaces;
+ BMFace *f;
+ int i, amount;
+
+ if (overlapface) *overlapface = NULL;
+
+ for(i=0; i < len; i++){
+ f = BMIter_New(&vertfaces, bm, BM_FACES_OF_VERT, varr[i] );
+ while(f){
+ amount = BM_Verts_In_Face(bm, f, varr, len);
+ if(amount >= len){
+ if (overlapface) *overlapface = f;
+ return 1;
+ }
+ f = BMIter_Step(&vertfaces);
+ }
+ }
+ return 0;
+}
+
+/*
+ * BMESH FACE EXISTS
+ *
+ * Given a set of vertices (varr), find out if
+ * there is a face with exactly those vertices
+ * (and only those vertices).
+ *
+ * Returns:
+ * 0 for no face found
+ * 1 for face found
+ *
+ *
+*/
+
+int BM_Face_Exists(BMesh *bm, BMVert **varr, int len, BMFace **existface)
+{
+ BMIter vertfaces;
+ BMFace *f;
+ int i, amount;
+
+ if (existface) *existface = NULL;
+
+ for(i=0; i < len; i++){
+ f = BMIter_New(&vertfaces, bm, BM_FACES_OF_VERT, varr[i] );
+ while(f){
+ amount = BM_Verts_In_Face(bm, f, varr, len);
+ if(amount == len && amount == f->len){
+ if (existface) *existface = f;
+ return 1;
+ }
+ f = BMIter_Step(&vertfaces);
+ }
+ }
+ return 0;
+}
diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c
new file mode 100644
index 00000000000..132c9dc3a79
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_structure.c
@@ -0,0 +1,1029 @@
+/**
+ * bmesh_structure.c jan 2007
+ *
+ * Low level routines for manipulating the BM structure.
+ *
+ * $Id: bmesh_structure.c,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** 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.
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "BKE_utildefines.h"
+#include "bmesh.h"
+#include "bmesh_private.h"
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+#include "BLI_ghash.h"
+/**
+ * MISC utility functions.
+ *
+ */
+
+int bmesh_vert_in_edge(BMEdge *e, BMVert *v){
+ if(e->v1 == v || e->v2 == v) return 1;
+ return 0;
+}
+int bmesh_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e){
+ if(e->v1 == v1 && e->v2 == v2) return 1;
+ else if(e->v1 == v2 && e->v2 == v1) return 1;
+ return 0;
+}
+
+BMVert *bmesh_edge_getothervert(BMEdge *e, BMVert *v){
+ if(e->v1 == v) return e->v2;
+ else if(e->v2 == v) return e->v1;
+ return NULL;
+}
+
+int bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *newv){
+ if(e->v1 == orig){
+ e->v1 = newv;
+ e->dlink1.next = e->dlink1.prev = NULL;
+ return 1;
+ }
+ else if(e->v2 == orig){
+ e->v2 = newv;
+ e->dlink2.next = e->dlink2.prev = NULL;
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * BMESH CYCLES
+ * (this is somewhat outdate, though bits of its API are still used) - joeedh
+ *
+ * Cycles are circular doubly linked lists that form the basis of adjacency
+ * information in the BME modeller. Full adjacency relations can be derived
+ * from examining these cycles very quickly. Although each cycle is a double
+ * circular linked list, each one is considered to have a 'base' or 'head',
+ * and care must be taken by Euler code when modifying the contents of a cycle.
+ *
+ * The contents of this file are split into two parts. First there are the
+ * bmesh_cycle family of functions which are generic circular double linked list
+ * procedures. The second part contains higher level procedures for supporting
+ * modification of specific cycle types.
+ *
+ * The three cycles explicitly stored in the BM data structure are as follows:
+ *
+ * 1: The Disk Cycle - A circle of edges around a vertex
+ * Base: vertex->edge pointer.
+ *
+ * This cycle is the most complicated in terms of its structure. Each bmesh_Edge contains
+ * two bmesh_CycleNode structures to keep track of that edge's membership in the disk cycle
+ * of each of its vertices. However for any given vertex it may be the first in some edges
+ * in its disk cycle and the second for others. The bmesh_disk_XXX family of functions contain
+ * some nice utilities for navigating disk cycles in a way that hides this detail from the
+ * tool writer.
+ *
+ * Note that the disk cycle is completley independant from face data. One advantage of this
+ * is that wire edges are fully integrated into the topology database. Another is that the
+ * the disk cycle has no problems dealing with non-manifold conditions involving faces.
+ *
+ * Functions relating to this cycle:
+ *
+ * bmesh_disk_append_edge
+ * bmesh_disk_remove_edge
+ * bmesh_disk_nextedge
+ * bmesh_disk_getpointer
+ *
+ * 2: The Radial Cycle - A circle of face edges (bmesh_Loop) around an edge
+ * Base: edge->l->radial structure.
+ *
+ * The radial cycle is similar to the radial cycle in the radial edge data structure.*
+ * Unlike the radial edge however, the radial cycle does not require a large amount of memory
+ * to store non-manifold conditions since BM does not keep track of region/shell
+ * information.
+ *
+ * Functions relating to this cycle:
+ *
+ * bmesh_radial_append
+ * bmesh_radial_remove_loop
+ * bmesh_radial_nextloop
+ * bmesh_radial_find_face
+ *
+ *
+ * 3: The Loop Cycle - A circle of face edges around a polygon.
+ * Base: polygon->lbase.
+ *
+ * The loop cycle keeps track of a faces vertices and edges. It should be noted that the
+ * direction of a loop cycle is either CW or CCW depending on the face normal, and is
+ * not oriented to the faces editedges.
+ *
+ * Functions relating to this cycle:
+ *
+ * bmesh_cycle_XXX family of functions.
+ *
+ *
+ * Note that the order of elements in all cycles except the loop cycle is undefined. This
+ * leads to slightly increased seek time for deriving some adjacency relations, however the
+ * advantage is that no intrinsic properties of the data structures are dependant upon the
+ * cycle order and all non-manifold conditions are represented trivially.
+ *
+*/
+int bmesh_disk_append_edge(struct BMEdge *e, struct BMVert *v)
+{
+ if (!v->e) {
+ Link *e1 = bm_get_edge_link(e, v);
+
+ v->e = e;
+ e1->next = e1->prev = (Link*)e;
+ } else {
+ Link *e1, *e2, *e3;
+
+ e1 = bm_get_edge_link(e, v);
+ e2 = bm_get_edge_link(v->e, v);
+ e3 = e2->prev ? bm_get_edge_link(e2->prev, v) : NULL;
+
+ e1->next = (Link*)v->e;
+ e1->prev = e2->prev;
+
+ e2->prev = (Link*)e;
+ if (e3)
+ e3->next = (Link*)e;
+ }
+
+ return 1;
+}
+
+void bmesh_disk_remove_edge(struct BMEdge *e, struct BMVert *v)
+{
+ Link *e1, *e2;
+
+ e1 = bm_get_edge_link(e, v);
+ if (e1->prev) {
+ e2 = bm_get_edge_link(e1->prev, v);
+ e2->next = e1->next;
+ }
+
+ if (e1->next) {
+ e2 = bm_get_edge_link(e1->next, v);
+ e2->prev = e1->prev;
+ }
+
+ if (v->e == e)
+ v->e = (e != (BMEdge *)e1->next) ? (BMEdge *)e1->next : NULL;
+
+ e1->next = e1->prev = NULL;
+}
+
+struct BMEdge *bmesh_disk_nextedge(struct BMEdge *e, struct BMVert *v)
+{
+ if (v == e->v1)
+ return e->dlink1.next;
+ if (v == e->v2)
+ return e->dlink2.next;
+ return NULL;
+}
+
+static BMEdge *bmesh_disk_prevedge(BMEdge *e, BMVert *v)
+{
+ if (v == e->v1)
+ return e->dlink1.prev;
+ if (v == e->v2)
+ return e->dlink2.prev;
+ return NULL;
+}
+
+BMEdge *bmesh_disk_existedge(BMVert *v1, BMVert *v2)
+{
+ BMEdge *curedge, *startedge;
+
+ if(v1->e) {
+ startedge = v1->e;
+ curedge = startedge;
+ do {
+ if (bmesh_verts_in_edge(v1,v2,curedge)) return curedge;
+ curedge = bmesh_disk_nextedge(curedge, v1);
+ } while (curedge != startedge);
+ }
+
+ return NULL;
+}
+
+int bmesh_disk_count(struct BMVert *v)
+{
+ BMEdge *e = v->e;
+ int i=0;
+
+ if (!e)
+ return 0;
+
+ do {
+ if (!e)
+ return 0;
+ e = bmesh_disk_nextedge(e, v);
+
+ if (i >= (1<<20)) {
+ printf("bmesh error: infinite loop in disk cycle!\n");
+ return 0;
+ }
+
+ i += 1;
+ } while (e != v->e);
+
+ return i;
+}
+
+int bmesh_disk_validate(int len, BMEdge *e, BMVert *v)
+{
+ BMEdge *e2;
+
+ if (!BM_Vert_In_Edge(e, v))
+ return 0;
+ if (bmesh_disk_count(v) != len || len == 0)
+ return 0;
+
+ e2 = e;
+ do {
+ if (len!=1 && bmesh_disk_prevedge(e2, v) == e2)
+ return 0;
+
+ e2 = bmesh_disk_nextedge(e2, v);
+ } while (e2 != e);
+
+ return 1;
+}
+
+/*
+ * BME DISK COUNT FACE VERT
+ *
+ * Counts the number of loop users
+ * for this vertex. Note that this is
+ * equivalent to counting the number of
+ * faces incident upon this vertex
+ *
+*/
+
+int bmesh_disk_count_facevert(BMVert *v)
+{
+ BMEdge *curedge;
+ int count = 0;
+
+ /*is there an edge on this vert at all?*/
+ if(!v->e)
+ return count;
+
+ /*first, loop around edges*/
+ curedge = v->e;
+ do{
+ if(curedge->l) count += bmesh_radial_count_facevert(curedge->l, v);
+ curedge = bmesh_disk_nextedge(curedge, v);
+ }while(curedge != v->e);
+
+ return count;
+}
+
+struct BMEdge *bmesh_disk_find_first_faceedge(struct BMEdge *e, struct BMVert *v)
+{
+ BMEdge *searchedge = NULL;
+ searchedge = e;
+ do{
+ if(searchedge->l && bmesh_radial_count_facevert(searchedge->l,v)) return searchedge;
+ searchedge = bmesh_disk_nextedge(searchedge,v);
+ }while(searchedge != e);
+
+ return NULL;
+}
+
+struct BMEdge *bmesh_disk_find_next_faceedge(struct BMEdge *e, struct BMVert *v)
+{
+ BMEdge *searchedge = NULL;
+ searchedge = bmesh_disk_nextedge(e,v);
+ do{
+ if(searchedge->l && bmesh_radial_count_facevert(searchedge->l,v)) return searchedge;
+ searchedge = bmesh_disk_nextedge(searchedge,v);
+ }while(searchedge !=e);
+ return e;
+}
+
+/*****radial cycle functions, e.g. loops surrounding edges******/
+int bmesh_radial_validate(int radlen, BMLoop *l)
+{
+ BMLoop *l2 = l;
+ int i=0;
+
+ if (bmesh_radial_length(l) != radlen)
+ return 0;
+
+ do {
+ if (!l2) {
+ bmesh_error();
+ return 0;
+ }
+
+ if (l2->e != l->e)
+ return 0;
+ if (l2->v != l->e->v1 && l2->v != l->e->v2)
+ return 0;
+
+ if (i > 3000000) {
+ bmesh_error();
+ return 0;
+ }
+
+ i++;
+ l2 = l2->radial_next;
+ } while (l2 != l);
+
+ return 1;
+}
+
+/*
+ * BMESH RADIAL REMOVE LOOP
+ *
+ * Removes a loop from an radial cycle. If edge e is non-NULL
+ * it should contain the radial cycle, and it will also get
+ * updated (in the case that the edge's link into the radial
+ * cycle was the loop which is being removed from the cycle).
+ */
+void bmesh_radial_remove_loop(BMLoop *l, BMEdge *e)
+{
+ /* if e is non-NULL, l must be in the radial cycle of e */
+ if (e && e != l->e) {
+ bmesh_error();
+ }
+
+ if (l->radial_next != l) {
+ if (e && l == e->l)
+ e->l = l->radial_next;
+
+ l->radial_next->radial_prev = l->radial_prev;
+ l->radial_prev->radial_next = l->radial_next;
+ } else {
+ if (e) {
+ if (l == e->l) {
+ e->l = NULL;
+ }
+ else {
+ bmesh_error();
+ }
+ }
+ }
+
+ /* l is no longer in a radial cycle; empty the links
+ to the cycle and the link back to an edge */
+ l->radial_next = l->radial_prev = NULL;
+ l->e = NULL;
+}
+
+
+/*
+ * BME RADIAL FIND FIRST FACE VERT
+ *
+ * Finds the first loop of v around radial
+ * cycle
+ *
+*/
+BMLoop *bmesh_radial_find_first_facevert(BMLoop *l, BMVert *v)
+{
+ BMLoop *curloop;
+ curloop = l;
+ do{
+ if(curloop->v == v) return curloop;
+ curloop = bmesh_radial_nextloop(curloop);
+ }while(curloop != l);
+ return NULL;
+}
+
+BMLoop *bmesh_radial_find_next_facevert(BMLoop *l, BMVert *v)
+{
+ BMLoop *curloop;
+ curloop = bmesh_radial_nextloop(l);
+ do{
+ if(curloop->v == v) return curloop;
+ curloop = bmesh_radial_nextloop(curloop);
+ }while(curloop !=l);
+ return l;
+}
+
+BMLoop *bmesh_radial_nextloop(BMLoop *l)
+{
+ return l->radial_next;
+}
+
+int bmesh_radial_length(BMLoop *l)
+{
+ BMLoop *l2 = l;
+ int i = 0;
+
+ if (!l)
+ return 0;
+
+ do {
+ if (!l2) {
+ /* radial cycle is broken (not a circulat loop) */
+ bmesh_error();
+ return 0;
+ }
+
+ i++;
+ l2 = l2->radial_next;
+ if (i >= 555555) {
+ bmesh_error();
+ return -1;
+ }
+ } while (l2 != l);
+
+ return i;
+}
+
+void bmesh_radial_append(BMEdge *e, BMLoop *l){
+ if(e->l == NULL) {
+ e->l = l;
+ l->radial_next = l->radial_prev = l;
+ } else {
+ l->radial_prev = e->l;
+ l->radial_next = e->l->radial_next;
+
+ e->l->radial_next->radial_prev = l;
+ e->l->radial_next = l;
+
+ e->l = l;
+ }
+
+ if (l->e && l->e != e) {
+ /* l is already in a radial cycle for a different edge */
+ bmesh_error();
+ }
+
+ l->e = e;
+}
+
+int bmesh_radial_find_face(BMEdge *e, BMFace *f)
+{
+ BMLoop *curloop;
+ int i, len;
+
+ len = bmesh_radial_length(e->l);
+ for(i = 0, curloop = e->l; i < len; i++, curloop = curloop->radial_next) {
+ if(curloop->f == f)
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * BME RADIAL COUNT FACE VERT
+ *
+ * Returns the number of times a vertex appears
+ * in a radial cycle
+ *
+*/
+
+int bmesh_radial_count_facevert(BMLoop *l, BMVert *v)
+{
+ BMLoop *curloop;
+ int count = 0;
+ curloop = l;
+ do{
+ if(curloop->v == v) count++;
+ curloop = bmesh_radial_nextloop(curloop);
+ }while(curloop != l);
+ return count;
+}
+
+/*****loop cycle functions, e.g. loops surrounding a face******/
+int bmesh_loop_validate(BMFace *f)
+{
+ int i;
+ int len = f->len;
+ BMLoop *curloop, *head;
+ head = bm_firstfaceloop(f);
+
+ if (head == NULL)
+ return 0;
+
+ /* Validate that the face loop cycle is the length specified by f->len */
+ for(i = 1, curloop = head->next; i < len; i++, curloop = curloop->next) {
+ if (curloop->f != f) return 0;
+ if (curloop == head) return 0;
+ }
+ if(curloop != head) return 0;
+
+ /* Validate the loop->prev links also form a cycle of length f->len */
+ for(i = 1, curloop = head->prev; i < len; i++, curloop = curloop->prev) {
+ if (curloop == head) return 0;
+ }
+ if(curloop != head) return 0;
+
+ return 1;
+}
+
+
+#if 0
+void bmesh_cycle_append(void *h, void *nt)
+{
+ BMNode *oldtail, *head, *newtail;
+
+ head = (BMNode*)h;
+ newtail = (BMNode*)nt;
+
+ if(head->next == NULL){
+ head->next = newtail;
+ head->prev = newtail;
+ newtail->next = head;
+ newtail->prev = head;
+ }
+ else{
+ oldtail = head->prev;
+ oldtail->next = newtail;
+ newtail->next = head;
+ newtail->prev = oldtail;
+ head->prev = newtail;
+
+ }
+}
+
+/**
+ * bmesh_cycle_length
+ *
+ * Count the nodes in a cycle.
+ *
+ * Returns -
+ * Integer
+ */
+
+int bmesh_cycle_length(BMEdge *e, BMVert *v) {
+ BMEdge *next, *prev, *cur;
+ int len, vi = v == e->v1 ? 0 : 1;
+
+ /*should skip 2 forward if v is 1, happily reduces to
+ v*2*/
+ prev = *(&e->v1_prev + vi*2);
+
+ cur = e;
+ len = 1;
+ while (cur != prev) {
+ vi = cur->v1 == v ? 0 : 1;
+
+ len++;
+ cur = *(&cur->v1_next + vi*2);
+ }
+
+ return len;
+}
+
+/**
+ * bmesh_cycle_remove
+ *
+ * Removes a node from a cycle.
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+
+int bmesh_cycle_remove(void *h, void *remn)
+{
+ int i, len;
+ BMNode *head, *remnode, *curnode;
+
+ head = (BMNode*)h;
+ remnode = (BMNode*)remn;
+ len = bmesh_cycle_length(h);
+
+ if(len == 1 && head == remnode){
+ head->next = NULL;
+ head->prev = NULL;
+ return 1;
+ }
+ else{
+ for(i=0, curnode = head; i < len; curnode = curnode->next){
+ if(curnode == remnode){
+ remnode->prev->next = remnode->next;
+ remnode->next->prev = remnode->prev;
+ /*zero out remnode pointers, important!*/
+ //remnode->next = NULL;
+ //remnode->prev = NULL;
+ return 1;
+
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * bmesh_cycle_validate
+ *
+ * Validates a cycle. Takes as an argument the expected length of the cycle and
+ * a pointer to the cycle head or base.
+ *
+ *
+ * Returns -
+ * 1 for success, 0 for failure.
+ */
+
+int bmesh_cycle_validate(int len, void *h){
+ int i;
+ BMNode *curnode, *head;
+ head = (BMNode*)h;
+
+ /*forward validation*/
+ for(i = 0, curnode = head; i < len; i++, curnode = curnode->next);
+ if(curnode != head) return 0;
+
+ /*reverse validation*/
+ for(i = 0, curnode = head; i < len; i++, curnode = curnode->prev);
+ if(curnode != head) return 0;
+
+ return 1;
+}
+
+/*Begin Disk Cycle routines*/
+
+/**
+ * bmesh_disk_nextedge
+ *
+ * Find the next edge in a disk cycle
+ *
+ * Returns -
+ * Pointer to the next edge in the disk cycle for the vertex v.
+ */
+
+BMEdge *bmesh_disk_nextedge(BMEdge *e, BMVert *v)
+{
+ if(bmesh_vert_in_edge(e, v)){
+ if(e->v1 == v) return e->d1.next->data;
+ else if(e->v2 == v) return e->d2.next->data;
+ }
+ return NULL;
+}
+
+/**
+ * bmesh_disk_getpointer
+ *
+ * Given an edge and one of its vertices, find the apporpriate CycleNode
+ *
+ * Returns -
+ * Pointer to bmesh_CycleNode.
+ */
+BMNode *bmesh_disk_getpointer(BMEdge *e, BMVert *v){
+ /*returns pointer to the cycle node for the appropriate vertex in this disk*/
+ if(e->v1 == v) return &(e->d1);
+ else if (e->v2 == v) return &(e->d2);
+ return NULL;
+}
+
+/**
+ * bmesh_disk_append_edge
+ *
+ * Appends edge to the end of a vertex disk cycle.
+ *
+ * Returns -
+ * 1 for success, 0 for failure
+ */
+
+int bmesh_disk_append_edge(BMEdge *e, BMVert *v)
+{
+
+ BMNode *base, *tail;
+
+ if(bmesh_vert_in_edge(e, v) == 0) return 0; /*check to make sure v is in e*/
+
+ /*check for loose vert first*/
+ if(v->e == NULL){
+ v->e = e;
+ base = tail = bmesh_disk_getpointer(e, v);
+ bmesh_cycle_append(base, tail); /*circular reference is ok!*/
+ return 1;
+ }
+
+ /*insert e at the end of disk cycle and make it the new v->e*/
+ base = bmesh_disk_getpointer(v->e, v);
+ tail = bmesh_disk_getpointer(e, v);
+ bmesh_cycle_append(base, tail);
+ return 1;
+}
+
+/**
+ * bmesh_disk_remove_edge
+ *
+ * Removes an edge from a disk cycle. If the edge to be removed is
+ * at the base of the cycle, the next edge becomes the new base.
+ *
+ *
+ * Returns -
+ * Nothing
+ */
+
+void bmesh_disk_remove_edge(BMEdge *e, BMVert *v)
+{
+ BMNode *base, *remnode;
+ BMEdge *newbase;
+ int len;
+
+ base = bmesh_disk_getpointer(v->e, v);
+ remnode = bmesh_disk_getpointer(e, v);
+
+ /*first deal with v->e pointer...*/
+ len = bmesh_cycle_length(base);
+ if(len == 1) newbase = NULL;
+ else if(v->e == e) newbase = base->next-> data;
+ else newbase = v->e;
+
+ /*remove and rebase*/
+ bmesh_cycle_remove(base, remnode);
+ v->e = newbase;
+}
+
+/**
+ * bmesh_disk_next_edgeflag
+ *
+ * Searches the disk cycle of v, starting with e, for the
+ * next edge that has either eflag or tflag.
+ *
+ * bmesh_Edge pointer.
+ */
+
+BMEdge *bmesh_disk_next_edgeflag(BMEdge *e, BMVert *v, int eflag, int tflag)
+{
+
+ BMNode *diskbase;
+ BMEdge *curedge;
+ int len, ok;
+
+ if(eflag && tflag) return NULL;
+
+ ok = bmesh_vert_in_edge(e,v);
+ if(ok){
+ diskbase = bmesh_disk_getpointer(e, v);
+ len = bmesh_cycle_length(diskbase);
+ curedge = bmesh_disk_nextedge(e,v);
+ while(curedge != e){
+ if(eflag){
+ if(curedge->head.eflag1 == eflag) return curedge;
+ }
+ curedge = bmesh_disk_nextedge(curedge, v);
+ }
+ }
+ return NULL;
+}
+
+/**
+ * bmesh_disk_count_edgeflag
+ *
+ * Counts number of edges in this verts disk cycle which have
+ * either eflag or tflag (but not both!)
+ *
+ * Returns -
+ * Integer.
+ */
+
+int bmesh_disk_count_edgeflag(BMVert *v, int eflag, int tflag)
+{
+ BMNode *diskbase;
+ BMEdge *curedge;
+ int i, len=0, count=0;
+
+ if(v->e){
+ if(eflag && tflag) return 0; /*tflag and eflag are reserved for different functions!*/
+ diskbase = bmesh_disk_getpointer(v->e, v);
+ len = bmesh_cycle_length(diskbase);
+
+ for(i = 0, curedge=v->e; i<len; i++){
+ if(eflag){
+ if(curedge->head.eflag1 == eflag) count++;
+ }
+ curedge = bmesh_disk_nextedge(curedge, v);
+ }
+ }
+ return count;
+}
+
+
+int bmesh_disk_hasedge(BMVert *v, BMEdge *e){
+ BMNode *diskbase;
+ BMEdge *curedge;
+ int i, len=0;
+
+ if(v->e){
+ diskbase = bmesh_disk_getpointer(v->e,v);
+ len = bmesh_cycle_length(diskbase);
+
+ for(i = 0, curedge=v->e; i<len; i++){
+ if(curedge == e) return 1;
+ else curedge=bmesh_disk_nextedge(curedge, v);
+ }
+ }
+ return 0;
+}
+
+BMEdge *bmesh_disk_existedge(BMVert *v1, BMVert *v2){
+ BMNode *diskbase;
+ BMEdge *curedge;
+ int i, len=0;
+
+ if(v1->e){
+ diskbase = bmesh_disk_getpointer(v1->e,v1);
+ len = bmesh_cycle_length(diskbase);
+
+ for(i=0,curedge=v1->e;i<len;i++,curedge = bmesh_disk_nextedge(curedge,v1)){
+ if(bmesh_verts_in_edge(v1,v2,curedge)) return curedge;
+ }
+ }
+
+ return NULL;
+}
+
+/*end disk cycle routines*/
+BMLoop *bmesh_radial_nextloop(BMLoop *l){
+ return l->radial_next;
+}
+
+void bmesh_radial_append(BMEdge *e, BMLoop *l){
+ if(e->l == NULL) e->l = l;
+ bmesh_cycle_append(&(e->l->radial), &(l->radial));
+}
+
+void bmesh_radial_remove_loop(BMLoop *l, BMEdge *e)
+{
+ BMLoop *newbase;
+ int len;
+
+ /*deal with edge->l pointer*/
+ len = bmesh_cycle_length(&(e->l->radial));
+ if(len == 1) newbase = NULL;
+ else if(e->l == l) newbase = e->l->radial_next;
+ else newbase = e->l;
+
+ /*remove and rebase*/
+ bmesh_cycle_remove(&(e->l->radial), &(l->radial));
+ e->l = newbase;
+}
+
+int bmesh_radial_find_face(BMEdge *e,BMFace *f)
+{
+
+ BMLoop *curloop;
+ int i, len;
+
+ len = bmesh_cycle_length(&(e->l->radial));
+ for(i = 0, curloop = e->l; i < len; i++, curloop = curloop->radial_next){
+ if(curloop->f == f) return 1;
+ }
+ return 0;
+}
+
+
+/*
+ * BME RADIAL COUNT FACE VERT
+ *
+ * Returns the number of times a vertex appears
+ * in a radial cycle
+ *
+*/
+
+int bmesh_radial_count_facevert(BMLoop *l, BMVert *v)
+{
+ BMLoop *curloop;
+ int count = 0;
+ curloop = l;
+ do{
+ if(curloop->v == v) count++;
+ curloop = bmesh_radial_nextloop(curloop);
+ }while(curloop != l);
+ return count;
+}
+
+/*
+ * BME DISK COUNT FACE VERT
+ *
+ * Counts the number of loop users
+ * for this vertex. Note that this is
+ * equivalent to counting the number of
+ * faces incident upon this vertex
+ *
+*/
+
+int bmesh_disk_count_facevert(BMVert *v)
+{
+ BMEdge *curedge;
+ int count = 0;
+
+ /*is there an edge on this vert at all?*/
+ if(!v->e)
+ return count;
+
+ /*first, loop around edges*/
+ curedge = v->e;
+ do{
+ if(curedge->l) count += bmesh_radial_count_facevert(curedge->l, v);
+ curedge = bmesh_disk_nextedge(curedge, v);
+ }while(curedge != v->e);
+
+ return count;
+}
+
+/*
+ * BME RADIAL FIND FIRST FACE VERT
+ *
+ * Finds the first loop of v around radial
+ * cycle
+ *
+*/
+BMLoop *bmesh_radial_find_first_facevert(BMLoop *l, BMVert *v)
+{
+ BMLoop *curloop;
+ curloop = l;
+ do{
+ if(curloop->v == v) return curloop;
+ curloop = bmesh_radial_nextloop(curloop);
+ }while(curloop != l);
+ return NULL;
+}
+
+BMLoop *bmesh_radial_find_next_facevert(BMLoop *l, BMVert *v)
+{
+ BMLoop *curloop;
+ curloop = bmesh_radial_nextloop(l);
+ do{
+ if(curloop->v == v) return curloop;
+ curloop = bmesh_radial_nextloop(curloop);
+ }while(curloop !=l);
+ return l;
+}
+
+
+/*
+ * BME FIND FIRST FACE EDGE
+ *
+ * Finds the first edge in a vertices
+ * Disk cycle that has one of this
+ * vert's loops attached
+ * to it.
+ *
+ *
+*/
+
+BMEdge *bmesh_disk_find_first_faceedge(BMEdge *e, BMVert *v)
+{
+ BMEdge *searchedge = NULL;
+ searchedge = e;
+ do{
+ if(searchedge->l && bmesh_radial_count_facevert(searchedge->l,v)) return searchedge;
+ searchedge = bmesh_disk_nextedge(searchedge,v);
+ }while(searchedge != e);
+
+ return NULL;
+}
+
+BMEdge *bmesh_disk_find_next_faceedge(BMEdge *e, BMVert *v)
+{
+ BMEdge *searchedge = NULL;
+ searchedge = bmesh_disk_nextedge(e,v);
+ do{
+ if(searchedge->l && bmesh_radial_count_facevert(searchedge->l,v)) return searchedge;
+ searchedge = bmesh_disk_nextedge(searchedge,v);
+ }while(searchedge !=e);
+ return e;
+}
+
+
+
+
+
+struct BMLoop *bmesh_loop_find_loop(struct BMFace *f, struct BMVert *v) {
+ BMLoop *l;
+ int i, len;
+
+ len = bmesh_cycle_length(f->lbase);
+ for (i = 0, l=f->loopbase; i < len; i++, l= l->next) {
+ if (l->v == v) return l;
+ }
+ return NULL;
+}
+
+#endif
diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h
new file mode 100644
index 00000000000..4bad77f0bf8
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_structure.h
@@ -0,0 +1,103 @@
+/**
+ * bmesh_structure.h jan 2007
+ *
+ * The lowest level of functionality for manipulating bmesh structures.
+ * None of these functions should ever be exported to the rest of Blender.
+ *
+ * ***** 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BM_STRUCTURE_H
+#define BM_STRUCTURE_H
+
+/*low-level, base bmesh API. in the vast majority of cases thes should not be
+ used directly. if absolutely necassary, see function defitions in code for
+ descriptive comments. but seriously, don't use this stuff.
+*/
+struct ListBase;
+
+void remove_loop_radial_link(BMLoop *l);
+
+/*DOUBLE CIRCULAR LINKED LIST FUNCTIONS*/
+void bmesh_cycle_append(void *h, void *nt);
+int bmesh_cycle_remove(void *h, void *remn);
+int bmesh_cycle_validate(int len, void *h);
+int bmesh_cycle_length(void *h);
+
+/* LOOP CYCLE MANAGEMENT */
+int bmesh_loop_validate(BMFace *f);
+
+/*DISK CYCLE MANAGMENT*/
+int bmesh_disk_append_edge(struct BMEdge *e, struct BMVert *v);
+void bmesh_disk_remove_edge(struct BMEdge *e, struct BMVert *v);
+struct BMEdge *bmesh_disk_nextedge(struct BMEdge *e, struct BMVert *v);
+struct BMNode *bmesh_disk_getpointer(struct BMEdge *e, struct BMVert *v);
+int bmesh_disk_count_facevert(struct BMVert *v);
+struct BMEdge *bmesh_disk_find_first_faceedge(struct BMEdge *e, struct BMVert *v);
+struct BMEdge *bmesh_disk_find_next_faceedge(struct BMEdge *e, struct BMVert *v);
+
+/*RADIAL CYCLE MANAGMENT*/
+void bmesh_radial_append(struct BMEdge *e, struct BMLoop *l);
+void bmesh_radial_remove_loop(struct BMLoop *l, struct BMEdge *e);
+int bmesh_radial_find_face(struct BMEdge *e, struct BMFace *f);
+struct BMLoop *bmesh_radial_nextloop(struct BMLoop *l);
+int bmesh_radial_count_facevert(struct BMLoop *l, struct BMVert *v);
+struct BMLoop *bmesh_radial_find_first_facevert(struct BMLoop *l, struct BMVert *v);
+struct BMLoop *bmesh_radial_find_next_facevert(struct BMLoop *l, struct BMVert *v);
+int bmesh_radial_validate(int radlen, struct BMLoop *l);
+
+/*EDGE UTILITIES*/
+int bmesh_vert_in_edge(struct BMEdge *e, struct BMVert *v);
+int bmesh_verts_in_edge(struct BMVert *v1, struct BMVert *v2, struct BMEdge *e);
+int bmesh_edge_swapverts(struct BMEdge *e, struct BMVert *orig, struct BMVert *newv); /*relink edge*/
+struct BMVert *bmesh_edge_getothervert(struct BMEdge *e, struct BMVert *v);
+int bmesh_disk_hasedge(struct BMVert *v, struct BMEdge *e);
+struct BMEdge *bmesh_disk_existedge(BMVert *v1, BMVert *v2);
+struct BMEdge *bmesh_disk_next_edgeflag(struct BMEdge *e, struct BMVert *v, int eflag, int tflag);
+int bmesh_disk_count_edgeflag(struct BMVert *v, int eflag, int tflag);
+int bmesh_disk_validate(int len, struct BMEdge *e, struct BMVert *v);
+
+/*EULER API - For modifying structure*/
+struct BMVert *bmesh_mv(struct BMesh *bm, float *vec);
+struct BMEdge *bmesh_me(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2);
+struct BMFace *bmesh_mf(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMEdge **elist, int len);
+int bmesh_kv(struct BMesh *bm, struct BMVert *v);
+int bmesh_ke(struct BMesh *bm, struct BMEdge *e);
+int bmesh_kf(struct BMesh *bm, struct BMFace *bply);
+struct BMVert *bmesh_semv(struct BMesh *bm, struct BMVert *tv, struct BMEdge *e, struct BMEdge **re);
+struct BMFace *bmesh_sfme(struct BMesh *bm, struct BMFace *f, struct BMVert *v1,
+ struct BMVert *v2, struct BMLoop **rl, struct ListBase *holes);
+int bmesh_jekv(struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv);
+int bmesh_loop_reverse(struct BMesh *bm, struct BMFace *f);
+struct BMFace *bmesh_jfke(struct BMesh *bm, struct BMFace *f1, struct BMFace *f2, struct BMEdge *e);
+
+struct BMVert *bmesh_urmv(struct BMesh *bm, struct BMFace *sf, struct BMVert *sv);
+//int *bmesh_grkv(struct BMesh *bm, struct BMFace *sf, struct BMVert *kv);
+
+#endif
diff --git a/source/blender/bmesh/intern/bmesh_to_editmesh.c b/source/blender/bmesh/intern/bmesh_to_editmesh.c
new file mode 100644
index 00000000000..cb9016c9e73
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_to_editmesh.c
@@ -0,0 +1,318 @@
+#if 0
+#include "MEM_guardedalloc.h"
+#include "BKE_customdata.h"
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include <string.h>
+#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+
+#include "BLI_editVert.h"
+#include "mesh_intern.h"
+#include "ED_mesh.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+#include "BLI_array.h"
+#include "BLI_array.h"
+
+#include "bmesh.h"
+
+/*
+ * BMESH TO EDITMESH
+ *
+ * This file contains functions for converting
+ * from a bmesh to an editmesh
+ *
+*/
+
+/*
+ * LOOPS TO EDITMESH CORNERS
+ *
+ * Converts N-Gon loop (face-edge)
+ * data (UVs, Verts Colors, ect) to
+ * face corner data.
+ *
+*/
+
+static void loops_to_editmesh_corners(BMesh *bm, CustomData *facedata, void *face_block, BMFace *f,int numCol, int numTex){
+ int i, j;
+ BMLoop *l;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i);
+ texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
+
+ texface->tpage = texpoly->tpage;
+ texface->flag = texpoly->flag;
+ texface->transp = texpoly->transp;
+ texface->mode = texpoly->mode;
+ texface->tile = texpoly->tile;
+ texface->unwrap = texpoly->unwrap;
+
+ j = 0;
+ l = f->loopbase;
+ do {
+ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
+ texface->uv[j][0] = mloopuv->uv[0];
+ texface->uv[j][1] = mloopuv->uv[1];
+ j++;
+ l = ((l->next));
+ } while(l!=f->lbase);
+
+ }
+
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i);
+ j = 0;
+ l = f->loopbase;
+ do {
+ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ j++;
+ l = ((l->next));
+ } while(l!=f->lbase);
+ }
+}
+
+static EditVert *bmeshvert_to_editvert(BMesh *bm, EditMesh *em, BMVert *v, int index, EditVert **evlist)
+{
+ EditVert *eve = NULL;
+
+ v->head.eflag1 = index; /*abuse!*/
+ eve = addvertlist(em, v->co, NULL);
+ eve->keyindex = index;
+ evlist[index]= eve;
+
+ /*copy flags*/
+ if(v->head.flag & BM_HIDDEN) eve->h = 1;
+ if (v->head.flag & BM_SELECT) eve->f |= SELECT;
+
+ eve->bweight = v->bweight;
+ CustomData_em_copy_data(&bm->vdata, &em->vdata, v->head.data, &eve->data);
+ /*copy normal*/
+ eve->no[0] = v->no[0];
+ eve->no[1] = v->no[1];
+ eve->no[2] = v->no[2];
+
+ return eve;
+}
+
+static void bmeshedge_to_editedge_internal(BMesh *bm, EditMesh *em, BMEdge *e, EditEdge *eed)
+{
+ eed->crease = e->crease;
+ eed->bweight = e->bweight;
+
+ //copy relavent flags
+ if (e->head.flag & BM_SELECT) eed->f |= SELECT;
+ if (e->head.flag & BM_SEAM) eed->seam = 1;
+ if (e->head.flag & BM_SHARP) eed->sharp = 1;
+ if (e->head.flag & BM_HIDDEN) eed->h = 1;
+ if (e->head.flag & BM_FGON) eed->h |= EM_FGON;
+
+ CustomData_em_copy_data(&bm->edata, &em->edata, e->head.data, &eed->data);
+}
+
+static EditEdge *bmeshedge_to_editedge(BMesh *bm, EditMesh *em, BMEdge *e, EditVert **evlist)
+{
+ EditEdge *eed = NULL;
+
+ if(!(findedgelist(em, evlist[e->v1->head.eflag1], evlist[e->v2->head.eflag1]))){
+ eed= addedgelist(em, evlist[e->v1->head.eflag1], evlist[e->v2->head.eflag1], NULL);
+ bmeshedge_to_editedge_internal(bm, em, e, eed);
+ }
+
+ return eed;
+}
+
+static EditFace *bmeshface_to_editface(BMesh *bm, EditMesh *em, BMFace *f, EditVert **evlist, int numCol, int numTex)
+{
+ EditVert *eve1, *eve2, *eve3, *eve4;
+ EditFace *efa = NULL;
+ int len;
+
+ len = f->len;
+
+ eve1= evlist[f->lbase->v->head.eflag1];
+ eve2= evlist[((f->lbase->next))->v->head.eflag1];
+ eve3= evlist[((f->lbase->next->next))->v->head.eflag1];
+ if (len == 4) {
+ eve4= evlist[ ((f->lbase->prev))->v->head.eflag1];
+ }
+ else {
+ eve4= NULL;
+ }
+
+ if (eve1==eve2 || eve1==eve3 || eve1==eve4 || eve2==eve3 || eve3==eve4
+ || eve2==eve4) return NULL;
+
+ efa = addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL);
+ if (!efa) return NULL;
+
+ bmeshedge_to_editedge_internal(bm, em, f->lbase->e, efa->e1);
+ bmeshedge_to_editedge_internal(bm, em, ((f->lbase->next))->e, efa->e2);
+ bmeshedge_to_editedge_internal(bm, em, ((f->lbase->next->next))->e, efa->e3);
+ if(eve4)
+ bmeshedge_to_editedge_internal(bm, em, ((f->lbase->prev))->e, efa->e4);
+
+ efa->mat_nr = (unsigned char)f->mat_nr;
+
+ /*Copy normal*/
+ efa->n[0] = f->no[0];
+ efa->n[1] = f->no[1];
+ efa->n[2] = f->no[2];
+
+ //copy relavent original flags
+ if (f->head.flag & BM_SELECT) efa->f |= SELECT;
+ if (f->head.flag & BM_HIDDEN) efa->h = 1;
+ if (f->head.flag & BM_SMOOTH) efa->flag |= ME_SMOOTH;
+ if (f->head.flag & BM_ACTIVE) EM_set_actFace(em, efa);
+
+ CustomData_em_copy_data(&bm->pdata, &em->fdata, f->head.data, &efa->data);
+ loops_to_editmesh_corners(bm, &em->fdata, efa->data, f, numCol,numTex);
+
+ return efa;
+}
+
+EditMesh *bmesh_to_editmesh_intern(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ EditMesh *em;
+ EditVert *eve, **evlist;
+
+ int totvert, i, numTex, numCol, flag;
+
+ em = MEM_callocN(sizeof(EditMesh), "EditMesh from bmesh");
+
+ em->selectmode = bm->selectmode;
+
+ flag = CD_MASK_BMESH & ~CD_MASK_MTEXPOLY;
+
+ CustomData_copy(&bm->vdata, &em->vdata, flag, CD_CALLOC, 0);
+ CustomData_copy(&bm->edata, &em->edata, flag, CD_CALLOC, 0);
+ CustomData_copy(&bm->pdata, &em->fdata, flag, CD_CALLOC, 0);
+ CustomData_from_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata,0);
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ totvert = BM_Count_Element(bm, BM_VERT);
+ evlist= MEM_mallocN(totvert*sizeof(EditVert *),"evlist");
+
+ /* make vertices */
+ for(i=0, v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts), i++)
+ eve = bmeshvert_to_editvert(bm, em, v, i, evlist);
+
+ /* make edges */
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges))
+ bmeshedge_to_editedge(bm, em, e, evlist);
+
+ /* make faces */
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces))
+ bmeshface_to_editface(bm, em, f, evlist, numCol, numTex);
+
+ MEM_freeN(evlist);
+
+ EM_fgon_flags(em);
+
+ EM_nvertices_selected(em);
+ EM_nedges_selected(em);
+ EM_nfaces_selected(em);
+
+ return em;
+}
+
+void bmesh2edit_exec(BMesh *bmesh, BMOperator *op)
+{
+ BMO_Set_Pnt(op, "emout", bmesh_to_editmesh_intern(bmesh));
+}
+
+#define FACE_NGON 1
+
+void bmesh_make_fgons_exec(BMesh *bmesh, BMOperator *op)
+{
+ BMOperator triop;
+ BMFace *face;
+ BMIter iter, liter;
+ BMEdge *edge;
+ BMLoop *l, *nl;
+ BMOpSlot *eout;
+ int i, trifan = BMO_Get_Int(op, "trifan");
+
+ if (!trifan) BMO_Init_Op(&triop, "triangulate");
+
+ /*instead of properly tesselate, just make a triangle fan, this
+ should make bmesh -> editmesh -> bmesh conversions always properly
+ work.*/
+ for (face = BMIter_New(&iter, bmesh, BM_FACES_OF_MESH, NULL); face; face=BMIter_Step(&iter)) {
+ if (face->len > 4) {
+ BMO_SetFlag(bmesh, face, FACE_NGON);
+ if (trifan) {
+ while (face->len > 4) {
+ face = BM_Split_Face(bmesh, face,
+ face->lbase->v,
+ (face->lbase->next->next)->v,
+ &nl, NULL);
+ BM_SetHFlag(nl->e, BM_FGON);
+ }
+ }
+ }
+ }
+
+ if (!trifan) {
+ BMO_Flag_To_Slot(bmesh, &triop, "faces", FACE_NGON, BM_FACE);
+ BMO_Exec_Op(bmesh, &triop);
+
+ eout = BMO_GetSlot(&triop, "edgeout");
+ for (i=0; i<eout->len; i++) {
+ edge = ((BMEdge**)eout->data.buf)[i];
+ edge->head.flag |= BM_FGON;
+ face = BMIter_New(&iter, bmesh, BM_FACES_OF_EDGE, edge);
+
+ for (; face; face=BMIter_Step(&iter)) {
+ face->head.flag |= BM_NONORMCALC;
+ }
+ }
+
+ BMO_Finish_Op(bmesh, &triop);
+ }
+}
+
+EditMesh *bmesh_to_editmesh(BMesh *bmesh)
+{
+ BMOperator conv, makefgon;
+ EditMesh *em;
+
+ /*first fgon-afy the mesh*/
+ BMO_Init_Op(&makefgon, "makefgon");
+ BMO_Set_Int(&makefgon, "trifan", 1);
+ BMO_Exec_Op(bmesh, &makefgon);
+ BMO_Finish_Op(bmesh, &makefgon);
+
+ BMO_Init_Op(&conv, "bmesh_to_editmesh");
+ BMO_Exec_Op(bmesh, &conv);
+ em = BMO_Get_Pnt(&conv, "emout");
+ BMO_Finish_Op(bmesh, &conv);
+
+ return em;
+}
+#endif
diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c
new file mode 100644
index 00000000000..fab187da587
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_walkers.c
@@ -0,0 +1,263 @@
+/**
+ * bmesh_walkers.c april 2011
+ *
+ * BMesh Walker API.
+ *
+ * $Id: $
+ *
+ * ***** 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Joseph Eagar, Geoffrey Bantle, Levi Schooley.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "BKE_customdata.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_mempool.h"
+#include "BLI_array.h"
+
+#include "bmesh.h"
+
+#include "bmesh_private.h"
+#include "bmesh_walkers_private.h"
+
+/*
+ - joeedh -
+ design notes:
+
+ original desing: walkers directly emulation recursive functions.
+ functions save their state onto a worklist, and also add new states
+ to implement recursive or looping behaviour. generally only one
+ state push per call with a specific state is desired.
+
+ basic design pattern: the walker step function goes through it's
+ list of possible choices for recursion, and recurses (by pushing a new state)
+ using the first non-visited one. this choise is the flagged as visited using
+ the ghash. each step may push multiple new states onto the worklist at once.
+
+ * walkers use tool flags, not header flags
+ * walkers now use ghash for storing visited elements,
+ rather then stealing flags. ghash can be rewritten
+ to be faster if necassary, in the far future :) .
+ * tools should ALWAYS have necassary error handling
+ for if walkers fail.
+*/
+
+void *BMW_Begin(BMWalker *walker, void *start) {
+ walker->begin(walker, start);
+
+ return BMW_currentstate(walker) ? walker->step(walker) : NULL;
+}
+
+/*
+ * BMW_CREATE
+ *
+ * Allocates and returns a new mesh walker of
+ * a given type. The elements visited are filtered
+ * by the bitmask 'searchmask'.
+ *
+*/
+
+void BMW_Init(BMWalker *walker, BMesh *bm, int type, int searchmask, int flag)
+{
+ memset(walker, 0, sizeof(BMWalker));
+
+ walker->flag = flag;
+ walker->bm = bm;
+ walker->restrictflag = searchmask;
+ walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh walkers 1");
+
+ if (type >= BMW_MAXWALKERS || type < 0) {
+ bmesh_error();
+ fprintf(stderr, "Invalid walker type in BMW_Init; type: %d, searchmask: %d, flag: %d\n", type, searchmask, flag);
+ }
+
+ if (type != BMW_CUSTOM) {
+ walker->begin = bm_walker_types[type]->begin;
+ walker->yield = bm_walker_types[type]->yield;
+ walker->step = bm_walker_types[type]->step;
+ walker->structsize = bm_walker_types[type]->structsize;
+ walker->order = bm_walker_types[type]->order;
+ }
+
+ walker->worklist = BLI_mempool_create(walker->structsize, 100, 100, 1, 0);
+ walker->states.first = walker->states.last = NULL;
+}
+
+/*
+ * BMW_End
+ *
+ * Frees a walker's worklist.
+ *
+*/
+
+void BMW_End(BMWalker *walker)
+{
+ BLI_mempool_destroy(walker->worklist);
+ BLI_ghash_free(walker->visithash, NULL, NULL);
+}
+
+
+/*
+ * BMW_Step
+ *
+*/
+
+void *BMW_Step(BMWalker *walker)
+{
+ BMHeader *head;
+
+ head = BMW_walk(walker);
+
+ return head;
+}
+
+/*
+ * BMW_CurrentDepth
+ *
+ * Returns the current depth of the walker.
+ *
+*/
+
+int BMW_CurrentDepth(BMWalker *walker)
+{
+ return walker->depth;
+}
+
+/*
+ * BMW_WALK
+ *
+ * Steps a mesh walker forward by one element
+ *
+ * BMESH_TODO:
+ * -add searchmask filtering
+ *
+*/
+
+void *BMW_walk(BMWalker *walker)
+{
+ void *current = NULL;
+
+ while(BMW_currentstate(walker)){
+ current = walker->step(walker);
+ if(current) return current;
+ }
+ return NULL;
+}
+
+/*
+ * BMW_currentstate
+ *
+ * Returns the first state from the walker state
+ * worklist. This state is the the next in the
+ * worklist for processing.
+ *
+*/
+
+void* BMW_currentstate(BMWalker *walker)
+{
+ bmesh_walkerGeneric *currentstate = walker->states.first;
+ if (currentstate) {
+ /* Automatic update of depth. For most walkers that
+ follow the standard "Step" pattern of:
+ - read current state
+ - remove current state
+ - push new states
+ - return walk result from just-removed current state
+ this simple automatic update should keep track of depth
+ just fine. Walkers that deviate from that pattern may
+ need to manually update the depth if they care about
+ keeping it correct. */
+ walker->depth = currentstate->depth + 1;
+ }
+ return currentstate;
+}
+
+/*
+ * BMW_removestate
+ *
+ * Remove and free an item from the end of the walker state
+ * worklist.
+ *
+*/
+
+void BMW_removestate(BMWalker *walker)
+{
+ void *oldstate;
+ oldstate = BMW_currentstate(walker);
+ BLI_remlink(&walker->states, oldstate);
+ BLI_mempool_free(walker->worklist, oldstate);
+}
+
+/*
+ * BMW_newstate
+ *
+ * Allocate a new empty state and put it on the worklist.
+ * A pointer to the new state is returned so that the caller
+ * can fill in the state data. The new state will be inserted
+ * at the front for depth-first walks, and at the end for
+ * breadth-first walks.
+ *
+*/
+
+void* BMW_addstate(BMWalker *walker)
+{
+ bmesh_walkerGeneric *newstate;
+ newstate = BLI_mempool_alloc(walker->worklist);
+ newstate->depth = walker->depth;
+ switch (walker->order)
+ {
+ case BMW_DEPTH_FIRST:
+ BLI_addhead(&walker->states, newstate);
+ break;
+ case BMW_BREADTH_FIRST:
+ BLI_addtail(&walker->states, newstate);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+ return newstate;
+}
+
+/*
+ * BMW_reset
+ *
+ * Frees all states from the worklist, resetting the walker
+ * for reuse in a new walk.
+ *
+*/
+
+void BMW_reset(BMWalker *walker) {
+ while (BMW_currentstate(walker)) {
+ BMW_removestate(walker);
+ }
+ walker->depth = 0;
+ BLI_ghash_free(walker->visithash, NULL, NULL);
+ walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh walkers 1");
+}
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c
new file mode 100644
index 00000000000..cf2a417d71c
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c
@@ -0,0 +1,883 @@
+/**
+ * bmesh_walkers_impl.c april 2011
+ *
+ * BMesh Walker Code.
+ *
+ * $Id: $
+ *
+ * ***** 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Joseph Eagar, Geoffrey Bantle, Levi Schooley.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "BKE_customdata.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_mempool.h"
+#include "BLI_array.h"
+
+#include "bmesh.h"
+
+#include "bmesh_private.h"
+#include "bmesh_walkers_private.h"
+
+/* Shell Walker:
+ *
+ * Starts at a vertex on the mesh and walks over the 'shell' it belongs
+ * to via visiting connected edges.
+ *
+ * TODO:
+ *
+ * Add restriction flag/callback for wire edges.
+ *
+*/
+
+static void shellWalker_visitEdge(BMWalker *walker, BMEdge *e) {
+ shellWalker *shellWalk = NULL;
+
+ if (BLI_ghash_haskey(walker->visithash, e)) {
+ return;
+ }
+
+ if (walker->restrictflag && !BMO_TestFlag(walker->bm, e, walker->restrictflag)) {
+ return;
+ }
+
+ shellWalk = BMW_addstate(walker);
+ shellWalk->curedge = e;
+ BLI_ghash_insert(walker->visithash, e, NULL);
+}
+
+static void shellWalker_begin(BMWalker *walker, void *data){
+ BMIter eiter;
+ BMHeader *h = data;
+ BMEdge *e;
+ BMVert *v;
+
+ if (h == NULL)
+ {
+ return;
+ }
+
+ switch (h->type) {
+ case BM_VERT:
+ {
+ /* starting the walk at a vert, add all the edges
+ to the worklist */
+ v = (BMVert*)h;
+ BM_ITER(e, &eiter, walker->bm, BM_EDGES_OF_VERT, v) {
+ shellWalker_visitEdge(walker, e);
+ }
+ break;
+ }
+
+ case BM_EDGE:
+ {
+ /* starting the walk at an edge, add the single edge
+ to the worklist */
+ e = (BMEdge*)h;
+ shellWalker_visitEdge(walker, e);
+ break;
+ }
+ }
+}
+
+static void *shellWalker_yield(BMWalker *walker)
+{
+ shellWalker *shellWalk = BMW_currentstate(walker);
+ return shellWalk->curedge;
+}
+
+static void *shellWalker_step(BMWalker *walker)
+{
+ shellWalker *swalk = BMW_currentstate(walker);
+ BMEdge *e, *e2;
+ BMVert *v;
+ BMIter iter;
+ int i;
+
+ e = swalk->curedge;
+ BMW_removestate(walker);
+
+ for (i=0; i<2; i++) {
+ v = i ? e->v2 : e->v1;
+ BM_ITER(e2, &iter, walker->bm, BM_EDGES_OF_VERT, v) {
+ shellWalker_visitEdge(walker, e2);
+ }
+ }
+
+ return e;
+}
+
+#if 0
+static void *shellWalker_step(BMWalker *walker)
+{
+ BMEdge *curedge, *next = NULL;
+ BMVert *ov = NULL;
+ int restrictpass = 1;
+ shellWalker shellWalk = *((shellWalker*)BMW_currentstate(walker));
+
+ if (!BLI_ghash_haskey(walker->visithash, shellWalk.base))
+ BLI_ghash_insert(walker->visithash, shellWalk.base, NULL);
+
+ BMW_removestate(walker);
+
+
+ /*find the next edge whose other vertex has not been visited*/
+ curedge = shellWalk.curedge;
+ do{
+ if (!BLI_ghash_haskey(walker->visithash, curedge)) {
+ if(!walker->restrictflag || (walker->restrictflag &&
+ BMO_TestFlag(walker->bm, curedge, walker->restrictflag)))
+ {
+ shellWalker *newstate;
+
+ ov = BM_OtherEdgeVert(curedge, shellWalk.base);
+
+ /*push a new state onto the stack*/
+ newState = BMW_addstate(walker);
+ BLI_ghash_insert(walker->visithash, curedge, NULL);
+
+ /*populate the new state*/
+
+ newState->base = ov;
+ newState->curedge = curedge;
+ }
+ }
+ curedge = bmesh_disk_nextedge(curedge, shellWalk.base);
+ }while(curedge != shellWalk.curedge);
+
+ return shellWalk.curedge;
+}
+#endif
+
+/* Connected Vertex Walker:
+ *
+ * Similar to shell walker, but visits vertices instead of edges.
+ *
+*/
+
+static void connectedVertexWalker_visitVertex(BMWalker *walker, BMVert *v)
+{
+ connectedVertexWalker *vwalk;
+
+ if (BLI_ghash_haskey(walker->visithash, v)) {
+ /* already visited */
+ return;
+ }
+ if (walker->restrictflag && !BMO_TestFlag(walker->bm, v, walker->restrictflag)) {
+ /* not flagged for walk */
+ return;
+ }
+
+ vwalk = BMW_addstate(walker);
+ vwalk->curvert = v;
+ BLI_ghash_insert(walker->visithash, v, NULL);
+}
+
+static void connectedVertexWalker_begin(BMWalker *walker, void *data)
+{
+ BMVert *v = data;
+ connectedVertexWalker_visitVertex(walker, v);
+}
+
+static void *connectedVertexWalker_yield(BMWalker *walker)
+{
+ connectedVertexWalker *vwalk = BMW_currentstate(walker);
+ return vwalk->curvert;
+}
+
+static void *connectedVertexWalker_step(BMWalker *walker)
+{
+ connectedVertexWalker *vwalk = BMW_currentstate(walker);
+ BMVert *v, *v2;
+ BMEdge *e;
+ BMIter iter;
+
+ v = vwalk->curvert;
+
+ BMW_removestate(walker);
+
+ BM_ITER(e, &iter, walker->bm, BM_EDGES_OF_VERT, v) {
+ v2 = BM_OtherEdgeVert(e, v);
+ if (!BLI_ghash_haskey(walker->visithash, v2)) {
+ connectedVertexWalker_visitVertex(walker, v2);
+ }
+ }
+
+ return v;
+}
+
+/* Island Boundary Walker:
+ *
+ * Starts at a edge on the mesh and walks over the boundary of an
+ * island it belongs to.
+ *
+ * TODO:
+ *
+ * Add restriction flag/callback for wire edges.
+ *
+*/
+
+static void islandboundWalker_begin(BMWalker *walker, void *data){
+ BMLoop *l = data;
+ islandboundWalker *iwalk = NULL;
+
+ iwalk = BMW_addstate(walker);
+
+ iwalk->base = iwalk->curloop = l;
+ iwalk->lastv = l->v;
+
+ BLI_ghash_insert(walker->visithash, data, NULL);
+
+}
+
+static void *islandboundWalker_yield(BMWalker *walker)
+{
+ islandboundWalker *iwalk = BMW_currentstate(walker);
+
+ return iwalk->curloop;
+}
+
+static void *islandboundWalker_step(BMWalker *walker)
+{
+ islandboundWalker *iwalk = BMW_currentstate(walker), owalk;
+ BMVert *v;
+ BMEdge *e = iwalk->curloop->e;
+ BMFace *f;
+ BMLoop *l = iwalk->curloop;
+ /* int found=0; */
+
+ owalk = *iwalk;
+
+ if (iwalk->lastv == e->v1) v = e->v2;
+ else v = e->v1;
+
+ if (BM_Nonmanifold_Vert(walker->bm, v)) {
+ BMW_reset(walker);
+ BMO_RaiseError(walker->bm, NULL,BMERR_WALKER_FAILED,
+ "Non-manifold vert"
+ " while searching region boundary");
+ return NULL;
+ }
+
+ /*pop off current state*/
+ BMW_removestate(walker);
+
+ f = l->f;
+
+ while (1) {
+ l = BM_OtherFaceLoop(e, f, v);
+ if (bmesh_radial_nextloop(l) != l) {
+ l = bmesh_radial_nextloop(l);
+ f = l->f;
+ e = l->e;
+ if(walker->restrictflag && !BMO_TestFlag(walker->bm, f, walker->restrictflag)){
+ l = l->radial_next;
+ break;
+ }
+ } else {
+ f = l->f;
+ e = l->e;
+ break;
+ }
+ }
+
+ if (l == owalk.curloop) return NULL;
+ if (BLI_ghash_haskey(walker->visithash, l)) return owalk.curloop;
+
+ BLI_ghash_insert(walker->visithash, l, NULL);
+ iwalk = BMW_addstate(walker);
+ iwalk->base = owalk.base;
+
+ //if (!BMO_TestFlag(walker->bm, l->f, walker->restrictflag))
+ // iwalk->curloop = l->radial_next;
+ iwalk->curloop = l; //else iwalk->curloop = l;
+ iwalk->lastv = v;
+
+ return owalk.curloop;
+}
+
+
+/* Island Walker:
+ *
+ * Starts at a tool flagged-face and walks over the face region
+ *
+ * TODO:
+ *
+ * Add restriction flag/callback for wire edges.
+ *
+*/
+
+static void islandWalker_begin(BMWalker *walker, void *data){
+ islandWalker *iwalk = NULL;
+
+ if (walker->restrictflag && !BMO_TestFlag(walker->bm, data, walker->restrictflag)) {
+ return;
+ }
+
+ iwalk = BMW_addstate(walker);
+ BLI_ghash_insert(walker->visithash, data, NULL);
+
+ iwalk->cur = data;
+}
+
+static void *islandWalker_yield(BMWalker *walker)
+{
+ islandWalker *iwalk = BMW_currentstate(walker);
+
+ return iwalk->cur;
+}
+
+static void *islandWalker_step(BMWalker *walker)
+{
+ islandWalker *iwalk = BMW_currentstate(walker), *owalk;
+ BMIter iter, liter;
+ BMFace *f, *curf = iwalk->cur;
+ BMLoop *l;
+ owalk = iwalk;
+
+ BMW_removestate(walker);
+
+ l = BMIter_New(&liter, walker->bm, BM_LOOPS_OF_FACE, iwalk->cur);
+ for (; l; l=BMIter_Step(&liter)) {
+ f = BMIter_New(&iter, walker->bm, BM_FACES_OF_EDGE, l->e);
+ for (; f; f=BMIter_Step(&iter)) {
+ if (walker->restrictflag && !BMO_TestFlag(walker->bm, f, walker->restrictflag)) {
+ continue;
+ }
+ if (BLI_ghash_haskey(walker->visithash, f)) continue;
+
+ iwalk = BMW_addstate(walker);
+ iwalk->cur = f;
+ BLI_ghash_insert(walker->visithash, f, NULL);
+ break;
+ }
+ }
+
+ return curf;
+}
+
+
+/* Edge Loop Walker:
+ *
+ * Starts at a tool-flagged edge and walks over the edge loop
+ *
+*/
+
+static void loopWalker_begin(BMWalker *walker, void *data){
+ loopWalker *lwalk = NULL, owalk;
+ BMEdge *e = data;
+ BMVert *v;
+ /* int found=1, val; */ /* UNUSED */
+
+ v = e->v1;
+
+ /* val = BM_Vert_EdgeCount(v); */ /* UNUSED */
+
+ lwalk = BMW_addstate(walker);
+ BLI_ghash_insert(walker->visithash, e, NULL);
+
+ lwalk->cur = lwalk->start = e;
+ lwalk->lastv = lwalk->startv = v;
+ lwalk->stage2 = 0;
+ lwalk->startrad = BM_Edge_FaceCount(e);
+
+ /*rewind*/
+ while (BMW_currentstate(walker)) {
+ owalk = *((loopWalker*)BMW_currentstate(walker));
+ BMW_walk(walker);
+ }
+
+ lwalk = BMW_addstate(walker);
+ *lwalk = owalk;
+
+ if (lwalk->lastv == owalk.cur->v1) lwalk->lastv = owalk.cur->v2;
+ else lwalk->lastv = owalk.cur->v1;
+
+ lwalk->startv = lwalk->lastv;
+
+ BLI_ghash_free(walker->visithash, NULL, NULL);
+ walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh walkers 2");
+ BLI_ghash_insert(walker->visithash, owalk.cur, NULL);
+}
+
+static void *loopWalker_yield(BMWalker *walker)
+{
+ loopWalker *lwalk = BMW_currentstate(walker);
+
+ return lwalk->cur;
+}
+
+static void *loopWalker_step(BMWalker *walker)
+{
+ loopWalker *lwalk = BMW_currentstate(walker), owalk;
+ BMEdge *e = lwalk->cur /* , *nexte = NULL */;
+ BMLoop *l, *l2;
+ BMVert *v;
+ int val, rlen /* , found=0 */, i=0, stopi;
+
+ owalk = *lwalk;
+
+ if (e->v1 == lwalk->lastv) v = e->v2;
+ else v = e->v1;
+
+ val = BM_Vert_EdgeCount(v);
+
+ BMW_removestate(walker);
+
+ rlen = owalk.startrad;
+ l = e->l;
+
+ /*handle wire edge case*/
+ if (!l && val == 2) {
+ e = bmesh_disk_nextedge(e, v);
+
+ if (!BLI_ghash_haskey(walker->visithash, e)) {
+ lwalk = BMW_addstate(walker);
+ *lwalk = owalk;
+ lwalk->cur = e;
+ lwalk->lastv = v;
+
+ BLI_ghash_insert(walker->visithash, e, NULL);
+ }
+
+ return owalk.cur;
+ }
+
+ if (val == 4 || val == 2 || rlen == 1) {
+ i = 0;
+ stopi = val / 2;
+ while (1) {
+ if (rlen != 1 && i == stopi) break;
+
+ l = BM_OtherFaceLoop(l->e, l->f, v);
+
+ if (!l)
+ break;
+
+ l2 = bmesh_radial_nextloop(l);
+
+ if (l2 == l) {
+ break;
+ }
+
+ l = l2;
+ i += 1;
+ }
+ }
+
+ if (!l)
+ return owalk.cur;
+
+ if (l != e->l && !BLI_ghash_haskey(walker->visithash, l->e)) {
+ if (!(rlen != 1 && i != stopi)) {
+ lwalk = BMW_addstate(walker);
+ *lwalk = owalk;
+ lwalk->cur = l->e;
+ lwalk->lastv = v;
+ BLI_ghash_insert(walker->visithash, l->e, NULL);
+ }
+ }
+
+ return owalk.cur;
+}
+
+/* Face Loop Walker:
+ *
+ * Starts at a tool-flagged face and walks over the face loop
+ * Conditions for starting and stepping the face loop have been
+ * tuned in an attempt to match the face loops built by EditMesh
+ *
+*/
+
+/*Check whether the face loop should includes the face specified
+ by the given BMLoop*/
+static int faceloopWalker_include_face(BMWalker *walker, BMLoop *l)
+{
+ /*face must have degree 4*/
+ if (l->f->len != 4)
+ return 0;
+
+ /*the face must not have been already visited*/
+ if (BLI_ghash_haskey(walker->visithash, l->f))
+ return 0;
+
+ return 1;
+}
+
+/*Check whether the face loop can start from the given edge*/
+static int faceloopWalker_edge_begins_loop(BMWalker *walker, BMEdge *e)
+{
+ BMesh *bm = walker->bm;
+
+ /*There is no face loop starting from a wire edges*/
+ if (BM_Wire_Edge(bm, e)) {
+ return 0;
+ }
+
+ /*Don't start a loop from a boundary edge if it cannot
+ be extended to cover any faces*/
+ if (BM_Edge_FaceCount(e) == 1) {
+ if (!faceloopWalker_include_face(walker, e->l))
+ return 0;
+ }
+
+ /*Don't start a face loop from non-manifold edges*/
+ if (BM_Nonmanifold_Edge(bm, e)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static void faceloopWalker_begin(BMWalker *walker, void *data)
+{
+ faceloopWalker *lwalk, owalk;
+ BMEdge *e = data;
+ /* BMesh *bm = walker->bm; */ /* UNUSED */
+ /* int fcount = BM_Edge_FaceCount(e); */ /* UNUSED */
+
+ if (!faceloopWalker_edge_begins_loop(walker, e))
+ return;
+
+ lwalk = BMW_addstate(walker);
+ lwalk->l = e->l;
+ lwalk->nocalc = 0;
+ BLI_ghash_insert(walker->visithash, lwalk->l->f, NULL);
+
+ /*rewind*/
+ while (BMW_currentstate(walker)) {
+ owalk = *((faceloopWalker*)BMW_currentstate(walker));
+ BMW_walk(walker);
+ }
+
+ lwalk = BMW_addstate(walker);
+ *lwalk = owalk;
+ lwalk->nocalc = 0;
+
+ BLI_ghash_free(walker->visithash, NULL, NULL);
+ walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh walkers 3");
+ BLI_ghash_insert(walker->visithash, lwalk->l->f, NULL);
+}
+
+static void *faceloopWalker_yield(BMWalker *walker)
+{
+ faceloopWalker *lwalk = BMW_currentstate(walker);
+
+ if (!lwalk) return NULL;
+
+ return lwalk->l->f;
+}
+
+static void *faceloopWalker_step(BMWalker *walker)
+{
+ faceloopWalker *lwalk = BMW_currentstate(walker);
+ BMFace *f = lwalk->l->f;
+ BMLoop *l = lwalk->l, *origl = lwalk->l;
+
+ BMW_removestate(walker);
+
+ l = l->radial_next;
+
+ if (lwalk->nocalc)
+ return f;
+
+ if (!faceloopWalker_include_face(walker, l)) {
+ l = lwalk->l;
+ l = l->next->next;
+ if (BM_Edge_FaceCount(l->e) != 2) {
+ l = l->prev->prev;
+ }
+ l = l->radial_next;
+ }
+
+ if (faceloopWalker_include_face(walker, l)) {
+ lwalk = BMW_addstate(walker);
+ lwalk->l = l;
+
+ if (l->f->len != 4) {
+ lwalk->nocalc = 1;
+ lwalk->l = origl;
+ } else
+ lwalk->nocalc = 0;
+
+ BLI_ghash_insert(walker->visithash, l->f, NULL);
+ }
+
+ return f;
+}
+
+/* Edge Ring Walker:
+ *
+ * Starts at a tool-flagged edge and walks over the edge ring
+ * Conditions for starting and stepping the edge ring have been
+ * tuned in an attempt to match the edge rings built by EditMesh
+ *
+*/
+
+static void edgeringWalker_begin(BMWalker *walker, void *data)
+{
+ edgeringWalker *lwalk, owalk;
+ BMEdge *e = data;
+
+ lwalk = BMW_addstate(walker);
+ lwalk->l = e->l;
+
+ if (!lwalk->l) {
+ lwalk->wireedge = e;
+ return;
+ } else {
+ lwalk->wireedge = NULL;
+ }
+
+ BLI_ghash_insert(walker->visithash, lwalk->l->e, NULL);
+
+ /*rewind*/
+ while (BMW_currentstate(walker)) {
+ owalk = *((edgeringWalker*)BMW_currentstate(walker));
+ BMW_walk(walker);
+ }
+
+ lwalk = BMW_addstate(walker);
+ *lwalk = owalk;
+
+ if (lwalk->l->f->len != 4)
+ lwalk->l = lwalk->l->radial_next;
+
+ BLI_ghash_free(walker->visithash, NULL, NULL);
+ walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh walkers 4");
+ BLI_ghash_insert(walker->visithash, lwalk->l->e, NULL);
+}
+
+static void *edgeringWalker_yield(BMWalker *walker)
+{
+ edgeringWalker *lwalk = BMW_currentstate(walker);
+
+ if (!lwalk) return NULL;
+
+ if (lwalk->l)
+ return lwalk->l->e;
+ else
+ return lwalk->wireedge;
+}
+
+static void *edgeringWalker_step(BMWalker *walker)
+{
+ edgeringWalker *lwalk = BMW_currentstate(walker);
+ BMEdge *e;
+ BMLoop *l = lwalk->l /* , *origl = lwalk->l */;
+ BMesh *bm = walker->bm;
+
+ BMW_removestate(walker);
+
+ if (!l)
+ return lwalk->wireedge;
+
+ e = l->e;
+ if (BM_Nonmanifold_Edge(bm, e)) {
+ /*walker won't traverse to a non-manifold edge, but may
+ be started on one, and should not traverse *away* from
+ a non-manfold edge (non-manifold edges are never in an
+ edge ring with manifold edges*/
+ return e;
+ }
+
+ l = l->radial_next;
+ l = l->next->next;
+
+ if ((l->f->len != 4) || BM_Nonmanifold_Edge(bm, l->e)) {
+ l = lwalk->l->next->next;
+ }
+
+ /*only walk to manifold edges*/
+ if ((l->f->len == 4) && !BM_Nonmanifold_Edge(bm, l->e) &&
+ !BLI_ghash_haskey(walker->visithash, l->e)) {
+ lwalk = BMW_addstate(walker);
+ lwalk->l = l;
+ lwalk->wireedge = NULL;
+
+ BLI_ghash_insert(walker->visithash, l->e, NULL);
+ }
+
+ return e;
+}
+
+static void uvedgeWalker_begin(BMWalker *walker, void *data)
+{
+ uvedgeWalker *lwalk;
+ BMLoop *l = data;
+
+ if (BLI_ghash_haskey(walker->visithash, l))
+ return;
+
+ lwalk = BMW_addstate(walker);
+ lwalk->l = l;
+ BLI_ghash_insert(walker->visithash, l, NULL);
+}
+
+static void *uvedgeWalker_yield(BMWalker *walker)
+{
+ uvedgeWalker *lwalk = BMW_currentstate(walker);
+
+ if (!lwalk) return NULL;
+
+ return lwalk->l;
+}
+
+static void *uvedgeWalker_step(BMWalker *walker)
+{
+ uvedgeWalker *lwalk = BMW_currentstate(walker);
+ BMLoop *l, *l2, *l3, *nl, *cl;
+ BMIter liter;
+ void *d1, *d2;
+ int i, j, rlen, type;
+
+ l = lwalk->l;
+ nl = l->next;
+ type = walker->bm->ldata.layers[walker->flag].type;
+
+ BMW_removestate(walker);
+
+ if (walker->restrictflag && !BMO_TestFlag(walker->bm, l->e, walker->restrictflag))
+ return l;
+
+ /*go over loops around l->v and nl->v and see which ones share l and nl's
+ mloopuv's coordinates. in addition, push on l->next if necassary.*/
+ for (i=0; i<2; i++) {
+ cl = i ? nl : l;
+ BM_ITER(l2, &liter, walker->bm, BM_LOOPS_OF_VERT, cl->v) {
+ d1 = CustomData_bmesh_get_layer_n(&walker->bm->ldata,
+ cl->head.data, walker->flag);
+
+ rlen = BM_Edge_FaceCount(l2->e);
+ for (j=0; j<rlen; j++) {
+ if (BLI_ghash_haskey(walker->visithash, l2))
+ continue;
+ if (walker->restrictflag && !(BMO_TestFlag(walker->bm, l2->e, walker->restrictflag)))
+ {
+ if (l2->v != cl->v)
+ continue;
+ }
+
+ l3 = l2->v != cl->v ? l2->next : l2;
+ d2 = CustomData_bmesh_get_layer_n(&walker->bm->ldata,
+ l3->head.data, walker->flag);
+
+ if (!CustomData_data_equals(type, d1, d2))
+ continue;
+
+ lwalk = BMW_addstate(walker);
+ BLI_ghash_insert(walker->visithash, l2, NULL);
+
+ lwalk->l = l2;
+
+ l2 = l2->radial_next;
+ }
+ }
+ }
+
+ return l;
+}
+
+static BMWalker shell_walker_type = {
+ shellWalker_begin,
+ shellWalker_step,
+ shellWalker_yield,
+ sizeof(shellWalker),
+ BMW_BREADTH_FIRST,
+};
+
+static BMWalker islandbound_walker_type = {
+ islandboundWalker_begin,
+ islandboundWalker_step,
+ islandboundWalker_yield,
+ sizeof(islandboundWalker),
+ BMW_DEPTH_FIRST,
+};
+
+static BMWalker island_walker_type = {
+ islandWalker_begin,
+ islandWalker_step,
+ islandWalker_yield,
+ sizeof(islandWalker),
+ BMW_BREADTH_FIRST,
+};
+
+static BMWalker loop_walker_type = {
+ loopWalker_begin,
+ loopWalker_step,
+ loopWalker_yield,
+ sizeof(loopWalker),
+ BMW_DEPTH_FIRST,
+};
+
+static BMWalker faceloop_walker_type = {
+ faceloopWalker_begin,
+ faceloopWalker_step,
+ faceloopWalker_yield,
+ sizeof(faceloopWalker),
+ BMW_DEPTH_FIRST,
+};
+
+static BMWalker edgering_walker_type = {
+ edgeringWalker_begin,
+ edgeringWalker_step,
+ edgeringWalker_yield,
+ sizeof(edgeringWalker),
+ BMW_DEPTH_FIRST,
+};
+
+static BMWalker loopdata_region_walker_type = {
+ uvedgeWalker_begin,
+ uvedgeWalker_step,
+ uvedgeWalker_yield,
+ sizeof(uvedgeWalker),
+ BMW_DEPTH_FIRST,
+};
+
+static BMWalker connected_vertex_walker_type = {
+ connectedVertexWalker_begin,
+ connectedVertexWalker_step,
+ connectedVertexWalker_yield,
+ sizeof(connectedVertexWalker),
+ BMW_BREADTH_FIRST,
+};
+
+BMWalker *bm_walker_types[] = {
+ &shell_walker_type,
+ &loop_walker_type,
+ &faceloop_walker_type,
+ &edgering_walker_type,
+ &loopdata_region_walker_type,
+ &islandbound_walker_type,
+ &island_walker_type,
+ &connected_vertex_walker_type,
+};
+
+int bm_totwalkers = sizeof(bm_walker_types) / sizeof(*bm_walker_types);
diff --git a/source/blender/bmesh/intern/bmesh_walkers_private.h b/source/blender/bmesh/intern/bmesh_walkers_private.h
new file mode 100644
index 00000000000..a087cbbef11
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_walkers_private.h
@@ -0,0 +1,87 @@
+/**
+ * bmesh_walkers_private.h april 2011
+ *
+ * BMesh walker API.
+ *
+ * $Id: $
+ *
+ * ***** 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Joseph Eagar, Geoffrey Bantle.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+extern BMWalker *bm_walker_types[];
+extern int bm_totwalkers;
+
+
+/* Pointer hiding*/
+typedef struct bmesh_walkerGeneric{
+ Link link;
+ int depth;
+} bmesh_walkerGeneric;
+
+
+typedef struct shellWalker{
+ bmesh_walkerGeneric header;
+ BMEdge *curedge;
+} shellWalker;
+
+typedef struct islandboundWalker {
+ bmesh_walkerGeneric header;
+ BMLoop *base;
+ BMVert *lastv;
+ BMLoop *curloop;
+} islandboundWalker;
+
+typedef struct islandWalker {
+ bmesh_walkerGeneric header;
+ BMFace *cur;
+} islandWalker;
+
+typedef struct loopWalker {
+ bmesh_walkerGeneric header;
+ BMEdge *cur, *start;
+ BMVert *lastv, *startv;
+ int startrad, stage2;
+} loopWalker;
+
+typedef struct faceloopWalker {
+ bmesh_walkerGeneric header;
+ BMLoop *l;
+ int nocalc;
+} faceloopWalker;
+
+typedef struct edgeringWalker {
+ bmesh_walkerGeneric header;
+ BMLoop *l;
+ BMEdge *wireedge;
+} edgeringWalker;
+
+typedef struct uvedgeWalker {
+ bmesh_walkerGeneric header;
+ BMLoop *l;
+} uvedgeWalker;
+
+typedef struct connectedVertexWalker {
+ bmesh_walkerGeneric header;
+ BMVert *curvert;
+} connectedVertexWalker;
diff --git a/source/blender/bmesh/intern/editmesh_to_bmesh.c b/source/blender/bmesh/intern/editmesh_to_bmesh.c
new file mode 100644
index 00000000000..89e03277dd4
--- /dev/null
+++ b/source/blender/bmesh/intern/editmesh_to_bmesh.c
@@ -0,0 +1,476 @@
+#if 0
+
+#include "MEM_guardedalloc.h"
+#include "BKE_customdata.h"
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include <string.h>
+#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+
+#include "BLI_editVert.h"
+#include "mesh_intern.h"
+#include "ED_mesh.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+#include "BLI_array.h"
+
+#include "bmesh.h"
+
+/*
+ * EDITMESH TO BMESH.C
+ *
+ * This file contains functions
+ * for converting an editmesh
+ * into a Bmesh
+ *
+*/
+
+/*
+ * EDITMESH CORNERS TO LOOPS
+ *
+ * Converts editmesh face corner data
+ * (UVs, Vert colors, ect) to N-Gon
+ * face-edge ('loop') data.
+ *
+*/
+
+static void editmesh_corners_to_loops(BMesh *bm, CustomData *facedata, void *face_block, BMFace *f,int numCol, int numTex){
+ int i, j;
+ BMLoop *l;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ BMIter iter;
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i);
+ texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
+
+ texpoly->tpage = texface->tpage;
+ texpoly->flag = texface->flag;
+ texpoly->transp = texface->transp;
+ texpoly->mode = texface->mode;
+ texpoly->tile = texface->tile;
+ texpoly->unwrap = texface->unwrap;
+
+ for (j=0, l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f); l; j++, l=BMIter_Step(&iter)) {
+ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
+ mloopuv->uv[0] = texface->uv[j][0];
+ mloopuv->uv[1] = texface->uv[j][1];
+ }
+
+ }
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i);
+ for (j=0, l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f); l; j++, l=BMIter_Step(&iter)) {
+ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
+ mloopcol->r = mcol[j].r;
+ mloopcol->g = mcol[j].g;
+ mloopcol->b = mcol[j].b;
+ mloopcol->a = mcol[j].a;
+ }
+ }
+}
+
+/*
+ * EDITVERT TO BMVert
+ *
+ * Converts an editvert to
+ * a BMVert.
+ *
+*/
+
+static BMVert *editvert_to_BMVert(BMesh *bm, BMOperator *op, EditMesh *em, EditVert *eve)
+{
+ BMVert *v = NULL;
+
+ v = BM_Make_Vert(bm, eve->co, NULL);
+ VECCOPY(v->no, eve->no);
+
+ /*transfer flags*/
+ v->head.flag = eve->h ? BM_HIDDEN : 0;
+ if(eve->f & SELECT) BM_Select_Vert(bm, v, 1);
+ v->bweight = eve->bweight;
+
+ BMO_Insert_MapPointer(bm, op, "map", eve, v);
+
+ /*Copy Custom Data*/
+ CustomData_bmesh_copy_data(&em->vdata, &bm->vdata, eve->data, &v->head.data);
+
+ return v;
+}
+
+/*
+ * EDITEDGE TO BMEdge
+ *
+ * Converts an editedge to
+ * a BMEdge
+ *
+*/
+
+static void editedge_to_BMEdge_internal(BMesh *bm, BMOperator *op, EditMesh *em, BMEdge *e, EditEdge *eed)
+{
+ e->crease = eed->crease;
+ e->bweight = eed->bweight;
+
+ BM_Select(bm, e, eed->f & SELECT);
+ e->head.flag |= eed->seam ? BM_SEAM : 0;
+ e->head.flag |= eed->h & 1 ? BM_HIDDEN : 0;
+ e->head.flag |= eed->h & EM_FGON ? BM_FGON : 0;
+ e->head.flag |= eed->sharp ? BM_SHARP : 0;
+
+ CustomData_bmesh_copy_data(&em->edata, &bm->edata, eed->data, &e->head.data);
+
+ BMO_Insert_MapPointer(bm, op, "map", eed, e);
+}
+
+static BMEdge *editedge_to_BMEdge(BMesh *bm, BMOperator *op, EditMesh *em, EditEdge *eed)
+{
+ BMVert *v1 = NULL, *v2 = NULL;
+ BMEdge *e = NULL;
+
+ v1 = eed->v1->tmp.p;
+ v2 = eed->v2->tmp.p;
+
+ e = BM_Make_Edge(bm, v1, v2,NULL, 0);
+
+ editedge_to_BMEdge_internal(bm, op, em, e, eed);
+
+ return e;
+}
+/*
+ * EDITFACE TO BMFace
+ *
+ * Converts an editface to a BMFace.
+ * Note that this also convert per-face
+ * corner data as well.
+ *
+*/
+
+static BMFace *editface_to_BMFace(BMesh *bm, BMOperator *op, EditMesh *em, EditFace *efa, int numCol, int numTex)
+{
+ BMVert *v1 = NULL, *v2 = NULL;
+ BMFace *f = NULL;
+ BMEdge *edar[4];
+ int len;
+
+ edar[0] = BM_Make_Edge(bm, efa->v1->tmp.p, efa->v2->tmp.p, NULL, 1);
+ edar[1] = BM_Make_Edge(bm, efa->v2->tmp.p, efa->v3->tmp.p, NULL, 1);
+ if(efa->v4){
+ edar[2] = BM_Make_Edge(bm, efa->v3->tmp.p, efa->v4->tmp.p, NULL, 1);
+ edar[3] = BM_Make_Edge(bm, efa->v4->tmp.p, efa->v1->tmp.p, NULL, 1);
+ }else{
+ edar[2] = BM_Make_Edge(bm, efa->v3->tmp.p, efa->v1->tmp.p, NULL, 1);
+ }
+
+ editedge_to_BMEdge_internal(bm, op, em, edar[0], efa->e1);
+ editedge_to_BMEdge_internal(bm, op, em, edar[1], efa->e2);
+ editedge_to_BMEdge_internal(bm, op, em, edar[2], efa->e3);
+ if(efa->v4)
+ editedge_to_BMEdge_internal(bm, op, em, edar[3], efa->e4);
+
+
+ if(efa->e1->fgoni) edar[0]->head.flag |= BM_FGON;
+ if(efa->e2->fgoni) edar[1]->head.flag |= BM_FGON;
+ if(efa->e3->fgoni) edar[2]->head.flag |= BM_FGON;
+ if(efa->v4 && efa->e4->fgoni) edar[3]->head.flag |= BM_FGON;
+
+ if(efa->v4) len = 4;
+ else len = 3;
+
+ /*find v1 and v2*/
+ v1 = efa->v1->tmp.p;
+ v2 = efa->v2->tmp.p;
+
+ f = BM_Make_Ngon(bm, v1, v2, edar, len, 0);
+
+ VECCOPY(f->no, efa->n);
+
+ BMO_Insert_MapPointer(bm, op, "map", efa, f);
+
+ f->head.flag = 0;
+ f->mat_nr = efa->mat_nr;
+ if(efa->f & SELECT) BM_Select_Face(bm, f, 1);
+ if (efa->flag & ME_SMOOTH) f->head.flag |= BM_SMOOTH;
+ if(efa->h) f->head.flag |= BM_HIDDEN;
+
+ if (efa == em->act_face) f->head.flag |= BM_ACTIVE;
+
+ CustomData_bmesh_copy_data(&em->fdata, &bm->pdata, efa->data, &f->head.data);
+ editmesh_corners_to_loops(bm, &em->fdata, efa->data, f,numCol,numTex);
+
+ return f;
+}
+
+/*
+ * BMESH FGONCONVERT
+ *
+ * This function and its associated structures
+ * /helpers (fgonsort, sortfgon, fuse_fgon) are
+ * used to convert f-gons to bmesh n-gons. This
+ * is accomplished by sorting a list of fgon faces
+ * such that faces that are part of the same fgon
+ * are next to each other. These faces are then
+ * converted as is into bmesh faces and
+ * fused togather.
+ *
+ * Note that currently, there is no support for
+ * holes in faces in the bmesh structure, so
+ * f-gons with holes will only partially convert.
+ *
+*/
+
+typedef struct fgonsort {
+ unsigned long x;
+ struct EditFace *efa;
+ struct BMFace *f;
+ int done;
+}fgonsort;
+
+static int sortfgon(const void *v1, const void *v2)
+{
+ const struct fgonsort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+
+static void fuse_fgon(BMesh *bm, BMFace *f)
+{
+ BMFace *sf;
+ BMLoop *l;
+ int done, act=0;
+
+ sf = f;
+ done = 0;
+ while(!done){
+ done = 1;
+ l = sf->loopbase;
+ do{
+ if(l->e->head.flag & BM_FGON) {
+ if (l->f->head.flag & BM_ACTIVE) act = BM_ACTIVE;
+ if (l->radial.next->data->f->head.flag & BM_ACTIVE) act = BM_ACTIVE;
+
+ sf = BM_Join_TwoFaces(bm,l->f, l->radial.next->data->f, l->e);
+ if (!sf) {
+ //tesselation error
+ break;
+ }
+
+ sf->head.flag |= act;
+ if(sf){
+ done = 0;
+ break;
+ } else { /*we have to get out of here...*/
+ return;
+ }
+ }
+ l = l->next;
+ }while(l != sf->loopbase);
+ }
+}
+
+static BM_fgonconvert(BMesh *bm, BMOperator *op, EditMesh *em, int numCol, int numTex)
+{
+ EditFace *efa;
+ BMFace *f;
+ BMIter iter;
+ struct fgonsort *sortblock, *sb, *sb1;
+ int a, b, amount=0;
+
+ /*
+ for (efa=em->faces.first; efa; efa=efa->next) {
+ f = editface_to_BMFace(bm, em, efa, numCol, numTex);
+ }
+
+ for (f=bm->polys.first; f; f=f->next) {
+ fuse_fgon(bm, f);
+ }
+
+ return;*/
+
+ EM_fgon_flags(em);
+
+ /*zero out efa->tmp, we store fgon index here*/
+ for(efa = em->faces.first; efa; efa = efa->next){
+ efa->tmp.l = 0;
+ amount++;
+ }
+ /*go through and give each editface an fgon index*/
+ for(efa = em->faces.first; efa; efa = efa->next){
+ if(efa->e1->fgoni) efa->tmp.l = efa->e1->fgoni;
+ else if(efa->e2->fgoni) efa->tmp.l = efa->e2->fgoni;
+ else if(efa->e3->fgoni) efa->tmp.l = efa->e3->fgoni;
+ else if(efa->e4 && efa->e4->fgoni) efa->tmp.l = efa->e4->fgoni;
+ }
+
+ sb= sortblock= MEM_mallocN(sizeof(fgonsort)* amount,"fgon sort block");
+
+ for(efa = em->faces.first; efa; efa=efa->next){
+ sb->x = efa->tmp.l;
+ sb->efa = efa;
+ sb->done = 0;
+ sb++;
+ }
+
+ qsort(sortblock, amount, sizeof(fgonsort), sortfgon);
+
+ sb = sortblock;
+ for(a=0; a<amount; a++, sb++) {
+ if(sb->x && sb->done == 0){
+ /*first pass: add in faces for this fgon*/
+ for(b=a, sb1 = sb; b<amount && sb1->x == sb->x; b++, sb1++){
+ efa = sb1->efa;
+ sb1->f = editface_to_BMFace(bm, op, em, efa, numCol, numTex);
+ sb1->done = 1;
+ }
+ /*fuse fgon*/
+ fuse_fgon(bm, sb->f);
+ }
+ }
+ MEM_freeN(sortblock);
+}
+
+/*
+ * TAG WIRE EDGES
+ *
+ * Flags editedges 'f1' member
+ * if the edge has no faces.
+ *
+*/
+
+static void tag_wire_edges(EditMesh *em){
+ EditFace *efa;
+ EditEdge *eed;
+ for(eed = em->edges.first; eed; eed = eed->next) eed->f1 = 1;
+ for(efa = em->faces.first; efa; efa = efa->next){
+ efa->e1->f1 = 0;
+ efa->e2->f1 = 0;
+ efa->e3->f1 = 0;
+ if(efa->e4) efa->e4->f1 = 0;
+ }
+}
+
+/*
+ * EDITMESH TO BMESH
+ *
+ * Function to convert an editmesh to a bmesh
+ * Currently all custom data as well as
+ * f-gons should be converted correctly.
+ *
+*/
+
+BMesh *editmesh_to_bmesh_intern(EditMesh *em, BMesh *bm, BMOperator *op) {
+ BMVert *v;
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+ BMEdge *e;
+ BMIter iter;
+ int allocsize[4] = {512,512,2048,512}, numTex, numCol;
+
+ /*make sure to update FGon flags*/
+ EM_fgon_flags(em);
+
+ /*copy custom data layout*/
+ CustomData_copy(&em->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&em->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+ /*copy face corner data*/
+ CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata, 0, 0);
+
+ CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
+
+ /*needed later*/
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ /*copy over selection mode*/
+ bm->selectmode = 0;
+ if(em->selectmode & SCE_SELECT_VERTEX) bm->selectmode |= SCE_SELECT_VERTEX;
+ if(em->selectmode & SCE_SELECT_EDGE) bm->selectmode |= SCE_SELECT_EDGE;
+ if(em->selectmode & SCE_SELECT_FACE) bm->selectmode |= SCE_SELECT_FACE;
+
+
+ /*begin editloop*/
+ //BM_Begin_Edit(bm);
+
+ /*tag wire edges*/
+ tag_wire_edges(em);
+
+ /*add verts*/
+ for(eve = em->verts.first; eve; eve = eve->next){
+ v = editvert_to_BMVert(bm, op, em, eve);
+ eve->tmp.p = v;
+ }
+ /*convert f-gons*/
+ BM_fgonconvert(bm, op, em, numCol, numTex);
+
+ /*clean up any dangling fgon flags*/
+ for (e=BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); e; e=BMIter_Step(&iter)){
+ e->head.flag &= ~BM_FGON;
+ }
+
+ /*do quads + triangles*/
+ for(efa = em->faces.first; efa; efa = efa->next){
+ if(!efa->tmp.l) editface_to_BMFace(bm, op, em, efa, numCol, numTex);
+ }
+
+ /*add wire edges*/
+ for(eed = em->edges.first; eed; eed = eed->next){
+ if(eed->f1) editedge_to_BMEdge(bm, op, em, eed);
+ }
+ //BM_end_edit(bm, BM_CALC_NORM);
+ return bm;
+}
+
+void edit2bmesh_exec(BMesh *bmesh, BMOperator *op)
+{
+ editmesh_to_bmesh_intern(BMO_Get_Pnt(op, "em"), bmesh, op);
+}
+
+BMesh *editmesh_to_bmesh(EditMesh *em)
+{
+ BMOperator conv;
+ BMesh *bm;
+ int allocsize[4] = {512,512,2048,512};
+
+ /*allocate a bmesh*/
+ bm = BM_Make_Mesh(allocsize);
+
+ BMO_Init_Op(&conv, "editmesh_to_bmesh");
+ BMO_Set_Pnt(&conv, "em", em);
+ BMO_Exec_Op(bm, &conv);
+ BMO_Finish_Op(bm, &conv);
+
+ return bm;
+}
+
+BMesh *init_editmesh_to_bmesh(EditMesh *em, BMOperator *op)
+{
+ BMesh *bm;
+ int allocsize[4] = {512,512,2048,512}, numTex, numCol;
+
+ /*allocate a bmesh*/
+ bm = BM_Make_Mesh(allocsize);
+
+ BMO_Init_Op(op, "editmesh_to_bmesh");
+ BMO_Set_Pnt(op, "em", em);
+
+ return bm;
+}
+#endif
diff --git a/source/blender/bmesh/intern/in-progress/BME_conversions.c b/source/blender/bmesh/intern/in-progress/BME_conversions.c
new file mode 100644
index 00000000000..d39bf689e76
--- /dev/null
+++ b/source/blender/bmesh/intern/in-progress/BME_conversions.c
@@ -0,0 +1,478 @@
+/**
+ * BME_conversions.c August 2008
+ *
+ * BM to Derived Mesh conversion functions.
+ *
+ * ***** 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.
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle, Levi Schooley.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+#include "BKE_customdata.h"
+
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
+#include "bmesh.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_edgehash.h"
+#include "bmesh_private.h"
+
+
+
+/*
+ * BMESH DERIVED MESH CONVERSION FUNCTIONS
+ *
+ * The functions in this file provides
+ * methods for converting to and from
+ * a bmesh.
+ *
+*/
+
+
+/*
+ * DMCORNERS TO LOOPS
+ *
+ * Function to convert derived mesh per-face
+ * corner data (uvs, vertex colors), to n-gon
+ * per-loop data.
+ *
+*/
+
+static void DMcorners_to_loops(BMMesh *bm, CustomData *facedata, int index, BMFace *f, int numCol, int numTex){
+ int i, j;
+ BMLoop *l;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+
+ for(i=0; i< numTex; i++){
+ texface = CustomData_get_layer_n(facedata, CD_MTFACE, i);
+ texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
+
+ texpoly->tpage = texface[index].tpage;
+ texpoly->flag = texface[index].flag;
+ texpoly->transp = texface[index].transp;
+ texpoly->mode = texface[index].mode;
+ texpoly->tile = texface[index].tile;
+ texpoly->unwrap = texface[index].unwrap;
+
+ j = 0;
+ l = f->loopbase;
+ do{
+ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
+ mloopuv->uv[0] = texface[index].uv[j][0];
+ mloopuv->uv[1] = texface[index].uv[j][1];
+ j++;
+ l = l->next;
+ }while(l!=f->loopbase);
+ }
+
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_get_layer_n(facedata, CD_MCOL, i);
+ j = 0;
+ l = f->loopbase;
+ do{
+ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
+ mloopcol->r = mcol[(index*4)+j].r;
+ mloopcol->g = mcol[(index*4)+j].g;
+ mloopcol->b = mcol[(index*4)+j].b;
+ mloopcol->a = mcol[(index*4)+j].a;
+ j++;
+ l = l->next;
+ }while(l!=f->loopbase);
+ }
+}
+
+/*
+ * LOOPS TO DMCORNERS
+ *
+ * Function to convert n-gon per-loop data
+ * (uvs, vertex colors, ect)to derived mesh
+ * face corner data.
+ *
+*/
+
+static void loops_to_DMcorners(BMMesh *bm, CustomData *facedata, int index, BMFace *f,int numCol, int numTex){
+ int i, j;
+ BMLoop *l;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_layer_n(facedata, CD_MTFACE, i);
+ texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
+
+ texface[index].tpage = texpoly->tpage;
+ texface[index].flag = texpoly->flag;
+ texface[index].transp = texpoly->transp;
+ texface[index].mode = texpoly->mode;
+ texface[index].tile = texpoly->tile;
+ texface[index].unwrap = texpoly->unwrap;
+
+ j = 0;
+ l = f->loopbase;
+ do{
+ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
+ texface[index].uv[j][0] = mloopuv->uv[0];
+ texface[index].uv[j][1] = mloopuv->uv[1];
+ j++;
+ l = l->next;
+ }while(l!=f->loopbase);
+
+ }
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_get_layer_n(facedata,CD_MCOL, i);
+ j = 0;
+ l = f->loopbase;
+ do{
+ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
+ mcol[(index*4) + j].r = mloopcol->r;
+ mcol[(index*4) + j].g = mloopcol->g;
+ mcol[(index*4) + j].b = mloopcol->b;
+ mcol[(index*4) + j].a = mloopcol->a;
+ j++;
+ l = l->next;
+ }while(l!=f->loopbase);
+ }
+}
+
+/*
+ * MVERT TO BMESHVERT
+ *
+ * Converts a MVert to a BMVert
+ *
+*/
+static BMVert *mvert_to_bmeshvert(BMMesh *bm, BMVert **vert_array, int index, MVert *mv, CustomData *data)
+{
+ BMVert *v = NULL;
+
+ v = bmesh_make_vert(bm, mv->co, NULL);
+ vert_array[index] = v;
+ if(mv->flag & SELECT) bmesh_set_flag(v, BMESH_SELECT);
+ v->bweight = mv->bweight/255.0f;
+ CustomData_to_bmesh_block(data, &bm->vdata, index, &v->data);
+
+ return v;
+}
+
+/*
+ * MEDGE TO BMESHEDGE
+ *
+ * Converts a MEdge to a BMEdge
+ *
+*/
+
+static BMEdge *medge_to_bmeshedge(BMMesh *bm, BMVert **vert_array, int index, MEdge *me, CustomData *data, Edge_Hash *edge_hash)
+{
+ BMVert *v1, *v2;
+ BMEdge *e = NULL;
+
+ v1 = vert_array[me->v1];
+ v2 = vert_array[me->v2];
+ e = bmesh_make_edge(bm, v1, v2, NULL, 0);
+ e->crease = me->crease/255.0f;
+ e->bweight = me->bweight/255.0f;
+ if(me->flag & 1) bmesh_set_flag(e, BMESH_SELECT);
+ if(me->flag & ME_SEAM) bmesh_set_flag(e, BMESH_SEAM);
+ BLI_edgehash_insert(edge_hash,me->v1,me->v2,e);
+ CustomData_to_bmesh_block(data, &bm->edata, index, &e->data);
+
+ return e;
+}
+
+/*
+ * MFACE TO BMESHFACE
+ *
+ * Converts a MFace to a BMFace.
+ * Note that this will fail on eekadoodle
+ * faces.
+ *
+*/
+
+static BMFace *mface_to_bmeshface(BMMesh *bm, BMVert **vert_array, int index, MFace *mf, CustomData *data, Edge_Hash *edge_hash)
+{
+ BMVert *v1, *v2;
+ BMEdge *edar[4];
+ BMFace *f = NULL;
+ int len;
+
+ if(mf->v4) len = 4;
+ else len = 3;
+
+ edar[0] = BLI_edgehash_lookup(edge_hash,mf->v1,mf->v2);
+ edar[1] = BLI_edgehash_lookup(edge_hash,mf->v2,mf->v3);
+ if(len == 4){
+ edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v4);
+ edar[3] = BLI_edgehash_lookup(edge_hash,mf->v4,mf->v1);
+ }
+ else
+ edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v1);
+
+ /*find v1 and v2*/
+ v1 = vert_array[mf->v1];
+ v2 = vert_array[mf->v2];
+
+ f = bmesh_make_ngon(bm, v1, v2, edar, len, 0);
+ f->mat_nr = mf->mat_nr;
+ if(mf->flag & 1) bmesh_set_flag(f, BMESH_SELECT);
+ if(mf->flag & ME_HIDE) bmesh_set_flag(f, BMESH_HIDDEN);
+ CustomData_to_bmesh_block(data, &bm->pdata, index, &f->data);
+
+ return f;
+}
+
+/*
+ * DERIVEDMESH TO BMESH
+ *
+ * Converts a derived mesh to a bmesh.
+ *
+*/
+
+BMMesh *derivedmesh_to_bmesh(DerivedMesh *dm)
+{
+
+ BMMesh *bm;
+ BMVert **vert_array;
+ BMFace *f=NULL;
+
+ MVert *mvert, *mv;
+ MEdge *medge, *me;
+ MFace *mface, *mf;
+
+ int totface,totedge,totvert,i,len, numTex, numCol;
+ int allocsize[4] = {512,512,2048,512};
+
+ EdgeHash *edge_hash = BLI_edgehash_new();
+
+ /*allocate a new bmesh*/
+ bm = bmesh_make_mesh(allocsize);
+
+ /*copy custom data layout*/
+ CustomData_copy(&dm->vertData, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&dm->edgeData, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+ /*copy face corner data*/
+ CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata);
+ /*initialize memory pools*/
+ CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
+
+ /*needed later*/
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ totvert = dm->getNumVerts(dm);
+ totedge = dm->getNumEdges(dm);
+ totface = dm->getNumFaces(dm);
+ mvert = dm->getVertArray(dm);
+ medge = dm->getEdgeArray(dm);
+ mface = dm->getFaceArray(dm);
+
+ vert_array = MEM_mallocN(sizeof(BMVert *)* totvert,"derivedmesh to bmesh vertex pointer array");
+
+ bmesh_begin_edit(bm);
+ /*add verts*/
+ for(i=0, mv = mvert; i < totvert; i++, mv++)
+ mvert_to_bmeshvert(bm, vert_array, i, mv, &dm->vertData);
+
+ /*add edges*/
+ for(i=0, me = medge; i < totedge; i++, me++)
+ medge_to_bmeshedge(bm, vert_array, i, me, &dm->edgeData, edge_hash);
+
+ /*add faces.*/
+ for(i=0, mf = mface; i < totface; i++, mf++){
+ f = mface_to_bmeshface(bm, vert_array, mf, &dm->faceData, edge_hash);
+ if(f) DMcorners_to_loops(bm, &dm->faceData, i, f, numCol, numTex);
+ }
+
+ bmesh_end__edit(bm);
+ BLI_edgehash_free(edge_hash, NULL);
+ MEM_freeN(vert_array);
+ return bm;
+}
+
+static void bmeshvert_to_mvert(BMMesh *bm, BMVert *v, MVert *mv, int index, CustomData *data)
+{
+ VECCOPY(mv->co,v->co);
+ if(bmesh_test_flag(v, BMESH_SELECT)) mv->flag |= 1;
+ if(bmesh_test_flag(v, BMESH_HIDDEN)) mv->flag |= ME_HIDE;
+ mv->bweight = (char)(255.0*v1->bweight);
+ CustomData_from_bmesh_block(&bm->vdata, data, &v1->data, index);
+}
+
+static int bmeshedge_to_medge(BMMesh *bm, BMEdge *e, MEdge *me, int index, CustomData *data)
+{
+ if(e->head.eflag2){
+ if(e->v1->head.eflag1 < e->v2->head.eflag1){
+ me->v1 = e->v1->head.eflag1;
+ me->v2 = e->v2->head.eflag1;
+ }
+ else{
+ me->v1 = e->v2->head.eflag1;
+ me->v2 = e->v1->eflag1;
+ }
+
+ me->crease = (char)(255.0*e->crease);
+ me->bweight = (char)(255.0*e->bweight);
+ if(bmesh_test_flag(e, BMESH_SELECT)) me->flag |= 1;
+ if(bmesh_test_flag(e, BMESH_HIDDEN)) me->flag |= ME_HIDE;
+ CustomData_from_bmesh_block(&bm->edata, data, &e->data, index);
+ return 1;
+ }
+ return 0;
+}
+
+static int bmeshface_to_mface(BMMesh *bm, BMFace *f, MFace *mf, int index, CustomData *data)
+{
+ if(f->len==3 || f->len==4){
+ mf->v1 = f->loopbase->v->head.eflag1;
+ mf->v2 = f->loopbase->next->v->head.eflag1;
+ mf->v3 = f->loopbase->next->next->v->head.eflag1;
+ if(len == 4){
+ mf->v4 = f->loopbase->prev->v->head.eflag1;
+ }
+ /* test and rotate indexes if necessary so that verts 3 and 4 aren't index 0 */
+ if(mf->v3 == 0 || (f->len == 4 && mf->v4 == 0)){
+ test_index_face(mf, NULL, index, f->len);
+ }
+ mf->mat_nr = (unsigned char)f->mat_nr;
+ if(bmesh_test_flag(f, BMESH_SELECT)) mf->flag |= 1;
+ if(bmesh_test_flag(f, BMESH_HIDDEN)) mf->flag |= ME_HIDE;
+ CustomData_from_bmesh_block(&bm->pdata, data, &f->data, index);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * BMESH TO DERIVEDMESH
+ *
+ * Converts a bmesh to a derived mesh.
+ *
+*/
+
+DerivedMesh *bmesh_to_derivedmesh(BMMesh *bm, DerivedMesh *dm)
+{
+ MFace *mface = NULL, *mf = NULL;
+ MEdge *medge = NULL, *me = NULL;
+ MVert *mvert = NULL, *mv = NULL;
+ DerivedMesh *result = NULL;
+
+ BMVert *v=NULL;
+ BMEdge *e=NULL, *oe=NULL;
+ BMFace *f=NULL;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ int totface = 0,totedge = 0,totvert = 0,i = 0, numTex, numCol;
+
+ EdgeHash *edge_hash = BLI_edgehash_new();
+
+ /*get element counts*/
+ totvert = bmesh_count_element(bm, BMESH_VERT);
+
+ /*store element indices. Note that the abuse of eflag here should NOT be duplicated!*/
+ for(i=0, v = bmeshIterator_init(verts, BM_VERTS, bm, 0); v; v = bmeshIterator_step(verts), i++)
+ v->head.eflag1 = i;
+
+ /*we cannot have double edges in a derived mesh!*/
+ for(e = bmeshIterator_init(edges, BM_EDGES, bm, 0); e; e = bmeshIterator_step(edges)){
+ oe = BLI_edgehash_lookup(edge_hash,e->v1->head.eflag1, e->v2->head.eflag1);
+ if(!oe){
+ totedge++;
+ BLI_edgehash_insert(edge_hash,e->v1->head.eflag1,e->v2->head.eflag1,e);
+ e->head.eflag2 = 1;
+ }
+ else{
+ e->head.eflag2 = 0;
+ }
+ }
+
+ /*count quads and tris*/
+ for(f = bmeshIterator_init(faces, BM_FACES, bm, 0); f; f = bmeshIterator_step(faces)){
+ if(f->len == 3 || f->len == 4) totface++;
+ }
+
+ /*Allocate derivedmesh and copy custom data*/
+ result = CDDM_from_template(dm,totvert,totedge,totface);
+ CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_BMESH, CD_CALLOC, totvert);
+ CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_BMESH, CD_CALLOC, totedge);
+ CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_BMESH, CD_CALLOC, totface);
+ CustomData_from_bmeshpoly(&result->faceData, &bm->pdata, &bm->ldata,totface);
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ /*Make Verts*/
+ mvert = CDDM_get_verts(result);
+ for(i = 0, v = bmeshIterator_init(verts, BM_VERTS, bm, 0); v; v = bmeshIterator_step(verts), i++, mv++){
+ bmeshvert_to_mvert(bm,v,mv,i,&result->vertData);
+ }
+
+ /*Make Edges*/
+ medge = CDDM_get_edges(result);
+ i=0;
+ for(e = bmeshIterator_init(edges, BM_EDGES, bm, 0); e; e = bmeshIterator_step(edges)){
+ me = &medge[i];
+ if(bmeshedge_to_medge(bm, e, me, i, &result->edgeData){
+ me++;
+ i++;
+ }
+ }
+ /*Make Faces*/
+ if(totface){
+ mface = CDDM_get_faces(result);
+ i=0;
+ for(f = bmeshIterator_init(faces, BM_FACES, bm, 0); f; f = bmeshIterator_step(faces)){
+ mf = &mface[i];
+ if(bmeshface_to_mface(bm, f, mf, i, &result->faceData)){
+ loops_to_DMcorners(bm, &result->faceData, i, f, numCol, numTex);
+ i++;
+ }
+ }
+ }
+ BLI_edgehash_free(edge_hash, NULL);
+ return result;
+}
diff --git a/source/blender/bmesh/operators/bevel.c b/source/blender/bmesh/operators/bevel.c
new file mode 100644
index 00000000000..717ba0a7621
--- /dev/null
+++ b/source/blender/bmesh/operators/bevel.c
@@ -0,0 +1,825 @@
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_memarena.h"
+#include "BLI_blenlib.h"
+#include "BLI_array.h"
+#include "BLI_math.h"
+#include "BLI_array.h"
+#include "BLI_utildefines.h"
+#include "BLI_smallhash.h"
+
+#include "bmesh.h"
+#include "bmesh_operators_private.h"
+
+#define BEVEL_FLAG 1
+#define BEVEL_DEL 2
+#define FACE_NEW 4
+#define EDGE_OLD 8
+#define FACE_OLD 16
+#define FACE_DONE 32
+#define VERT_OLD 64
+#define FACE_SPAN 128
+#define FACE_HOLE 256
+
+typedef struct LoopTag {
+ BMVert *newv;
+} LoopTag;
+
+typedef struct EdgeTag {
+ BMVert *newv1, *newv2;
+} EdgeTag;
+
+static void calc_corner_co(BMesh *bm, BMLoop *l, float *co, float fac)
+{
+ float no[3], /*tan[3]*,*/ vec1[3], vec2[3], v1[3], v2[3], v3[3], v4[3];
+ /*float p1[3], p2[3], w[3];
+ float l1, l2;*/
+ int /*ret,*/ inv=0;
+
+ if (l->f->len > 2) {
+ copy_v3_v3(v1, l->prev->v->co);
+ copy_v3_v3(v2, l->v->co);
+ copy_v3_v3(v3, l->v->co);
+ copy_v3_v3(v4, l->next->v->co);
+ } else {
+ BMIter iter;
+ BMLoop *l2;
+ float up[3] = {0.0f, 0.0f, 1.0f};
+
+ copy_v3_v3(v1, l->prev->v->co);
+ copy_v3_v3(v2, l->v->co);
+ copy_v3_v3(v3, l->v->co);
+
+ BM_ITER(l2, &iter, bm, BM_LOOPS_OF_VERT, l->v) {
+ if (l2->f != l->f) {
+ copy_v3_v3(v4, BM_OtherEdgeVert(l2->e, l2->next->v)->co);
+ break;
+ }
+ }
+
+ sub_v3_v3v3(vec1, v1, v2);
+ sub_v3_v3v3(vec2, v4, v3);
+
+ cross_v3_v3v3(no, vec1, vec2);
+ if (dot_v3v3(no, no) == 0.0f) {
+ no[0] = no[1] = 0.0f; no[2] = -1.0f;
+ }
+
+ inv = dot_v3v3(no, up) < 0.0f;
+ }
+
+ /*calculate normal*/
+ sub_v3_v3v3(vec1, v1, v2);
+ sub_v3_v3v3(vec2, v4, v3);
+
+#if 0
+ cross_v3_v3v3(no, vec2, vec1);
+ normalize_v3(no);
+
+ if (dot_v3v3(no, no) < FLT_EPSILON*10) {
+ copy_v3_v3(no, l->f->no);
+ }
+
+ if (dot_v3v3(no, no) < FLT_EPSILON*10) {
+ no[0] = 0.0; no[1] = 0.0; no[2] = 1.0f;
+ }
+
+ /*compute offsets*/
+ l1 = len_v3(vec1)*fac; //(1.0-(cos(angle_v3v3(vec1, vec2))*0.5+0.5))
+ l2 = len_v3(vec2)*fac;
+
+ l2 = (l1 + l2)*0.5;
+ l1 = l2;
+ if (dot_v3v3(no, l->f->no) < 0.0) {
+ negate_v3(no);
+ }
+
+ /*compute tangent and offset first edge*/
+ cross_v3_v3v3(tan, vec1, no);
+ normalize_v3(tan);
+
+ mul_v3_fl(tan, l1);
+
+ add_v3_v3(v1, tan);
+ add_v3_v3(v2, tan);
+
+ /*compute tangent and offset second edge*/
+ cross_v3_v3v3(tan, no, vec2);
+ normalize_v3(tan);
+
+ mul_v3_fl(tan, l2);
+
+ add_v3_v3(v3, tan);
+ add_v3_v3(v4, tan);
+
+ /*compute intersection*/
+ ret = isect_line_line_v3(v1, v2, v3, v4, p1, p2);
+
+ if (ret==1) {
+ copy_v3_v3(co, p1);
+ } else if (ret==2) {
+ add_v3_v3v3(co, p1, p2);
+ mul_v3_fl(co, 0.5);
+ } else { /*colinear case*/
+ add_v3_v3v3(co, v2, v3);
+ mul_v3_fl(co, 0.5);
+ }
+#else
+ /*oddly, this simplistic method seems to work the best*/
+ add_v3_v3(vec1, vec2);
+ mul_v3_fl(vec1, fac * 0.5);
+
+ if (inv)
+ negate_v3(vec1);
+
+ add_v3_v3v3(co, vec1, l->v->co);
+#endif
+}
+
+#define ETAG_SET(e, v, nv) (v) == (e)->v1 ? (etags[BM_GetIndex((e))].newv1 = (nv)) : (etags[BM_GetIndex((e))].newv2 = (nv))
+#define ETAG_GET(e, v) ((v) == (e)->v1 ? (etags[BM_GetIndex((e))].newv1) : (etags[BM_GetIndex((e))].newv2))
+
+void bmesh_bevel_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMIter iter;
+ BMEdge *e;
+ BMVert *v;
+ BMFace **faces = NULL, *f;
+ LoopTag *tags=NULL, *tag;
+ EdgeTag *etags = NULL;
+ BMVert **verts = NULL;
+ BMEdge **edges = NULL;
+ BLI_array_declare(faces);
+ BLI_array_declare(tags);
+ BLI_array_declare(etags);
+ BLI_array_declare(verts);
+ BLI_array_declare(edges);
+ SmallHash hash;
+ float fac = BMO_Get_Float(op, "percent");
+ int i, li, has_elens, HasMDisps = CustomData_has_layer(&bm->ldata, CD_MDISPS);
+
+ has_elens = CustomData_has_layer(&bm->edata, CD_PROP_FLT) && BMO_Get_Int(op, "uselengths");
+ if (has_elens) {
+ li = BMO_Get_Int(op, "lengthlayer");
+ }
+
+ BLI_smallhash_init(&hash);
+
+ BMO_ITER(e, &siter, bm, op, "geom", BM_EDGE) {
+ BMO_SetFlag(bm, e, BEVEL_FLAG|BEVEL_DEL);
+ BMO_SetFlag(bm, e->v1, BEVEL_FLAG|BEVEL_DEL);
+ BMO_SetFlag(bm, e->v2, BEVEL_FLAG|BEVEL_DEL);
+
+ if (BM_Edge_FaceCount(e) < 2) {
+ BMO_ClearFlag(bm, e, BEVEL_DEL);
+ BMO_ClearFlag(bm, e->v1, BEVEL_DEL);
+ BMO_ClearFlag(bm, e->v2, BEVEL_DEL);
+ }
+#if 0
+ if (BM_Edge_FaceCount(e) == 0) {
+ BMVert *verts[2] = {e->v1, e->v2};
+ BMEdge *edges[2] = {e, BM_Make_Edge(bm, e->v1, e->v2, e, 0)};
+
+ BMO_SetFlag(bm, edges[1], BEVEL_FLAG);
+ BM_Make_Face(bm, verts, edges, 2, 0);
+ }
+#endif
+ }
+
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ BMO_SetFlag(bm, v, VERT_OLD);
+ }
+
+#if 0
+ //a bit of cleaner code that, alas, doens't work.
+ /*build edge tags*/
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, e->v1, BEVEL_FLAG) || BMO_TestFlag(bm, e->v2, BEVEL_FLAG)) {
+ BMIter liter;
+ BMLoop *l;
+
+ if (!BMO_TestFlag(bm, e, EDGE_OLD)) {
+ BM_SetIndex(e, BLI_array_count(etags));
+ BLI_array_growone(etags);
+
+ BMO_SetFlag(bm, e, EDGE_OLD);
+ }
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_EDGE, e) {
+ BMLoop *l2;
+ BMIter liter2;
+
+ if (BMO_TestFlag(bm, l->f, BEVEL_FLAG))
+ continue;
+
+ BM_ITER(l2, &liter2, bm, BM_LOOPS_OF_FACE, l->f) {
+ BM_SetIndex(l2, BLI_array_count(tags));
+ BLI_array_growone(tags);
+
+ if (!BMO_TestFlag(bm, l2->e, EDGE_OLD)) {
+ BM_SetIndex(l2->e, BLI_array_count(etags));
+ BLI_array_growone(etags);
+
+ BMO_SetFlag(bm, l2->e, EDGE_OLD);
+ }
+ }
+
+ BMO_SetFlag(bm, l->f, BEVEL_FLAG);
+ BLI_array_append(faces, l->f);
+ }
+ } else {
+ BM_SetIndex(e, -1);
+ }
+ }
+#endif
+
+ /*create and assign looptag structures*/
+ BMO_ITER(e, &siter, bm, op, "geom", BM_EDGE) {
+ BMLoop *l;
+ BMIter liter;
+
+ BMO_SetFlag(bm, e->v1, BEVEL_FLAG|BEVEL_DEL);
+ BMO_SetFlag(bm, e->v2, BEVEL_FLAG|BEVEL_DEL);
+
+ if (BM_Edge_FaceCount(e) < 2) {
+ BMO_ClearFlag(bm, e, BEVEL_DEL);
+ BMO_ClearFlag(bm, e->v1, BEVEL_DEL);
+ BMO_ClearFlag(bm, e->v2, BEVEL_DEL);
+ }
+
+ if (!BLI_smallhash_haskey(&hash, (intptr_t)e)) {
+ BLI_array_growone(etags);
+ BM_SetIndex(e, BLI_array_count(etags)-1);
+ BLI_smallhash_insert(&hash, (intptr_t)e, NULL);
+ BMO_SetFlag(bm, e, EDGE_OLD);
+ }
+
+ /*find all faces surrounding e->v1 and, e->v2*/
+ for (i=0; i<2; i++) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_VERT, i?e->v2:e->v1) {
+ BMLoop *l2;
+ BMIter liter2;
+
+ /*see if we've already processed this loop's face*/
+ if (BLI_smallhash_haskey(&hash, (intptr_t)l->f))
+ continue;
+
+ /*create tags for all loops in l->f*/
+ BM_ITER(l2, &liter2, bm, BM_LOOPS_OF_FACE, l->f) {
+ BLI_array_growone(tags);
+ BM_SetIndex(l2, BLI_array_count(tags)-1);
+
+ if (!BLI_smallhash_haskey(&hash, (intptr_t)l2->e)) {
+ BLI_array_growone(etags);
+ BM_SetIndex(l2->e, BLI_array_count(etags)-1);
+ BLI_smallhash_insert(&hash, (intptr_t)l2->e, NULL);
+ BMO_SetFlag(bm, l2->e, EDGE_OLD);
+ }
+ }
+
+ BLI_smallhash_insert(&hash, (intptr_t)l->f, NULL);
+ BMO_SetFlag(bm, l->f, BEVEL_FLAG);
+ BLI_array_append(faces, l->f);
+ }
+ }
+ }
+
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ BMIter eiter;
+
+ if (!BMO_TestFlag(bm, v, BEVEL_FLAG))
+ continue;
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ if (!BMO_TestFlag(bm, e, BEVEL_FLAG) && !ETAG_GET(e, v)) {
+ BMVert *v2;
+ float co[3];
+
+ v2 = BM_OtherEdgeVert(e, v);
+ sub_v3_v3v3(co, v2->co, v->co);
+ if (has_elens) {
+ float elen = *(float*)CustomData_bmesh_get_n(&bm->edata, e->head.data, CD_PROP_FLT, li);
+
+ normalize_v3(co);
+ mul_v3_fl(co, elen);
+ }
+
+ mul_v3_fl(co, fac);
+ add_v3_v3(co, v->co);
+
+ v2 = BM_Make_Vert(bm, co, v);
+ ETAG_SET(e, v, v2);
+ }
+ }
+ }
+
+ for (i=0; i<BLI_array_count(faces); i++) {
+ BMLoop *l;
+ BMIter liter;
+
+ BMO_SetFlag(bm, faces[i], FACE_OLD);
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, faces[i]) {
+ float co[3];
+
+ if (BMO_TestFlag(bm, l->e, BEVEL_FLAG)) {
+ if (BMO_TestFlag(bm, l->prev->e, BEVEL_FLAG))
+ {
+ tag = tags + BM_GetIndex(l);
+ calc_corner_co(bm, l, co, fac);
+ tag->newv = BM_Make_Vert(bm, co, l->v);
+ } else {
+ tag = tags + BM_GetIndex(l);
+ tag->newv = ETAG_GET(l->prev->e, l->v);
+
+ if (!tag->newv) {
+ sub_v3_v3v3(co, l->prev->v->co, l->v->co);
+ if (has_elens) {
+ float elen = *(float*)CustomData_bmesh_get_n(&bm->edata, l->prev->e->head.data, CD_PROP_FLT, li);
+
+ normalize_v3(co);
+ mul_v3_fl(co, elen);
+ }
+
+ mul_v3_fl(co, fac);
+ add_v3_v3(co, l->v->co);
+
+ tag->newv = BM_Make_Vert(bm, co, l->v);
+
+ ETAG_SET(l->prev->e, l->v, tag->newv);
+ }
+ }
+ } else if (BMO_TestFlag(bm, l->v, BEVEL_FLAG)) {
+ tag = tags + BM_GetIndex(l);
+ tag->newv = ETAG_GET(l->e, l->v);
+
+ if (!tag->newv) {
+ sub_v3_v3v3(co, l->next->v->co, l->v->co);
+ if (has_elens) {
+ float elen = *(float*)CustomData_bmesh_get_n(&bm->edata, l->e->head.data, CD_PROP_FLT, li);
+
+ normalize_v3(co);
+ mul_v3_fl(co, elen);
+ }
+
+ mul_v3_fl(co, fac);
+ add_v3_v3(co, l->v->co);
+
+ tag = tags + BM_GetIndex(l);
+ tag->newv = BM_Make_Vert(bm, co, l->v);
+
+ ETAG_SET(l->e, l->v, tag->newv);
+ }
+ } else {
+ tag = tags + BM_GetIndex(l);
+ tag->newv = l->v;
+ BMO_ClearFlag(bm, l->v, BEVEL_DEL);
+ }
+ }
+ }
+
+ /*create new faces inset from original faces*/
+ for (i=0; i<BLI_array_count(faces); i++) {
+ BMLoop *l;
+ BMIter liter;
+ BMFace *f;
+ BMVert *lastv=NULL, *firstv=NULL;
+
+ BMO_SetFlag(bm, faces[i], BEVEL_DEL);
+
+ BLI_array_empty(verts);
+ BLI_array_empty(edges);
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, faces[i]) {
+ BMVert *v2;
+
+ tag = tags + BM_GetIndex(l);
+ BLI_array_append(verts, tag->newv);
+
+ if (!firstv)
+ firstv = tag->newv;
+
+ if (lastv) {
+ e = BM_Make_Edge(bm, lastv, tag->newv, l->e, 1);
+ BM_Copy_Attributes(bm, bm, l->prev->e, e);
+ BLI_array_append(edges, e);
+ }
+ lastv=tag->newv;
+
+ v2 = ETAG_GET(l->e, l->next->v);
+
+ tag = tags + BM_GetIndex(l->next);
+ if (!BMO_TestFlag(bm, l->e, BEVEL_FLAG) && v2 && v2 != tag->newv) {
+ BLI_array_append(verts, v2);
+
+ e = BM_Make_Edge(bm, lastv, v2, l->e, 1);
+ BM_Copy_Attributes(bm, bm, l->e, e);
+
+ BLI_array_append(edges, e);
+ lastv = v2;
+ }
+ }
+
+ e = BM_Make_Edge(bm, firstv, lastv, bm_firstfaceloop(faces[i])->e, 1);
+ if (bm_firstfaceloop(faces[i])->prev->e != e)
+ BM_Copy_Attributes(bm, bm, bm_firstfaceloop(faces[i])->prev->e, e);
+ BLI_array_append(edges, e);
+
+ f = BM_Make_Ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), 0);
+ if (!f) {
+ printf("eek!!\n");
+ continue;
+ }
+
+ BMO_SetFlag(bm, f, FACE_NEW);
+ }
+
+ for (i=0; i<BLI_array_count(faces); i++) {
+ BMLoop *l;
+ BMIter liter;
+ int j;
+
+ /*create quad spans between split edges*/
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, faces[i]) {
+ BMVert *v1=NULL, *v2=NULL, *v3=NULL, *v4=NULL;
+
+ if (!BMO_TestFlag(bm, l->e, BEVEL_FLAG))
+ continue;
+
+ v1 = tags[BM_GetIndex(l)].newv;
+ v2 = tags[BM_GetIndex(l->next)].newv;
+ if (l->radial_next != l) {
+ v3 = tags[BM_GetIndex(l->radial_next)].newv;
+ if (l->radial_next->next->v == l->next->v) {
+ v4 = v3;
+ v3 = tags[BM_GetIndex(l->radial_next->next)].newv;
+ } else {
+ v4 = tags[BM_GetIndex(l->radial_next->next)].newv;
+ }
+ } else {
+ /*the loop is on a boundary*/
+ v3 = l->next->v;
+ v4 = l->v;
+
+ for (j=0; j<2; j++) {
+ BMIter eiter;
+ BMVert *v = j ? v4 : v3;
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ if (!BM_Vert_In_Edge(e, v3) || !BM_Vert_In_Edge(e, v4))
+ continue;
+
+ if (!BMO_TestFlag(bm, e, BEVEL_FLAG) && BMO_TestFlag(bm, e, EDGE_OLD)) {
+ BMVert *vv;
+
+ vv = ETAG_GET(e, v);
+ if (!vv || BMO_TestFlag(bm, vv, BEVEL_FLAG))
+ continue;
+
+ if (j)
+ v1 = vv;
+ else
+ v2 = vv;
+ break;
+ }
+ }
+ }
+
+ BMO_ClearFlag(bm, v3, BEVEL_DEL);
+ BMO_ClearFlag(bm, v4, BEVEL_DEL);
+ }
+
+ if (v1 != v2 && v2 != v3 && v3 != v4) {
+ BMIter liter2;
+ BMLoop *l2, *l3;
+ BMEdge *e1, *e2;
+ float d1, d2, *d3;
+
+ f = BM_Make_QuadTri(bm, v4, v3, v2, v1, l->f, 1);
+
+ e1 = BM_Edge_Exist(v4, v3);
+ e2 = BM_Edge_Exist(v2, v1);
+ BM_Copy_Attributes(bm, bm, l->e, e1);
+ BM_Copy_Attributes(bm, bm, l->e, e2);
+
+ /*set edge lengths of cross edges as the average of the cross edges they're based on*/
+ if (has_elens) {
+#if 0 /* angle happens not to be used. why? - not sure it just isnt - campbell. leave this in incase we need to use it later */
+ float ang;
+#endif
+ e1 = BM_Edge_Exist(v1, v4);
+ e2 = BM_Edge_Exist(v2, v3);
+
+ if (l->radial_next->v == l->v) {
+ l2 = l->radial_next->prev;
+ l3 = l->radial_next->next;
+ } else {
+ l2 = l->radial_next->next;
+ l3 = l->radial_next->prev;
+ }
+
+ d3 = CustomData_bmesh_get_n(&bm->edata, e1->head.data, CD_PROP_FLT, li);
+ d1 = *(float*)CustomData_bmesh_get_n(&bm->edata, l->prev->e->head.data, CD_PROP_FLT, li);
+ d2 = *(float*)CustomData_bmesh_get_n(&bm->edata, l2->e->head.data, CD_PROP_FLT, li);
+#if 0
+ ang = angle_v3v3v3(l->prev->v->co, l->v->co, BM_OtherEdgeVert(l2->e, l->v)->co);
+#endif
+ *d3 = (d1+d2)*0.5f;
+
+ d3 = CustomData_bmesh_get_n(&bm->edata, e2->head.data, CD_PROP_FLT, li);
+ d1 = *(float*)CustomData_bmesh_get_n(&bm->edata, l->next->e->head.data, CD_PROP_FLT, li);
+ d2 = *(float*)CustomData_bmesh_get_n(&bm->edata, l3->e->head.data, CD_PROP_FLT, li);
+#if 0
+ ang = angle_v3v3v3(BM_OtherEdgeVert(l->next->e, l->next->v)->co, l->next->v->co, BM_OtherEdgeVert(l3->e, l->next->v)->co);
+#endif
+ *d3 = (d1+d2)*0.5f;
+ }
+
+ if (!f) {
+ fprintf(stderr, "%s: face index out of range! (bmesh internal error)\n", __func__);
+ continue;
+ }
+
+ BMO_SetFlag(bm, f, FACE_NEW|FACE_SPAN);
+
+ /*un-tag edges in f for deletion*/
+ BM_ITER(l2, &liter2, bm, BM_LOOPS_OF_FACE, f) {
+ BMO_ClearFlag(bm, l2->e, BEVEL_DEL);
+ }
+ } else {
+ f = NULL;
+ }
+ }
+ }
+
+ /*fill in holes at vertices*/
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ BMIter eiter;
+ BMVert *vv, *vstart=NULL, *lastv=NULL;
+ SmallHash tmphash;
+ int rad, insorig=0, err=0;
+
+ BLI_smallhash_init(&tmphash);
+
+ if (!BMO_TestFlag(bm, v, BEVEL_FLAG))
+ continue;
+
+ BLI_array_empty(verts);
+ BLI_array_empty(edges);
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ BMIter liter;
+ BMVert *v1=NULL, *v2=NULL;
+ BMLoop *l;
+
+ if (BM_Edge_FaceCount(e) < 2)
+ insorig = 1;
+
+ rad = 0;
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_EDGE, e) {
+ if (!BMO_TestFlag(bm, l->f, FACE_OLD))
+ continue;
+
+ rad++;
+
+ if (l->v == v)
+ tag = tags + BM_GetIndex(l);
+ else
+ tag = tags + BM_GetIndex(l->next);
+
+ if (!v1)
+ v1 = tag->newv;
+ else if (!v2)
+ v2 = tag->newv;
+ }
+
+ if (rad < 2)
+ insorig = 1;
+
+ if (!v1)
+ v1 = ETAG_GET(e, v);
+ if (!v2 || v1 == v2)
+ v2 = ETAG_GET(e, v);
+
+ if (v1) {
+ if (!BLI_smallhash_haskey(&tmphash, (intptr_t)v1)) {
+ BLI_array_append(verts, v1);
+ BLI_smallhash_insert(&tmphash, (intptr_t)v1, NULL);
+ }
+
+ if (v2 && v1 != v2 && !BLI_smallhash_haskey(&tmphash, (intptr_t)v2)) {
+ BLI_array_append(verts, v2);
+ BLI_smallhash_insert(&tmphash, (intptr_t)v2, NULL);
+ }
+ }
+ }
+
+ if (!BLI_array_count(verts))
+ continue;
+
+ if (insorig) {
+ BLI_array_append(verts, v);
+ BLI_smallhash_insert(&tmphash, (intptr_t)v, NULL);
+ }
+
+ /*find edges that exist between vertices in verts. this is basically
+ a topological walk of the edges connecting them.*/
+ vstart = vstart ? vstart : verts[0];
+ vv = vstart;
+ do {
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, vv) {
+ BMVert *vv2 = BM_OtherEdgeVert(e, vv);
+
+ if (vv2 != lastv && BLI_smallhash_haskey(&tmphash, (intptr_t)vv2)) {
+ /*if we've go over the same vert twice, break out of outer loop*/
+ if (BLI_smallhash_lookup(&tmphash, (intptr_t)vv2) != NULL) {
+ e = NULL;
+ err = 1;
+ break;
+ }
+
+ /*use self pointer as tag*/
+ BLI_smallhash_remove(&tmphash, (intptr_t)vv2);
+ BLI_smallhash_insert(&tmphash, (intptr_t)vv2, vv2);
+
+ lastv = vv;
+ BLI_array_append(edges, e);
+ vv = vv2;
+ break;
+ }
+ }
+ if (e == NULL)
+ break;
+ } while (vv != vstart);
+
+ if (err)
+ continue;
+
+ /*there may not be a complete loop of edges, so start again and make
+ final edge afterwards. in this case, the previous loop worked to
+ find one of the two edges at the extremes.*/
+ if (vv != vstart) {
+ /*undo previous tagging*/
+ for (i=0; i<BLI_array_count(verts); i++) {
+ BLI_smallhash_remove(&tmphash, (intptr_t)verts[i]);
+ BLI_smallhash_insert(&tmphash, (intptr_t)verts[i], NULL);
+ }
+
+ vstart = vv;
+ lastv = NULL;
+ BLI_array_empty(edges);
+ do {
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, vv) {
+ BMVert *vv2 = BM_OtherEdgeVert(e, vv);
+
+ if (vv2 != lastv && BLI_smallhash_haskey(&tmphash, (intptr_t)vv2)) {
+ /*if we've go over the same vert twice, break out of outer loop*/
+ if (BLI_smallhash_lookup(&tmphash, (intptr_t)vv2) != NULL) {
+ e = NULL;
+ err = 1;
+ break;
+ }
+
+ /*use self pointer as tag*/
+ BLI_smallhash_remove(&tmphash, (intptr_t)vv2);
+ BLI_smallhash_insert(&tmphash, (intptr_t)vv2, vv2);
+
+ lastv = vv;
+ BLI_array_append(edges, e);
+ vv = vv2;
+ break;
+ }
+ }
+ if (e == NULL)
+ break;
+ } while (vv != vstart);
+
+ if (!err) {
+ e = BM_Make_Edge(bm, vv, vstart, NULL, 1);
+ BLI_array_append(edges, e);
+ }
+ }
+
+ if (err)
+ continue;
+
+ if (BLI_array_count(edges) >= 3) {
+ BMFace *f;
+
+ if (BM_Face_Exists(bm, verts, BLI_array_count(verts), &f))
+ continue;
+
+ f = BM_Make_Ngon(bm, lastv, vstart, edges, BLI_array_count(edges), 0);
+ if (!f) {
+ fprintf(stderr, "%s: in bevel vert fill! (bmesh internal error)\n", __func__);
+ } else {
+ BMO_SetFlag(bm, f, FACE_NEW|FACE_HOLE);
+ }
+ }
+ BLI_smallhash_release(&tmphash);
+ }
+
+ /*copy over customdata*/
+ for (i=0; i<BLI_array_count(faces); i++) {
+ BMLoop *l;
+ BMIter liter;
+ BMFace *f = faces[i];
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BMLoop *l2;
+ BMIter liter2;
+
+ tag = tags + BM_GetIndex(l);
+ if (!tag->newv)
+ continue;
+
+ BM_ITER(l2, &liter2, bm, BM_LOOPS_OF_VERT, tag->newv) {
+ if (!BMO_TestFlag(bm, l2->f, FACE_NEW) || (l2->v != tag->newv && l2->v != l->v))
+ continue;
+
+ if (tag->newv != l->v || HasMDisps) {
+ BM_Copy_Attributes(bm, bm, l->f, l2->f);
+ BM_loop_interp_from_face(bm, l2, l->f, 1, 1);
+ } else {
+ BM_Copy_Attributes(bm, bm, l->f, l2->f);
+ BM_Copy_Attributes(bm, bm, l, l2);
+ }
+
+ if (HasMDisps) {
+ BMLoop *l3;
+ BMIter liter3;
+
+ BM_ITER(l3, &liter3, bm, BM_LOOPS_OF_FACE, l2->f) {
+ BM_loop_interp_multires(bm, l3, l->f);
+ }
+ }
+ }
+ }
+ }
+
+ /*handle vertices along boundary edges*/
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, v, VERT_OLD) && BMO_TestFlag(bm, v, BEVEL_FLAG) && !BMO_TestFlag(bm, v, BEVEL_DEL)) {
+ BMLoop *l;
+ BMLoop *lorig=NULL;
+ BMIter liter;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_VERT, v) {
+ // BMIter liter2;
+ // BMLoop *l2 = l->v == v ? l : l->next, *l3;
+
+ if (BMO_TestFlag(bm, l->f, FACE_OLD)) {
+ lorig = l;
+ break;
+ }
+ }
+
+ if (!lorig)
+ continue;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_VERT, v) {
+ BMLoop *l2 = l->v == v ? l : l->next;
+
+ BM_Copy_Attributes(bm, bm, lorig->f, l2->f);
+ BM_Copy_Attributes(bm, bm, lorig, l2);
+ }
+ }
+ }
+#if 0
+ /*clean up any remaining 2-edged faces*/
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if (f->len == 2) {
+ BMFace *faces[2] = {f, bm_firstfaceloop(f)->radial_next->f};
+
+ if (faces[0] == faces[1])
+ BM_Kill_Face(bm, f);
+ else
+ BM_Join_Faces(bm, faces, 2);
+ }
+ }
+#endif
+
+ BMO_CallOpf(bm, "del geom=%fv context=%i", BEVEL_DEL, DEL_VERTS);
+
+ /*clean up any edges that might not get properly deleted*/
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, e, EDGE_OLD) && !e->l)
+ BMO_SetFlag(bm, e, BEVEL_DEL);
+ }
+
+ BMO_CallOpf(bm, "del geom=%fe context=%i", BEVEL_DEL, DEL_EDGES);
+ BMO_CallOpf(bm, "del geom=%ff context=%i", BEVEL_DEL, DEL_FACES);
+
+ BLI_smallhash_release(&hash);
+ BLI_array_free(tags);
+ BLI_array_free(etags);
+ BLI_array_free(verts);
+ BLI_array_free(edges);
+ BLI_array_free(faces);
+
+ BMO_Flag_To_Slot(bm, op, "face_spans", FACE_SPAN, BM_FACE);
+ BMO_Flag_To_Slot(bm, op, "face_holes", FACE_HOLE, BM_FACE);
+}
diff --git a/source/blender/bmesh/operators/bmesh_dupeops.c b/source/blender/bmesh/operators/bmesh_dupeops.c
new file mode 100644
index 00000000000..1a19aa820de
--- /dev/null
+++ b/source/blender/bmesh/operators/bmesh_dupeops.c
@@ -0,0 +1,618 @@
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "BLI_ghash.h"
+#include "BLI_memarena.h"
+#include "BLI_blenlib.h"
+#include "BLI_array.h"
+#include "BLI_math.h"
+
+#include "bmesh.h"
+#include "bmesh_operators_private.h"
+
+/*local flag defines*/
+#define DUPE_INPUT 1 /*input from operator*/
+#define DUPE_NEW 2
+#define DUPE_DONE 4
+#define DUPE_MAPPED 8
+
+/*
+ * COPY VERTEX
+ *
+ * Copy an existing vertex from one bmesh to another.
+ *
+*/
+static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *target_mesh, GHash *vhash)
+{
+ BMVert *target_vertex = NULL;
+
+ /*Create a new vertex*/
+ target_vertex = BM_Make_Vert(target_mesh, source_vertex->co, NULL);
+
+ /*Insert new vertex into the vert hash*/
+ BLI_ghash_insert(vhash, source_vertex, target_vertex);
+
+ /*Copy attributes*/
+ BM_Copy_Attributes(source_mesh, target_mesh, source_vertex, target_vertex);
+
+ /*Set internal op flags*/
+ BMO_SetFlag(target_mesh, (BMHeader*)target_vertex, DUPE_NEW);
+
+ return target_vertex;
+}
+
+/*
+ * COPY EDGE
+ *
+ * Copy an existing edge from one bmesh to another.
+ *
+*/
+static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh,
+ BMEdge *source_edge, BMesh *target_mesh,
+ GHash *vhash, GHash *ehash)
+{
+ BMEdge *target_edge = NULL;
+ BMVert *target_vert1, *target_vert2;
+ BMFace *face;
+ BMIter fiter;
+ int rlen;
+
+ /*see if any of the neighboring faces are
+ not being duplicated. in that case,
+ add it to the new/old map.*/
+ rlen = 0;
+ for (face=BMIter_New(&fiter,source_mesh, BM_FACES_OF_EDGE,source_edge);
+ face; face=BMIter_Step(&fiter)) {
+ if (BMO_TestFlag(source_mesh, face, DUPE_INPUT)) {
+ rlen++;
+ }
+ }
+
+ /*Lookup v1 and v2*/
+ target_vert1 = BLI_ghash_lookup(vhash, source_edge->v1);
+ target_vert2 = BLI_ghash_lookup(vhash, source_edge->v2);
+
+ /*Create a new edge*/
+ target_edge = BM_Make_Edge(target_mesh, target_vert1, target_vert2, NULL, 0);
+
+ /*add to new/old edge map if necassary*/
+ if (rlen < 2) {
+ /*not sure what non-manifold cases of greater then three
+ radial should do.*/
+ BMO_Insert_MapPointer(source_mesh,op, "boundarymap",
+ source_edge, target_edge);
+ }
+
+ /*Insert new edge into the edge hash*/
+ BLI_ghash_insert(ehash, source_edge, target_edge);
+
+ /*Copy attributes*/
+ BM_Copy_Attributes(source_mesh, target_mesh, source_edge, target_edge);
+
+ /*Set internal op flags*/
+ BMO_SetFlag(target_mesh, (BMHeader*)target_edge, DUPE_NEW);
+
+ return target_edge;
+}
+
+/*
+ * COPY FACE
+ *
+ * Copy an existing face from one bmesh to another.
+ *
+*/
+static BMFace *copy_face(BMOperator *op, BMesh *source_mesh,
+ BMFace *source_face, BMesh *target_mesh,
+ BMVert **vtar, BMEdge **edar, GHash *vhash, GHash *ehash)
+{
+ BMVert *target_vert1, *target_vert2;
+ BMLoop *source_loop, *target_loop;
+ BMFace *target_face = NULL;
+ BMIter iter, iter2;
+ int i;
+
+ /*lookup the first and second verts*/
+ target_vert1 = BLI_ghash_lookup(vhash, BMIter_New(&iter, source_mesh, BM_VERTS_OF_FACE, source_face));
+ target_vert2 = BLI_ghash_lookup(vhash, BMIter_Step(&iter));
+
+ /*lookup edges*/
+ for (i=0,source_loop=BMIter_New(&iter, source_mesh, BM_LOOPS_OF_FACE, source_face);
+ source_loop; source_loop=BMIter_Step(&iter), i++) {
+ vtar[i] = BLI_ghash_lookup(vhash, source_loop->v);
+ edar[i] = BLI_ghash_lookup(ehash, source_loop->e);
+ }
+
+ /*create new face*/
+ target_face = BM_Make_Face(target_mesh, vtar, edar, source_face->len, 0);
+ BMO_Insert_MapPointer(source_mesh, op,
+ "facemap", source_face, target_face);
+ BMO_Insert_MapPointer(source_mesh, op,
+ "facemap", target_face, source_face);
+
+ BM_Copy_Attributes(source_mesh, target_mesh, source_face, target_face);
+
+ /*mark the face for output*/
+ BMO_SetFlag(target_mesh, (BMHeader*)target_face, DUPE_NEW);
+
+ /*copy per-loop custom data*/
+ BM_ITER(source_loop, &iter, source_mesh, BM_LOOPS_OF_FACE, source_face) {
+ BM_ITER(target_loop, &iter2, target_mesh, BM_LOOPS_OF_FACE, target_face) {
+ if (BLI_ghash_lookup(vhash, source_loop->v) == target_loop->v) {
+ BM_Copy_Attributes(source_mesh, target_mesh, source_loop, target_loop);
+ break;
+ }
+ }
+ }
+
+ return target_face;
+}
+
+/*
+ * COPY MESH
+ *
+ * Internal Copy function.
+ */
+static void copy_mesh(BMOperator *op, BMesh *source, BMesh *target)
+{
+
+ BMVert *v = NULL, *v2, **vtar = NULL;
+ BMEdge *e = NULL, **edar = NULL;
+ BMFace *f = NULL;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ GHash *vhash;
+ GHash *ehash;
+
+ int maxlength = 0;
+
+ /*initialize pointer hashes*/
+ vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh dupeops v");
+ ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh dupeops e");
+
+ /*initialize edge pointer array*/
+ for(f = BMIter_New(&faces, source, BM_FACES_OF_MESH, source); f; f = BMIter_Step(&faces)){
+ if(f->len > maxlength) maxlength = f->len;
+ }
+ edar = MEM_callocN(sizeof(BMEdge*) * maxlength, "BM copy mesh edge pointer array");
+ vtar = MEM_callocN(sizeof(BMVert*) * maxlength, "BM copy mesh vert pointer array");
+
+ for(v = BMIter_New(&verts, source, BM_VERTS_OF_MESH, source); v; v = BMIter_Step(&verts)){
+ if(BMO_TestFlag(source, (BMHeader*)v, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE))){
+ BMIter iter;
+ int iso = 1;
+
+ v2 = copy_vertex(source, v, target, vhash);
+
+ BM_ITER(f, &iter, source, BM_FACES_OF_VERT, v) {
+ if (BMO_TestFlag(source, f, DUPE_INPUT)) {
+ iso = 0;
+ break;
+ }
+ }
+
+ if (iso) {
+ BM_ITER(e, &iter, source, BM_EDGES_OF_VERT, v) {
+ if (BMO_TestFlag(source, e, DUPE_INPUT)) {
+ iso = 0;
+ break;
+ }
+ }
+ }
+
+ if (iso)
+ BMO_Insert_MapPointer(source, op, "isovertmap", v, v2);
+
+ BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
+ }
+ }
+
+ /*now we dupe all the edges*/
+ for(e = BMIter_New(&edges, source, BM_EDGES_OF_MESH, source); e; e = BMIter_Step(&edges)){
+ if(BMO_TestFlag(source, (BMHeader*)e, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE))){
+ /*make sure that verts are copied*/
+ if(!BMO_TestFlag(source, (BMHeader*)e->v1, DUPE_DONE)) {
+ copy_vertex(source, e->v1, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)e->v1, DUPE_DONE);
+ }
+ if(!BMO_TestFlag(source, (BMHeader*)e->v2, DUPE_DONE)) {
+ copy_vertex(source, e->v2, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)e->v2, DUPE_DONE);
+ }
+ /*now copy the actual edge*/
+ copy_edge(op, source, e, target, vhash, ehash);
+ BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE);
+ }
+ }
+
+ /*first we dupe all flagged faces and their elements from source*/
+ for(f = BMIter_New(&faces, source, BM_FACES_OF_MESH, source); f; f= BMIter_Step(&faces)){
+ if(BMO_TestFlag(source, (BMHeader*)f, DUPE_INPUT)){
+ /*vertex pass*/
+ for(v = BMIter_New(&verts, source, BM_VERTS_OF_FACE, f); v; v = BMIter_Step(&verts)){
+ if(!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE)){
+ copy_vertex(source,v, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
+ }
+ }
+
+ /*edge pass*/
+ for(e = BMIter_New(&edges, source, BM_EDGES_OF_FACE, f); e; e = BMIter_Step(&edges)){
+ if(!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE)){
+ copy_edge(op, source, e, target, vhash, ehash);
+ BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE);
+ }
+ }
+ copy_face(op, source, f, target, vtar, edar, vhash, ehash);
+ BMO_SetFlag(source, (BMHeader*)f, DUPE_DONE);
+ }
+ }
+
+ /*free pointer hashes*/
+ BLI_ghash_free(vhash, NULL, NULL);
+ BLI_ghash_free(ehash, NULL, NULL);
+
+ /*free edge pointer array*/
+ if (edar) {
+ MEM_freeN(edar);
+ }
+ /*free vert pointer array*/
+ if (vtar) {
+ MEM_freeN(vtar);
+ }
+}
+
+/*
+ * Duplicate Operator
+ *
+ * Duplicates verts, edges and faces of a mesh.
+ *
+ * INPUT SLOTS:
+ *
+ * BMOP_DUPE_VINPUT: Buffer containing pointers to mesh vertices to be duplicated
+ * BMOP_DUPE_EINPUT: Buffer containing pointers to mesh edges to be duplicated
+ * BMOP_DUPE_FINPUT: Buffer containing pointers to mesh faces to be duplicated
+ *
+ * OUTPUT SLOTS:
+ *
+ * BMOP_DUPE_VORIGINAL: Buffer containing pointers to the original mesh vertices
+ * BMOP_DUPE_EORIGINAL: Buffer containing pointers to the original mesh edges
+ * BMOP_DUPE_FORIGINAL: Buffer containing pointers to the original mesh faces
+ * BMOP_DUPE_VNEW: Buffer containing pointers to the new mesh vertices
+ * BMOP_DUPE_ENEW: Buffer containing pointers to the new mesh edges
+ * BMOP_DUPE_FNEW: Buffer containing pointers to the new mesh faces
+ *
+*/
+
+void dupeop_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator *dupeop = op;
+ BMesh *bm2 = BMO_Get_Pnt(op, "dest");
+
+ if (!bm2)
+ bm2 = bm;
+
+ /*flag input*/
+ BMO_Flag_Buffer(bm, dupeop, "geom", DUPE_INPUT, BM_ALL);
+
+ /*use the internal copy function*/
+ copy_mesh(dupeop, bm, bm2);
+
+ /*Output*/
+ /*First copy the input buffers to output buffers - original data*/
+ BMO_CopySlot(dupeop, dupeop, "geom", "origout");
+
+ /*Now alloc the new output buffers*/
+ BMO_Flag_To_Slot(bm, dupeop, "newout", DUPE_NEW, BM_ALL);
+}
+
+/*executes the duplicate operation, feeding elements of
+ type flag etypeflag and header flag flag to it. note,
+ to get more useful information (such as the mapping from
+ original to new elements) you should run the dupe op manually.*/
+void BMOP_DupeFromFlag(BMesh *bm, int etypeflag, int flag)
+{
+ BMOperator dupeop;
+
+ BMO_Init_Op(&dupeop, "dupe");
+ BMO_HeaderFlag_To_Slot(bm, &dupeop, "geom", flag, etypeflag);
+
+ BMO_Exec_Op(bm, &dupeop);
+ BMO_Finish_Op(bm, &dupeop);
+}
+
+/*
+ * Split Operator
+ *
+ * Duplicates verts, edges and faces of a mesh but also deletes the originals.
+ *
+ * INPUT SLOTS:
+ *
+ * BMOP_DUPE_VINPUT: Buffer containing pointers to mesh vertices to be split
+ * BMOP_DUPE_EINPUT: Buffer containing pointers to mesh edges to be split
+ * BMOP_DUPE_FINPUT: Buffer containing pointers to mesh faces to be split
+ *
+ * OUTPUT SLOTS:
+ *
+ * BMOP_DUPE_VOUTPUT: Buffer containing pointers to the split mesh vertices
+ * BMOP_DUPE_EOUTPUT: Buffer containing pointers to the split mesh edges
+ * BMOP_DUPE_FOUTPUT: Buffer containing pointers to the split mesh faces
+ *
+*/
+
+#define SPLIT_INPUT 1
+void splitop_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator *splitop = op;
+ BMOperator dupeop;
+ BMOperator delop;
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+ BMIter iter, iter2;
+ int found;
+
+ /*initialize our sub-operators*/
+ BMO_Init_Op(&dupeop, "dupe");
+ BMO_Init_Op(&delop, "del");
+
+ BMO_CopySlot(splitop, &dupeop, "geom", "geom");
+ BMO_Exec_Op(bm, &dupeop);
+
+ BMO_Flag_Buffer(bm, splitop, "geom", SPLIT_INPUT, BM_ALL);
+
+ /*make sure to remove edges and verts we don't need.*/
+ for (e= BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);e;e=BMIter_Step(&iter)) {
+ found = 0;
+ f = BMIter_New(&iter2, bm, BM_FACES_OF_EDGE, e);
+ for (; f; f=BMIter_Step(&iter2)) {
+ if (!BMO_TestFlag(bm, f, SPLIT_INPUT)) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) BMO_SetFlag(bm, e, SPLIT_INPUT);
+ }
+
+ for (v= BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);v;v=BMIter_Step(&iter)) {
+ found = 0;
+ e = BMIter_New(&iter2, bm, BM_EDGES_OF_VERT, v);
+ for (; e; e=BMIter_Step(&iter2)) {
+ if (!BMO_TestFlag(bm, e, SPLIT_INPUT)) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) BMO_SetFlag(bm, v, SPLIT_INPUT);
+
+ }
+
+ /*connect outputs of dupe to delete, exluding keep geometry*/
+ BMO_Set_Int(&delop, "context", DEL_FACES);
+ BMO_Flag_To_Slot(bm, &delop, "geom", SPLIT_INPUT, BM_ALL);
+
+ BMO_Exec_Op(bm, &delop);
+
+ /*now we make our outputs by copying the dupe outputs*/
+ BMO_CopySlot(&dupeop, splitop, "newout", "geomout");
+ BMO_CopySlot(&dupeop, splitop, "boundarymap",
+ "boundarymap");
+ BMO_CopySlot(&dupeop, splitop, "isovertmap",
+ "isovertmap");
+
+ /*cleanup*/
+ BMO_Finish_Op(bm, &delop);
+ BMO_Finish_Op(bm, &dupeop);
+}
+
+#define DEL_INPUT 1
+#define DEL_WIREVERT 2
+
+static void delete_verts(BMesh *bm);
+static void delete_context(BMesh *bm, int type);
+
+void delop_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator *delop = op;
+
+ /*Mark Buffers*/
+ BMO_Flag_Buffer(bm, delop, "geom", DEL_INPUT, BM_ALL);
+
+ delete_context(bm, BMO_Get_Int(op, "context"));
+}
+
+static void delete_verts(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMLoop *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
+ if(BMO_TestFlag(bm, (BMHeader*)v, DEL_INPUT)) {
+ /*Visit edges*/
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_VERT, v); e; e = BMIter_Step(&edges))
+ BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
+ /*Visit faces*/
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_VERT, v); f; f = BMIter_Step(&faces))
+ BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
+ }
+ }
+
+ BM_remove_tagged_faces(bm, DEL_INPUT);
+ BM_remove_tagged_edges(bm, DEL_INPUT);
+ BM_remove_tagged_verts(bm, DEL_INPUT);
+}
+
+static void delete_edges(BMesh *bm){
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter edges;
+ BMIter faces;
+
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
+ if(BMO_TestFlag(bm, (BMHeader*)e, DEL_INPUT)) {
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_EDGE, e); f; f = BMIter_Step(&faces)){
+ BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
+ }
+ }
+ }
+ BM_remove_tagged_faces(bm, DEL_INPUT);
+ BM_remove_tagged_edges(bm, DEL_INPUT);
+}
+
+/*you need to make remove tagged verts/edges/faces
+ api functions that take a filter callback.....
+ and this new filter type will be for opstack flags.
+ This is because the BM_remove_taggedXXX functions bypass iterator API.
+ -Ops dont care about 'UI' considerations like selection state, hide state, ect. If you want to work on unhidden selections for instance,
+ copy output from a 'select context' operator to another operator....
+*/
+
+/*Break this into smaller functions*/
+
+static void delete_context(BMesh *bm, int type){
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ if(type == DEL_VERTS) delete_verts(bm);
+ else if(type == DEL_EDGES){
+ /*flush down to verts*/
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
+ if(BMO_TestFlag(bm, (BMHeader*)e, DEL_INPUT)){
+ BMO_SetFlag(bm, (BMHeader*)(e->v1), DEL_INPUT);
+ BMO_SetFlag(bm, (BMHeader*)(e->v2), DEL_INPUT);
+ }
+ }
+ delete_edges(bm);
+ /*remove loose vertices*/
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
+ if(BMO_TestFlag(bm, (BMHeader*)v, DEL_INPUT) && (!(v->e)))
+ BMO_SetFlag(bm, (BMHeader*)v, DEL_WIREVERT);
+ }
+ BM_remove_tagged_verts(bm, DEL_WIREVERT);
+ }
+ else if(type == DEL_EDGESFACES) delete_edges(bm);
+ else if(type == DEL_ONLYFACES) BM_remove_tagged_faces(bm, DEL_INPUT);
+ else if (type == DEL_ONLYTAGGED) {
+ BM_remove_tagged_faces(bm, DEL_INPUT);
+ BM_remove_tagged_edges(bm, DEL_INPUT);
+ BM_remove_tagged_verts(bm, DEL_INPUT);
+ } else if(type == DEL_FACES){
+ /*go through and mark all edges and all verts of all faces for delete*/
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
+ if(BMO_TestFlag(bm, (BMHeader*)f, DEL_INPUT)){
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_FACE, f); e; e = BMIter_Step(&edges))
+ BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_FACE, f); v; v = BMIter_Step(&verts))
+ BMO_SetFlag(bm, (BMHeader*)v, DEL_INPUT);
+ }
+ }
+ /*now go through and mark all remaining faces all edges for keeping.*/
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
+ if(!BMO_TestFlag(bm, (BMHeader*)f, DEL_INPUT)){
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_FACE, f); e; e= BMIter_Step(&edges)){
+ BMO_ClearFlag(bm, (BMHeader*)e, DEL_INPUT);
+ }
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_FACE, f); v; v= BMIter_Step(&verts)){
+ BMO_ClearFlag(bm, (BMHeader*)v, DEL_INPUT);
+ }
+ }
+ }
+ /*also mark all the vertices of remaining edges for keeping.*/
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
+ if(!BMO_TestFlag(bm, (BMHeader*)e, DEL_INPUT)){
+ BMO_ClearFlag(bm, (BMHeader*)e->v1, DEL_INPUT);
+ BMO_ClearFlag(bm, (BMHeader*)e->v2, DEL_INPUT);
+ }
+ }
+ /*now delete marked faces*/
+ BM_remove_tagged_faces(bm, DEL_INPUT);
+ /*delete marked edges*/
+ BM_remove_tagged_edges(bm, DEL_INPUT);
+ /*remove loose vertices*/
+ BM_remove_tagged_verts(bm, DEL_INPUT);
+ }
+ /*does this option even belong in here?*/
+ else if(type == DEL_ALL){
+ for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces))
+ BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
+ for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges))
+ BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
+ for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts))
+ BMO_SetFlag(bm, (BMHeader*)v, DEL_INPUT);
+
+ BM_remove_tagged_faces(bm, DEL_INPUT);
+ BM_remove_tagged_edges(bm, DEL_INPUT);
+ BM_remove_tagged_verts(bm, DEL_INPUT);
+ }
+}
+
+/*
+ * Spin Operator
+ *
+ * Extrude or duplicate geometry a number of times,
+ * rotating and possibly translating after each step
+*/
+
+void spinop_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator dupop, extop;
+ float cent[3], dvec[3];
+ float axis[3] = {0.0f, 0.0f, 1.0f};
+ float q[4];
+ float rmat[3][3];
+ float phi, si;
+ int steps, dupli, a, usedvec;
+
+ BMO_Get_Vec(op, "cent", cent);
+ BMO_Get_Vec(op, "axis", axis);
+ normalize_v3(axis);
+ BMO_Get_Vec(op, "dvec", dvec);
+ usedvec = !is_zero_v3(dvec);
+ steps = BMO_Get_Int(op, "steps");
+ phi = BMO_Get_Float(op, "ang")*(float)M_PI/(360.0f*steps);
+ dupli = BMO_Get_Int(op, "dupli");
+
+ si = (float)sin(phi);
+ q[0] = (float)cos(phi);
+ q[1] = axis[0]*si;
+ q[2] = axis[1]*si;
+ q[3] = axis[2]*si;
+ quat_to_mat3(rmat, q);
+
+ BMO_CopySlot(op, op, "geom", "lastout");
+ for(a=0; a<steps; a++) {
+ if(dupli) {
+ BMO_InitOpf(bm, &dupop, "dupe geom=%s", op, "lastout");
+ BMO_Exec_Op(bm, &dupop);
+ BMO_CallOpf(bm, "rotate cent=%v mat=%m3 verts=%s",
+ cent, rmat, &dupop, "newout");
+ BMO_CopySlot(&dupop, op, "newout", "lastout");
+ BMO_Finish_Op(bm, &dupop);
+ } else {
+ BMO_InitOpf(bm, &extop, "extrudefaceregion edgefacein=%s",
+ op, "lastout");
+ BMO_Exec_Op(bm, &extop);
+ BMO_CallOpf(bm, "rotate cent=%v mat=%m3 verts=%s",
+ cent, rmat, &extop, "geomout");
+ BMO_CopySlot(&extop, op, "geomout", "lastout");
+ BMO_Finish_Op(bm, &extop);
+ }
+
+ if(usedvec)
+ BMO_CallOpf(bm, "translate vec=%v verts=%s", dvec, op, "lastout");
+ }
+}
diff --git a/source/blender/bmesh/operators/connectops.c b/source/blender/bmesh/operators/connectops.c
new file mode 100644
index 00000000000..1e7dbc3f08c
--- /dev/null
+++ b/source/blender/bmesh/operators/connectops.c
@@ -0,0 +1,398 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "bmesh.h"
+#include "mesh_intern.h"
+#include "bmesh_private.h"
+#include "BLI_math.h"
+#include "BLI_array.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#define VERT_INPUT 1
+#define EDGE_OUT 1
+#define FACE_NEW 2
+#define EDGE_MARK 4
+#define EDGE_DONE 8
+
+void connectverts_exec(BMesh *bm, BMOperator *op)
+{
+ BMIter iter, liter;
+ BMFace *f, *nf;
+ BMLoop **loops = NULL, *lastl = NULL;
+ BLI_array_declare(loops);
+ BMLoop *l, *nl;
+ BMVert **verts = NULL;
+ BLI_array_declare(verts);
+ int i;
+
+ BMO_Flag_Buffer(bm, op, "verts", VERT_INPUT, BM_VERT);
+
+ for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f=BMIter_Step(&iter)){
+ BLI_array_empty(loops);
+ BLI_array_empty(verts);
+
+ if (BMO_TestFlag(bm, f, FACE_NEW)) continue;
+
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ lastl = NULL;
+ for (; l; l=BMIter_Step(&liter)) {
+ if (BMO_TestFlag(bm, l->v, VERT_INPUT)) {
+ if (!lastl) {
+ lastl = l;
+ continue;
+ }
+
+ if (lastl != l->prev && lastl !=
+ l->next)
+ {
+ BLI_array_growone(loops);
+ loops[BLI_array_count(loops)-1] = lastl;
+
+ BLI_array_growone(loops);
+ loops[BLI_array_count(loops)-1] = l;
+
+ }
+ lastl = l;
+ }
+ }
+
+ if (BLI_array_count(loops) == 0) continue;
+
+ if (BLI_array_count(loops) > 2) {
+ BLI_array_growone(loops);
+ loops[BLI_array_count(loops)-1] = loops[BLI_array_count(loops)-2];
+
+ BLI_array_growone(loops);
+ loops[BLI_array_count(loops)-1] = loops[0];
+ }
+
+ BM_LegalSplits(bm, f, (BMLoop *(*)[2])loops, BLI_array_count(loops)/2);
+
+ for (i=0; i<BLI_array_count(loops)/2; i++) {
+ if (loops[i*2]==NULL) continue;
+
+ BLI_array_growone(verts);
+ verts[BLI_array_count(verts)-1] = loops[i*2]->v;
+
+ BLI_array_growone(verts);
+ verts[BLI_array_count(verts)-1] = loops[i*2+1]->v;
+ }
+
+ for (i=0; i<BLI_array_count(verts)/2; i++) {
+ nf = BM_Split_Face(bm, f, verts[i*2],
+ verts[i*2+1], &nl, NULL);
+ f = nf;
+
+ if (!nl || !nf) {
+ BMO_RaiseError(bm, op,
+ BMERR_CONNECTVERT_FAILED, NULL);
+ BLI_array_free(loops);
+ return;
+ }
+ BMO_SetFlag(bm, nf, FACE_NEW);
+ BMO_SetFlag(bm, nl->e, EDGE_OUT);
+ }
+ }
+
+ BMO_Flag_To_Slot(bm, op, "edgeout", EDGE_OUT, BM_EDGE);
+
+ BLI_array_free(loops);
+ BLI_array_free(verts);
+}
+
+static BMVert *get_outer_vert(BMesh *bm, BMEdge *e)
+{
+ BMIter iter;
+ BMEdge *e2;
+ int i;
+
+ i= 0;
+ BM_ITER(e2, &iter, bm, BM_EDGES_OF_VERT, e->v1) {
+ if (BMO_TestFlag(bm, e2, EDGE_MARK))
+ i++;
+ }
+
+ if (i==2)
+ return e->v2;
+ else
+ return e->v1;
+}
+
+/* Clamp x to the interval {0..len-1}, with wrap-around */
+#ifdef CLAMP_INDEX
+#undef CLAMP_INDEX
+#endif
+#define CLAMP_INDEX(x, len) (((x) < 0) ? (len - (-(x) % len)) : ((x) % len))
+
+/* There probably is a better way to swap BLI_arrays, or if there
+ isn't there should be... */
+#define ARRAY_SWAP(elemtype, arr1, arr2) \
+ { \
+ int i; \
+ elemtype *arr_tmp = NULL; \
+ BLI_array_declare(arr_tmp); \
+ for (i = 0; i < BLI_array_count(arr1); i++) { \
+ BLI_array_append(arr_tmp, arr1[i]); \
+ } \
+ BLI_array_empty(arr1); \
+ for (i = 0; i < BLI_array_count(arr2); i++) { \
+ BLI_array_append(arr1, arr2[i]); \
+ } \
+ BLI_array_empty(arr2); \
+ for (i = 0; i < BLI_array_count(arr_tmp); i++) { \
+ BLI_array_append(arr2, arr_tmp[i]); \
+ } \
+ BLI_array_free(arr_tmp); \
+ }
+
+void bmesh_bridge_loops_exec(BMesh *bm, BMOperator *op)
+{
+ BMEdge **ee1 = NULL, **ee2 = NULL;
+ BMVert **vv1 = NULL, **vv2 = NULL;
+ BLI_array_declare(ee1);
+ BLI_array_declare(ee2);
+ BLI_array_declare(vv1);
+ BLI_array_declare(vv2);
+ BMOIter siter;
+ BMIter iter;
+ BMEdge *e, *nexte;
+ int c=0, cl1=0, cl2=0;
+
+ BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE);
+
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ if (!BMO_TestFlag(bm, e, EDGE_DONE)) {
+ BMVert *v, *ov;
+ /* BMEdge *e2, *e3, *oe = e; */ /* UNUSED */
+ BMEdge *e2, *e3;
+
+ if (c > 2) {
+ BMO_RaiseError(bm, op, BMERR_INVALID_SELECTION, "Select only two edge loops");
+ goto cleanup;
+ }
+
+ e2 = e;
+ v = e->v1;
+ do {
+ v = BM_OtherEdgeVert(e2, v);
+ nexte = NULL;
+ BM_ITER(e3, &iter, bm, BM_EDGES_OF_VERT, v) {
+ if (e3 != e2 && BMO_TestFlag(bm, e3, EDGE_MARK)) {
+ if (nexte == NULL) {
+ nexte = e3;
+ }
+ else {
+ /* edges do not form a loop: there is a disk
+ with more than two marked edges. */
+ BMO_RaiseError(bm, op, BMERR_INVALID_SELECTION,
+ "Selection must only contain edges from two edge loops");
+ goto cleanup;
+ }
+ }
+ }
+
+ if (nexte)
+ e2 = nexte;
+ } while (nexte && e2 != e);
+
+ if (!e2)
+ e2 = e;
+
+ e = e2;
+ ov = v;
+ do {
+ if (c==0) {
+ BLI_array_append(ee1, e2);
+ BLI_array_append(vv1, v);
+ } else {
+ BLI_array_append(ee2, e2);
+ BLI_array_append(vv2, v);
+ }
+
+ BMO_SetFlag(bm, e2, EDGE_DONE);
+
+ v = BM_OtherEdgeVert(e2, v);
+ BM_ITER(e3, &iter, bm, BM_EDGES_OF_VERT, v) {
+ if (e3 != e2 && BMO_TestFlag(bm, e3, EDGE_MARK) && !BMO_TestFlag(bm, e3, EDGE_DONE)) {
+ break;
+ }
+ }
+ if (e3)
+ e2 = e3;
+ } while (e3 && e2 != e);
+
+ if (v && !e3) {
+ if (c==0) {
+ if (BLI_array_count(vv1) && v == vv1[BLI_array_count(vv1)-1]) {
+ printf("eck!\n");
+ }
+ BLI_array_append(vv1, v);
+ } else {
+ BLI_array_append(vv2, v);
+ }
+ }
+
+ /*test for connected loops, and set cl1 or cl2 if so*/
+ if (v == ov) {
+ if (c==0)
+ cl1 = 1;
+ else
+ cl2 = 1;
+ }
+
+ c++;
+ }
+ }
+
+ if (ee1 && ee2) {
+ int i, j;
+ BMVert *v1, *v2, *v3, *v4;
+ int starti=0, dir1=1, wdir=0, lenv1, lenv2;
+
+ /* Simplify code below by avoiding the (!cl1 && cl2) case */
+ if (!cl1 && cl2) {
+ SWAP(int, cl1, cl2);
+ ARRAY_SWAP(BMVert *, vv1, vv2);
+ ARRAY_SWAP(BMEdge *, ee1, ee2);
+ }
+
+ lenv1=BLI_array_count(vv1);
+ lenv2=BLI_array_count(vv1);
+
+ /* Below code assumes vv1/vv2 each have at least two verts. should always be
+ a safe assumption, since ee1/ee2 are non-empty and an edge has two verts. */
+ BLI_assert((lenv1 > 1) && (lenv2 > 1));
+
+ /* BMESH_TODO: Would be nice to handle cases where the edge loops
+ have different edge counts by generating triangles & quads for
+ the bridge instead of quads only. */
+ if (BLI_array_count(ee1) != BLI_array_count(ee2)) {
+ BMO_RaiseError(bm, op, BMERR_INVALID_SELECTION,
+ "Selected loops must have equal edge counts");
+ goto cleanup;
+ }
+
+ j = 0;
+ if (vv1[0] == vv1[lenv1-1]) {
+ lenv1--;
+ }
+ if (vv2[0] == vv2[lenv2-1]) {
+ lenv2--;
+ }
+
+ /* Find starting point and winding direction for two unclosed loops */
+ if (!cl1 && !cl2) {
+ /* First point of loop 1 */
+ v1 = get_outer_vert(bm, ee1[0]);
+ /* Last point of loop 1 */
+ v2 = get_outer_vert(bm, ee1[CLAMP_INDEX(-1, BLI_array_count(ee1))]);
+ /* First point of loop 2 */
+ v3 = get_outer_vert(bm, ee2[0]);
+ /* Last point of loop 2 */
+ v4 = get_outer_vert(bm, ee2[CLAMP_INDEX(-1, BLI_array_count(ee2))]);
+
+ /* If v1 is a better match for v4 than v3, AND v2 is a better match
+ for v3 than v4, the loops are in opposite directions, so reverse
+ the order of reads from vv1 */
+ if (len_v3v3(v1->co, v3->co) > len_v3v3(v1->co, v4->co) &&
+ len_v3v3(v2->co, v4->co) > len_v3v3(v2->co, v3->co)) {
+ dir1 = -1;
+ starti = CLAMP_INDEX(-1, lenv1);
+ }
+ }
+
+ /* Find the shortest distance from a vert in vv1 to vv2[0]. Use that
+ vertex in vv1 as a starting point in the first loop, while starting
+ from vv2[0] in the second loop. This is a simplistic attempt to get
+ a better edge-to-edge match between the two loops. */
+ if (cl1) {
+ int previ, nexti;
+ float min = 1e32;
+
+ /* BMESH_TODO: Would be nice to do a more thorough analysis of all
+ the vertices in both loops to find a more accurate match for the
+ starting point and winding direction of the bridge generation. */
+
+ for (i=0; i<BLI_array_count(vv1); i++) {
+ if (len_v3v3(vv1[i]->co, vv2[0]->co) < min) {
+ min = len_v3v3(vv1[i]->co, vv2[0]->co);
+ starti = i;
+ }
+ }
+
+ /* Reverse iteration order for the first loop if the distance of
+ * the (starti-1) vert from vv1 is a better match for vv2[1] than
+ * the (starti+1) vert.
+ *
+ * This is not always going to be right, but it will work better in
+ * the average case.
+ */
+ previ = CLAMP_INDEX(starti - 1, lenv1);
+ nexti = CLAMP_INDEX(starti + 1, lenv1);
+
+ if (len_v3v3(vv1[nexti]->co, vv2[1]->co) > len_v3v3(vv1[previ]->co, vv2[1]->co)) {
+ /* reverse direction for reading vv1 (1 is forward, -1 is backward) */
+ dir1 = -1;
+ }
+ }
+
+ /* Vert rough attempt to determine proper winding for the bridge quads:
+ just uses the first loop it finds for any of the edges of ee2 or ee1 */
+ if (wdir == 0) {
+ for (i=0; i<BLI_array_count(ee2); i++) {
+ if (ee2[i]->l) {
+ wdir = (ee2[i]->l->v == vv2[i]) ? (-1) : (1);
+ break;
+ }
+ }
+ }
+ if (wdir == 0) {
+ for (i=0; i<BLI_array_count(ee1); i++) {
+ j = CLAMP_INDEX((i*dir1)+starti, lenv1);
+ if (ee1[j]->l) {
+ wdir = (ee2[j]->l->v == vv2[j]) ? (1) : (-1);
+ break;
+ }
+ }
+ }
+
+ /* Generate the bridge quads */
+ for (i=0; i<BLI_array_count(ee1) && i<BLI_array_count(ee2); i++) {
+ BMFace *f;
+ int i1, i1next, i2, i2next;
+
+ i1 = CLAMP_INDEX(i*dir1 + starti, lenv1);
+ i1next = CLAMP_INDEX((i+1)*dir1 + starti, lenv1);
+ i2 = i;
+ i2next = CLAMP_INDEX(i+1, lenv2);
+
+ if (vv1[i1] == vv1[i1next]) {
+ continue;
+ }
+
+ if (wdir < 0) {
+ SWAP(int, i1, i1next);
+ SWAP(int, i2, i2next);
+ }
+
+ f = BM_Make_QuadTri(bm,
+ vv1[i1],
+ vv2[i2],
+ vv2[i2next],
+ vv1[i1next],
+ NULL, 1);
+ if (!f || f->len != 4) {
+ fprintf(stderr, "%s: in bridge! (bmesh internal error)\n", __func__);
+ }
+ }
+ }
+
+cleanup:
+ BLI_array_free(ee1);
+ BLI_array_free(ee2);
+ BLI_array_free(vv1);
+ BLI_array_free(vv2);
+}
diff --git a/source/blender/bmesh/operators/createops.c b/source/blender/bmesh/operators/createops.c
new file mode 100644
index 00000000000..9b7dc422de1
--- /dev/null
+++ b/source/blender/bmesh/operators/createops.c
@@ -0,0 +1,1257 @@
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "BLI_memarena.h"
+#include "BLI_mempool.h"
+#include "BLI_heap.h"
+#include "BLI_ghash.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_array.h"
+#include "BLI_smallhash.h"
+#include "BLI_rand.h"
+
+#include "bmesh.h"
+#include "bmesh_operators_private.h"
+
+#define EDGE_MARK 1
+#define EDGE_VIS 2
+
+#define FACE_NEW 1
+
+#define ELE_NEW 1
+#define ELE_OUT 2
+#define ELE_ORIG 4
+
+#define FACE_IGNORE 16
+
+typedef struct EPathNode {
+ struct EPathNode *next, *prev;
+ BMVert *v;
+ BMEdge *e;
+ BMEdge *cure;
+} EPathNode;
+
+typedef struct EPath {
+ ListBase nodes;
+ float weight;
+ int group;
+} EPath;
+
+typedef struct PathBase {
+ BLI_mempool *nodepool, *pathpool;
+} PathBase;
+
+typedef struct EdgeData {
+ int tag;
+ int ftag;
+
+ struct {
+ struct BMEdge *next, *prev;
+ } dlink1;
+ struct {
+ struct BMEdge *next, *prev;
+ } dlink2;
+} EdgeData;
+
+typedef struct VertData {
+ BMEdge *e;
+ float no[3], offco[3], sco[3]; /*offco is vertex coordinate slightly offset randomly*/
+ int tag;
+} VertData;
+
+static int count_edge_faces(BMesh *bm, BMEdge *e);
+
+/**** rotation system code ***/
+
+#define rs_get_edge_link(e, v, ed) ((v) == ((BMEdge*)(e))->v1 ? (Link*)&(((EdgeData*)(ed))->dlink1) : (Link*)&(((EdgeData*)(ed))->dlink2))
+
+static int rotsys_append_edge(struct BMEdge *e, struct BMVert *v,
+ EdgeData *edata, VertData *vdata)
+{
+ EdgeData *ed = &edata[BM_GetIndex(e)];
+ VertData *vd = &vdata[BM_GetIndex(v)];
+
+ if (!vd->e) {
+ Link *e1 = (Link*)rs_get_edge_link(e, v, ed);
+
+ vd->e = e;
+ e1->next = e1->prev = (Link*)e;
+ } else {
+ Link *e1, *e2, *e3;
+ EdgeData *ved = &edata[BM_GetIndex(vd->e)];
+
+ e1 = rs_get_edge_link(e, v, ed);
+ e2 = rs_get_edge_link(vd->e, v, ved);
+ e3 = e2->prev ? rs_get_edge_link(e2->prev, v, &edata[BM_GetIndex(e2->prev)]) : NULL;
+
+ e1->next = (Link*)vd->e;
+ e1->prev = e2->prev;
+
+ e2->prev = (Link*)e;
+ if (e3)
+ e3->next = (Link*)e;
+ }
+
+ return 1;
+}
+
+static void rotsys_remove_edge(struct BMEdge *e, struct BMVert *v,
+ EdgeData *edata, VertData *vdata)
+{
+ EdgeData *ed = edata + BM_GetIndex(e);
+ VertData *vd = vdata + BM_GetIndex(v);
+ Link *e1, *e2;
+
+ e1 = rs_get_edge_link(e, v, ed);
+ if (e1->prev) {
+ e2 = rs_get_edge_link(e1->prev, v, ed);
+ e2->next = e1->next;
+ }
+
+ if (e1->next) {
+ e2 = rs_get_edge_link(e1->next, v, ed);
+ e2->prev = e1->prev;
+ }
+
+ if (vd->e == e)
+ vd->e = (e != (BMEdge *)e1->next) ? (BMEdge*)e1->next : NULL;
+
+ e1->next = e1->prev = NULL;
+}
+
+static struct BMEdge *rotsys_nextedge(struct BMEdge *e, struct BMVert *v,
+ EdgeData *edata, VertData *UNUSED(vdata))
+{
+ if (v == e->v1)
+ return edata[BM_GetIndex(e)].dlink1.next;
+ if (v == e->v2)
+ return edata[BM_GetIndex(e)].dlink2.next;
+ return NULL;
+}
+
+static BMEdge *rotsys_prevedge(BMEdge *e, BMVert *v,
+ EdgeData *edata, VertData *UNUSED(vdata))
+{
+ if (v == e->v1)
+ return edata[BM_GetIndex(e)].dlink1.prev;
+ if (v == e->v2)
+ return edata[BM_GetIndex(e)].dlink2.prev;
+ return NULL;
+}
+
+static struct BMEdge *rotsys_reverse(struct BMEdge *UNUSED(e), struct BMVert *v, EdgeData *edata, VertData *vdata)
+{
+ BMEdge **edges = NULL;
+ BMEdge *e2;
+ BLI_array_staticdeclare(edges, 256);
+ int i, totedge;
+
+ e2 = vdata[BM_GetIndex(v)].e;
+ do {
+ BLI_array_append(edges, e2);
+ e2 = rotsys_nextedge(e2, v, edata, vdata);
+ } while (e2 != vdata[BM_GetIndex(v)].e);
+
+ totedge = BLI_array_count(edges);
+ for (i=0; i<totedge/2; i++) {
+ SWAP(BMEdge*, edges[i], edges[totedge-1-i]);
+ }
+
+ vdata[BM_GetIndex(v)].e = NULL;
+ for (i=0; i<totedge; i++) {
+ rotsys_append_edge(edges[i], v, edata, vdata);
+ }
+
+ BLI_array_free(edges);
+
+ return 0;
+}
+
+static int rotsys_count(struct BMVert *v, EdgeData *edata, VertData *vdata)
+{
+ BMEdge *e = vdata[BM_GetIndex(v)].e;
+ int i=0;
+
+ if (!e)
+ return 0;
+
+ do {
+ if (!e)
+ return 0;
+ e = rotsys_nextedge(e, v, edata, vdata);
+
+ if (i >= (1<<20)) {
+ printf("bmesh error: infinite loop in disk cycle!\n");
+ return 0;
+ }
+
+ i += 1;
+ } while (e != vdata[BM_GetIndex(v)].e);
+
+ return i;
+}
+
+static int rotsys_fill_faces(BMesh *bm, EdgeData *edata, VertData *vdata)
+{
+ BMIter iter;
+ BMEdge *e, **edges = NULL;
+ BLI_array_declare(edges);
+ BMVert *v, **verts = NULL;
+ BMFace *f;
+ BLI_array_declare(verts);
+ SmallHash visithash, *hash=&visithash;
+ int i;
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ BMEdge *e2, *starte;
+ BMVert *startv;
+ int rad, ok;
+
+ rad = count_edge_faces(bm, e);
+
+ if (rad < 2)
+ starte = e;
+ else
+ continue;
+
+ /*do two passes, going forward then backward*/
+ for (i=0; i<2; i++) {
+ BLI_smallhash_init(hash);
+
+ BLI_array_empty(verts);
+ BLI_array_empty(edges);
+
+ startv = v = starte->v1;
+ e2 = starte;
+ ok = 1;
+ if (!v || !e2)
+ continue;
+
+ do {
+ if (BLI_smallhash_haskey(hash, (intptr_t)e2)
+ || BLI_smallhash_haskey(hash, (intptr_t)v)) {
+ ok = 0;
+ break;
+ }
+
+ BLI_array_append(verts, v);
+ BLI_array_append(edges, e2);
+
+ BLI_smallhash_insert(hash, (intptr_t)e2, NULL);
+
+ v = BM_OtherEdgeVert(e2, v);
+ e2 = i ? rotsys_prevedge(e2, v, edata, vdata) : rotsys_nextedge(e2, v, edata, vdata);
+ } while (e2 != starte && v != startv);
+
+ BLI_smallhash_release(hash);
+
+ if (!ok || BLI_array_count(edges) < 3)
+ continue;
+
+ f = BM_Make_Ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), 1);
+ if (!f)
+ continue;
+ }
+ }
+
+ return 0;
+}
+
+static void rotsys_make_consistent(BMesh *bm, EdgeData *edata, VertData *vdata)
+{
+ BMIter iter;
+ BMEdge *e;
+ BMVert *v, **stack=NULL;
+ BLI_array_declare(stack);
+ int i;
+
+ for (i=0; i<bm->totvert; i++) {
+ vdata[i].tag = 0;
+ }
+
+ while (1) {
+ VertData *vd;
+ BMVert *startv = NULL;
+ float dis;
+
+ v = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; i<bm->totvert; i++, BMIter_Step(&iter)) {
+ vd = vdata + BM_GetIndex(v);
+
+ if (vd->tag)
+ continue;
+
+ if (!startv || dot_v3v3(vd->offco, vd->offco) > dis) {
+ dis = dot_v3v3(vd->offco, vd->offco);
+ startv = v;
+ }
+ }
+
+ if (!startv)
+ break;
+
+ vd = vdata + BM_GetIndex(startv);
+
+ BLI_array_empty(stack);
+ BLI_array_append(stack, startv);
+
+ vd->tag = 1;
+
+ while (BLI_array_count(stack)) {
+ v = BLI_array_pop(stack);
+ vd = vdata + BM_GetIndex(v);
+
+ if (!vd->e)
+ continue;
+
+ e = vd->e;
+ do {
+ BMVert *v2 = BM_OtherEdgeVert(e, v);
+ VertData *vd2 = vdata + BM_GetIndex(v2);
+
+ if (dot_v3v3(vd->no, vd2->no) < 0.0f+FLT_EPSILON*2) {
+ rotsys_reverse(e, v2, edata, vdata);
+ mul_v3_fl(vd2->no, -1.0f);
+ }
+
+ if (!vd2->tag) {
+ BLI_array_append(stack, v2);
+ vd2->tag = 1;
+ }
+
+ e = rotsys_nextedge(e, v, edata, vdata);
+ } while (e != vd->e);
+ }
+ }
+
+ BLI_array_free(stack);
+}
+
+static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata)
+{
+ BMIter iter;
+ BMEdge *e;
+ BMEdge **edges = NULL;
+ BLI_array_staticdeclare(edges, 256);
+ BMVert *v;
+ /*BMVert **verts = NULL; */
+ /*BLI_array_staticdeclare(verts, 256);*/ /*UNUSED*/
+ int i;
+
+ #define SIGN(n) ((n)<0.0f)
+
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ BMIter eiter;
+ float no[3], cent[3];
+ int j, k=0, totedge=0;
+
+ if (BM_GetIndex(v) == -1)
+ continue;
+
+ BLI_array_empty(edges);
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ if (BMO_TestFlag(bm, e, EDGE_MARK)) {
+ BLI_array_append(edges, e);
+ totedge++;
+ }
+ }
+
+ copy_v3_v3(cent, v->co);
+
+ zero_v3(no);
+ for (i=0; i<totedge; i++) {
+ BMEdge *e1, *e2;
+ float cno[3], vec1[3], vec2[3];
+
+ e1 = edges[i];
+ e2 = edges[(i+1)%totedge];
+
+ sub_v3_v3v3(vec1, (BM_OtherEdgeVert(e1, v))->co, v->co);
+ sub_v3_v3v3(vec2, (BM_OtherEdgeVert(e2, v))->co, v->co);
+
+ cross_v3_v3v3(cno, vec1, vec2);
+ normalize_v3(cno);
+
+ if (i && dot_v3v3(cno, no) < 0.0f+FLT_EPSILON*10)
+ mul_v3_fl(cno, -1.0f);
+
+ add_v3_v3(no, cno);
+ normalize_v3(no);
+ }
+
+ /*generate plane-flattened coordinates*/
+ for (i=0; i<totedge; i++) {
+ BMEdge *e1;
+ BMVert *v2;
+ float cvec[3], vec1[3];
+
+ e1 = edges[i];
+ v2 = BM_OtherEdgeVert(e1, v);
+
+ sub_v3_v3v3(vec1, v2->co, v->co);
+
+ cross_v3_v3v3(cvec, vec1, no);
+ cross_v3_v3v3(vec1, cvec, no);
+ normalize_v3(vec1);
+
+ mul_v3_fl(vec1, len_v3v3(v2->co, v->co));
+ add_v3_v3(vec1, v->co);
+
+ copy_v3_v3(vdata[BM_GetIndex(v2)].sco, vec1);
+ }
+
+ BLI_srandom(0);
+
+ /*first, ensure no 0 or 180 angles between adjacent
+ (and that adjacent's adjacent) edges*/
+ for (i=0, k=0; i<totedge; i++) {
+ BMEdge *e1, *e2, *e3=NULL;
+ BMVert *v1, *v2, *v3;
+ VertData *vd1, *vd2, *vd3;
+ float vec1[3], vec2[3], vec3[3], size;
+ int s1, s2, s3;
+
+ if (totedge < 3)
+ continue;
+
+ e1 = edges[(i+totedge-1) % totedge];
+ e2 = edges[i];
+ e3 = edges[(i+1) % totedge];
+
+ v1 = BM_OtherEdgeVert(e1, v); v2 = BM_OtherEdgeVert(e2, v); v3 = BM_OtherEdgeVert(e3, v);
+ vd1 = vdata+BM_GetIndex(v1); vd2 = vdata+BM_GetIndex(v2); vd3 = vdata+BM_GetIndex(v3);
+
+ sub_v3_v3v3(vec1, vd1->sco, cent);
+ sub_v3_v3v3(vec2, vd2->sco, cent);
+ sub_v3_v3v3(vec3, vd3->sco, cent);
+
+ size = (len_v3(vec1) + len_v3(vec3)) * 0.01f;
+ normalize_v3(vec1); normalize_v3(vec2); normalize_v3(vec3);
+
+ #ifdef STRAIGHT
+ #undef STRAIGHT
+ #endif
+ #define STRAIGHT(vec11, vec22) (fabsf(dot_v3v3((vec11), (vec22))) > 1.0f - ((float)FLT_EPSILON*1000.0f))
+
+ s1 = STRAIGHT(vec1, vec2); s2 = STRAIGHT(vec2, vec3); s3 = STRAIGHT(vec1, vec3);
+
+ if (s1 || s2 || s3) {
+ copy_v3_v3(cent, v->co);
+
+ for (j=0; j<3; j++) {
+ float fac = (BLI_frand()-0.5f)*size;
+ cent[j] += fac;
+ }
+
+ if (k < 2000) {
+ i = 0;
+ k++;
+ continue;
+ } else {
+ k++;
+ continue;
+ }
+
+ }
+ }
+
+ copy_v3_v3(vdata[BM_GetIndex(v)].offco, cent);
+ //copy_v3_v3(v->co, cent);
+
+ /*now, sort edges so the triangle fan of all edges
+ has a consistent normal. this is the same as
+ sorting by polar coordinates along a group normal*/
+ for (j=0; j<totedge; j++) {
+ for (i=0; i<totedge; i++) {
+ BMEdge *e1, *e2, *e3=NULL;
+ BMVert *v1, *v2, *v3;
+ VertData *vd1, *vd2, *vd3;
+ float vec1[3], vec2[3], vec3[3], n1[3], n2[3], n3[3];
+ int s1, s2, s3;
+
+ e1 = edges[(i+totedge-1) % totedge];
+ e2 = edges[i];
+ e3 = edges[(i+1) % totedge];
+
+ v1 = BM_OtherEdgeVert(e1, v); v2 = BM_OtherEdgeVert(e2, v); v3 = BM_OtherEdgeVert(e3, v);
+ vd1 = vdata+BM_GetIndex(v1); vd2 = vdata+BM_GetIndex(v2); vd3 = vdata+BM_GetIndex(v3);
+
+ sub_v3_v3v3(vec1, vd1->sco, cent);
+ sub_v3_v3v3(vec2, vd2->sco, cent);
+ sub_v3_v3v3(vec3, vd3->sco, cent);
+
+ cross_v3_v3v3(n1, vec1, vec2);
+ cross_v3_v3v3(n2, vec2, vec3);
+ cross_v3_v3v3(n3, vec1, vec3);
+
+ /* Other way to determine if two vectors approach are (nearly) parallel: the
+ cross product of the two vectors will approach zero */
+ s1 = (dot_v3v3(n1, n1) < (0.0f + FLT_EPSILON*10));
+ s2 = (dot_v3v3(n2, n2) < (0.0f + FLT_EPSILON*10));
+ s3 = (totedge < 3) ? 0 : (dot_v3v3(n3, n3) < (0.0f + FLT_EPSILON*10));
+
+ normalize_v3(n1); normalize_v3(n2); normalize_v3(n3);
+
+ if (s1 || s2 || s3) {
+ fprintf(stderr, "%s: s1: %d, s2: %d, s3: %dx (bmesh internal error)\n", __func__, s1, s2, s3);
+ }
+ if (dot_v3v3(n1, n2) < 0.0f) {
+ if (dot_v3v3(n1, n3) >= 0.0f + FLT_EPSILON*10) {
+ SWAP(BMEdge*, edges[i], edges[(i+1)%totedge]);
+ } else {
+ SWAP(BMEdge*, edges[(i+totedge-1)%totedge], edges[(i+1)%totedge])
+ SWAP(BMEdge*, edges[i], edges[(i+1)%totedge])
+ }
+ }
+ }
+ }
+
+ #undef STRAIGHT
+
+ zero_v3(no);
+
+ /*yay, edges is sorted*/
+ for (i=0; i<totedge; i++) {
+ BMEdge *e1 = edges[i], *e2 = edges[(i+1)%totedge];
+ float eno[3];
+
+ normal_tri_v3(eno, BM_OtherEdgeVert(e1, v)->co, v->co, BM_OtherEdgeVert(e2, v)->co);
+ add_v3_v3(no, eno);
+
+ rotsys_append_edge(edges[i], v, edata, vdata);
+ }
+
+ normalize_v3(no);
+ copy_v3_v3(vdata[BM_GetIndex(v)].no, no);
+ }
+
+ /*now, make sure rotation system is topologically consistent
+ (e.g. vert normals consistently point either inside or outside)*/
+ rotsys_make_consistent(bm, edata, vdata);
+
+ //rotsys_fill_faces(bm, edata, vdata);
+
+#if 0
+ /*create visualizing geometry*/
+ BMVert *lastv;
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ BMVert *v2;
+ BMFace *f;
+ int totedge = BM_Vert_EdgeCount(v);
+
+ if (BM_GetIndex(v) == -1)
+ continue;
+
+ //cv = BM_Make_Vert(bm, cent, v);
+ //BM_SetIndex(cv, -1);
+ i = 0;
+ e = vdata[BM_GetIndex(v)].e;
+ lastv = NULL;
+ do {
+ BMEdge *e2;
+ BMVert *v2;
+ float f = ((float)i / (float)totedge)*0.35 + 0.05;
+ float co[3];
+
+ if (!e)
+ break;
+
+ if (!BM_OtherEdgeVert(e, v))
+ continue;
+
+ sub_v3_v3v3(co, (BM_OtherEdgeVert(e, v))->co, vdata[BM_GetIndex(v)].offco);
+ mul_v3_fl(co, f);
+ add_v3_v3(co, vdata[BM_GetIndex(v)].offco);
+
+ v2 = BM_Make_Vert(bm, co, NULL);
+ BM_SetIndex(v2, -1);
+ //BM_Make_Edge(bm, cv, v2, NULL, 0);
+
+ BM_Select(bm, v2, 1);
+ if (lastv) {
+ e2 =
+ BM_Make_Edge(bm, lastv, v2, NULL, 0);
+ BM_Select(bm, e2, 1);
+ }
+
+ lastv = v2;
+
+ e = rotsys_nextedge(e, v, edata, vdata);
+ i++;
+ } while (e != vdata[BM_GetIndex(v)].e);
+ }
+#endif
+
+ BLI_array_free(edges);
+}
+
+static PathBase *edge_pathbase_new(void)
+{
+ PathBase *pb = MEM_callocN(sizeof(PathBase), "PathBase");
+
+ pb->nodepool = BLI_mempool_create(sizeof(EPathNode), 1, 512, 1, 0);
+ pb->pathpool = BLI_mempool_create(sizeof(EPath), 1, 512, 1, 0);
+
+ return pb;
+}
+
+static void edge_pathbase_free(PathBase *pathbase)
+{
+ BLI_mempool_destroy(pathbase->nodepool);
+ BLI_mempool_destroy(pathbase->pathpool);
+ MEM_freeN(pathbase);
+}
+
+static EPath *edge_copy_add_path(PathBase *pb, EPath *path, BMVert *appendv, BMEdge *e)
+{
+ EPath *path2;
+ EPathNode *node, *node2;
+
+ path2 = BLI_mempool_alloc(pb->pathpool);
+ path2->nodes.first = path2->nodes.last = NULL;
+ path2->weight = 0.0f;
+ path2->group = path->group;
+
+ for (node=path->nodes.first; node; node=node->next) {
+ node2 = BLI_mempool_alloc(pb->nodepool);
+ *node2 = *node;
+ BLI_addtail(&path2->nodes, node2);
+ }
+
+ node2 = BLI_mempool_alloc(pb->nodepool);
+ node2->v = appendv;
+ node2->e = e;
+ node2->cure = NULL;
+
+ BLI_addtail(&path2->nodes, node2);
+
+ return path2;
+}
+
+static EPath *edge_path_new(PathBase *pb, BMVert *start, BMEdge *starte)
+{
+ EPath *path;
+ EPathNode *node;
+
+ path = BLI_mempool_alloc(pb->pathpool);
+ node = BLI_mempool_alloc(pb->nodepool);
+
+ path->nodes.first = path->nodes.last = NULL;
+
+ node->v = start;
+ node->e = starte;
+ node->cure = NULL;
+
+ BLI_addtail(&path->nodes, node);
+ path->weight = 0.0f;
+
+ return path;
+}
+
+static float edge_weight_path(EPath *path, EdgeData *edata, VertData *UNUSED(vdata))
+{
+ EPathNode *node, *first=path->nodes.first;
+ float w = 0.0;
+
+ for (node=path->nodes.first; node; node=node->next) {
+ if (node->e && node != path->nodes.first) {
+ w += edata[BM_GetIndex(node->e)].ftag;
+ if (node->prev) {
+ /*BMESH_TODO*/
+ (void)first;
+ //w += len_v3v3(node->v->co, first->e->v1->co)*0.0001f;
+ //w += len_v3v3(node->v->co, first->e->v2->co)*0.0001f;
+ }
+ }
+
+ w += 1.0f;
+ }
+
+ return w;
+}
+
+
+static void edge_free_path(PathBase *pathbase, EPath *path)
+{
+ EPathNode *node, *next;
+
+ for (node=path->nodes.first; node; node=next) {
+ next = node->next;
+ BLI_mempool_free(pathbase->nodepool, node);
+ }
+
+ BLI_mempool_free(pathbase->pathpool, path);
+}
+
+static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, EdgeData *edata,
+ VertData *vdata, PathBase *pathbase, int group)
+{
+ BMEdge *e;
+ GHash *gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createops find shortest path");
+ BMVert *v1, *v2;
+ BMVert **verts = NULL;
+ BLI_array_staticdeclare(verts, 1024);
+ Heap *heap = BLI_heap_new();
+ EPath *path = NULL, *path2;
+ BMVert *startv;
+ BMVert *endv;
+ EPathNode *node;
+ int i, use_restrict = BMO_Get_Int(op, "use_restrict");
+
+ startv = edata[BM_GetIndex(edge)].ftag ? edge->v2 : edge->v1;
+ endv = edata[BM_GetIndex(edge)].ftag ? edge->v1 : edge->v2;
+
+ path = edge_path_new(pathbase, startv, edge);
+ BLI_ghash_insert(gh, startv, NULL);
+ BLI_heap_insert(heap, path->weight, path);
+ path->group = group;
+
+ while (BLI_heap_size(heap)) {
+ VertData *vd;
+ EPathNode *last;
+ BMFace *f = NULL;
+
+ path = BLI_heap_popmin(heap);
+ last = path->nodes.last;
+ v1 = last->v;
+
+ if (v1 == endv) {
+ /*make sure this path loop doesn't already exist*/
+ i = 0;
+ BLI_array_empty(verts);
+ for (i=0, node = path->nodes.first; node; node=node->next, i++) {
+ BLI_array_growone(verts);
+ verts[i] = node->v;
+ }
+
+ if (BM_Face_Exists(bm, verts, i, &f)) {
+ if (!BMO_TestFlag(bm, f, FACE_IGNORE)) {
+ BLI_ghash_remove(gh, endv, NULL, NULL);
+ continue;
+ }
+ }
+ break;
+ }
+
+ vd = vdata + BM_GetIndex(v1);
+ if (!vd->e)
+ continue;
+
+ v2 = NULL;
+ while (1) {
+ if (!last->cure) {
+ last->cure = e = vdata[BM_GetIndex(last->v)].e;
+ } else {
+ last->cure = e = rotsys_nextedge(last->cure, last->v, edata, vdata);
+ if (last->cure == vdata[BM_GetIndex(last->v)].e) {
+ v2 = NULL;
+ break;
+ }
+ }
+
+ if (e == edge || !BMO_TestFlag(bm, e, EDGE_MARK)) {
+ continue;
+ }
+
+ v2 = BM_OtherEdgeVert(e, last->v);
+
+ if (BLI_ghash_haskey(gh, v2)) {
+ v2 = NULL;
+ continue;
+ }
+
+ if (use_restrict && BMO_InMap(bm, op, "restrict", e)) {
+ int group = BMO_Get_MapInt(bm, op, "restrict", e);
+
+ if (!(group & path->group)) {
+ v2 = NULL;
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ if (!v2) {
+ if (path) {
+ edge_free_path(pathbase, path);
+ path = NULL;
+ }
+ continue;
+ }
+
+ /*add path back into heap*/
+ BLI_heap_insert(heap, path->weight, path);
+
+ /*put v2 in gh map*/
+ BLI_ghash_insert(gh, v2, NULL);
+
+ path2 = edge_copy_add_path(pathbase, path, v2, e);
+ path2->weight = edge_weight_path(path2, edata, vdata);
+
+ BLI_heap_insert(heap, path2->weight, path2);
+ }
+
+ if (path && ((EPathNode*)path->nodes.last)->v != endv) {
+ edge_free_path(pathbase, path);
+ path = NULL;
+ }
+
+ BLI_array_free(verts);
+ BLI_heap_free(heap, NULL);
+ BLI_ghash_free(gh, NULL, NULL);
+
+ return path;
+}
+
+static int count_edge_faces(BMesh *bm, BMEdge *e) {
+ int i=0;
+ BMLoop *l = e->l;
+
+ if (!l)
+ return 0;
+
+ do {
+ if (!BMO_TestFlag(bm, l->f, FACE_IGNORE))
+ i++;
+
+ l = l->radial_next;
+ } while (l != e->l);
+
+ return i;
+}
+
+void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op)
+{
+ BMIter iter;
+ BMOIter siter;
+ BMFace *f;
+ BMEdge *e, *edge;
+ BMVert *v, **verts = NULL;
+ BLI_array_declare(verts);
+ EPath *path;
+ EPathNode *node;
+ EdgeData *edata;
+ VertData *vdata;
+ BMEdge **edges = NULL;
+ PathBase *pathbase = edge_pathbase_new();
+ BLI_array_declare(edges);
+ int use_restrict = BMO_Get_Int(op, "use_restrict");
+ int i, j, group = 0;
+
+ if (!bm->totvert || !bm->totedge)
+ return;
+
+ edata = MEM_callocN(sizeof(EdgeData)*bm->totedge, "EdgeData");
+ vdata = MEM_callocN(sizeof(VertData)*bm->totvert, "VertData");
+
+ BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE);
+ BMO_Flag_Buffer(bm, op, "excludefaces", FACE_IGNORE, BM_FACE);
+
+ i = 0;
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(v, i);
+ i++;
+ }
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ BMO_SetFlag(bm, f, ELE_ORIG);
+ }
+
+ i = 0;
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ BM_SetIndex(e, i);
+
+ if (!BMO_TestFlag(bm, e, EDGE_MARK)) {
+ edata[i].tag = 2;
+ }
+
+ i += 1;
+ }
+
+ init_rotsys(bm, edata, vdata);
+
+ while (1) {
+ edge = NULL;
+ group = 0;
+
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ /*if restrict is on, only start on faces in the restrict map*/
+ if (use_restrict && !BMO_InMap(bm, op, "restrict", e))
+ continue;
+
+ if (edata[BM_GetIndex(e)].tag < 2) {
+ edge = e;
+
+ if (use_restrict) {
+ int i=0, j=0, gi=0;
+
+ group = BMO_Get_MapInt(bm, op, "restrict", e);
+
+ for (i=0; i<30; i++) {
+ if (group & (1<<i)) {
+ j++;
+ gi = i;
+
+ if (j-1 == edata[BM_GetIndex(e)].tag)
+ break;
+ }
+ }
+
+ group = 1<<gi;
+ }
+
+ break;
+ }
+ }
+
+ if (!edge)
+ break;
+
+ edata[BM_GetIndex(edge)].tag += 1;
+
+ path = edge_find_shortest_path(bm, op, edge, edata, vdata, pathbase, group);
+ if (!path)
+ continue;
+
+ BLI_array_empty(edges);
+ BLI_array_empty(verts);
+ i = 0;
+ for (node=path->nodes.first; node; node=node->next) {
+ if (!node->next)
+ continue;
+
+ e = BM_Edge_Exist(node->v, node->next->v);
+
+ /*this should never happen*/
+ if (!e)
+ break;
+
+ edata[BM_GetIndex(e)].ftag++;
+ BLI_array_growone(edges);
+ edges[i++] = e;
+
+ BLI_array_append(verts, node->v);
+ }
+
+ BLI_array_growone(edges);
+ edges[i++] = edge;
+ edata[BM_GetIndex(edge)].ftag++;
+
+ for (j=0; j<i; j++) {
+ if (count_edge_faces(bm, edges[j]) >= 2) {
+ edge_free_path(pathbase, path);
+ break;
+ }
+ }
+
+ if (j != i)
+ continue;
+
+ if (i) {
+ f = BM_Make_Ngon(bm, edge->v1, edge->v2, edges, i, 1);
+ if (f && !BMO_TestFlag(bm, f, ELE_ORIG)) {
+ BMO_SetFlag(bm, f, FACE_NEW);
+ }
+
+ if (use_restrict)
+ BMO_Insert_MapInt(bm, op, "faceout_groupmap", f, path->group);
+ }
+
+ edge_free_path(pathbase, path);
+ }
+
+ BMO_Flag_To_Slot(bm, op, "faceout", FACE_NEW, BM_FACE);
+
+ BLI_array_free(edges);
+ BLI_array_free(verts);
+ edge_pathbase_free(pathbase);
+ MEM_freeN(edata);
+ MEM_freeN(vdata);
+}
+
+static BMEdge *edge_next(BMesh *bm, BMEdge *e)
+{
+ BMIter iter;
+ BMEdge *e2;
+ int i;
+
+ for (i=0; i<2; i++) {
+ BM_ITER(e2, &iter, bm, BM_EDGES_OF_VERT, i?e->v2:e->v1) {
+ if (BMO_TestFlag(bm, e2, EDGE_MARK)
+ && !BMO_TestFlag(bm, e2, EDGE_VIS) && e2 != e)
+ {
+ return e2;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void bmesh_edgenet_prepare(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMEdge *e;
+ BMEdge **edges1 = NULL, **edges2 = NULL, **edges;
+ BLI_array_declare(edges1);
+ BLI_array_declare(edges2);
+ BLI_array_declare(edges);
+ int ok = 1;
+ int i, count;
+
+ BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE);
+
+ /*validate that each edge has at most one other tagged edge in the
+ disk cycle around each of it's vertices*/
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ for (i=0; i<2; i++) {
+ count = BMO_Vert_CountEdgeFlags(bm, i?e->v2:e->v1, EDGE_MARK);
+ if (count > 2) {
+ ok = 0;
+ break;
+ }
+ }
+
+ if (!ok) break;
+ }
+
+ /*we don't have valid edge layouts, return*/
+ if (!ok)
+ return;
+
+
+ /*find connected loops within the input edges*/
+ count = 0;
+ while (1) {
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ if (!BMO_TestFlag(bm, e, EDGE_VIS)) {
+ if (BMO_Vert_CountEdgeFlags(bm, e->v1, EDGE_MARK)==1)
+ break;
+ if (BMO_Vert_CountEdgeFlags(bm, e->v2, EDGE_MARK)==1)
+ break;
+ }
+ }
+
+ if (!e) break;
+
+ if (!count)
+ edges = edges1;
+ else if (count==1)
+ edges = edges2;
+ else break;
+
+ i = 0;
+ while (e) {
+ BMO_SetFlag(bm, e, EDGE_VIS);
+ BLI_array_growone(edges);
+ edges[i] = e;
+
+ e = edge_next(bm, e);
+ i++;
+ }
+
+ if (!count) {
+ edges1 = edges;
+ BLI_array_set_length(edges1, BLI_array_count(edges));
+ } else {
+ edges2 = edges;
+ BLI_array_set_length(edges2, BLI_array_count(edges));
+ }
+
+ BLI_array_empty(edges);
+ count++;
+ }
+
+#define EDGECON(e1, e2) (e1->v1 == e2->v1 || e1->v2 == e2->v2 || e1->v1 == e2->v2)
+
+ if (edges1 && BLI_array_count(edges1) > 2 && EDGECON(edges1[0], edges1[BLI_array_count(edges1)-1])) {
+ if (edges2 && BLI_array_count(edges2) > 2 && EDGECON(edges2[0], edges2[BLI_array_count(edges2)-1])) {
+ BLI_array_free(edges1);
+ BLI_array_free(edges2);
+ return;
+ } else {
+ edges1 = edges2;
+ edges2 = NULL;
+ }
+ }
+
+ if (edges2 && BLI_array_count(edges2) > 2 && EDGECON(edges2[0], edges2[BLI_array_count(edges2)-1])) {
+ edges2 = NULL;
+ }
+
+ /*two unconnected loops, connect them*/
+ if (edges1 && edges2) {
+ BMVert *v1, *v2, *v3, *v4;
+
+ if (BLI_array_count(edges1)==1) {
+ v1 = edges1[0]->v1;
+ v2 = edges1[0]->v2;
+ } else {
+ if (BM_Vert_In_Edge(edges1[1], edges1[0]->v1))
+ v1 = edges1[0]->v2;
+ else v1 = edges1[0]->v1;
+
+ i = BLI_array_count(edges1)-1;
+ if (BM_Vert_In_Edge(edges1[i-1], edges1[i]->v1))
+ v2 = edges1[i]->v2;
+ else v2 = edges1[i]->v1;
+ }
+
+ if (BLI_array_count(edges2)==1) {
+ v3 = edges2[0]->v1;
+ v4 = edges2[0]->v2;
+ } else {
+ if (BM_Vert_In_Edge(edges2[1], edges2[0]->v1))
+ v3 = edges2[0]->v2;
+ else v3 = edges2[0]->v1;
+
+ i = BLI_array_count(edges2)-1;
+ if (BM_Vert_In_Edge(edges2[i-1], edges2[i]->v1))
+ v4 = edges2[i]->v2;
+ else v4 = edges2[i]->v1;
+ }
+
+ if (len_v3v3(v1->co, v3->co) + len_v3v3(v2->co, v4->co) >
+ len_v3v3(v1->co, v4->co) + len_v3v3(v2->co, v3->co)) {
+ BMVert *v;
+ v = v3;
+ v3 = v4;
+ v4 = v;
+ }
+
+ e = BM_Make_Edge(bm, v1, v3, NULL, 1);
+ BMO_SetFlag(bm, e, ELE_NEW);
+ e = BM_Make_Edge(bm, v2, v4, NULL, 1);
+ BMO_SetFlag(bm, e, ELE_NEW);
+ } else if (edges1) {
+ BMVert *v1, *v2;
+
+ if (BLI_array_count(edges1) > 1) {
+ if (BM_Vert_In_Edge(edges1[1], edges1[0]->v1))
+ v1 = edges1[0]->v2;
+ else v1 = edges1[0]->v1;
+
+ i = BLI_array_count(edges1)-1;
+ if (BM_Vert_In_Edge(edges1[i-1], edges1[i]->v1))
+ v2 = edges1[i]->v2;
+ else v2 = edges1[i]->v1;
+
+ e = BM_Make_Edge(bm, v1, v2, NULL, 1);
+ BMO_SetFlag(bm, e, ELE_NEW);
+ }
+ }
+
+ BMO_Flag_To_Slot(bm, op, "edgeout", ELE_NEW, BM_EDGE);
+
+ BLI_array_free(edges1);
+ BLI_array_free(edges2);
+
+#undef EDGECON
+}
+
+/*this is essentially new fkey*/
+void bmesh_contextual_create_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator op2;
+ BMOIter oiter;
+ BMIter iter;
+ BMHeader *h;
+ BMVert *v, *verts[4];
+ BMEdge *e;
+ BMFace *f;
+ int totv=0, tote=0, totf=0, amount;
+
+ /*count number of each element type we were passed*/
+ BMO_ITER(h, &oiter, bm, op, "geom", BM_VERT|BM_EDGE|BM_FACE) {
+ switch (h->type) {
+ case BM_VERT: totv++; break;
+ case BM_EDGE: tote++; break;
+ case BM_FACE: totf++; break;
+ }
+
+ BMO_SetFlag(bm, h, ELE_NEW);
+ }
+
+ /*call edgenet create*/
+ /* call edgenet prepare op so additional face creation cases work*/
+ BMO_InitOpf(bm, &op2, "edgenet_prepare edges=%fe", ELE_NEW);
+ BMO_Exec_Op(bm, &op2);
+ BMO_Flag_Buffer(bm, &op2, "edgeout", ELE_NEW, BM_EDGE);
+ BMO_Finish_Op(bm, &op2);
+
+ BMO_InitOpf(bm, &op2, "edgenet_fill edges=%fe", ELE_NEW);
+ BMO_Exec_Op(bm, &op2);
+
+ /*return if edge net create did something*/
+ if (BMO_CountSlotBuf(bm, &op2, "faceout")) {
+ BMO_CopySlot(&op2, op, "faceout", "faceout");
+ BMO_Finish_Op(bm, &op2);
+ return;
+ }
+
+ BMO_Finish_Op(bm, &op2);
+
+ /*now call dissolve faces*/
+ BMO_InitOpf(bm, &op2, "dissolvefaces faces=%ff", ELE_NEW);
+ BMO_Exec_Op(bm, &op2);
+
+ /*if we dissolved anything, then return.*/
+ if (BMO_CountSlotBuf(bm, &op2, "regionout")) {
+ BMO_CopySlot(&op2, op, "regionout", "faceout");
+ BMO_Finish_Op(bm, &op2);
+ return;
+ }
+
+ BMO_Finish_Op(bm, &op2);
+
+ /*now, count how many verts we have*/
+ amount = 0;
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, v, ELE_NEW)) {
+ verts[amount] = v;
+ amount++;
+
+ if (amount > 4) break;
+ }
+ }
+
+ if (amount == 2) {
+ /*create edge*/
+ e = BM_Make_Edge(bm, verts[0], verts[1], NULL, 1);
+ BMO_SetFlag(bm, e, ELE_OUT);
+ } else if (amount == 3) {
+ /*create triangle*/
+ BM_Make_QuadTri(bm, verts[0], verts[1], verts[2], NULL, NULL, 1);
+ } else if (amount == 4) {
+ f = NULL;
+
+ /* the order of vertices can be anything, 6 cases to check */
+ if( is_quad_convex_v3(verts[0]->co, verts[1]->co, verts[2]->co, verts[3]->co) ) {
+ f= BM_Make_QuadTri(bm, verts[0], verts[1], verts[2], verts[3], NULL, 1);
+ }
+ else if( is_quad_convex_v3(verts[0]->co, verts[2]->co, verts[3]->co, verts[1]->co) ) {
+ f= BM_Make_QuadTri(bm, verts[0], verts[2], verts[3], verts[1], NULL, 1);
+ }
+ else if( is_quad_convex_v3(verts[0]->co, verts[2]->co, verts[1]->co, verts[3]->co) ) {
+ f= BM_Make_QuadTri(bm, verts[0], verts[2], verts[1], verts[3], NULL, 1);
+ }
+ else if( is_quad_convex_v3(verts[0]->co, verts[1]->co, verts[3]->co, verts[2]->co) ) {
+ f= BM_Make_QuadTri(bm, verts[0], verts[1], verts[3], verts[2], NULL, 1);
+ }
+ else if( is_quad_convex_v3(verts[0]->co, verts[3]->co, verts[2]->co, verts[1]->co) ) {
+ f= BM_Make_QuadTri(bm, verts[0], verts[3], verts[2], verts[1], NULL, 1);
+ }
+ else if( is_quad_convex_v3(verts[0]->co, verts[3]->co, verts[1]->co, verts[2]->co) ) {
+ f= BM_Make_QuadTri(bm, verts[0], verts[3], verts[1], verts[2], NULL, 1);
+ }
+ else {
+ printf("cannot find nice quad from concave set of vertices\n");
+ }
+
+ if (f) BMO_SetFlag(bm, f, ELE_OUT);
+ }
+}
diff --git a/source/blender/bmesh/operators/dissolveops.c b/source/blender/bmesh/operators/dissolveops.c
new file mode 100644
index 00000000000..87c331915fc
--- /dev/null
+++ b/source/blender/bmesh/operators/dissolveops.c
@@ -0,0 +1,374 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "bmesh.h"
+#include "mesh_intern.h"
+#include "bmesh_private.h"
+#include "BLI_math.h"
+#include "BLI_array.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define FACE_MARK 1
+#define FACE_ORIG 2
+#define FACE_NEW 4
+#define EDGE_MARK 1
+
+#define VERT_MARK 1
+
+static int check_hole_in_region(BMesh *bm, BMFace *f) {
+ BMWalker regwalker;
+ BMIter liter2;
+ BMLoop *l2, *l3;
+ BMFace *f2;
+
+ /*checks if there are any unmarked boundary edges in the face region*/
+
+ BMW_Init(&regwalker, bm, BMW_ISLAND, FACE_MARK, 0);
+ f2 = BMW_Begin(&regwalker, f);
+ for (; f2; f2=BMW_Step(&regwalker)) {
+ l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
+ for (; l2; l2=BMIter_Step(&liter2)) {
+ l3 = bmesh_radial_nextloop(l2);
+ if (BMO_TestFlag(bm, l3->f, FACE_MARK)
+ != BMO_TestFlag(bm, l2->f, FACE_MARK))
+ {
+ if (!BMO_TestFlag(bm, l2->e, EDGE_MARK)) {
+ return 0;
+ }
+ }
+ }
+ }
+ BMW_End(&regwalker);
+
+ return 1;
+}
+
+void dissolvefaces_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter oiter;
+ BMFace *f, *f2 /* , *nf = NULL */;
+ BLI_array_declare(faces);
+ BLI_array_declare(regions);
+ BMFace ***regions = NULL;
+ BMFace **faces = NULL;
+ BMWalker regwalker;
+ int i;
+
+ BMO_Flag_Buffer(bm, op, "faces", FACE_MARK, BM_FACE);
+
+ /*collect regions*/
+ BMO_ITER(f, &oiter, bm, op, "faces", BM_FACE) {
+ if (!BMO_TestFlag(bm, f, FACE_MARK)) continue;
+
+ BLI_array_empty(faces);
+ faces = NULL; /*forces different allocation*/
+
+ /*yay, walk!*/
+ BMW_Init(&regwalker, bm, BMW_ISLAND, FACE_MARK, 0);
+ f2 = BMW_Begin(&regwalker, f);
+ for (; f2; f2=BMW_Step(&regwalker)) {
+ BLI_array_append(faces, f2);
+ }
+ BMW_End(&regwalker);
+
+ for (i=0; i<BLI_array_count(faces); i++) {
+ f2 = faces[i];
+ BMO_ClearFlag(bm, f2, FACE_MARK);
+ BMO_SetFlag(bm, f2, FACE_ORIG);
+ }
+
+ if (BMO_HasError(bm)) {
+ BMO_ClearStack(bm);
+ BMO_RaiseError(bm, op, BMERR_DISSOLVEFACES_FAILED, NULL);
+ goto cleanup;
+ }
+
+ BLI_array_append(faces, NULL);
+ BLI_array_append(regions, faces);
+ }
+
+ for (i=0; i<BLI_array_count(regions); i++) {
+ int tot=0;
+
+ faces = regions[i];
+ if (!faces[0]) {
+ BMO_RaiseError(bm, op, BMERR_DISSOLVEFACES_FAILED,
+ "Could not find boundary of dissolve region");
+ goto cleanup;
+ }
+
+ /**/
+ while (faces[tot])
+ tot++;
+
+ f = BM_Join_Faces(bm, faces, tot);
+ if (!f) {
+ BMO_RaiseError(bm, op, BMERR_DISSOLVEFACES_FAILED,
+ "Could not create merged face");
+ goto cleanup;
+ }
+
+ /*if making the new face failed (e.g. overlapping test)
+ unmark the original faces for deletion.*/
+ BMO_ClearFlag(bm, f, FACE_ORIG);
+ BMO_SetFlag(bm, f, FACE_NEW);
+
+ }
+
+ BMO_CallOpf(bm, "del geom=%ff context=%d", FACE_ORIG, DEL_FACES);
+ if (BMO_HasError(bm)) goto cleanup;
+
+ BMO_Flag_To_Slot(bm, op, "regionout", FACE_NEW, BM_FACE);
+
+cleanup:
+ /*free/cleanup*/
+ for (i=0; i<BLI_array_count(regions); i++) {
+ if (regions[i]) MEM_freeN(regions[i]);
+ }
+
+ BLI_array_free(regions);
+}
+
+/*almost identical to dissolve edge, except it cleans up vertices*/
+void dissolve_edgeloop_exec(BMesh *bm, BMOperator *op)
+{
+ /* BMOperator fop; */
+ BMOIter oiter;
+ BMIter iter;
+ BMVert *v, **verts = NULL;
+ BLI_array_declare(verts);
+ BMEdge *e;
+ /* BMFace *f; */
+ int i;
+
+ BMO_ITER(e, &oiter, bm, op, "edges", BM_EDGE) {
+ if (BM_Edge_FaceCount(e) == 2) {
+ BMO_SetFlag(bm, e->v1, VERT_MARK);
+ BMO_SetFlag(bm, e->v2, VERT_MARK);
+
+ BM_Join_TwoFaces(bm, e->l->f,
+ e->l->radial_next->f,
+ e);
+ }
+ }
+
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, v, VERT_MARK) &&
+ BM_Vert_EdgeCount(v) == 2)
+ {
+ BLI_array_growone(verts);
+ verts[BLI_array_count(verts)-1] = v;
+ }
+ }
+
+ /*clean up extreneous 2-valence vertices*/
+ for (i=0; i<BLI_array_count(verts); i++) {
+ if (verts[i]->e)
+ BM_Collapse_Vert(bm, verts[i]->e, verts[i], 1.0);
+ }
+
+ BLI_array_free(verts);
+
+ //BMO_InitOpf(bm, &fop, "dissolvefaces faces=%ff", FACE_MARK);
+ //BMO_Exec_Op(bm, &fop);
+
+ //BMO_CopySlot(op, &fop, "regionout", "regionout");
+
+ //BMO_Finish_Op(bm, &fop);
+}
+
+
+void dissolveedges_exec(BMesh *bm, BMOperator *op)
+{
+ /* BMOperator fop; */
+ BMOIter oiter;
+ /* BMIter iter; */
+ /* BMVert *v; */
+ BMEdge *e;
+ /* BMFace *f; */
+ /* int i; */
+
+ BMO_ITER(e, &oiter, bm, op, "edges", BM_EDGE) {
+ if (BM_Edge_FaceCount(e) == 2) {
+ BM_Join_TwoFaces(bm, e->l->f,
+ e->l->radial_next->f,
+ e);
+ }
+ }
+}
+
+static int test_extra_verts(BMesh *bm, BMVert *v)
+{
+ BMIter iter, liter, iter2, iter3;
+ BMFace *f, *f2;
+ BMLoop *l;
+ BMEdge *e;
+ int found;
+
+ /*test faces around verts for verts that would be wronly killed
+ by dissolve faces.*/
+ f = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v);
+ for (; f; f=BMIter_Step(&iter)) {
+ l=BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ for (; l; l=BMIter_Step(&liter)) {
+ if (!BMO_TestFlag(bm, l->v, VERT_MARK)) {
+ /*if an edge around a vert is a boundary edge,
+ then dissolve faces won't destroy it.
+ also if it forms a boundary with one
+ of the face regions*/
+ found = 0;
+ e = BMIter_New(&iter2, bm, BM_EDGES_OF_VERT, l->v);
+ for (; e; e=BMIter_Step(&iter2)) {
+ if (BM_Edge_FaceCount(e)==1) found = 1;
+ f2 = BMIter_New(&iter3, bm, BM_FACES_OF_EDGE, e);
+ for (; f2; f2=BMIter_Step(&iter3)) {
+ if (!BMO_TestFlag(bm, f2, FACE_MARK)) {
+ found = 1;
+ break;
+ }
+ }
+ if (found) break;
+ }
+ if (!found) return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+void dissolveverts_exec(BMesh *bm, BMOperator *op)
+{
+ BMOpSlot *vinput;
+ BMIter iter, fiter;
+ BMVert *v;
+ BMFace *f;
+ /* int i; */
+
+ vinput = BMO_GetSlot(op, "verts");
+ BMO_Flag_Buffer(bm, op, "verts", VERT_MARK, BM_VERT);
+
+ for (v=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); v; v=BMIter_Step(&iter)) {
+ if (BMO_TestFlag(bm, v, VERT_MARK)) {
+ /*check if it's a two-valence vert*/
+ if (BM_Vert_EdgeCount(v) == 2) {
+
+ /*collapse the vert*/
+ BM_Collapse_Vert(bm, v->e, v, 0.5f);
+ continue;
+ }
+
+ f=BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
+ for (; f; f=BMIter_Step(&fiter)) {
+ BMO_SetFlag(bm, f, FACE_ORIG);
+ BMO_SetFlag(bm, f, FACE_MARK);
+ }
+
+ /*check if our additions to the input to face dissolve
+ will destroy nonmarked vertices.*/
+ if (!test_extra_verts(bm, v)) {
+ f=BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
+ for (; f; f=BMIter_Step(&fiter)) {
+ if (BMO_TestFlag(bm, f, FACE_ORIG)) {
+ BMO_ClearFlag(bm, f, FACE_MARK);
+ BMO_ClearFlag(bm, f, FACE_ORIG);
+ }
+ }
+ } else {
+ f=BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
+ for (; f; f=BMIter_Step(&fiter)) {
+ BMO_ClearFlag(bm, f, FACE_ORIG);
+ }
+ }
+ }
+ }
+
+ BMO_CallOpf(bm, "dissolvefaces faces=%ff", FACE_MARK);
+ if (BMO_HasError(bm)) {
+ const char *msg;
+
+ BMO_GetError(bm, &msg, NULL);
+ BMO_ClearStack(bm);
+ BMO_RaiseError(bm, op, BMERR_DISSOLVEVERTS_FAILED,msg);
+ }
+
+ /*clean up any remaining*/
+ for (v=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL); v; v=BMIter_Step(&iter)) {
+ if (BMO_TestFlag(bm, v, VERT_MARK)) {
+ if (!BM_Dissolve_Vert(bm, v)) {
+ BMO_RaiseError(bm, op,
+ BMERR_DISSOLVEVERTS_FAILED, NULL);
+ return;
+ }
+ }
+ }
+
+}
+
+/*this code is for cleaning up two-edged faces, it shall become
+ it's own function one day.*/
+#if 0
+ /*clean up two-edged faces*/
+ /*basic idea is to keep joining 2-edged faces until their
+ gone. this however relies on joining two 2-edged faces
+ together to work, which doesn't.*/
+ found3 = 1;
+ while (found3) {
+ found3 = 0;
+ for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f=BMIter_Step(&iter)){
+ if (!BM_Validate_Face(bm, f, stderr)) {
+ printf("error.\n");
+ }
+
+ if (f->len == 2) {
+ //this design relies on join faces working
+ //with two-edged faces properly.
+ //commenting this line disables the
+ //outermost loop.
+ //found3 = 1;
+ found2 = 0;
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ fe = l->e;
+ for (; l; l=BMIter_Step(&liter)) {
+ f2 = BMIter_New(&fiter, bm,
+ BM_FACES_OF_EDGE, l->e);
+ for (; f2; f2=BMIter_Step(&fiter)) {
+ if (f2 != f) {
+ BM_Join_TwoFaces(bm, f, f2, l->e);
+ found2 = 1;
+ break;
+ }
+ }
+ if (found2) break;
+ }
+
+ if (!found2) {
+ bmesh_kf(bm, f);
+ bmesh_ke(bm, fe);
+ }
+ } /*else if (f->len == 3) {
+ BMEdge *ed[3];
+ BMVert *vt[3];
+ BMLoop *lp[3];
+ int i=0;
+
+ //check for duplicate edges
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ for (; l; l=BMIter_Step(&liter)) {
+ ed[i] = l->e;
+ lp[i] = l;
+ vt[i++] = l->v;
+ }
+ if (vt[0] == vt[1] || vt[0] == vt[2]) {
+ i += 1;
+ }
+ }*/
+ }
+ }
+ if (oldlen == len) break;
+ oldlen = len;
+
+#endif
diff --git a/source/blender/bmesh/operators/edgesplitop.c b/source/blender/bmesh/operators/edgesplitop.c
new file mode 100644
index 00000000000..d0869f46078
--- /dev/null
+++ b/source/blender/bmesh/operators/edgesplitop.c
@@ -0,0 +1,447 @@
+/**
+ * $Id:
+ *
+ * ***** 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
+
+#include "BLI_math.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_array.h"
+
+#include "DNA_object_types.h"
+
+#include "ED_mesh.h"
+
+#include "bmesh.h"
+#include "mesh_intern.h"
+#include "subdivideop.h"
+
+#include "bmesh_operators_private.h" /* own include */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+typedef struct EdgeTag {
+ BMVert *newv1, *newv2;
+ BMEdge *newe1, *newe2;
+ int tag;
+} EdgeTag;
+
+#define EDGE_SEAM 1
+#define EDGE_DEL 2
+#define EDGE_MARK 4
+#define EDGE_RET1 8
+#define EDGE_RET2 16
+
+#define FACE_DEL 1
+#define FACE_NEW 2
+
+static BMFace *remake_face(BMesh *bm, EdgeTag *etags, BMFace *f, BMVert **verts, BMEdge **edges_tmp)
+{
+ BMIter liter1, liter2;
+ EdgeTag *et;
+ BMFace *f2;
+ BMLoop *l, *l2;
+ BMEdge *e;
+ BMVert *lastv1, *lastv2, *v1, *v2;
+ int i;
+
+ /*we do final edge last*/
+ lastv1 = verts[f->len-1];
+ lastv2 = verts[0];
+ v1 = verts[0];
+ v2 = verts[1];
+ for (i=0; i<f->len-1; i++) {
+ e = BM_Make_Edge(bm, verts[i], verts[i+1], NULL, 1);
+ if (!e) {
+ return NULL;
+ }
+ edges_tmp[i] = e;
+ }
+
+ edges_tmp[i] = BM_Make_Edge(bm, lastv1, lastv2, NULL, 1);
+
+ f2 = BM_Make_Face(bm, verts, edges_tmp, f->len, 0);
+ if (!f2) {
+ return NULL;
+ }
+
+ BM_Copy_Attributes(bm, bm, f, f2);
+
+ l = BMIter_New(&liter1, bm, BM_LOOPS_OF_FACE, f);
+ l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
+ for (; l && l2; l=BMIter_Step(&liter1), l2=BMIter_Step(&liter2)) {
+ BM_Copy_Attributes(bm, bm, l, l2);
+ if (l->e != l2->e) {
+ /*set up data for figuring out the two sides of
+ the splits*/
+ BM_SetIndex(l2->e, BM_GetIndex(l->e));
+ et = etags + BM_GetIndex(l->e);
+
+ if (!et->newe1) {
+ et->newe1 = l2->e;
+ }
+ else if (!et->newe2) {
+ et->newe2 = l2->e;
+ }
+ else {
+ /* Only two new edges should be created from each original edge
+ for edge split operation */
+ //BLI_assert(et->newe1 == l2->e || et->newe2 == l2->e);
+ et->newe2 = l2->e;
+ }
+
+ if (BMO_TestFlag(bm, l->e, EDGE_SEAM)) {
+ BMO_SetFlag(bm, l2->e, EDGE_SEAM);
+ }
+
+ BM_Copy_Attributes(bm, bm, l->e, l2->e);
+ }
+
+ BMO_SetFlag(bm, l->e, EDGE_MARK);
+ BMO_SetFlag(bm, l2->e, EDGE_MARK);
+ }
+
+ return f2;
+}
+
+static void tag_out_edges(BMesh *bm, EdgeTag *etags, BMOperator *UNUSED(op))
+{
+ EdgeTag *et;
+ BMIter iter;
+ BMLoop *l, *startl;
+ BMEdge *e;
+ BMVert *v;
+ int i, j, ok;
+
+ ok=0;
+ while (ok++ < 100000) {
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, e, EDGE_SEAM))
+ continue;
+
+ et = etags + BM_GetIndex(e);
+ if (!et->tag && e->l) {
+ break;
+ }
+ }
+
+ if (!e)
+ break;
+
+ /*ok we found an edge, part of a region of splits we need
+ to identify. now walk along it.*/
+ for (i=0; i<2; i++) {
+ l = e->l;
+
+ v = i ? l->next->v : l->v;
+
+ j = 0;
+ while (1) {
+ et = etags + BM_GetIndex(l->e);
+ if (et->newe1 == l->e) {
+ if (et->newe1) {
+ BMO_SetFlag(bm, et->newe1, EDGE_RET1);
+ BMO_ClearFlag(bm, et->newe1, EDGE_SEAM);
+ }
+ if (et->newe2) {
+ BMO_SetFlag(bm, et->newe2, EDGE_RET2);
+ BMO_ClearFlag(bm, et->newe2, EDGE_SEAM);
+ }
+ }
+ else {
+ if (et->newe1) {
+ BMO_SetFlag(bm, et->newe1, EDGE_RET2);
+ BMO_ClearFlag(bm, et->newe1, EDGE_SEAM);
+ }
+ if (et->newe2) {
+ BMO_SetFlag(bm, et->newe2, EDGE_RET1);
+ BMO_ClearFlag(bm, et->newe2, EDGE_SEAM);
+ }
+ }
+
+ startl = l;
+ do {
+ l = BM_OtherFaceLoop(l->e, l->f, v);
+ if (BM_Edge_FaceCount(l->e) != 2) {
+ break;
+ }
+ l = l->radial_next;
+ } while (l != startl && !BMO_TestFlag(bm, l->e, EDGE_SEAM));
+
+ if (l == startl || !BMO_TestFlag(bm, l->e, EDGE_SEAM)) {
+ break;
+ }
+
+ v = (l->v == v) ? l->next->v : l->v;
+
+ /*
+ * temporary workaround for #28869: this inner loop is hanging
+ * on loading some file with edge split modifier. the loop visits
+ * vertices, and shouldn't execute more iterations than there are
+ * vertices in the mesh.
+ *
+ * clear tags and bail if things start to seem flaky.
+ */
+ if (++j > bm->totvert) {
+ BLI_assert(0);
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ BMO_SetFlag(bm, e, EDGE_RET1);
+ BMO_SetFlag(bm, e, EDGE_RET2);
+ }
+
+ return;
+ }
+ }
+ }
+ }
+}
+
+void bmesh_edgesplitop_exec(BMesh *bm, BMOperator *op)
+{
+ EdgeTag *etags, *et;
+ BMIter iter, liter;
+ BMOIter siter;
+ BMFace *f, *f2;
+ BMLoop *l, *nextl, *prevl, *l2, *l3;
+ BMEdge *e, *e2;
+ BMVert *v, *v2, **verts = NULL;
+ BLI_array_declare(verts);
+ BMEdge **edges_tmp = NULL;
+ BLI_array_declare(edges_tmp);
+ int i, j;
+
+ BMO_Flag_Buffer(bm, op, "edges", EDGE_SEAM, BM_EDGE);
+
+ /* single marked edges unconnected to any other marked edges
+ * are illegal, go through and unmark them */
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ for (i=0; i<2; i++) {
+ BM_ITER(e2, &iter, bm, BM_EDGES_OF_VERT, i ? e->v2 : e->v1) {
+ if (e != e2 && BMO_TestFlag(bm, e2, EDGE_SEAM)) {
+ break;
+ }
+ }
+ if (e2) {
+ break;
+ }
+ }
+
+ if (!e2) {
+ BMO_ClearFlag(bm, e, EDGE_SEAM);
+ }
+ }
+
+ etags = MEM_callocN(sizeof(EdgeTag)*bm->totedge, "EdgeTag");
+
+ i = 0;
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ BM_SetIndex(e, i);
+ i++;
+ }
+
+#ifdef ETV
+# undef ETV
+#endif
+#ifdef SETETV
+# undef SETETV
+#endif
+
+#define ETV(et, v, l) (l->e->v1 == v ? et->newv1 : et->newv2)
+#define SETETV(et, v, l, vs) l->e->v1 == v ? (et->newv1 = vs) : (et->newv2 = vs)
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+
+ if (BMO_TestFlag(bm, f, FACE_NEW)) {
+ continue;
+ }
+
+ BLI_array_empty(verts);
+ BLI_array_growitems(verts, f->len);
+ memset(verts, 0, sizeof(BMVert*)*f->len);
+
+ /* this is passed onto remake_face() so it doesnt need to allocate
+ * a new array on each call. */
+ BLI_array_empty(edges_tmp);
+ BLI_array_growitems(edges_tmp, f->len);
+
+ i = 0;
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ if (!BMO_TestFlag(bm, l->e, EDGE_SEAM)) {
+ if (!verts[i]) {
+
+ et = etags + BM_GetIndex(l->e);
+ if (ETV(et, l->v, l)) {
+ verts[i] = ETV(et, l->v, l);
+ }
+ else
+ {
+ verts[i] = l->v;
+ }
+ }
+ i++;
+ continue;
+ }
+
+ nextl = l->next;
+ prevl = l->prev;
+
+ for (j=0; j<2; j++) {
+ /* correct as long as i & j dont change during the loop */
+ const int fv_index= j ? (i+1) % f->len : i; /* face vert index */
+ l2 = j ? nextl : prevl;
+ v = j ? l2->v : l->v;
+
+ if (BMO_TestFlag(bm, l2->e, EDGE_SEAM)) {
+ if (verts[fv_index] == NULL) {
+ /*make unique vert here for this face only*/
+ v2 = BM_Make_Vert(bm, v->co, v);
+ verts[fv_index] = v2;
+ }
+ else {
+ v2 = verts[fv_index];
+ }
+ }
+ else {
+ /* generate unique vert for non-seam edge(s)
+ * around the manifold vert fan if necassary */
+
+ /* first check that we have two seam edges
+ * somewhere within this fan*/
+ l3 = l2;
+ do {
+ if (BM_Edge_FaceCount(l3->e) != 2) {
+ /* if we hit a boundary edge, tag
+ * l3 as null so we know to disconnect
+ * it */
+ if (BM_Edge_FaceCount(l3->e) == 1) {
+ l3 = NULL;
+ }
+ break;
+ }
+
+ l3 = l3->radial_next;
+ l3 = BM_OtherFaceLoop(l3->e, l3->f, v);
+ } while (l3 != l2 && !BMO_TestFlag(bm, l3->e, EDGE_SEAM));
+
+ if (l3 == NULL || (BMO_TestFlag(bm, l3->e, EDGE_SEAM) && l3->e != l->e)) {
+ et = etags + BM_GetIndex(l2->e);
+ if (ETV(et, v, l2) == NULL) {
+ v2 = BM_Make_Vert(bm, v->co, v);
+
+ l3 = l2;
+ do {
+ SETETV(et, v, l3, v2);
+ if (BM_Edge_FaceCount(l3->e) != 2) {
+ break;
+ }
+
+ l3 = l3->radial_next;
+ l3 = BM_OtherFaceLoop(l3->e, l3->f, v);
+
+ et = etags + BM_GetIndex(l3->e);
+ } while (l3 != l2 && !BMO_TestFlag(bm, l3->e, EDGE_SEAM));
+ }
+ else {
+ v2 = ETV(et, v, l2);
+ }
+
+ verts[fv_index] = v2;
+ }
+ else {
+ verts[fv_index] = v;
+ }
+ }
+ }
+
+ i++;
+ }
+
+ /* debugging code, quick way to find the face/vert combination
+ * which is failing assuming quads start planer - campbell */
+#if 0
+ if(f->len == 4) {
+ float no1[3];
+ float no2[3];
+ float angle_error;
+ printf(" ** found QUAD\n");
+ normal_tri_v3(no1, verts[0]->co, verts[1]->co, verts[2]->co);
+ normal_tri_v3(no2, verts[0]->co, verts[2]->co, verts[3]->co);
+ if((angle_error= angle_v3v3(no1, no2)) > 0.05) {
+ printf(" ERROR %.4f\n", angle_error);
+ print_v3("0", verts[0]->co);
+ print_v3("1", verts[1]->co);
+ print_v3("2", verts[2]->co);
+ print_v3("3", verts[3]->co);
+
+ }
+ }
+ else {
+ printf(" ** fount %d len face\n", f->len);
+ }
+#endif
+
+ f2 = remake_face(bm, etags, f, verts, edges_tmp);
+ if (!f2) {
+ continue;
+ }
+
+ BMO_SetFlag(bm, f, FACE_DEL);
+ BMO_SetFlag(bm, f2, FACE_NEW);
+ }
+
+ BMO_CallOpf(bm, "del geom=%ff context=%i", FACE_DEL, DEL_ONLYFACES);
+
+ /* test EDGE_MARK'd edges if we need to delete them, EDGE_MARK
+ * is set in remake_face */
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, e, EDGE_MARK)) {
+ if (!e->l) {
+ BMO_SetFlag(bm, e, EDGE_DEL);
+ }
+ }
+ }
+
+ BMO_CallOpf(bm, "del geom=%fe context=%i", EDGE_DEL, DEL_EDGES);
+
+ tag_out_edges(bm, etags, op);
+ BMO_Flag_To_Slot(bm, op, "edgeout1", EDGE_RET1, BM_EDGE);
+ BMO_Flag_To_Slot(bm, op, "edgeout2", EDGE_RET2, BM_EDGE);
+
+ BLI_array_free(verts);
+ BLI_array_free(edges_tmp);
+ if (etags) MEM_freeN(etags);
+}
+
+#undef ETV
+#undef SETETV
diff --git a/source/blender/bmesh/operators/extrudeops.c b/source/blender/bmesh/operators/extrudeops.c
new file mode 100644
index 00000000000..a6d2bd93047
--- /dev/null
+++ b/source/blender/bmesh/operators/extrudeops.c
@@ -0,0 +1,577 @@
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "BLI_ghash.h"
+#include "BLI_memarena.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_array.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+#include "bmesh_operators_private.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define EXT_INPUT 1
+#define EXT_KEEP 2
+#define EXT_DEL 4
+
+#define VERT_MARK 1
+#define EDGE_MARK 1
+#define FACE_MARK 1
+#define VERT_NONMAN 2
+#define EDGE_NONMAN 2
+
+void bmesh_extrude_face_indiv_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMIter liter, liter2;
+ BMFace *f, *f2, *f3;
+ BMLoop *l, *l2, *l3, *l4;
+ BMEdge **edges = NULL, *e, *laste;
+ BMVert *v, *lastv, *firstv;
+ BLI_array_declare(edges);
+ int i;
+
+ BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
+ BLI_array_empty(edges);
+ i = 0;
+ firstv = lastv = NULL;
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BLI_array_growone(edges);
+
+ v = BM_Make_Vert(bm, l->v->co, l->v);
+
+ if (lastv) {
+ e = BM_Make_Edge(bm, lastv, v, l->e, 0);
+ edges[i++] = e;
+ }
+
+ lastv = v;
+ laste = l->e;
+ if (!firstv) firstv = v;
+ }
+
+ BLI_array_growone(edges);
+ e = BM_Make_Edge(bm, v, firstv, laste, 0);
+ edges[i++] = e;
+
+ BMO_SetFlag(bm, f, EXT_DEL);
+
+ f2 = BM_Make_Ngon(bm, firstv, BM_OtherEdgeVert(edges[0], firstv), edges, f->len, 0);
+ if (!f2) {
+ BMO_RaiseError(bm, op, BMERR_MESH_ERROR, "Extrude failed; could not create face");
+ BLI_array_free(edges);
+ return;
+ }
+
+ BMO_SetFlag(bm, f2, EXT_KEEP);
+ BM_Copy_Attributes(bm, bm, f, f2);
+
+ l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BM_Copy_Attributes(bm, bm, l, l2);
+
+ l3 = l->next;
+ l4 = l2->next;
+
+ f3 = BM_Make_QuadTri(bm, l3->v, l4->v, l2->v, l->v, f, 0);
+
+ BM_Copy_Attributes(bm, bm, l->next, bm_firstfaceloop(f3));
+ BM_Copy_Attributes(bm, bm, l->next, bm_firstfaceloop(f3)->next);
+ BM_Copy_Attributes(bm, bm, l, bm_firstfaceloop(f3)->next->next);
+ BM_Copy_Attributes(bm, bm, l, bm_firstfaceloop(f3)->next->next->next);
+
+ l2 = BMIter_Step(&liter2);
+ }
+ }
+
+ BLI_array_free(edges);
+
+ BMO_CallOpf(bm, "del geom=%ff context=%d", EXT_DEL, DEL_ONLYFACES);
+ BMO_Flag_To_Slot(bm, op, "faceout", EXT_KEEP, BM_FACE);
+}
+
+void bmesh_extrude_onlyedge_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMOperator dupeop;
+ BMVert *v1, *v2, *v3, *v4;
+ BMEdge *e, *e2;
+ BMFace *f;
+
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ BMO_SetFlag(bm, e, EXT_INPUT);
+ BMO_SetFlag(bm, e->v1, EXT_INPUT);
+ BMO_SetFlag(bm, e->v2, EXT_INPUT);
+ }
+
+ BMO_InitOpf(bm, &dupeop, "dupe geom=%fve", EXT_INPUT);
+ BMO_Exec_Op(bm, &dupeop);
+
+ e = BMO_IterNew(&siter, bm, &dupeop, "boundarymap", 0);
+ for (; e; e=BMO_IterStep(&siter)) {
+ e2 = BMO_IterMapVal(&siter);
+ e2 = *(BMEdge**)e2;
+
+ if (e->l && e->v1 != e->l->v) {
+ v1 = e->v1;
+ v2 = e->v2;
+ v3 = e2->v2;
+ v4 = e2->v1;
+ } else {
+ v1 = e2->v1;
+ v2 = e2->v2;
+ v3 = e->v2;
+ v4 = e->v1;
+ }
+ /*not sure what to do about example face, pass NULL for now.*/
+ f = BM_Make_QuadTri(bm, v1, v2, v3, v4, NULL, 0);
+
+ if (BMO_TestFlag(bm, e, EXT_INPUT))
+ e = e2;
+
+ BMO_SetFlag(bm, f, EXT_KEEP);
+ BMO_SetFlag(bm, e, EXT_KEEP);
+ BMO_SetFlag(bm, e->v1, EXT_KEEP);
+ BMO_SetFlag(bm, e->v2, EXT_KEEP);
+
+ }
+
+ BMO_Finish_Op(bm, &dupeop);
+
+ BMO_Flag_To_Slot(bm, op, "geomout", EXT_KEEP, BM_ALL);
+}
+
+void extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMVert *v, *dupev;
+ BMEdge *e;
+
+ v = BMO_IterNew(&siter, bm, op, "verts", BM_VERT);
+ for (; v; v=BMO_IterStep(&siter)) {
+ dupev = BM_Make_Vert(bm, v->co, v);
+
+ e = BM_Make_Edge(bm, v, dupev, NULL, 0);
+
+ BMO_SetFlag(bm, e, EXT_KEEP);
+ BMO_SetFlag(bm, dupev, EXT_KEEP);
+ }
+
+ BMO_Flag_To_Slot(bm, op, "vertout", EXT_KEEP, BM_VERT);
+ BMO_Flag_To_Slot(bm, op, "edgeout", EXT_KEEP, BM_EDGE);
+}
+
+void extrude_edge_context_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator dupeop, delop;
+ BMOIter siter;
+ BMIter iter, fiter, viter;
+ BMEdge *e, *newedge;
+ BMLoop *l, *l2;
+ BMVert *verts[4], *v, *v2;
+ BMFace *f;
+ int rlen, found, fwd, delorig=0;
+
+ /*initialize our sub-operators*/
+ BMO_Init_Op(&dupeop, "dupe");
+
+ BMO_Flag_Buffer(bm, op, "edgefacein", EXT_INPUT, BM_EDGE|BM_FACE);
+
+ /*if one flagged face is bordered by an unflagged face, then we delete
+ original geometry unless caller explicitly asked to keep it. */
+ if (!BMO_Get_Int(op, "alwayskeeporig")) {
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, e, EXT_INPUT)) continue;
+
+ found = 0;
+ f = BMIter_New(&fiter, bm, BM_FACES_OF_EDGE, e);
+ for (rlen=0; f; f=BMIter_Step(&fiter), rlen++) {
+ if (!BMO_TestFlag(bm, f, EXT_INPUT)) {
+ found = 1;
+ delorig = 1;
+ break;
+ }
+ }
+
+ if (!found && (rlen > 1)) BMO_SetFlag(bm, e, EXT_DEL);
+ }
+ }
+
+ /*calculate verts to delete*/
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ found = 0;
+
+ BM_ITER(e, &viter, bm, BM_EDGES_OF_VERT, v) {
+ if (!BMO_TestFlag(bm, e, EXT_INPUT) || !BMO_TestFlag(bm, e, EXT_DEL)){
+ found = 1;
+ break;
+ }
+ }
+
+ BM_ITER(f, &viter, bm, BM_FACES_OF_VERT, v) {
+ if (!BMO_TestFlag(bm, f, EXT_INPUT)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ BMO_SetFlag(bm, v, EXT_DEL);
+ }
+ }
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, f, EXT_INPUT))
+ BMO_SetFlag(bm, f, EXT_DEL);
+ }
+
+ if (delorig) {
+ BMO_InitOpf(bm, &delop, "del geom=%fvef context=%d",
+ EXT_DEL, DEL_ONLYTAGGED);
+ }
+
+ BMO_CopySlot(op, &dupeop, "edgefacein", "geom");
+ BMO_Exec_Op(bm, &dupeop);
+
+ if (bm->act_face && BMO_TestFlag(bm, bm->act_face, EXT_INPUT))
+ bm->act_face = BMO_Get_MapPointer(bm, &dupeop, "facemap", bm->act_face);
+
+ if (delorig) BMO_Exec_Op(bm, &delop);
+
+ /*if not delorig, reverse loops of original faces*/
+ if (!delorig) {
+ for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f=BMIter_Step(&iter)) {
+ if (BMO_TestFlag(bm, f, EXT_INPUT)) {
+ BM_flip_normal(bm, f);
+ }
+ }
+ }
+
+ BMO_CopySlot(&dupeop, op, "newout", "geomout");
+ e = BMO_IterNew(&siter, bm, &dupeop, "boundarymap", 0);
+ for (; e; e=BMO_IterStep(&siter)) {
+ if (BMO_InMap(bm, op, "exclude", e)) continue;
+
+ newedge = BMO_IterMapVal(&siter);
+ newedge = *(BMEdge**)newedge;
+ if (!newedge) continue;
+
+ /* orient loop to give same normal as a loop of newedge
+ if it exists (will be an extruded face),
+ else same normal as a loop of e, if it exists */
+ if (!newedge->l)
+ fwd = !e->l || !(e->l->v == e->v1);
+ else
+ fwd = (newedge->l->v == newedge->v1);
+
+
+ if (fwd) {
+ verts[0] = e->v1;
+ verts[1] = e->v2;
+ verts[2] = newedge->v2;
+ verts[3] = newedge->v1;
+ } else {
+ verts[3] = e->v1;
+ verts[2] = e->v2;
+ verts[1] = newedge->v2;
+ verts[0] = newedge->v1;
+ }
+
+ /*not sure what to do about example face, pass NULL for now.*/
+ f = BM_Make_Quadtriangle(bm, verts, NULL, 4, NULL, 0);
+
+ /*copy attributes*/
+ l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f);
+ for (; l; l=BMIter_Step(&iter)) {
+ if (l->e != e && l->e != newedge) continue;
+ l2 = l->radial_next;
+
+ if (l2 == l) {
+ l2 = newedge->l;
+ BM_Copy_Attributes(bm, bm, l2->f, l->f);
+
+ BM_Copy_Attributes(bm, bm, l2, l);
+ l2 = l2->next;
+ l = l->next;
+ BM_Copy_Attributes(bm, bm, l2, l);
+ } else {
+ BM_Copy_Attributes(bm, bm, l2->f, l->f);
+
+ /*copy data*/
+ if (l2->v == l->v) {
+ BM_Copy_Attributes(bm, bm, l2, l);
+ l2 = l2->next;
+ l = l->next;
+ BM_Copy_Attributes(bm, bm, l2, l);
+ } else {
+ l2 = l2->next;
+ BM_Copy_Attributes(bm, bm, l2, l);
+ l2 = l2->prev;
+ l = l->next;
+ BM_Copy_Attributes(bm, bm, l2, l);
+ }
+ }
+ }
+ }
+
+ /*link isolated verts*/
+ v = BMO_IterNew(&siter, bm, &dupeop, "isovertmap", 0);
+ for (; v; v=BMO_IterStep(&siter)) {
+ v2 = *((void**)BMO_IterMapVal(&siter));
+ BM_Make_Edge(bm, v, v2, v->e, 1);
+ }
+
+ /*cleanup*/
+ if (delorig) BMO_Finish_Op(bm, &delop);
+ BMO_Finish_Op(bm, &dupeop);
+}
+
+/*
+ * Compute higher-quality vertex normals used by solidify.
+ * Only considers geometry in the marked solidify region.
+ * Note that this does not work so well for non-manifold
+ * regions.
+ */
+static void calc_solidify_normals(BMesh *bm)
+{
+ BMIter viter, eiter, fiter;
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f, *f1, *f2;
+ float edge_normal[3];
+ int i;
+
+ /* Clear indices of verts & edges */
+ BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(v, 0);
+ }
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_MESH, NULL) {
+ BM_SetIndex(e, 0);
+ }
+
+ BM_ITER(f, &fiter, bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, f, FACE_MARK)) {
+ continue;
+ }
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_FACE, f) {
+ /* Count number of marked faces using e */
+ i = BM_GetIndex(e);
+ BM_SetIndex(e, i+1);
+
+ /* And mark all edges and vertices on the
+ marked faces */
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ BMO_SetFlag(bm, e->v1, VERT_MARK);
+ BMO_SetFlag(bm, e->v2, VERT_MARK);
+ }
+ }
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, e, EDGE_MARK)) {
+ continue;
+ }
+
+ i = BM_GetIndex(e);
+
+ if (i == 0 || i > 2) {
+ /* Edge & vertices are non-manifold even when considering
+ only marked faces */
+ BMO_SetFlag(bm, e, EDGE_NONMAN);
+ BMO_SetFlag(bm, e->v1, VERT_NONMAN);
+ BMO_SetFlag(bm, e->v2, VERT_NONMAN);
+ }
+ }
+
+ BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_Nonmanifold_Vert(bm, v)) {
+ BMO_SetFlag(bm, v, VERT_NONMAN);
+ continue;
+ }
+
+ if (BMO_TestFlag(bm, v, VERT_MARK)) {
+ zero_v3(v->no);
+ }
+ }
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_MESH, NULL) {
+ float angle;
+
+ /* If the edge is not part of a the solidify region
+ its normal should not be considered */
+ if (!BMO_TestFlag(bm, e, EDGE_MARK)) {
+ continue;
+ }
+
+ /* If the edge joins more than two marked faces high
+ quality normal computation won't work */
+ if (BMO_TestFlag(bm, e, EDGE_NONMAN)) {
+ continue;
+ }
+
+ f1 = f2 = NULL;
+
+ BM_ITER(f, &fiter, bm, BM_FACES_OF_EDGE, e) {
+ if (BMO_TestFlag(bm, f, FACE_MARK)) {
+ if (f1 == NULL) {
+ f1 = f;
+ }
+ else {
+ BLI_assert(f2 == NULL);
+ f2 = f;
+ }
+ }
+ }
+
+ BLI_assert(f1 != NULL);
+
+ if (f2 != NULL) {
+ angle = angle_normalized_v3v3(f1->no, f2->no);
+
+ if (angle > 0.0f) {
+ /* two faces using this edge, calculate the edge normal
+ * using the angle between the faces as a weighting */
+ add_v3_v3v3(edge_normal, f1->no, f2->no);
+ normalize_v3(edge_normal);
+ mul_v3_fl(edge_normal, angle);
+ }
+ else {
+ /* can't do anything useful here!
+ Set the face index for a vert incase it gets a zero normal */
+ BM_SetIndex(e->v1, -1);
+ BM_SetIndex(e->v2, -1);
+ continue;
+ }
+ }
+ else {
+ /* only one face attached to that edge */
+ /* an edge without another attached- the weight on this is
+ * undefined, M_PI/2 is 90d in radians and that seems good enough */
+ copy_v3_v3(edge_normal, f1->no);
+ mul_v3_fl(edge_normal, M_PI/2);
+ }
+
+ add_v3_v3(e->v1->no, edge_normal);
+ add_v3_v3(e->v2->no, edge_normal);
+ }
+
+ /* normalize accumulated vertex normals*/
+ BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, v, VERT_MARK)) {
+ continue;
+ }
+
+ if (BMO_TestFlag(bm, v, VERT_NONMAN)) {
+ /* use standard normals for vertices connected to non-manifold
+ edges */
+ BM_Vert_UpdateNormal(bm, v);
+ }
+ else if (normalize_v3(v->no) == 0.0f && BM_GetIndex(v) < 0) {
+ /* exceptional case, totally flat. use the normal
+ of any marked face around the vertex */
+ BM_ITER(f, &fiter, bm, BM_FACES_OF_VERT, v) {
+ if (BMO_TestFlag(bm, f, FACE_MARK)) {
+ break;
+ }
+ }
+ copy_v3_v3(v->no, f->no);
+ }
+ }
+}
+
+static void solidify_add_thickness(BMesh *bm, float dist)
+{
+ BMFace *f;
+ BMVert *v;
+ BMLoop *l;
+ BMIter iter, loopIter;
+ float *vert_angles = MEM_callocN(sizeof(float) * bm->totvert * 2, "solidify"); /* 2 in 1 */
+ float *vert_accum = vert_angles + bm->totvert;
+ float angle;
+ int i, index;
+ float maxdist = dist * sqrtf(3.0f);
+
+ /* array for passing verts to angle_poly_v3 */
+ float **verts = NULL;
+ BLI_array_staticdeclare(verts, 16);
+ /* array for receiving angles from angle_poly_v3 */
+ float *angles = NULL;
+ BLI_array_staticdeclare(angles, 16);
+
+ i = 0;
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(v, i++);
+ }
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if(!BMO_TestFlag(bm, f, FACE_MARK)) {
+ continue;
+ }
+
+ BM_ITER(l, &loopIter, bm, BM_LOOPS_OF_FACE, f) {
+ BLI_array_append(verts, l->v->co);
+ BLI_array_growone(angles);
+ }
+
+ angle_poly_v3(angles, (const float **)verts, f->len);
+
+ i = 0;
+ BM_ITER(l, &loopIter, bm, BM_LOOPS_OF_FACE, f) {
+ v = l->v;
+ index = BM_GetIndex(v);
+ angle = angles[i];
+ vert_accum[index] += angle;
+ vert_angles[index] += shell_angle_to_dist(angle_normalized_v3v3(v->no, f->no)) * angle;
+ i++;
+ }
+
+ BLI_array_empty(verts);
+ BLI_array_empty(angles);
+ }
+
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ index = BM_GetIndex(v);
+ if(vert_accum[index]) { /* zero if unselected */
+ float vdist = MIN2(maxdist, dist * vert_angles[index] / vert_accum[index]);
+ madd_v3_v3fl(v->co, v->no, vdist);
+ }
+ }
+
+ MEM_freeN(vert_angles);
+}
+
+void bmesh_solidify_face_region_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator extrudeop;
+ BMOperator reverseop;
+ float thickness;
+
+ thickness = BMO_Get_Float(op, "thickness");
+
+ /* Flip original faces (so the shell is extruded inward) */
+ BMO_Init_Op(&reverseop, "reversefaces");
+ BMO_CopySlot(op, &reverseop, "geom", "faces");
+ BMO_Exec_Op(bm, &reverseop);
+ BMO_Finish_Op(bm, &reverseop);
+
+ /* Extrude the region */
+ BMO_InitOpf(bm, &extrudeop, "extrudefaceregion alwayskeeporig=%i", 1);
+ BMO_CopySlot(op, &extrudeop, "geom", "edgefacein");
+ BMO_Exec_Op(bm, &extrudeop);
+
+ /* Push the verts of the extruded faces inward to create thickness */
+ BMO_Flag_Buffer(bm, &extrudeop, "geomout", FACE_MARK, BM_FACE);
+ calc_solidify_normals(bm);
+ solidify_add_thickness(bm, thickness);
+
+ BMO_CopySlot(&extrudeop, op, "geomout", "geomout");
+
+ BMO_Finish_Op(bm, &extrudeop);
+}
diff --git a/source/blender/bmesh/operators/join_triangles.c b/source/blender/bmesh/operators/join_triangles.c
new file mode 100644
index 00000000000..dafcf7c4ae4
--- /dev/null
+++ b/source/blender/bmesh/operators/join_triangles.c
@@ -0,0 +1,358 @@
+#if 1
+#include "MEM_guardedalloc.h"
+#include "BKE_customdata.h"
+#include "DNA_listBase.h"
+#include "DNA_customdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include <string.h>
+#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+
+#include "BLI_editVert.h"
+#include "mesh_intern.h"
+#include "ED_mesh.h"
+
+#include "BLI_math.h"
+#include "BLI_array.h"
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+
+#include "BLI_heap.h"
+
+#include "bmesh.h"
+
+#include "bmesh_operators_private.h" /* own include */
+
+/*
+ * JOIN_TRIANGLES.C
+ *
+ * utility bmesh operators, e.g. transform,
+ * translate, rotate, scale, etc.
+ *
+*/
+
+/*Bitflags for edges.*/
+#define T2QDELETE 1
+#define T2QCOMPLEX 2
+#define T2QJOIN 4
+
+/*assumes edges are validated before reaching this point*/
+static float measure_facepair(BMesh *UNUSED(bm), BMVert *v1, BMVert *v2,
+ BMVert *v3, BMVert *v4, float limit)
+{
+ /*gives a 'weight' to a pair of triangles that join an edge to decide how good a join they would make*/
+ /*Note: this is more complicated than it needs to be and should be cleaned up...*/
+ float n1[3], n2[3], measure = 0.0f, angle1, angle2, diff;
+ float edgeVec1[3], edgeVec2[3], edgeVec3[3], edgeVec4[3];
+ float minarea, maxarea, areaA, areaB;
+
+ /*First Test: Normal difference*/
+ normal_tri_v3(n1, v1->co, v2->co, v3->co);
+ normal_tri_v3(n2, v1->co, v3->co, v4->co);
+
+ if(n1[0] == n2[0] && n1[1] == n2[1] && n1[2] == n2[2]) angle1 = 0.0f;
+ else angle1 = angle_v3v3(n1, n2);
+
+ normal_tri_v3(n1, v2->co, v3->co, v4->co);
+ normal_tri_v3(n2, v4->co, v1->co, v2->co);
+
+ if(n1[0] == n2[0] && n1[1] == n2[1] && n1[2] == n2[2]) angle2 = 0.0f;
+ else angle2 = angle_v3v3(n1, n2);
+
+ measure += angle1 + angle2;
+ if(measure > limit) return measure;
+
+ /*Second test: Colinearity*/
+ sub_v3_v3v3(edgeVec1, v1->co, v2->co);
+ sub_v3_v3v3(edgeVec2, v2->co, v3->co);
+ sub_v3_v3v3(edgeVec3, v3->co, v4->co);
+ sub_v3_v3v3(edgeVec4, v4->co, v1->co);
+
+ diff = (
+ fabsf(angle_v3v3(edgeVec1, edgeVec2) - (float)M_PI_2) +
+ fabsf(angle_v3v3(edgeVec2, edgeVec3) - (float)M_PI_2) +
+ fabsf(angle_v3v3(edgeVec3, edgeVec4) - (float)M_PI_2) +
+ fabsf(angle_v3v3(edgeVec4, edgeVec1) - (float)M_PI_2));
+ if(!diff) return 0.0;
+
+ measure += diff;
+ if(measure > limit) return measure;
+
+ /*Third test: Concavity*/
+ areaA = area_tri_v3(v1->co, v2->co, v3->co) + area_tri_v3(v1->co, v3->co, v4->co);
+ areaB = area_tri_v3(v2->co, v3->co, v4->co) + area_tri_v3(v4->co, v1->co, v2->co);
+
+ if(areaA <= areaB) minarea = areaA;
+ else minarea = areaB;
+
+ if(areaA >= areaB) maxarea = areaA;
+ else maxarea = areaB;
+
+ if(!maxarea) measure += 1;
+ else measure += (1 - (minarea / maxarea));
+
+ return measure;
+}
+
+#define T2QUV_LIMIT 0.005f
+#define T2QCOL_LIMIT 3
+
+static int compareFaceAttribs(BMesh *bm, BMEdge *e, int douvs, int dovcols)
+{
+ MTexPoly *tp1, *tp2;
+ MLoopCol *lcol1, *lcol2, *lcol3, *lcol4;
+ MLoopUV *luv1, *luv2, *luv3, *luv4;
+ BMLoop *l1, *l2, *l3, *l4;
+ int mergeok_uvs=!douvs, mergeok_vcols=!dovcols;
+
+ l1 = e->l;
+ l3 = e->l->radial_next;
+
+ /*match up loops on each side of an edge corrusponding to each vert*/
+ if (l1->v == l3->v) {
+ l2 = l1->next;
+ l4 = l2->next;
+ } else {
+ l2 = l1->next;
+
+ l4 = l3;
+ l3 = l4->next;
+ }
+
+ lcol1 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPCOL);
+ lcol2 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPCOL);
+ lcol3 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPCOL);
+ lcol4 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPCOL);
+
+ luv1 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPUV);
+ luv2 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPUV);
+ luv3 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPUV);
+ luv4 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPUV);
+
+ tp1 = CustomData_bmesh_get(&bm->pdata, l1->f->head.data, CD_MTEXPOLY);
+ tp2 = CustomData_bmesh_get(&bm->pdata, l2->f->head.data, CD_MTEXPOLY);
+
+ if (!lcol1)
+ mergeok_vcols = 1;
+
+ if (!luv1)
+ mergeok_uvs = 1;
+
+ /*compare faceedges for each face attribute. Additional per face attributes can be added later*/
+
+ /*do VCOLs*/
+ if(lcol1 && dovcols){
+ char *cols[4] = {(char*)lcol1, (char*)lcol2, (char*)lcol3, (char*)lcol4};
+ int i;
+
+ for (i=0; i<3; i++) {
+ if (cols[0][i] + T2QCOL_LIMIT < cols[2][i] - T2QCOL_LIMIT)
+ break;
+ if (cols[1][i] + T2QCOL_LIMIT < cols[3][i] - T2QCOL_LIMIT)
+ break;
+ }
+
+ if (i == 3)
+ mergeok_vcols = 1;
+ }
+
+ /*do UVs*/
+ if (luv1 && douvs) {
+ if(tp1->tpage != tp2->tpage); /*do nothing*/
+ else {
+ int i;
+
+ for(i = 0; i < 2; i++) {
+ if(luv1->uv[0] + T2QUV_LIMIT > luv3->uv[0] && luv1->uv[0] - T2QUV_LIMIT < luv3->uv[0] &&
+ luv1->uv[1] + T2QUV_LIMIT > luv3->uv[1] && luv1->uv[1] - T2QUV_LIMIT < luv3->uv[1])
+ {
+ if(luv2->uv[0] + T2QUV_LIMIT > luv4->uv[0] && luv2->uv[0] - T2QUV_LIMIT < luv4->uv[0] &&
+ luv2->uv[1] + T2QUV_LIMIT > luv4->uv[1] && luv2->uv[1] - T2QUV_LIMIT < luv4->uv[1])
+ {
+ mergeok_uvs = 1;
+ }
+ }
+ }
+ }
+ }
+
+ if (douvs == mergeok_uvs && dovcols == mergeok_vcols)
+ return 1;
+ return 0;
+}
+
+typedef struct JoinEdge {
+ float weight;
+ BMEdge *e;
+} JoinEdge;
+
+#define EDGE_MARK 1
+#define EDGE_CHOSEN 2
+
+#define FACE_MARK 1
+#define FACE_INPUT 2
+
+static int fplcmp(const void *v1, const void *v2)
+{
+ const JoinEdge *e1= ((JoinEdge*)v1), *e2=((JoinEdge*)v2);
+
+ if( e1->weight > e2->weight) return 1;
+ else if( e1->weight < e2->weight) return -1;
+
+ return 0;
+}
+
+void bmesh_jointriangles_exec(BMesh *bm, BMOperator *op)
+{
+ BMIter iter, liter;
+ BMOIter siter;
+ BMFace *f1, *f2;
+ BMLoop *l;
+ BMEdge *e;
+ BLI_array_declare(jedges);
+ JoinEdge *jedges = NULL;
+ int dosharp = BMO_Get_Int(op, "compare_sharp"), douvs=BMO_Get_Int(op, "compare_uvs");
+ int dovcols = BMO_Get_Int(op, "compare_vcols"), domat=BMO_Get_Int(op, "compare_materials");
+ float limit = BMO_Get_Float(op, "limit")/180.0f*(float)M_PI;
+ int i, totedge;
+
+ /*flag all edges of all input faces*/
+ BMO_ITER(f1, &siter, bm, op, "faces", BM_FACE) {
+ BMO_SetFlag(bm, f1, FACE_INPUT);
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f1) {
+ BMO_SetFlag(bm, l->e, EDGE_MARK);
+ }
+ }
+
+ /*unflag edges that are invalid; e.g. aren't surrounded by triangles*/
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, e, EDGE_MARK))
+ continue;
+
+ if (BM_Edge_FaceCount(e) < 2) {
+ BMO_ClearFlag(bm, e, EDGE_MARK);
+ continue;
+ }
+
+ f1 = e->l->f;
+ f2 = e->l->radial_next->f;
+
+ if (f1->len != 3 || f2->len != 3) {
+ BMO_ClearFlag(bm, e, EDGE_MARK);
+ continue;
+ }
+
+ if (!BMO_TestFlag(bm, f1, FACE_INPUT) || !BMO_TestFlag(bm, f2, FACE_INPUT)) {
+ BMO_ClearFlag(bm, e, EDGE_MARK);
+ continue;
+ }
+ }
+
+ i = 0;
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ BMVert *v1, *v2, *v3, *v4;
+ BMFace *f1, *f2;
+ float measure;
+
+ if (!BMO_TestFlag(bm, e, EDGE_MARK))
+ continue;
+
+ f1 = e->l->f;
+ f2 = e->l->radial_next->f;
+
+ v1 = e->l->v;
+ v2 = e->l->prev->v;
+ v3 = e->l->next->v;
+ v4 = e->l->radial_next->prev->v;
+
+ if (dosharp && BM_TestHFlag(e, BM_SHARP))
+ continue;
+
+ if ((douvs || dovcols) && compareFaceAttribs(bm, e, douvs, dovcols))
+ continue;
+
+ if (domat && f1->mat_nr != f2->mat_nr)
+ continue;
+
+ measure = measure_facepair(bm, v1, v2, v3, v4, limit);
+ if(measure < limit) {
+ BLI_array_growone(jedges);
+
+ jedges[i].e = e;
+ jedges[i].weight = measure;
+
+ i++;
+ }
+ }
+
+ if (!jedges)
+ return;
+
+ qsort(jedges, BLI_array_count(jedges), sizeof(JoinEdge), fplcmp);
+
+ totedge = BLI_array_count(jedges);
+ for (i=0; i<totedge; i++) {
+ BMFace *f1, *f2;
+
+ e = jedges[i].e;
+ f1 = e->l->f;
+ f2 = e->l->radial_next->f;
+
+ if (BMO_TestFlag(bm, f1, FACE_MARK) || BMO_TestFlag(bm, f2, FACE_MARK))
+ continue;
+
+ BMO_SetFlag(bm, f1, FACE_MARK);
+ BMO_SetFlag(bm, f2, FACE_MARK);
+ BMO_SetFlag(bm, e, EDGE_CHOSEN);
+ }
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, e, EDGE_CHOSEN))
+ continue;
+
+ f1 = e->l->f;
+ f2 = e->l->radial_next->f;
+
+ BM_Join_TwoFaces(bm, f1, f2, e);
+ }
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, e, EDGE_MARK)) {
+ /*ok, this edge wasn't merged, check if it's
+ in a 2-tri-pair island, and if so merge*/
+
+ f1 = e->l->f;
+ f2 = e->l->radial_next->f;
+
+ if (f1->len != 3 || f2->len != 3)
+ continue;
+
+ for (i=0; i<2; i++) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, i ? f2 : f1) {
+ if (l->e != e && BMO_TestFlag(bm, l->e, EDGE_MARK))
+ break;
+ }
+
+ /*if l isn't NULL, we broke out of the loop*/
+ if (l)
+ break;
+ }
+
+ /*if i isn't 2, we broke out of that loop*/
+ if (i != 2)
+ continue;
+
+ BM_Join_TwoFaces(bm, f1, f2, e);
+ }
+ }
+
+ BLI_array_free(jedges);
+}
+
+#endif
diff --git a/source/blender/bmesh/operators/mesh_conv.c b/source/blender/bmesh/operators/mesh_conv.c
new file mode 100644
index 00000000000..625b38a2e69
--- /dev/null
+++ b/source/blender/bmesh/operators/mesh_conv.c
@@ -0,0 +1,873 @@
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_customdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_mesh.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_key.h"
+#include "BKE_main.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+#include "BLI_editVert.h"
+#include "BLI_scanfill.h"
+#include "BLI_array.h"
+#include "BLI_utildefines.h"
+
+#include "ED_mesh.h"
+
+#include "mesh_intern.h"
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+/*
+ * MESH CONV.C
+ *
+ * This file contains functions
+ * for converting a Mesh
+ * into a Bmesh, and back again.
+ *
+*/
+
+void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
+ Object *ob = BMO_Get_Pnt(op, "object");
+ Mesh *me = BMO_Get_Pnt(op, "mesh");
+ MVert *mvert;
+ BLI_array_declare(verts);
+ MEdge *medge;
+ MLoop *ml;
+ MPoly *mpoly;
+ KeyBlock *actkey, *block;
+ BMVert *v, **vt=NULL, **verts = NULL;
+ BMEdge *e, **fedges=NULL, **et = NULL;
+ BMFace *f;
+ BLI_array_declare(fedges);
+ float (*keyco)[3]= NULL;
+ int *keyi;
+ int set_key = BMO_Get_Int(op, "set_shapekey");
+ int totuv, i, j, allocsize[4] = {512, 512, 2048, 512};
+
+ if (!me || !me->totvert) return; /*sanity check*/
+
+ vt = MEM_mallocN(sizeof(void**)*me->totvert, "mesh to bmesh vtable");
+
+ CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+ /*make sure uv layer names are consistent*/
+ totuv = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ for (i=0; i<totuv; i++) {
+ int li = CustomData_get_layer_index_n(&bm->pdata, CD_MTEXPOLY, i);
+ CustomData_set_layer_name(&bm->ldata, CD_MLOOPUV, i, bm->pdata.layers[li].name);
+ }
+
+ if (!CustomData_has_layer(&bm->edata, CD_CREASE))
+ CustomData_add_layer(&bm->edata, CD_CREASE, CD_ASSIGN, NULL, 0);
+
+ if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT))
+ CustomData_add_layer(&bm->edata, CD_BWEIGHT, CD_ASSIGN, NULL, 0);
+
+ if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT))
+ CustomData_add_layer(&bm->vdata, CD_BWEIGHT, CD_ASSIGN, NULL, 0);
+
+
+ if (me->key && ob->shapenr > me->key->totkey) {
+ ob->shapenr = me->key->totkey-1;
+ }
+
+ actkey = ob_get_keyblock(ob);
+ if(actkey && actkey->totelem == me->totvert) {
+ CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0);
+
+ /*check if we need to generate unique ids for the shapekeys.
+ this also exists in the file reading code, but is here for
+ a sanity check*/
+ if (!me->key->uidgen) {
+ fprintf(stderr, "%s had to generate shape key uid's in a situation we shouldn't need to! (bmesh internal error)\n", __func__);
+ me->key->uidgen = 1;
+ for (block=me->key->block.first; block; block=block->next) {
+ block->uid = me->key->uidgen++;
+ }
+ }
+
+ keyco= actkey->data;
+ bm->shapenr= ob->shapenr;
+ for (i=0, block=me->key->block.first; block; block=block->next, i++) {
+ CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY,
+ CD_ASSIGN, NULL, 0, block->name);
+
+ j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i);
+ bm->vdata.layers[j].uid = block->uid;
+ }
+ } else if (actkey) {
+ printf("shapekey<->mesh mismatch!\n");
+ }
+
+ CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
+
+ for (i=0, mvert = me->mvert; i<me->totvert; i++, mvert++) {
+ v = BM_Make_Vert(bm, keyco&&set_key ? keyco[i] : mvert->co, NULL);
+ normal_short_to_float_v3(v->no, mvert->no);
+
+ vt[i] = v;
+ BM_SetIndex(v, i);
+
+ /*transfer flags*/
+ v->head.flag = MEFlags_To_BMFlags(mvert->flag, BM_VERT);
+
+ /*this is necassary for selection counts to work properly*/
+ if(v->head.flag & BM_SELECT) BM_Select_Vert(bm, v, 1);
+
+ BM_SetCDf(&bm->vdata, v, CD_BWEIGHT, (float)mvert->bweight / 255.0f);
+
+ /*Copy Custom Data*/
+ CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data);
+
+ /*set shapekey data*/
+ if (me->key) {
+ /*set shape key original index*/
+ keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX);
+ if (keyi) {
+ *keyi = i;
+ }
+
+ for (block=me->key->block.first, j=0; block; block=block->next, j++) {
+ float *co = CustomData_bmesh_get_n(&bm->vdata, v->head.data,
+ CD_SHAPEKEY, j);
+ if (co)
+ VECCOPY(co, ((float*)block->data)+3*i);
+ }
+ }
+ }
+
+ if (!me->totedge) {
+ MEM_freeN(vt);
+ return;
+ }
+
+ et = MEM_mallocN(sizeof(void**)*me->totedge, "mesh to bmesh etable");
+
+ medge = me->medge;
+ for (i=0; i<me->totedge; i++, medge++) {
+ e = BM_Make_Edge(bm, vt[medge->v1], vt[medge->v2], NULL, 0);
+ et[i] = e;
+
+ /*Copy Custom Data*/
+ CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data);
+
+ BM_SetCDf(&bm->edata, e, CD_CREASE, (float)medge->crease / 255.0f);
+ BM_SetCDf(&bm->edata, e, CD_BWEIGHT, (float)medge->bweight / 255.0f);
+
+ /*transfer flags*/
+ e->head.flag = MEFlags_To_BMFlags(medge->flag, BM_EDGE);
+
+ /*this is necassary for selection counts to work properly*/
+ if (e->head.flag & BM_SELECT) BM_Select(bm, e, 1);
+ }
+
+ if (!me->totpoly) {
+ MEM_freeN(vt);
+ MEM_freeN(et);
+ return;
+ }
+
+ mpoly = me->mpoly;
+ for (i=0; i<me->totpoly; i++, mpoly++) {
+ BMVert *v1, *v2;
+ BMIter iter;
+ BMLoop *l;
+
+ BLI_array_empty(fedges);
+ BLI_array_empty(verts);
+ for (j=0; j<mpoly->totloop; j++) {
+ ml = &me->mloop[mpoly->loopstart+j];
+ v = vt[ml->v];
+ e = et[ml->e];
+
+ BLI_array_growone(fedges);
+ BLI_array_growone(verts);
+
+ fedges[j] = e;
+ verts[j] = v;
+ }
+
+ v1 = vt[me->mloop[mpoly->loopstart].v];
+ /* v2 = vt[me->mloop[mpoly->loopstart+1].v]; */ /* UNUSED */ /* code below always overwrites */
+
+ if (v1 == fedges[0]->v1) v2 = fedges[0]->v2;
+ else {
+ v1 = fedges[0]->v2;
+ v2 = fedges[0]->v1;
+ }
+
+ f = BM_Make_Face(bm, verts, fedges, mpoly->totloop, 0);
+
+ if (!f) {
+ printf("Warning! Bad face in mesh"
+ " \"%s\" at index %d!\n", me->id.name+2, i);
+ continue;
+ }
+
+ /*transfer flags*/
+ f->head.flag = MEFlags_To_BMFlags(mpoly->flag, BM_FACE);
+
+ /*this is necassary for selection counts to work properly*/
+ if (f->head.flag & BM_SELECT) BM_Select(bm, f, 1);
+
+ f->mat_nr = mpoly->mat_nr;
+ if (i == me->act_face) bm->act_face = f;
+
+ /*Copy over loop customdata*/
+ j = 0;
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
+ CustomData_to_bmesh_block(&me->ldata, &bm->ldata, mpoly->loopstart+j, &l->head.data);
+ j++;
+ }
+
+ /*Copy Custom Data*/
+ CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data);
+ }
+
+ {
+ BMIter iter;
+ BMVert *vertex;
+ BMEdge *edge;
+ BMFace *face;
+ BMVert **vertex_array = MEM_callocN(sizeof(BMVert *) * bm->totvert,
+ "Selection Conversion Vertex Pointer Array");
+ BMEdge **edge_array = MEM_callocN(sizeof(BMEdge *) * bm->totedge,
+ "Selection Conversion Edge Pointer Array");
+ BMFace **face_array = MEM_callocN(sizeof(BMFace *) * bm->totface,
+ "Selection Conversion Face Pointer Array");
+
+ for(i = 0, vertex = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ vertex; i++, vertex = BMIter_Step(&iter)){
+ vertex_array[i] = vertex;
+ }
+
+ for(i = 0, edge = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
+ edge; i++, edge = BMIter_Step(&iter)){
+ edge_array[i] = edge;
+ }
+
+ for(i = 0, face = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
+ face; i++, face = BMIter_Step(&iter)){
+ face_array[i] = face;
+ }
+
+ if(me->mselect) {
+ for(i = 0; i < me->totselect; i++){
+ if(me->mselect[i].type == ME_VSEL){
+ BM_store_selection(bm, vertex_array[me->mselect[i].index]);
+ }else if(me->mselect[i].type == ME_ESEL){
+ BM_store_selection(bm, edge_array[me->mselect[i].index]);
+ }else if(me->mselect[i].type == ME_FSEL){
+ BM_store_selection(bm, face_array[me->mselect[i].index]);
+ }
+ }
+ }
+ else {
+ me->totselect= 0;
+ }
+
+ MEM_freeN(vertex_array);
+ MEM_freeN(edge_array);
+ MEM_freeN(face_array);
+ }
+
+ BLI_array_free(fedges);
+ BLI_array_free(verts);
+
+ MEM_freeN(vt);
+ MEM_freeN(et);
+}
+
+
+static void loops_to_corners(BMesh *bm, Mesh *me, int findex,
+ BMFace *f, BMLoop *ls[3], int numTex, int numCol)
+{
+ BMLoop *l;
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ int i, j;
+
+ for(i=0; i < numTex; i++){
+ texface = CustomData_get_n(&me->fdata, CD_MTFACE, findex, i);
+ texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
+
+ texface->tpage = texpoly->tpage;
+ texface->flag = texpoly->flag;
+ texface->transp = texpoly->transp;
+ texface->mode = texpoly->mode;
+ texface->tile = texpoly->tile;
+ texface->unwrap = texpoly->unwrap;
+
+ for (j=0; j<3; j++) {
+ l = ls[j];
+ mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
+ texface->uv[j][0] = mloopuv->uv[0];
+ texface->uv[j][1] = mloopuv->uv[1];
+ }
+ }
+
+ for(i=0; i < numCol; i++){
+ mcol = CustomData_get_n(&me->fdata, CD_MCOL, findex, i);
+
+ for (j=0; j<3; j++) {
+ l = ls[j];
+ mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
+ mcol[j].r = mloopcol->r;
+ mcol[j].g = mloopcol->g;
+ mcol[j].b = mloopcol->b;
+ mcol[j].a = mloopcol->a;
+ }
+ }
+}
+
+void object_load_bmesh_exec(BMesh *bm, BMOperator *op) {
+ Object *ob = BMO_Get_Pnt(op, "object");
+ /* Scene *scene = BMO_Get_Pnt(op, "scene"); */
+ Mesh *me = ob->data;
+
+ BMO_CallOpf(bm, "bmesh_to_mesh mesh=%p object=%p", me, ob);
+}
+
+
+static BMVert **bmesh_to_mesh_vertex_map(BMesh *bm, int ototvert)
+{
+ BMVert **vertMap = NULL;
+ BMVert *eve;
+ int i= 0;
+ BMIter iter;
+
+ vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
+ if(CustomData_has_layer(&bm->vdata, CD_SHAPE_KEYINDEX)) {
+ int *keyi;
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
+ if(keyi) {
+ if (*keyi != ORIGINDEX_NONE)
+ vertMap[*keyi] = eve;
+ }
+ else {
+ if(i < ototvert) {
+ vertMap[i] = eve;
+ }
+ }
+ i++;
+ }
+ }
+ else {
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if(i < ototvert) {
+ vertMap[i] = eve;
+ }
+ else {
+ break;
+ }
+ i++;
+ }
+ }
+
+ return vertMap;
+}
+
+void bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) {
+ Mesh *me = BMO_Get_Pnt(op, "mesh");
+ /* Object *ob = BMO_Get_Pnt(op, "object"); */
+ MLoop *mloop;
+ KeyBlock *block;
+ MPoly *mpoly;
+ MVert *mvert, *oldverts;
+ MEdge *medge;
+ MFace *mface;
+ BMVert *v, *eve;
+ BMEdge *e;
+ BMLoop *l;
+ BMFace *f;
+ BMIter iter, liter; float *facenors = NULL;
+ int i, j, *keyi, ototvert, totloop, totface, numTex, numCol;
+ int dotess = !BMO_Get_Int(op, "notesselation");
+
+ numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+
+ ototvert = me->totvert;
+
+ /* new Vertex block */
+ if(bm->totvert==0) mvert= NULL;
+ else mvert= MEM_callocN(bm->totvert*sizeof(MVert), "loadeditbMesh vert");
+
+ /* new Edge block */
+ if(bm->totedge==0) medge= NULL;
+ else medge= MEM_callocN(bm->totedge*sizeof(MEdge), "loadeditbMesh edge");
+
+ /*build ngon data*/
+ /* new Ngon Face block */
+ if(bm->totface==0) mpoly = NULL;
+ else mpoly= MEM_callocN(bm->totface*sizeof(MPoly), "loadeditbMesh poly");
+
+ /*find number of loops to allocate*/
+ totloop = 0;
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ totloop += f->len;
+ }
+
+ if (totloop==0) mloop = NULL;
+ else mloop = MEM_callocN(totloop*sizeof(MLoop), "loadeditbMesh loop");
+
+ /* lets save the old verts just in case we are actually working on
+ * a key ... we now do processing of the keys at the end */
+ oldverts= me->mvert;
+
+ /* don't free this yet */
+ CustomData_set_layer(&me->vdata, CD_MVERT, NULL);
+
+ /* free custom data */
+ CustomData_free(&me->vdata, me->totvert);
+ CustomData_free(&me->edata, me->totedge);
+ CustomData_free(&me->fdata, me->totface);
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
+
+ /* add new custom data */
+ me->totvert= bm->totvert;
+ me->totedge= bm->totedge;
+ me->totloop= totloop;
+ me->totpoly= bm->totface;
+ /* will be overwritten with a valid value if 'dotess' is set, otherwise we
+ * end up with 'me->totface' and me->mface == NULL which can crash [#28625]
+ */
+ me->totface= 0;
+
+ CustomData_copy(&bm->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert);
+ CustomData_copy(&bm->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge);
+ CustomData_copy(&bm->ldata, &me->ldata, CD_MASK_MESH, CD_CALLOC, me->totloop);
+ CustomData_copy(&bm->pdata, &me->pdata, CD_MASK_MESH, CD_CALLOC, me->totpoly);
+
+ CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
+ CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
+ CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
+ CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
+
+ i = 0;
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ float *bweight = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BWEIGHT);
+
+ mvert->bweight = bweight ? (char)((*bweight)*255) : 0;
+
+ VECCOPY(mvert->co, v->co);
+
+ mvert->no[0] = (short) (v->no[0]*32767.0f);
+ mvert->no[1] = (short) (v->no[1]*32767.0f);
+ mvert->no[2] = (short) (v->no[2]*32767.0f);
+
+ mvert->flag = BMFlags_To_MEFlags(v);
+
+ BM_SetIndex(v, i);
+
+ /*copy over customdata*/
+ CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i);
+
+ i++;
+ mvert++;
+
+ CHECK_ELEMENT(bm, v);
+ }
+
+ i = 0;
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ float *crease = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE);
+ float *bweight = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT);
+
+ medge->v1 = BM_GetIndex(e->v1);
+ medge->v2 = BM_GetIndex(e->v2);
+ medge->crease = crease ? (char)((*crease)*255) : 0;
+ medge->bweight = bweight ? (char)((*bweight)*255) : 0;
+
+ medge->flag = BMFlags_To_MEFlags(e);
+
+ BM_SetIndex(e, i);
+
+ /*copy over customdata*/
+ CustomData_from_bmesh_block(&bm->edata, &me->edata, e->head.data, i);
+
+ i++;
+ medge++;
+ CHECK_ELEMENT(bm, e);
+ }
+
+ /*new scanfill tesselation code*/
+ if (dotess) {
+ /*first counter number of faces we'll need*/
+ totface = 0;
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ EditVert *eve, *lasteve = NULL, *firsteve = NULL;
+
+ BLI_begin_edgefill();
+ i = 0;
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ eve = BLI_addfillvert(l->v->co);
+ eve->tmp.p = l;
+
+ BM_SetIndex(l, i);
+
+ if (lasteve) {
+ BLI_addfilledge(lasteve, eve);
+ }
+
+ lasteve = eve;
+ if (!firsteve) firsteve = eve;
+
+ i++;
+ }
+
+ BLI_addfilledge(lasteve, firsteve);
+ totface += BLI_edgefill(0);
+
+ BLI_end_edgefill();
+ }
+
+ me->totface = totface;
+
+ /* new tess face block */
+ if(totface==0) mface= NULL;
+ else {
+ mface= MEM_callocN(totface*sizeof(MFace), "loadeditbMesh face");
+ facenors = MEM_callocN(totface*sizeof(float)*3, "facenors");
+ }
+
+ CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface);
+ CustomData_add_layer(&me->fdata, CD_NORMAL, CD_ASSIGN, facenors, me->totface);
+ CustomData_from_bmeshpoly(&me->fdata, &bm->pdata, &bm->ldata, totface);
+
+ mesh_update_customdata_pointers(me);
+
+ i = 0;
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ EditVert *eve, *lasteve = NULL, *firsteve = NULL;
+ EditFace *efa;
+ BMLoop *ls[3];
+
+ BLI_begin_edgefill();
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ eve = BLI_addfillvert(l->v->co);
+ eve->tmp.p = l;
+
+ if (lasteve) {
+ BLI_addfilledge(lasteve, eve);
+ }
+
+ lasteve = eve;
+ if (!firsteve) firsteve = eve;
+ }
+
+ BLI_addfilledge(lasteve, firsteve);
+ BLI_edgefill(0);
+
+ for (efa=fillfacebase.first; efa; efa=efa->next) {
+ ls[0] = efa->v1->tmp.p;
+ ls[1] = efa->v2->tmp.p;
+ ls[2] = efa->v3->tmp.p;
+
+ /*ensure correct winding. I believe this is
+ analogous to bubble sort on three elements.*/
+ if (BM_GetIndex(ls[0]) > BM_GetIndex(ls[1])) {
+ SWAP(BMLoop*, ls[0], ls[1]);
+ }
+ if (BM_GetIndex(ls[1]) > BM_GetIndex(ls[2])) {
+ SWAP(BMLoop*, ls[1], ls[2]);
+ }
+ if (BM_GetIndex(ls[0]) > BM_GetIndex(ls[1])) {
+ SWAP(BMLoop*, ls[0], ls[1]);
+ }
+
+ mface->mat_nr = f->mat_nr;
+ mface->flag = BMFlags_To_MEFlags(f);
+
+ mface->v1 = BM_GetIndex(ls[0]->v);
+ mface->v2 = BM_GetIndex(ls[1]->v);
+ mface->v3 = BM_GetIndex(ls[2]->v);
+
+ test_index_face(mface, &me->fdata, i, 1);
+
+ loops_to_corners(bm, me, i, f, ls, numTex, numCol);
+ VECCOPY(facenors, ls[0]->f->no);
+
+ mface++;
+ facenors += 3;
+ i++;
+ }
+ BLI_end_edgefill();
+ }
+ }
+
+ i = 0;
+ j = 0;
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ mpoly->loopstart = j;
+ mpoly->totloop = f->len;
+ mpoly->mat_nr = f->mat_nr;
+ mpoly->flag = BMFlags_To_MEFlags(f);
+
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+ for ( ; l; l=BMIter_Step(&liter), j++, mloop++) {
+ mloop->e = BM_GetIndex(l->e);
+ mloop->v = BM_GetIndex(l->v);
+
+ /*copy over customdata*/
+ CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l->head.data, j);
+ CHECK_ELEMENT(bm, l);
+ CHECK_ELEMENT(bm, l->e);
+ CHECK_ELEMENT(bm, l->v);
+ }
+
+ if (f == bm->act_face) me->act_face = i;
+
+ /*copy over customdata*/
+ CustomData_from_bmesh_block(&bm->pdata, &me->pdata, f->head.data, i);
+
+ i++;
+ mpoly++;
+ CHECK_ELEMENT(bm, f);
+ }
+
+ /* patch hook indices and vertex parents */
+ {
+ Object *ob;
+ ModifierData *md;
+ BMVert **vertMap = NULL;
+ int i,j;
+
+ for (ob=G.main->object.first; ob; ob=ob->id.next) {
+ if (ob->parent==bm->ob && ELEM(ob->partype, PARVERT1,PARVERT3)) {
+
+ if (vertMap == NULL) {
+ vertMap= bmesh_to_mesh_vertex_map(bm, ototvert);
+ }
+
+ if(ob->par1 < ototvert) {
+ eve = vertMap[ob->par1];
+ if(eve) ob->par1= BM_GetIndex(eve);
+ }
+ if(ob->par2 < ototvert) {
+ eve = vertMap[ob->par2];
+ if(eve) ob->par2= BM_GetIndex(eve);
+ }
+ if(ob->par3 < ototvert) {
+ eve = vertMap[ob->par3];
+ if(eve) ob->par3= BM_GetIndex(eve);
+ }
+
+ }
+ if (ob->data==me) {
+ for (md=ob->modifiers.first; md; md=md->next) {
+ if (md->type==eModifierType_Hook) {
+ HookModifierData *hmd = (HookModifierData*) md;
+
+ if (vertMap == NULL) {
+ vertMap= bmesh_to_mesh_vertex_map(bm, ototvert);
+ }
+
+ for (i=j=0; i<hmd->totindex; i++) {
+ if(hmd->indexar[i] < ototvert) {
+ eve = vertMap[hmd->indexar[i]];
+
+ if (eve) {
+ hmd->indexar[j++] = BM_GetIndex(eve);
+ }
+ }
+ else j++;
+ }
+
+ hmd->totindex = j;
+ }
+ }
+ }
+ }
+
+ if (vertMap) MEM_freeN(vertMap);
+ }
+
+ mesh_update_customdata_pointers(me);
+
+ {
+ BMEditSelection *selected;
+ me->totselect = BLI_countlist(&(bm->selected));
+
+ if(me->mselect) MEM_freeN(me->mselect);
+
+ me->mselect = MEM_callocN(sizeof(MSelect) * me->totselect, "Mesh selection history");
+
+
+ for(i = 0, selected = bm->selected.first; selected; i++, selected = selected->next){
+ if(selected->type == BM_VERT){
+ me->mselect[i].type = ME_VSEL;
+
+ }else if(selected->type == BM_EDGE){
+ me->mselect[i].type = ME_ESEL;
+
+ }else if(selected->type == BM_FACE){
+ me->mselect[i].type = ME_FSEL;
+ }
+
+ me->mselect[i].index = BM_GetIndex(selected->data);
+ }
+ }
+
+ if (me->key) {
+ KeyBlock *actkey= BLI_findlink(&me->key->block, bm->shapenr-1);
+
+ /*go through and find any shapekey customdata layers
+ that might not have corrusponding KeyBlocks, and add them if
+ necassary.*/
+ j = 0;
+ for (i=0; i<bm->vdata.totlayer; i++) {
+ if (bm->vdata.layers[i].type != CD_SHAPEKEY)
+ continue;
+
+ for (block=me->key->block.first; block; block=block->next) {
+ if (block->uid == bm->vdata.layers[i].uid)
+ break;
+ }
+
+ if (!block) {
+ block = MEM_callocN(sizeof(KeyBlock), "KeyBlock mesh_conv.c");
+ block->type = KEY_LINEAR;
+ block->slidermin = 0.0f;
+ block->slidermax = 1.0f;
+
+ BLI_addtail(&me->key->block, block);
+ me->key->totkey++;
+ }
+
+ j++;
+ }
+
+ for (block=me->key->block.first; block; block=block->next) {
+ j = 0;
+
+ for (i=0; i<bm->vdata.totlayer; i++) {
+ if (bm->vdata.layers[i].type != CD_SHAPEKEY)
+ continue;
+
+ if (block->uid == bm->vdata.layers[i].uid) {
+ float *fp, *co;
+
+ if (block->data)
+ MEM_freeN(block->data);
+ block->data = fp = MEM_mallocN(sizeof(float)*3*bm->totvert, "shape key data");
+ block->totelem = bm->totvert;
+
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ co = block==actkey ? eve->co : CustomData_bmesh_get_n(&bm->vdata, eve->head.data, CD_SHAPEKEY, j);
+
+ VECCOPY(fp, co);
+ fp += 3;
+ }
+ break;
+ }
+
+ j++;
+ }
+
+ /*if we didn't find a shapekey, tag the block to be reconstructed
+ via the old method below*/
+ if (j == CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY)) {
+ block->flag |= KEYBLOCK_MISSING;
+ }
+ }
+ }
+
+ /* old method of reconstructing keys via vertice's original key indices,
+ currently used if the new method above fails (which is theoretically
+ possible in certain cases of undo).*/
+ if(me->key) {
+ float *fp, *newkey, *oldkey;
+ KeyBlock *currkey;
+ KeyBlock *actkey= BLI_findlink(&me->key->block, bm->shapenr-1);
+
+ /* Lets reorder the key data so that things line up roughly
+ * with the way things were before editmode */
+ currkey = me->key->block.first;
+ while(currkey) {
+ if (!(currkey->flag & KEYBLOCK_MISSING)) {
+ currkey = currkey->next;
+ continue;
+ }
+
+ printf("warning: had to hackishly reconstruct shape key \"%s\","
+ " it may not be correct anymore.\n", currkey->name);
+
+ currkey->flag &= ~KEYBLOCK_MISSING;
+
+ fp= newkey= MEM_callocN(me->key->elemsize*bm->totvert, "currkey->data");
+ oldkey = currkey->data;
+
+ eve= BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+
+ i = 0;
+ mvert = me->mvert;
+ while(eve) {
+ keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
+ if (!keyi) {
+ break;
+ }
+ if (*keyi >= 0 && *keyi < currkey->totelem) { // valid old vertex
+ if(currkey == actkey) {
+ if(actkey == me->key->refkey) {
+ VECCOPY(fp, mvert->co);
+ }
+ else {
+ VECCOPY(fp, mvert->co);
+ if(oldverts) {
+ VECCOPY(mvert->co, oldverts[*keyi].co);
+ }
+ }
+ }
+ else {
+ if(oldkey) {
+ VECCOPY(fp, oldkey + 3 * *keyi);
+ }
+ }
+ }
+ else {
+ VECCOPY(fp, mvert->co);
+ }
+ fp+= 3;
+ ++i;
+ ++mvert;
+ eve= BMIter_Step(&iter);
+ }
+ currkey->totelem= bm->totvert;
+ if(currkey->data) MEM_freeN(currkey->data);
+ currkey->data = newkey;
+
+ currkey= currkey->next;
+ }
+ }
+
+ if(oldverts) MEM_freeN(oldverts);
+}
diff --git a/source/blender/bmesh/operators/mirror.c b/source/blender/bmesh/operators/mirror.c
new file mode 100644
index 00000000000..a97a891be02
--- /dev/null
+++ b/source/blender/bmesh/operators/mirror.c
@@ -0,0 +1,127 @@
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_customdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include <string.h>
+
+#include "BKE_customdata.h"
+#include "BKE_mesh.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_utildefines.h"
+
+#include "BLI_editVert.h"
+#include "mesh_intern.h"
+#include "ED_mesh.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+#include "BLI_array.h"
+#include "BLI_utildefines.h"
+
+#include "bmesh.h"
+#include "bmesh_operators_private.h" /* own include */
+
+/*
+ * MIRROR.C
+ *
+ * mirror bmop.
+ *
+*/
+
+#define ELE_NEW 1
+
+void bmesh_mirror_exec(BMesh *bm, BMOperator *op) {
+ BMOperator dupeop, weldop;
+ BMOIter siter;
+ BMIter iter;
+ BMVert *v, *v2, **vmap = NULL;
+ BLI_array_declare(vmap);
+ BMEdge /* *e, */ **emap = NULL;
+ BLI_array_declare(emap);
+ float mtx[4][4];
+ float imtx[4][4];
+ float scale[3] = {1.0f, 1.0f, 1.0f};
+ float dist = BMO_Get_Float(op, "mergedist");
+ int i, ototvert, ototedge, axis = BMO_Get_Int(op, "axis");
+ int mirroru = BMO_Get_Int(op, "mirror_u");
+ int mirrorv = BMO_Get_Int(op, "mirror_v");
+
+ ototvert = bm->totvert;
+ ototedge = bm->totedge;
+
+ BMO_Get_Mat4(op, "mat", mtx);
+ invert_m4_m4(imtx, mtx);
+
+ BMO_InitOpf(bm, &dupeop, "dupe geom=%s", op, "geom");
+ BMO_Exec_Op(bm, &dupeop);
+
+ BMO_Flag_Buffer(bm, &dupeop, "newout", ELE_NEW, BM_ALL);
+
+ /*create old -> new mapping*/
+ i = 0;
+ v2 = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ BMO_ITER(v, &siter, bm, &dupeop, "newout", BM_VERT) {
+ BLI_array_growone(vmap);
+ vmap[i] = v;
+
+ BM_SetIndex(v2, i);
+ v2 = BMIter_Step(&iter);
+
+ i += 1;
+ }
+
+ /*feed old data to transform bmop*/
+ scale[axis] = -1.0f;
+ BMO_CallOpf(bm, "transform verts=%fv mat=%m4", ELE_NEW, mtx);
+ BMO_CallOpf(bm, "scale verts=%fv vec=%v", ELE_NEW, scale);
+ BMO_CallOpf(bm, "transform verts=%fv mat=%m4", ELE_NEW, imtx);
+
+ BMO_Init_Op(&weldop, "weldverts");
+
+ v = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; i<ototvert; i++) {
+ if (ABS(v->co[axis]) <= dist) {
+ BMO_Insert_MapPointer(bm, &weldop, "targetmap", vmap[i], v);
+ }
+ v = BMIter_Step(&iter);
+ }
+
+ if (mirroru || mirrorv) {
+ BMFace *f;
+ BMLoop *l;
+ MLoopUV *luv;
+ int totlayer;
+ BMIter liter;
+
+ BMO_ITER(f, &siter, bm, &dupeop, "newout", BM_FACE) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ totlayer = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
+ for (i=0; i<totlayer; i++) {
+ luv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
+ if (mirroru)
+ luv->uv[0]= 1.0f - luv->uv[0];
+ if (mirrorv)
+ luv->uv[1]= 1.0f - luv->uv[1];
+ }
+ }
+ }
+ }
+
+ BMO_Exec_Op(bm, &weldop);
+
+ BMO_Finish_Op(bm, &weldop);
+ BMO_Finish_Op(bm, &dupeop);
+
+ BMO_Flag_To_Slot(bm, op, "newout", ELE_NEW, BM_ALL);
+
+ BLI_array_free(vmap);
+ BLI_array_free(emap);
+}
diff --git a/source/blender/bmesh/operators/primitiveops.c b/source/blender/bmesh/operators/primitiveops.c
new file mode 100644
index 00000000000..7fda346306f
--- /dev/null
+++ b/source/blender/bmesh/operators/primitiveops.c
@@ -0,0 +1,687 @@
+#include "MEM_guardedalloc.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BLI_math.h"
+#include "BLI_ghash.h"
+#include "BLI_blenlib.h"
+#include "BLI_array.h"
+
+#include "ED_mesh.h"
+
+#include "bmesh.h"
+#include "mesh_intern.h"
+#include "bmesh_private.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* ************************ primitives ******************* */
+
+static float icovert[12][3] = {
+ {0.0f,0.0f,-200.0f},
+ {144.72f, -105.144f,-89.443f},
+ {-55.277f, -170.128,-89.443f},
+ {-178.885f,0.0f,-89.443f},
+ {-55.277f,170.128f,-89.443f},
+ {144.72f,105.144f,-89.443f},
+ {55.277f,-170.128f,89.443f},
+ {-144.72f,-105.144f,89.443f},
+ {-144.72f,105.144f,89.443f},
+ {55.277f,170.128f,89.443f},
+ {178.885f,0.0f,89.443f},
+ {0.0f,0.0f,200.0f}
+};
+
+static short icoface[20][3] = {
+ {0,1,2},
+ {1,0,5},
+ {0,2,3},
+ {0,3,4},
+ {0,4,5},
+ {1,5,10},
+ {2,1,6},
+ {3,2,7},
+ {4,3,8},
+ {5,4,9},
+ {1,10,6},
+ {2,6,7},
+ {3,7,8},
+ {4,8,9},
+ {5,9,10},
+ {6,10,11},
+ {7,6,11},
+ {8,7,11},
+ {9,8,11},
+ {10,9,11}
+};
+
+// HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker
+// this hack is only used so that scons+mingw + split-sources hack works
+ // ------------------------------- start copied code
+/* these are not the monkeys you are looking for */
+static int monkeyo= 4;
+static int monkeynv= 271;
+static int monkeynf= 250;
+static signed char monkeyv[271][3]= {
+{-71,21,98},{-63,12,88},{-57,7,74},{-82,-3,79},{-82,4,92},
+{-82,17,100},{-92,21,102},{-101,12,95},{-107,7,83},
+{-117,31,84},{-109,31,95},{-96,31,102},{-92,42,102},
+{-101,50,95},{-107,56,83},{-82,66,79},{-82,58,92},
+{-82,46,100},{-71,42,98},{-63,50,88},{-57,56,74},
+{-47,31,72},{-55,31,86},{-67,31,97},{-66,31,99},
+{-70,43,100},{-82,48,103},{-93,43,105},{-98,31,105},
+{-93,20,105},{-82,31,106},{-82,15,103},{-70,20,100},
+{-127,55,95},{-127,45,105},{-127,-87,94},{-127,-41,100},
+{-127,-24,102},{-127,-99,92},{-127,52,77},{-127,73,73},
+{-127,115,-70},{-127,72,-109},{-127,9,-106},{-127,-49,-45},
+{-101,-24,72},{-87,-56,73},{-82,-89,73},{-80,-114,68},
+{-85,-121,67},{-104,-124,71},{-127,-126,74},{-71,-18,68},
+{-46,-5,69},{-21,19,57},{-17,55,76},{-36,62,80},
+{-64,77,88},{-86,97,94},{-107,92,97},{-119,63,96},
+{-106,53,99},{-111,39,98},{-101,12,95},{-79,2,90},
+{-64,8,86},{-47,24,83},{-45,38,83},{-50,48,85},
+{-72,56,92},{-95,60,97},{-127,-98,94},{-113,-92,94},
+{-112,-107,91},{-119,-113,89},{-127,-114,88},{-127,-25,96},
+{-127,-18,95},{-114,-19,95},{-111,-29,96},{-116,-37,95},
+{-76,-6,86},{-48,7,80},{-34,26,77},{-32,48,84},
+{-39,53,93},{-71,70,102},{-87,82,107},{-101,79,109},
+{-114,55,108},{-111,-13,104},{-100,-57,91},{-95,-90,88},
+{-93,-105,85},{-97,-117,81},{-106,-119,81},{-127,-121,82},
+{-127,6,93},{-127,27,98},{-85,61,95},{-106,18,96},
+{-110,27,97},{-112,-88,94},{-117,-57,96},{-127,-57,96},
+{-127,-42,95},{-115,-35,100},{-110,-29,102},{-113,-17,100},
+{-122,-16,100},{-127,-26,106},{-121,-19,104},{-115,-20,104},
+{-113,-29,106},{-117,-32,103},{-127,-37,103},{-94,-40,71},
+{-106,-31,91},{-104,-40,91},{-97,-32,71},{-127,-112,88},
+{-121,-111,88},{-115,-105,91},{-115,-95,93},{-127,-100,84},
+{-115,-96,85},{-115,-104,82},{-121,-109,81},{-127,-110,81},
+{-105,28,100},{-103,20,99},{-84,55,97},{-92,54,99},
+{-73,51,99},{-55,45,89},{-52,37,88},{-53,25,87},
+{-66,13,92},{-79,8,95},{-98,14,100},{-104,38,100},
+{-100,48,100},{-97,46,97},{-102,38,97},{-96,16,97},
+{-79,11,93},{-68,15,90},{-57,27,86},{-56,36,86},
+{-59,43,87},{-74,50,96},{-91,51,98},{-84,52,96},
+{-101,22,96},{-102,29,96},{-113,59,78},{-102,85,79},
+{-84,88,76},{-65,71,71},{-40,58,63},{-25,52,59},
+{-28,21,48},{-50,0,53},{-71,-12,60},{-127,115,37},
+{-127,126,-10},{-127,-25,-86},{-127,-59,24},{-127,-125,59},
+{-127,-103,44},{-127,-73,41},{-127,-62,36},{-18,30,7},
+{-17,41,-6},{-28,34,-56},{-68,56,-90},{-33,-6,9},
+{-51,-16,-21},{-45,-1,-55},{-84,7,-85},{-97,-45,52},
+{-104,-53,33},{-90,-91,49},{-95,-64,50},{-85,-117,51},
+{-109,-97,47},{-111,-69,46},{-106,-121,56},{-99,-36,55},
+{-100,-29,60},{-101,-22,64},{-100,-50,21},{-89,-40,-34},
+{-83,-19,-69},{-69,111,-49},{-69,119,-9},{-69,109,30},
+{-68,67,55},{-34,52,43},{-46,58,36},{-45,90,7},
+{-25,72,16},{-25,79,-15},{-45,96,-25},{-45,87,-57},
+{-25,69,-46},{-48,42,-75},{-65,3,-70},{-22,42,-26},
+{-75,-22,19},{-72,-25,-27},{-13,52,-30},{-28,-18,-16},
+{6,-13,-42},{37,7,-55},{46,41,-54},{31,65,-54},
+{4,61,-40},{3,53,-37},{25,56,-50},{35,37,-52},
+{28,10,-52},{5,-5,-39},{-21,-9,-17},{-9,46,-28},
+{-6,39,-37},{-14,-3,-27},{6,0,-47},{25,12,-57},
+{31,32,-57},{23,46,-56},{4,44,-46},{-19,37,-27},
+{-20,22,-35},{-30,12,-35},{-22,11,-35},{-19,2,-35},
+{-23,-2,-35},{-34,0,-9},{-35,-3,-22},{-35,5,-24},
+{-25,26,-27},{-13,31,-34},{-13,30,-41},{-23,-2,-41},
+{-18,2,-41},{-21,10,-41},{-29,12,-41},{-19,22,-41},
+{6,42,-53},{25,44,-62},{34,31,-63},{28,11,-62},
+{7,0,-54},{-14,-2,-34},{-5,37,-44},{-13,14,-42},
+{-7,8,-43},{1,16,-47},{-4,22,-45},{3,30,-48},
+{8,24,-49},{15,27,-50},{12,35,-50},{4,56,-62},
+{33,60,-70},{48,38,-64},{41,7,-68},{6,-11,-63},
+{-26,-16,-42},{-17,49,-49},
+};
+
+static signed char monkeyf[250][4]= {
+{27,4,5,26}, {25,4,5,24}, {3,6,5,4}, {1,6,5,2}, {5,6,7,4},
+{3,6,7,2}, {5,8,7,6}, {3,8,7,4}, {7,8,9,6},
+{5,8,9,4}, {7,10,9,8}, {5,10,9,6}, {9,10,11,8},
+{7,10,11,6}, {9,12,11,10}, {7,12,11,8}, {11,6,13,12},
+{5,4,13,12}, {3,-2,13,12}, {-3,-4,13,12}, {-5,-10,13,12},
+{-11,-12,14,12}, {-13,-18,14,13}, {-19,4,5,13}, {10,12,4,4},
+{10,11,9,9}, {8,7,9,9}, {7,5,6,6}, {6,3,4,4},
+{5,1,2,2}, {4,-1,0,0}, {3,-3,-2,-2}, {22,67,68,23},
+{20,65,66,21}, {18,63,64,19}, {16,61,62,17}, {14,59,60,15},
+{12,19,48,57}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47},
+{18,19,48,47}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47},
+{18,19,48,47}, {18,-9,-8,47}, {18,27,45,46}, {26,55,43,44},
+{24,41,42,54}, {22,39,40,23}, {20,37,38,21}, {18,35,36,19},
+{16,33,34,17}, {14,31,32,15}, {12,39,30,13}, {11,48,45,38},
+{8,36,-19,9}, {8,-20,44,47}, {42,45,46,43}, {18,19,40,39},
+{16,17,38,37}, {14,15,36,35}, {32,44,43,33}, {12,33,32,42},
+{19,44,43,42}, {40,41,42,-27}, {8,9,39,-28}, {15,43,42,16},
+{13,43,42,14}, {11,43,42,12}, {9,-30,42,10}, {37,12,38,-32},
+{-33,37,45,46}, {-33,40,41,39}, {38,40,41,37}, {36,40,41,35},
+{34,40,41,33}, {36,39,38,37}, {35,40,39,38}, {1,2,14,21},
+{1,2,40,13}, {1,2,40,39}, {1,24,12,39}, {-34,36,38,11},
+{35,38,36,37}, {-37,8,35,37}, {-11,-12,-45,40}, {-11,-12,39,38},
+{-11,-12,37,36}, {-11,-12,35,34}, {33,34,40,41}, {33,34,38,39},
+{33,34,36,37}, {33,-52,34,35}, {33,37,36,34}, {33,35,34,34},
+{8,7,37,36}, {-32,7,35,46}, {-34,-33,45,46}, {4,-33,43,34},
+{-34,-33,41,42}, {-34,-33,39,40}, {-34,-33,37,38}, {-34,-33,35,36},
+{-34,-33,33,34}, {-34,-33,31,32}, {-34,-4,28,30}, {-5,-34,28,27},
+{-35,-44,36,27}, {26,35,36,45}, {24,25,44,45}, {25,23,44,42},
+{25,24,41,40}, {25,24,39,38}, {25,24,37,36}, {25,24,35,34},
+{25,24,33,32}, {25,24,31,30}, {15,24,29,38}, {25,24,27,26},
+{23,12,37,26}, {11,12,35,36}, {-86,-59,36,-80}, {-60,-61,36,35},
+{-62,-63,36,35}, {-64,-65,36,35}, {-66,-67,36,35}, {-68,-69,36,35},
+{-70,-71,36,35}, {-72,-73,36,35}, {-74,-75,36,35}, {42,43,53,58},
+{40,41,57,56}, {38,39,55,57}, {-81,-80,37,56}, {-83,-82,55,52},
+{-85,-84,51,49}, {-87,-86,48,49}, {47,50,51,48}, {46,48,51,49},
+{43,46,49,44}, {-92,-91,45,42}, {-23,49,50,-20}, {-94,40,48,-24},
+{-96,-22,48,49}, {-97,48,21,-90}, {-100,36,50,23}, {22,49,48,-100},
+{-101,47,46,22}, {21,45,35,25}, {33,34,44,41}, {13,14,28,24},
+{-107,26,30,-106}, {14,46,45,15}, {14,44,43,-110}, {-111,42,23,-110},
+{6,7,45,46}, {45,44,47,46}, {45,46,47,48}, {47,46,49,48},
+{17,49,47,48}, {17,36,46,48}, {35,36,44,45}, {35,36,40,43},
+{35,36,38,39}, {-4,-3,37,35}, {-123,34,33,1}, {-9,-8,-7,-6},
+{-10,-7,32,-125}, {-127,-11,-126,-126}, {-7,-6,5,31}, {4,5,33,30},
+{4,39,33,32}, {4,35,32,38}, {20,21,39,38}, {4,37,38,5},
+{-11,-10,36,3}, {-11,15,14,35}, {13,16,34,34}, {-13,14,13,13},
+{-3,1,30,29}, {-3,28,29,1}, {-2,31,28,-1}, {12,13,27,30},
+{-2,26,12,12}, {35,29,42,36}, {34,35,36,33}, {32,35,36,31},
+{30,35,36,29}, {28,35,36,27}, {26,35,36,25}, {34,39,38,35},
+{32,39,38,33}, {30,39,38,31}, {28,39,38,29}, {26,39,38,27},
+{25,31,32,38}, {-18,-17,45,44}, {-18,17,28,44}, {-24,-20,42,-23},
+{11,35,27,14}, {25,28,39,41}, {37,41,40,38}, {34,40,36,35},
+{32,40,39,33}, {30,39,31,40}, {21,29,39,22}, {-31,37,28,4},
+{-32,33,35,36}, {32,33,34,34}, {18,35,36,48}, {34,25,40,35},
+{24,25,38,39}, {24,25,36,37}, {24,25,34,35}, {24,25,32,33},
+{24,13,41,31}, {17,11,41,35}, {15,16,34,35}, {13,14,34,35},
+{11,12,34,35}, {9,10,34,35}, {7,8,34,35}, {26,25,37,36},
+{35,36,37,38}, {37,36,39,38}, {37,38,39,40}, {25,31,36,39},
+{18,34,35,30}, {17,22,30,33}, {19,29,21,20}, {16,26,29,17},
+{24,29,28,25}, {22,31,28,23}, {20,31,30,21}, {18,31,30,19},
+{16,30,17,17}, {-21,-22,35,34}, {-21,-22,33,32}, {-21,-22,31,30},
+{-21,-22,29,28}, {-21,-22,27,26}, {-28,-22,25,31}, {24,28,29,30},
+{23,24,26,27}, {23,24,25,25}, {-69,-35,-32,27}, {-70,26,25,-66},
+{-68,-67,24,-33},
+};
+
+#define VERT_MARK 1
+
+#define EDGE_ORIG 1
+#define EDGE_MARK 2
+
+#define FACE_MARK 1
+#define FACE_NEW 2
+
+void bmesh_create_grid_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator bmop, prevop;
+ BMVert *eve, *preveve;
+ BMEdge *e;
+ float vec[3], mat[4][4], phi, phid, dia=BMO_Get_Float(op, "size");
+ int a, tot=BMO_Get_Int(op, "xsegments"), seg=BMO_Get_Int(op, "ysegments");
+
+ if (tot < 2) tot = 2;
+ if (seg < 2) seg = 2;
+
+ BMO_Get_Mat4(op, "mat", mat);
+
+ /* one segment first: the X axis */
+ phi= 1.0f;
+ phid= 2.0f/((float)tot-1);
+ for(a=0;a<tot;a++) {
+ vec[0]= dia*phi;
+ vec[1]= - dia;
+ vec[2]= 0.0f;
+ mul_m4_v3(mat,vec);
+
+ eve= BM_Make_Vert(bm, vec, NULL);
+ BM_Select(bm, eve, 1);
+
+ if (a) {
+ e = BM_Make_Edge(bm, preveve, eve, NULL, 1);
+ BMO_SetFlag(bm, e, EDGE_ORIG);
+ }
+
+ preveve = eve;
+ phi-=phid;
+ }
+
+ /* extrude and translate */
+ vec[0]= vec[2]= 0.0;
+ vec[1]= dia*phid;
+ mul_mat3_m4_v3(mat, vec);
+
+ for(a=0;a<seg-1;a++) {
+ if (a) {
+ BMO_InitOpf(bm, &bmop, "extrude_edge_only edges=%s", &prevop, "geomout");
+ BMO_Exec_Op(bm, &bmop);
+ BMO_Finish_Op(bm, &prevop);
+
+ BMO_Flag_Buffer(bm, &bmop, "geomout", VERT_MARK, BM_VERT);
+ } else {
+ BMO_InitOpf(bm, &bmop, "extrude_edge_only edges=%fe", EDGE_ORIG);
+ BMO_Exec_Op(bm, &bmop);
+ BMO_Flag_Buffer(bm, &bmop, "geomout", VERT_MARK, BM_VERT);
+ }
+
+ BMO_CallOpf(bm, "translate vec=%v verts=%s", vec, &bmop, "geomout");
+ prevop = bmop;
+ }
+
+ if (a)
+ BMO_Finish_Op(bm, &bmop);
+
+ BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT);
+}
+
+void bmesh_create_uvsphere_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator bmop, prevop;
+ BMVert *eve, *preveve, *v1;
+ BMEdge *e;
+ BMIter iter;
+ float vec[3], mat[4][4], cmat[3][3], phi, q[4];
+ float phid, dia=BMO_Get_Float(op, "diameter");
+ int a, seg=BMO_Get_Int(op, "segments"), tot=BMO_Get_Int(op, "revolutions");
+
+ BMO_Get_Mat4(op, "mat", mat);
+
+ phid= 2.0f*(float)M_PI/tot;
+ phi= .25f*(float)M_PI;
+
+ /* one segment first */
+ phi= 0;
+ phid/=2;
+ for(a=0; a<=tot; a++) {
+ /* Going in this direction, then edge extruding, makes normals face outward */
+ vec[0]= -dia*sinf(phi);
+ vec[1]= 0.0;
+ vec[2]= dia*cosf(phi);
+ eve= BM_Make_Vert(bm, vec, NULL);
+ BMO_SetFlag(bm, eve, VERT_MARK);
+
+ if(a==0) v1= eve;
+ else {
+ e = BM_Make_Edge(bm, preveve, eve, NULL, 0);
+ BMO_SetFlag(bm, e, EDGE_ORIG);
+ }
+
+ phi+= phid;
+ preveve = eve;
+ }
+
+ /* extrude and rotate; negative phi to make normals face outward */
+ phi= -M_PI/seg;
+ q[0]= cos(phi);
+ q[3]= sin(phi);
+ q[1]=q[2]= 0;
+ quat_to_mat3(cmat, q);
+
+ for(a=0; a<seg; a++) {
+ if (a) {
+ BMO_InitOpf(bm, &bmop, "extrude_edge_only edges=%s", &prevop, "geomout");
+ BMO_Exec_Op(bm, &bmop);
+ BMO_Finish_Op(bm, &prevop);
+ } else {
+ BMO_InitOpf(bm, &bmop, "extrude_edge_only edges=%fe", EDGE_ORIG);
+ BMO_Exec_Op(bm, &bmop);
+ }
+
+ BMO_Flag_Buffer(bm, &bmop, "geomout", VERT_MARK, BM_VERT);
+ BMO_CallOpf(bm, "rotate cent=%v mat=%m3 verts=%s", vec, cmat, &bmop, "geomout");
+
+ prevop = bmop;
+ }
+
+ if (a)
+ BMO_Finish_Op(bm, &bmop);
+
+ BMO_CallOpf(bm, "removedoubles verts=%fv dist=%f", VERT_MARK, 0.001f);
+
+ /* and now do imat */
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if(BMO_TestFlag(bm, eve, VERT_MARK)) {
+ mul_m4_v3(mat, eve->co);
+ }
+ }
+
+ BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT);
+}
+
+void bmesh_create_icosphere_exec(BMesh *bm, BMOperator *op)
+{
+ BMVert *eva[12];
+ BMIter liter;
+ BMLoop *l;
+ float vec[3], mat[4][4] /* , phi, phid */;
+ float dia = BMO_Get_Float(op, "diameter");
+ int a, subdiv = BMO_Get_Int(op, "subdivisions");
+
+ BMO_Get_Mat4(op, "mat", mat);
+
+ /* phid= 2.0f*(float)M_PI/subdiv; */ /* UNUSED */
+ /* phi= .25f*(float)M_PI; */ /* UNUSED */
+
+ dia/=200;
+ for(a=0;a<12;a++) {
+ vec[0]= dia*icovert[a][0];
+ vec[1]= dia*icovert[a][1];
+ vec[2]= dia*icovert[a][2];
+ eva[a]= BM_Make_Vert(bm, vec, NULL);
+
+ mul_m4_v3(mat, eva[a]->co);
+ BM_Select(bm, eva[a], 1);
+ }
+
+ for(a=0;a<20;a++) {
+ BMFace *eftemp;
+ BMVert *v1, *v2, *v3;
+
+ v1= eva[ icoface[a][0] ];
+ v2= eva[ icoface[a][1] ];
+ v3= eva[ icoface[a][2] ];
+
+ eftemp = BM_Make_QuadTri(bm, v1, v2, v3, NULL, NULL, 0);
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, eftemp) {
+ BMO_SetFlag(bm, l->e, EDGE_MARK);
+ }
+
+ BMO_SetFlag(bm, eftemp, FACE_MARK);
+ }
+
+ dia*=200;
+
+ for(a=1; a<subdiv; a++) {
+ BMOperator bmop;
+
+ BMO_InitOpf(bm, &bmop,
+ "esubd edges=%fe smooth=%f numcuts=%i gridfill=%i beauty=%i",
+ EDGE_MARK, dia, 1, 1, B_SPHERE);
+ BMO_Exec_Op(bm, &bmop);
+ BMO_Flag_Buffer(bm, &bmop, "geomout", VERT_MARK, BM_VERT);
+ BMO_Flag_Buffer(bm, &bmop, "geomout", EDGE_MARK, BM_EDGE);
+ BMO_Finish_Op(bm, &bmop);
+ }
+
+ BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT);
+}
+
+void bmesh_create_monkey_exec(BMesh *bm, BMOperator *op)
+{
+ BMVert *eve;
+ BMVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv");
+ float mat[4][4];
+ int i;
+
+ BMO_Get_Mat4(op, "mat", mat);
+
+ for (i=0; i<monkeynv; i++) {
+ float v[3];
+
+ v[0]= (monkeyv[i][0]+127)/128.0, v[1]= monkeyv[i][1]/128.0, v[2]= monkeyv[i][2]/128.0;
+
+ tv[i]= BM_Make_Vert(bm, v, NULL);
+ BMO_SetFlag(bm, tv[i], VERT_MARK);
+
+ tv[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]: (eve=BM_Make_Vert(bm, v, NULL), mul_m4_v3(mat, eve->co), eve);
+ BMO_SetFlag(bm, tv[monkeynv+i], VERT_MARK);
+
+ mul_m4_v3(mat, tv[i]->co);
+ }
+
+ for (i=0; i<monkeynf; i++) {
+ BM_Make_QuadTri(bm, tv[monkeyf[i][0]+i-monkeyo], tv[monkeyf[i][1]+i-monkeyo], tv[monkeyf[i][2]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeyf[i][3]+i-monkeyo]:NULL, NULL, 0);
+ BM_Make_QuadTri(bm, tv[monkeynv+monkeyf[i][2]+i-monkeyo], tv[monkeynv+monkeyf[i][1]+i-monkeyo], tv[monkeynv+monkeyf[i][0]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeynv+monkeyf[i][3]+i-monkeyo]:NULL, NULL, 0);
+ }
+
+ MEM_freeN(tv);
+
+ BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT);
+}
+
+
+void bmesh_create_circle_exec(BMesh *bm, BMOperator *op)
+{
+ BMVert *v1, *lastv1=NULL, *cent1, *firstv1=NULL;
+ float vec[3], mat[4][4], phi, phid;
+ float dia = BMO_Get_Float(op, "diameter");
+ int cap_ends = BMO_Get_Int(op, "cap_ends"), segs=BMO_Get_Int(op, "segments");
+ int cap_tris=BMO_Get_Int(op, "cap_tris");
+ int a;
+
+ if (!segs)
+ return;
+
+ BMO_Get_Mat4(op, "mat", mat);
+
+ phid= 2.0f*(float)M_PI/segs;
+ phi= .25f*(float)M_PI;
+
+ if (cap_ends) {
+ vec[0] = vec[1] = 0.0f;
+ vec[2] = 0.0;
+ mul_m4_v3(mat, vec);
+
+ cent1 = BM_Make_Vert(bm, vec, NULL);
+ }
+
+ for (a=0; a<segs; a++, phi+=phid) {
+ /* Going this way ends up with normal(s) upward */
+ vec[0]= -dia*sinf(phi);
+ vec[1]= dia*cosf(phi);
+ vec[2]= 0.0f;
+ mul_m4_v3(mat, vec);
+ v1 = BM_Make_Vert(bm, vec, NULL);
+
+ BMO_SetFlag(bm, v1, VERT_MARK);
+
+ if (lastv1)
+ BM_Make_Edge(bm, v1, lastv1, NULL, 0);
+
+ if (a && cap_ends) {
+ BMFace *f;
+
+ f = BM_Make_QuadTri(bm, cent1, lastv1, v1, NULL, NULL, 0);
+ BMO_SetFlag(bm, f, FACE_NEW);
+ }
+
+ if (!firstv1)
+ firstv1 = v1;
+
+ lastv1 = v1;
+ }
+
+ if (!a)
+ return;
+
+ BM_Make_Edge(bm, lastv1, firstv1, NULL, 0);
+
+ if (cap_ends) {
+ BMFace *f;
+
+ f = BM_Make_QuadTri(bm, cent1, v1, firstv1, NULL, NULL, 0);
+ BMO_SetFlag(bm, f, FACE_NEW);
+ }
+
+ if (!cap_tris) {
+ BMO_CallOpf(bm, "dissolvefaces faces=%ff", FACE_NEW);
+ }
+
+ BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT);
+}
+
+void bmesh_create_cone_exec(BMesh *bm, BMOperator *op)
+{
+ BMVert *v1, *v2, *lastv1=NULL, *lastv2=NULL, *cent1, *cent2, *firstv1, *firstv2;
+ float vec[3], mat[4][4], phi, phid;
+ float dia1 = BMO_Get_Float(op, "diameter1");
+ float dia2 = BMO_Get_Float(op, "diameter2");
+ float depth = BMO_Get_Float(op, "depth");
+ int cap_ends = BMO_Get_Int(op, "cap_ends"), segs=BMO_Get_Int(op, "segments");
+ int cap_tris=BMO_Get_Int(op, "cap_tris");
+ int a;
+
+ if (!segs)
+ return;
+
+ BMO_Get_Mat4(op, "mat", mat);
+
+ phid= 2.0f*(float)M_PI/segs;
+ phi= .25f*(float)M_PI;
+
+ depth *= 0.5f;
+ if (cap_ends) {
+ vec[0] = vec[1] = 0.0f;
+ vec[2] = -depth;
+ mul_m4_v3(mat, vec);
+
+ cent1 = BM_Make_Vert(bm, vec, NULL);
+
+ vec[0] = vec[1] = 0.0f;
+ vec[2] = depth;
+ mul_m4_v3(mat, vec);
+
+ cent2 = BM_Make_Vert(bm, vec, NULL);
+
+ BMO_SetFlag(bm, cent1, VERT_MARK);
+ BMO_SetFlag(bm, cent2, VERT_MARK);
+ }
+
+ for (a=0; a<segs; a++, phi+=phid) {
+ vec[0]= dia1*sinf(phi);
+ vec[1]= dia1*cosf(phi);
+ vec[2]= -depth;
+ mul_m4_v3(mat, vec);
+ v1 = BM_Make_Vert(bm, vec, NULL);
+
+ vec[0]= dia2*sinf(phi);
+ vec[1]= dia2*cosf(phi);
+ vec[2]= depth;
+ mul_m4_v3(mat, vec);
+ v2 = BM_Make_Vert(bm, vec, NULL);
+
+ BMO_SetFlag(bm, v1, VERT_MARK);
+ BMO_SetFlag(bm, v2, VERT_MARK);
+
+ if (a) {
+ if (cap_ends) {
+ BMFace *f;
+
+ f = BM_Make_QuadTri(bm, cent1, lastv1, v1, NULL, NULL, 0);
+ BMO_SetFlag(bm, f, FACE_NEW);
+ f = BM_Make_QuadTri(bm, cent2, v2, lastv2, NULL, NULL, 0);
+ BMO_SetFlag(bm, f, FACE_NEW);
+ }
+ BM_Make_QuadTri(bm, lastv1, lastv2, v2, v1, NULL, 0);
+ } else {
+ firstv1 = v1;
+ firstv2 = v2;
+ }
+
+ lastv1 = v1;
+ lastv2 = v2;
+ }
+
+ if (!a)
+ return;
+
+ if (cap_ends) {
+ BMFace *f;
+
+ f = BM_Make_QuadTri(bm, cent1, v1, firstv1, NULL, NULL, 0);
+ BMO_SetFlag(bm, f, FACE_NEW);
+ f = BM_Make_QuadTri(bm, cent2, firstv2, v2, NULL, NULL, 0);
+ BMO_SetFlag(bm, f, FACE_NEW);
+ }
+
+ if (!cap_tris) {
+ BMO_CallOpf(bm, "dissolvefaces faces=%ff", FACE_NEW);
+ }
+
+ BM_Make_QuadTri(bm, v1, v2, firstv2, firstv1, NULL, 0);
+
+ BMO_CallOpf(bm, "removedoubles verts=%fv dist=%f", VERT_MARK, 0.000001);
+ BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT);
+}
+
+void bmesh_create_cube_exec(BMesh *bm, BMOperator *op)
+{
+ BMVert *v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8;
+ float vec[3], mat[4][4], off = BMO_Get_Float(op, "size") / 2.0f;
+
+ BMO_Get_Mat4(op, "mat", mat);
+
+ if (!off) off = 0.5f;
+
+ vec[0] = -off;
+ vec[1] = -off;
+ vec[2] = -off;
+ mul_m4_v3(mat, vec);
+ v1 = BM_Make_Vert(bm, vec, NULL);
+ BMO_SetFlag(bm, v1, VERT_MARK);
+
+ vec[0] = -off;
+ vec[1] = off;
+ vec[2] = -off;
+ mul_m4_v3(mat, vec);
+ v2 = BM_Make_Vert(bm, vec, NULL);
+ BMO_SetFlag(bm, v2, VERT_MARK);
+
+ vec[0] = off;
+ vec[1] = off;
+ vec[2] = -off;
+ mul_m4_v3(mat, vec);
+ v3 = BM_Make_Vert(bm, vec, NULL);
+ BMO_SetFlag(bm, v3, VERT_MARK);
+
+ vec[0] = off;
+ vec[1] = -off;
+ vec[2] = -off;
+ mul_m4_v3(mat, vec);
+ v4 = BM_Make_Vert(bm, vec, NULL);
+ BMO_SetFlag(bm, v4, VERT_MARK);
+
+ vec[0] = -off;
+ vec[1] = -off;
+ vec[2] = off;
+ mul_m4_v3(mat, vec);
+ v5 = BM_Make_Vert(bm, vec, NULL);
+ BMO_SetFlag(bm, v5, VERT_MARK);
+
+ vec[0] = -off;
+ vec[1] = off;
+ vec[2] = off;
+ mul_m4_v3(mat, vec);
+ v6 = BM_Make_Vert(bm, vec, NULL);
+ BMO_SetFlag(bm, v6, VERT_MARK);
+
+ vec[0] = off;
+ vec[1] = off;
+ vec[2] = off;
+ mul_m4_v3(mat, vec);
+ v7 = BM_Make_Vert(bm, vec, NULL);
+ BMO_SetFlag(bm, v7, VERT_MARK);
+
+ vec[0] = off;
+ vec[1] = -off;
+ vec[2] = off;
+ mul_m4_v3(mat, vec);
+ v8 = BM_Make_Vert(bm, vec, NULL);
+ BMO_SetFlag(bm, v8, VERT_MARK);
+
+ /*the four sides*/
+ BM_Make_QuadTri(bm, v5, v6, v2, v1, NULL, 0);
+ BM_Make_QuadTri(bm, v6, v7, v3, v2, NULL, 0);
+ BM_Make_QuadTri(bm, v7, v8, v4, v3, NULL, 0);
+ BM_Make_QuadTri(bm, v8, v5, v1, v4, NULL, 0);
+
+ /*top/bottom*/
+ BM_Make_QuadTri(bm, v1, v2, v3, v4, NULL, 0);
+ BM_Make_QuadTri(bm, v8, v7, v6, v5, NULL, 0);
+
+ BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT);
+}
diff --git a/source/blender/bmesh/operators/removedoubles.c b/source/blender/bmesh/operators/removedoubles.c
new file mode 100644
index 00000000000..b4c99c9ce9a
--- /dev/null
+++ b/source/blender/bmesh/operators/removedoubles.c
@@ -0,0 +1,561 @@
+#include "MEM_guardedalloc.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BLI_math.h"
+#include "BLI_ghash.h"
+#include "BLI_blenlib.h"
+#include "BLI_array.h"
+#include "BLI_utildefines.h"
+
+#include "bmesh.h"
+#include "mesh_intern.h"
+#include "bmesh_private.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BL(ptr) ((BMLoop*)(ptr))
+
+static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op)
+{
+ BMIter liter;
+ BMLoop *l;
+ BMVert *v2, *doub;
+ int split=0;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ v2 = BMO_Get_MapPointer(bm, op, "targetmap", l->v);
+ /*ok: if v2 is NULL (e.g. not in the map) then it's
+ a target vert, otherwise it's a double*/
+ if (v2 && BM_Vert_In_Face(f, v2) && v2 != BL(l->prev)->v
+ && v2 != BL(l->next)->v)
+ {
+ doub = l->v;
+ split = 1;
+ break;
+ }
+ }
+
+ if (split && doub != v2) {
+ BMLoop *nl;
+ BMFace *f2 = BM_Split_Face(bm, f, doub, v2, &nl, NULL);
+
+ remdoubles_splitface(f, bm, op);
+ remdoubles_splitface(f2, bm, op);
+ }
+}
+
+#define ELE_DEL 1
+#define EDGE_COL 2
+#define FACE_MARK 2
+
+#if 0
+int remdoubles_face_overlaps(BMesh *bm, BMVert **varr,
+ int len, BMFace *exclude,
+ BMFace **overlapface)
+{
+ BMIter vertfaces;
+ BMFace *f;
+ int i, amount;
+
+ if (overlapface) *overlapface = NULL;
+
+ for(i=0; i < len; i++){
+ f = BMIter_New(&vertfaces, bm, BM_FACES_OF_VERT, varr[i] );
+ while(f){
+ amount = BM_Verts_In_Face(bm, f, varr, len);
+ if(amount >= len){
+ if (overlapface) *overlapface = f;
+ return 1;
+ }
+ f = BMIter_Step(&vertfaces);
+ }
+ }
+ return 0;
+}
+#endif
+
+void bmesh_weldverts_exec(BMesh *bm, BMOperator *op)
+{
+ BMIter iter, liter;
+ BMVert *v, *v2;
+ BMEdge *e, *e2, **edges = NULL;
+ BLI_array_declare(edges);
+ BMLoop *l, *l2, **loops = NULL;
+ BLI_array_declare(loops);
+ BMFace *f, *f2;
+ int a, b;
+
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if ((v2= BMO_Get_MapPointer(bm, op, "targetmap", v))) {
+ BMO_SetFlag(bm, v, ELE_DEL);
+
+ /* merge the vertex flags, else we get randomly selected/unselected verts */
+ BM_MergeHFlag(v, v2);
+ }
+ }
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ remdoubles_splitface(f, bm, op);
+ }
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (BMO_TestFlag(bm, e->v1, ELE_DEL) || BMO_TestFlag(bm, e->v2, ELE_DEL)) {
+ v = BMO_Get_MapPointer(bm, op, "targetmap", e->v1);
+ v2 = BMO_Get_MapPointer(bm, op, "targetmap", e->v2);
+
+ if (!v) v = e->v1;
+ if (!v2) v2 = e->v2;
+
+ if (v == v2)
+ BMO_SetFlag(bm, e, EDGE_COL);
+ else if (!BM_Edge_Exist(v, v2))
+ BM_Make_Edge(bm, v, v2, e, 1);
+
+ BMO_SetFlag(bm, e, ELE_DEL);
+ }
+ }
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ BM_SetIndex(f, 0);
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ if (BMO_TestFlag(bm, l->v, ELE_DEL))
+ BMO_SetFlag(bm, f, FACE_MARK|ELE_DEL);
+ if (BMO_TestFlag(bm, l->e, EDGE_COL))
+ BM_SetIndex(f, BM_GetIndex(f)+1);
+ }
+ }
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, f, FACE_MARK))
+ continue;
+
+ if (f->len - BM_GetIndex(f) < 3) {
+ BMO_SetFlag(bm, f, ELE_DEL);
+ continue;
+ }
+
+ BLI_array_empty(edges);
+ BLI_array_empty(loops);
+ a = 0;
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ v = l->v;
+ v2 = BL(l->next)->v;
+ if (BMO_TestFlag(bm, v, ELE_DEL))
+ v = BMO_Get_MapPointer(bm, op, "targetmap", v);
+ if (BMO_TestFlag(bm, v2, ELE_DEL))
+ v2 = BMO_Get_MapPointer(bm, op, "targetmap", v2);
+
+ e2 = v != v2 ? BM_Edge_Exist(v, v2) : NULL;
+ if (e2) {
+ for (b=0; b<a; b++) {
+ if (edges[b] == e2)
+ break;
+ }
+ if (b != a)
+ continue;
+
+ BLI_array_growone(edges);
+ BLI_array_growone(loops);
+
+ edges[a] = e2;
+ loops[a] = l;
+
+ a++;
+ }
+ }
+
+ if (BLI_array_count(loops) < 3)
+ continue;
+ v = loops[0]->v;
+ v2 = loops[1]->v;
+
+ if (BMO_TestFlag(bm, v, ELE_DEL))
+ v = BMO_Get_MapPointer(bm, op, "targetmap", v);
+ if (BMO_TestFlag(bm, v2, ELE_DEL))
+ v2 = BMO_Get_MapPointer(bm, op, "targetmap", v2);
+
+ f2 = BM_Make_Ngon(bm, v, v2, edges, a, 1);
+ if (f2 != f) {
+ BM_Copy_Attributes(bm, bm, f, f2);
+
+ a = 0;
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f2) {
+ l2 = loops[a];
+ BM_Copy_Attributes(bm, bm, l2, l);
+
+ a++;
+ }
+ }
+ }
+
+ BMO_CallOpf(bm, "del geom=%fvef context=%i", ELE_DEL, DEL_ONLYTAGGED);
+
+ BLI_array_free(edges);
+ BLI_array_free(loops);
+}
+
+static int vergaverco(const void *e1, const void *e2)
+{
+ const BMVert *v1 = *(void**)e1, *v2 = *(void**)e2;
+ float x1 = v1->co[0] + v1->co[1] + v1->co[2];
+ float x2 = v2->co[0] + v2->co[1] + v2->co[2];
+
+ if (x1 > x2) return 1;
+ else if (x1 < x2) return -1;
+ else return 0;
+}
+
+#define VERT_TESTED 1
+#define VERT_DOUBLE 2
+#define VERT_TARGET 4
+#define VERT_KEEP 8
+#define VERT_MARK 16
+#define VERT_IN 32
+
+#define EDGE_MARK 1
+
+void bmesh_pointmerge_facedata_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMIter iter;
+ BMVert *v, *snapv;
+ BMLoop *l, *firstl = NULL;
+ float fac;
+ int i, tot;
+
+ snapv = BMO_IterNew(&siter, bm, op, "snapv", BM_VERT);
+ tot = BM_Vert_FaceCount(snapv);
+
+ if (!tot)
+ return;
+
+ fac = 1.0f / tot;
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, snapv) {
+ if (!firstl) {
+ firstl = l;
+ }
+
+ for (i=0; i<bm->ldata.totlayer; i++) {
+ if (CustomData_layer_has_math(&bm->ldata, i)) {
+ int type = bm->ldata.layers[i].type;
+ void *e1, *e2;
+
+ e1 = CustomData_bmesh_get_layer_n(&bm->ldata, firstl->head.data, i);
+ e2 = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
+
+ CustomData_data_multiply(type, e2, fac);
+
+ if (l != firstl)
+ CustomData_data_add(type, e1, e2);
+ }
+ }
+ }
+
+ BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
+ if (l == firstl)
+ continue;
+
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, firstl->head.data, &l->head.data);
+ }
+ }
+}
+
+void bmesh_vert_average_facedata_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMIter iter;
+ BMVert *v;
+ BMLoop *l /* , *firstl = NULL */;
+ CDBlockBytes min, max;
+ void *block;
+ int i, type;
+
+ for (i=0; i<bm->ldata.totlayer; i++) {
+ if (!CustomData_layer_has_math(&bm->ldata, i))
+ continue;
+
+ type = bm->ldata.layers[i].type;
+ CustomData_data_initminmax(type, &min, &max);
+
+ BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
+ block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
+ CustomData_data_dominmax(type, block, &min, &max);
+ }
+ }
+
+ CustomData_data_multiply(type, &min, 0.5f);
+ CustomData_data_multiply(type, &max, 0.5f);
+ CustomData_data_add(type, &min, &max);
+
+ BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+ BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
+ block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
+ CustomData_data_copy_value(type, &min, block);
+ }
+ }
+ }
+}
+
+void bmesh_pointmerge_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator weldop;
+ BMOIter siter;
+ BMVert *v, *snapv = NULL;
+ float vec[3];
+
+ BMO_Get_Vec(op, "mergeco", vec);
+
+ //BMO_CallOpf(bm, "collapse_uvs edges=%s", op, "edges");
+ BMO_Init_Op(&weldop, "weldverts");
+
+ BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+ if (!snapv) {
+ snapv = v;
+ copy_v3_v3(snapv->co, vec);
+ } else {
+ BMO_Insert_MapPointer(bm, &weldop, "targetmap", v, snapv);
+ }
+ }
+
+ BMO_Exec_Op(bm, &weldop);
+ BMO_Finish_Op(bm, &weldop);
+}
+
+void bmesh_collapse_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator weldop;
+ BMWalker walker;
+ BMIter iter;
+ BMEdge *e, **edges = NULL;
+ BLI_array_declare(edges);
+ float min[3], max[3];
+ int i, tot;
+
+ BMO_CallOpf(bm, "collapse_uvs edges=%s", op, "edges");
+ BMO_Init_Op(&weldop, "weldverts");
+
+ BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE);
+ BMW_Init(&walker, bm, BMW_SHELL, EDGE_MARK, 0);
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, e, EDGE_MARK))
+ continue;
+
+ e = BMW_Begin(&walker, e->v1);
+ BLI_array_empty(edges);
+
+ INIT_MINMAX(min, max);
+ for (tot=0; e; tot++, e=BMW_Step(&walker)) {
+ BLI_array_growone(edges);
+ edges[tot] = e;
+
+ DO_MINMAX(e->v1->co, min, max);
+ DO_MINMAX(e->v2->co, min, max);
+ }
+
+ add_v3_v3v3(min, min, max);
+ mul_v3_fl(min, 0.5f);
+
+ /*snap edges to a point. for initial testing purposes anyway.*/
+ for (i=0; i<tot; i++) {
+ VECCOPY(edges[i]->v1->co, min);
+ VECCOPY(edges[i]->v2->co, min);
+
+ if (edges[i]->v1 != edges[0]->v1)
+ BMO_Insert_MapPointer(bm, &weldop, "targetmap", edges[i]->v1, edges[0]->v1);
+ if (edges[i]->v2 != edges[0]->v1)
+ BMO_Insert_MapPointer(bm, &weldop, "targetmap", edges[i]->v2, edges[0]->v1);
+ }
+ }
+
+ BMO_Exec_Op(bm, &weldop);
+ BMO_Finish_Op(bm, &weldop);
+
+ BMW_End(&walker);
+ BLI_array_free(edges);
+}
+
+/*uv collapse function*/
+static void bmesh_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer)
+{
+ BMIter iter, liter;
+ BMFace *f;
+ BMLoop *l, *l2;
+ BMWalker walker;
+ void **blocks = NULL;
+ BLI_array_declare(blocks);
+ CDBlockBytes min, max;
+ int i, tot, type = bm->ldata.layers[layer].type;
+
+ BMO_Clear_Flag_All(bm, op, BM_ALL, 65535);
+
+ BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE);
+ BMW_Init(&walker, bm, BMW_LOOPDATA_ISLAND, EDGE_MARK, layer);
+
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ if (BMO_TestFlag(bm, l->e, EDGE_MARK)) {
+ /*walk*/
+ BLI_array_empty(blocks);
+ tot = 0;
+ l2 = BMW_Begin(&walker, l);
+
+ CustomData_data_initminmax(type, &min, &max);
+ for (tot=0; l2; tot++, l2=BMW_Step(&walker)) {
+ BLI_array_growone(blocks);
+ blocks[tot] = CustomData_bmesh_get_layer_n(&bm->ldata, l2->head.data, layer);
+ CustomData_data_dominmax(type, blocks[tot], &min, &max);
+ }
+
+ if (tot) {
+ CustomData_data_multiply(type, &min, 0.5f);
+ CustomData_data_multiply(type, &max, 0.5f);
+ CustomData_data_add(type, &min, &max);
+
+ /*snap CD (uv, vcol) points to their centroid*/
+ for (i=0; i<tot; i++) {
+ CustomData_data_copy_value(type, &min, blocks[i]);
+ }
+ }
+ }
+ }
+ }
+
+ BMW_End(&walker);
+ BLI_array_free(blocks);
+}
+
+void bmesh_collapsecon_exec(BMesh *bm, BMOperator *op)
+{
+ int i;
+
+ for (i=0; i<bm->ldata.totlayer; i++) {
+ if (CustomData_layer_has_math(&bm->ldata, i))
+ bmesh_collapsecon_do_layer(bm, op, i);
+ }
+}
+
+void bmesh_finddoubles_common(BMesh *bm, BMOperator *op, BMOperator *optarget, const char *targetmapname)
+{
+ BMOIter oiter;
+ BMVert *v, *v2;
+ BMVert **verts=NULL;
+ BLI_array_declare(verts);
+ float dist, dist3;
+ int i, j, len, keepvert = 0;
+
+ dist = BMO_Get_Float(op, "dist");
+ dist3 = dist * 3.0f;
+
+ i = 0;
+ BMO_ITER(v, &oiter, bm, op, "verts", BM_VERT) {
+ BLI_array_growone(verts);
+ verts[i++] = v;
+ }
+
+ /* Test whether keepverts arg exists and is non-empty */
+ if (BMO_HasSlot(op, "keepverts")) {
+ keepvert = BMO_IterNew(&oiter, bm, op, "keepverts", BM_VERT) != NULL;
+ }
+
+ /*sort by vertex coordinates added together*/
+ qsort(verts, BLI_array_count(verts), sizeof(void*), vergaverco);
+
+ /* Flag keepverts */
+ if (keepvert) {
+ BMO_Flag_Buffer(bm, op, "keepverts", VERT_KEEP, BM_VERT);
+ }
+
+ len = BLI_array_count(verts);
+ for (i=0; i<len; i++) {
+ v = verts[i];
+ if (BMO_TestFlag(bm, v, VERT_DOUBLE)) continue;
+
+ for (j=i+1; j<len; j++) {
+ v2 = verts[j];
+
+ /* Compare sort values of the verts using 3x tolerance (allowing for the tolerance
+ on each of the three axes). This avoids the more expensive length comparison
+ for most vertex pairs. */
+ if ((v2->co[0]+v2->co[1]+v2->co[2])-(v->co[0]+v->co[1]+v->co[2]) > dist3)
+ break;
+
+ if (keepvert) {
+ if (BMO_TestFlag(bm, v2, VERT_KEEP) == BMO_TestFlag(bm, v, VERT_KEEP))
+ continue;
+ }
+
+ if (compare_len_v3v3(v->co, v2->co, dist)) {
+
+ /* If one vert is marked as keep, make sure it will be the target */
+ if (BMO_TestFlag(bm, v2, VERT_KEEP)) {
+ SWAP(BMVert *, v, v2);
+ }
+
+ BMO_SetFlag(bm, v2, VERT_DOUBLE);
+ BMO_SetFlag(bm, v, VERT_TARGET);
+
+ BMO_Insert_MapPointer(bm, optarget, targetmapname, v2, v);
+ }
+ }
+ }
+
+ BLI_array_free(verts);
+}
+
+void bmesh_removedoubles_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator weldop;
+
+ BMO_Init_Op(&weldop, "weldverts");
+ bmesh_finddoubles_common(bm, op, &weldop, "targetmap");
+ BMO_Exec_Op(bm, &weldop);
+ BMO_Finish_Op(bm, &weldop);
+}
+
+
+void bmesh_finddoubles_exec(BMesh *bm, BMOperator *op)
+{
+ bmesh_finddoubles_common(bm, op, op, "targetmapout");
+}
+
+void bmesh_automerge_exec(BMesh *bm, BMOperator *op)
+{
+ BMOperator findop, weldop;
+ BMIter viter;
+ BMVert *v;
+
+ /* The "verts" input sent to this op is the set of verts that
+ can be merged away into any other verts. Mark all other verts
+ as VERT_KEEP. */
+ BMO_Flag_Buffer(bm, op, "verts", VERT_IN, BM_VERT);
+ BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) {
+ if (!BMO_TestFlag(bm, v, VERT_IN)) {
+ BMO_SetFlag(bm, v, VERT_KEEP);
+ }
+ }
+
+ /* Search for doubles among all vertices, but only merge non-VERT_KEEP
+ vertices into VERT_KEEP vertices. */
+ BMO_InitOpf(bm, &findop, "finddoubles verts=%av keepverts=%fv", VERT_KEEP);
+ BMO_CopySlot(op, &findop, "dist", "dist");
+ BMO_Exec_Op(bm, &findop);
+
+ /* weld the vertices */
+ BMO_Init_Op(&weldop, "weldverts");
+ BMO_CopySlot(&findop, &weldop, "targetmapout", "targetmap");
+ BMO_Exec_Op(bm, &weldop);
+
+ BMO_Finish_Op(bm, &findop);
+ BMO_Finish_Op(bm, &weldop);
+}
diff --git a/source/blender/bmesh/operators/subdivideop.c b/source/blender/bmesh/operators/subdivideop.c
new file mode 100644
index 00000000000..6f03d527b3e
--- /dev/null
+++ b/source/blender/bmesh/operators/subdivideop.c
@@ -0,0 +1,1183 @@
+/**
+ * $Id:
+ *
+ * ***** 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Joseph Eagar.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
+
+#include "BLI_math.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_array.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_object_types.h"
+
+#include "ED_mesh.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#include "mesh_intern.h"
+#include "subdivideop.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+/*flags for all elements share a common bitfield space*/
+#define SUBD_SPLIT 1
+
+#define EDGE_PERCENT 2
+
+/*I don't think new faces are flagged, currently, but
+ better safe than sorry.*/
+#define FACE_NEW 4
+#define FACE_CUSTOMFILL 8
+#define ELE_INNER 16
+#define ELE_SPLIT 32
+#define ELE_CONNECT 64
+
+/*stuff for the flag paramter. note that
+ what used to live in "beauty" and
+ in "seltype" live here. still have to
+ convert the beauty flags over, which
+ is why it starts at 128 (to avoid
+ collision).*/
+#define SELTYPE_INNER 128
+
+/*
+NOTE: beauty has been renamed to flag!
+*/
+
+/*generic subdivision rules:
+
+ * two selected edges in a face should make a link
+ between them.
+
+ * one edge should do, what? make pretty topology, or just
+ split the edge only?
+*/
+
+#if 0 //misc. code, maps a parametric coordinate to a fractal line
+float lastrnd[3], vec2[3] = {0.0f, 0.0f, 0.0f};
+int seed = BLI_rand();
+int d, i, j, dp, lvl, wid;
+float df;
+
+BLI_srandom(seed);
+
+wid = (params->numcuts+2);
+dp = perc*wid;
+wid /= 2;
+d = lvl = 0;
+while (1) {
+ if (d > dp) {
+ d -= wid;
+ } else if (d < dp) {
+ d += wid;
+ } else {
+ break;
+ }
+
+
+ wid = MAX2((wid/2), 1);
+ lvl++;
+}
+
+zero_v3(vec1);
+df = 1.0f;
+for (i=0; i<lvl; i++, df /= 4.0f) {
+ int tot = (1<<i);
+
+ lastrnd[0] = BLI_drand()-0.5f;
+ lastrnd[1] = BLI_drand()-0.5f;
+ lastrnd[2] = BLI_drand()-0.5f;
+ for (j=0; j<tot; j++) {
+ float a, b, rnd[3], rnd2[3];
+
+ rnd[0] = BLI_drand()-0.5f;
+ rnd[1] = BLI_drand()-0.5f;
+ rnd[2] = BLI_drand()-0.5f;
+
+ a = (float)j*(float)((float)params->numcuts/(float)tot);
+ b = (float)(j+1)*(float)((float)params->numcuts/(float)tot);
+ if (d >= a && d <= b) {
+ interp_v3_v3v3(rnd2, lastrnd, rnd, (((float)d)-a)/(b-a));
+ mul_v3_fl(rnd2, df);
+ add_v3_v3(vec1, rnd2);
+ }
+
+ copy_v3_v3(lastrnd, rnd);
+ }
+}
+#endif
+/*connects face with smallest len, which I think should always be correct for
+ edge subdivision*/
+static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) {
+ BMIter iter, iter2;
+ BMVert *v;
+ BMLoop *nl;
+ BMFace *face, *curf = NULL;
+
+ /*this isn't the best thing in the world. it doesn't handle cases where there's
+ multiple faces yet. that might require a convexity test to figure out which
+ face is "best," and who knows what for non-manifold conditions.*/
+ for (face = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v1); face; face=BMIter_Step(&iter)) {
+ for (v=BMIter_New(&iter2, bm, BM_VERTS_OF_FACE, face); v; v=BMIter_Step(&iter2)) {
+ if (v == v2) {
+ if (!curf || face->len < curf->len) curf = face;
+ }
+ }
+ }
+
+ if (curf) {
+ face = BM_Split_Face(bm, curf, v1, v2, &nl, NULL);
+
+ if (nf) *nf = face;
+ return nl ? nl->e : NULL;
+ }
+
+ return NULL;
+}
+/* calculates offset for co, based on fractal, sphere or smooth settings */
+static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), subdparams *params, float perc,
+ BMVert *vsta, BMVert *vend)
+{
+ float vec1[3], fac;
+ float *co=NULL, *origco=NULL;
+ int i, totlayer = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY);
+
+ BM_Vert_UpdateAllNormals(bm, v);
+
+ origco = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, params->origkey);
+ sub_v3_v3v3(vec1, origco, v->co);
+
+ for (i=0; i<totlayer; i++) {
+ co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, i);
+ sub_v3_v3(co, vec1);
+ }
+
+ for (i=0; i<totlayer; i++) {
+ co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, i);
+
+ if(params->beauty & B_SMOOTH) {
+ /* we calculate an offset vector vec1[], to be added to *co */
+ float len, fac, nor[3], nor1[3], nor2[3], smooth=params->smooth;
+
+ sub_v3_v3v3(nor, vsta->co, vend->co);
+ len= 0.5f*normalize_v3(nor);
+
+ copy_v3_v3(nor1, vsta->no);
+ copy_v3_v3(nor2, vend->no);
+
+ /* cosine angle */
+ fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
+
+ vec1[0]= fac*nor1[0];
+ vec1[1]= fac*nor1[1];
+ vec1[2]= fac*nor1[2];
+
+ /* cosine angle */
+ fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
+
+ vec1[0]+= fac*nor2[0];
+ vec1[1]+= fac*nor2[1];
+ vec1[2]+= fac*nor2[2];
+
+ /* falloff for multi subdivide */
+ smooth *= sqrtf(fabsf(1.0f - 2.0f*fabsf(0.5f-perc)));
+
+ vec1[0]*= smooth*len;
+ vec1[1]*= smooth*len;
+ vec1[2]*= smooth*len;
+
+ co[0] += vec1[0];
+ co[1] += vec1[1];
+ co[2] += vec1[2];
+ }
+ else if(params->beauty & B_SPHERE) { /* subdivide sphere */
+ normalize_v3(co);
+ co[0]*= params->smooth;
+ co[1]*= params->smooth;
+ co[2]*= params->smooth;
+ }
+
+ if(params->beauty & B_FRACTAL) {
+ float len = len_v3v3(vsta->co, vend->co);
+ float vec2[3] = {0.0f, 0.0f, 0.0f}, co2[3];
+
+ fac= params->fractal*len;
+
+ add_v3_v3(vec2, vsta->no);
+ add_v3_v3(vec2, vend->no);
+ mul_v3_fl(vec2, 0.5f);
+
+ add_v3_v3v3(co2, v->co, params->off);
+ vec1[0] = fac*(BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 1)-0.5f);
+ vec1[1] = fac*(BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 1)-0.5f);
+ vec1[2] = fac*(BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 1)-0.5f);
+
+ mul_v3_v3(vec2, vec1);
+
+ /*add displacement*/
+ add_v3_v3v3(co, co, vec2);
+ }
+ }
+}
+
+/* assumes in the edge is the correct interpolated vertices already */
+/* percent defines the interpolation, rad and flag are for special options */
+/* results in new vertex with correct coordinate, vertex normal and weight group info */
+static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge,BMEdge *oedge,
+ subdparams *params, float percent,
+ float percent2,
+ BMEdge **out,BMVert *vsta,BMVert *vend)
+{
+ BMVert *ev;
+
+ ev = BM_Split_Edge(bm, edge->v1, edge, out, percent);
+
+ BMO_SetFlag(bm, ev, ELE_INNER);
+
+ /* offset for smooth or sphere or fractal */
+ alter_co(bm, ev, oedge, params, percent2, vsta, vend);
+
+#if 0 //BMESH_TODO
+ /* clip if needed by mirror modifier */
+ if (edge->v1->f2) {
+ if ( edge->v1->f2 & edge->v2->f2 & 1) {
+ co[0]= 0.0f;
+ }
+ if ( edge->v1->f2 & edge->v2->f2 & 2) {
+ co[1]= 0.0f;
+ }
+ if ( edge->v1->f2 & edge->v2->f2 & 4) {
+ co[2]= 0.0f;
+ }
+ }
+#endif
+
+ return ev;
+}
+
+static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge,
+ int curpoint, int totpoint, subdparams *params,
+ BMEdge **newe, BMVert *vsta, BMVert *vend)
+{
+ BMVert *ev;
+ float percent, percent2 = 0.0f;
+
+ if (BMO_TestFlag(bm, edge, EDGE_PERCENT) && totpoint == 1)
+ percent = BMO_Get_MapFloat(bm, params->op,
+ "edgepercents", edge);
+ else {
+ percent= 1.0f/(float)(totpoint+1-curpoint);
+ percent2 = (float)(curpoint+1) / (float)(totpoint+1);
+
+ }
+
+ ev= bm_subdivide_edge_addvert(bm, edge, oedge, params, percent,
+ percent2, newe, vsta, vend);
+ return ev;
+}
+
+static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, subdparams *params,
+ BMVert *vsta, BMVert *vend) {
+ BMEdge *eed = edge, *newe, temp = *edge;
+ BMVert *v, ov1=*edge->v1, ov2=*edge->v2, *v1=edge->v1, *v2=edge->v2;
+ int i, numcuts = params->numcuts;
+
+ temp.v1 = &ov1;
+ temp.v2 = &ov2;
+
+ for(i=0;i<numcuts;i++) {
+ v = subdivideedgenum(bm, eed, &temp, i, params->numcuts, params,
+ &newe, vsta, vend);
+
+ BMO_SetFlag(bm, v, SUBD_SPLIT);
+ BMO_SetFlag(bm, eed, SUBD_SPLIT);
+ BMO_SetFlag(bm, newe, SUBD_SPLIT);
+
+ BMO_SetFlag(bm, v, ELE_SPLIT);
+ BMO_SetFlag(bm, eed, ELE_SPLIT);
+ BMO_SetFlag(bm, newe, SUBD_SPLIT);
+
+ CHECK_ELEMENT(bm, v);
+ if (v->e) CHECK_ELEMENT(bm, v->e);
+ if (v->e && v->e->l) CHECK_ELEMENT(bm, v->e->l->f);
+ }
+
+ alter_co(bm, v1, &temp, params, 0, &ov1, &ov2);
+ alter_co(bm, v2, &temp, params, 1.0, &ov1, &ov2);
+}
+
+/*note: the patterns are rotated as necassary to
+ match the input geometry. they're based on the
+ pre-split state of the face*/
+
+/*
+
+v3---------v2
+| |
+| |
+| |
+| |
+v4---v0---v1
+
+*/
+static void quad_1edge_split(BMesh *bm, BMFace *UNUSED(face),
+ BMVert **verts, subdparams *params) {
+ BMFace *nf;
+ int i, add, numcuts = params->numcuts;
+
+ /*if it's odd, the middle face is a quad, otherwise it's a triangle*/
+ if (numcuts % 2==0) {
+ add = 2;
+ for (i=0; i<numcuts; i++) {
+ if (i == numcuts/2) add -= 1;
+ connect_smallest_face(bm, verts[i], verts[numcuts+add],
+ &nf);
+ }
+ } else {
+ add = 2;
+ for (i=0; i<numcuts; i++) {
+ connect_smallest_face(bm, verts[i], verts[numcuts+add],
+ &nf);
+ if (i == numcuts/2) {
+ add -= 1;
+ connect_smallest_face(bm, verts[i],
+ verts[numcuts+add],
+ &nf);
+ }
+ }
+
+ }
+}
+
+static subdpattern quad_1edge = {
+ {1, 0, 0, 0},
+ quad_1edge_split,
+ 4,
+};
+
+
+/*
+v6--------v5
+| |
+| |v4s
+| |v3s
+| s s |
+v7-v0--v1-v2
+
+*/
+static void quad_2edge_split_path(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ int i, numcuts = params->numcuts;
+
+ for (i=0; i<numcuts; i++) {
+ connect_smallest_face(bm, verts[i], verts[numcuts+(numcuts-i)],
+ &nf);
+ }
+ connect_smallest_face(bm, verts[numcuts*2+3], verts[numcuts*2+1], &nf);
+}
+
+static subdpattern quad_2edge_path = {
+ {1, 1, 0, 0},
+ quad_2edge_split_path,
+ 4,
+};
+
+/*
+v6--------v5
+| |
+| |v4s
+| |v3s
+| s s |
+v7-v0--v1-v2
+
+*/
+static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ BMVert *v, *lastv;
+ BMEdge *e, *ne, olde;
+ int i, numcuts = params->numcuts;
+
+ lastv = verts[numcuts];
+
+ for (i=numcuts-1; i>=0; i--) {
+ e = connect_smallest_face(bm, verts[i], verts[numcuts+(numcuts-i)],
+ &nf);
+
+ olde = *e;
+ v = bm_subdivide_edge_addvert(bm, e, &olde, params, 0.5f, 0.5f, &ne, e->v1, e->v2);
+
+ if (i != numcuts-1)
+ connect_smallest_face(bm, lastv, v, &nf);
+
+ lastv = v;
+ }
+
+ connect_smallest_face(bm, lastv, verts[numcuts*2+2], &nf);
+}
+
+static subdpattern quad_2edge_innervert = {
+ {1, 1, 0, 0},
+ quad_2edge_split_innervert,
+ 4,
+};
+
+/*
+v6--------v5
+| |
+| |v4s
+| |v3s
+| s s |
+v7-v0--v1-v2
+
+*/
+static void quad_2edge_split_fan(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ /* BMVert *v; */ /* UNUSED */
+ /* BMVert *lastv= verts[2]; */ /* UNUSED */
+ /* BMEdge *e, *ne; */ /* UNUSED */
+ int i, numcuts = params->numcuts;
+
+ for (i=0; i<numcuts; i++) {
+ connect_smallest_face(bm, verts[i], verts[numcuts*2+2], &nf);
+ connect_smallest_face(bm, verts[numcuts+(numcuts-i)],
+ verts[numcuts*2+2], &nf);
+ }
+}
+
+static subdpattern quad_2edge_fan = {
+ {1, 1, 0, 0},
+ quad_2edge_split_fan,
+ 4,
+};
+
+/* s s
+v8--v7--v6-v5
+| |
+| v4 s
+| |
+| v3 s
+| s s |
+v9-v0--v1-v2
+
+*/
+static void quad_3edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ int i, add=0, numcuts = params->numcuts;
+
+ for (i=0; i<numcuts; i++) {
+ if (i == numcuts/2) {
+ if (numcuts % 2 != 0) {
+ connect_smallest_face(bm, verts[numcuts-i-1+add],
+ verts[i+numcuts+1], &nf);
+ }
+ add = numcuts*2+2;
+ }
+ connect_smallest_face(bm, verts[numcuts-i-1+add],
+ verts[i+numcuts+1], &nf);
+ }
+
+ for (i=0; i<numcuts/2+1; i++) {
+ connect_smallest_face(bm, verts[i],verts[(numcuts-i)+numcuts*2+1],
+ &nf);
+ }
+}
+
+static subdpattern quad_3edge = {
+ {1, 1, 1, 0},
+ quad_3edge_split,
+ 4,
+};
+
+/*
+
+ v8--v7-v6--v5
+ | s |
+ |v9 s s|v4
+first line | | last line
+ |v10s s s|v3
+ v11-v0--v1-v2
+
+ it goes from bottom up
+*/
+static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ BMVert *v, *v1, *v2;
+ BMEdge *e, *ne, temp;
+ BMVert **lines;
+ int numcuts = params->numcuts;
+ int i, j, a, b, s=numcuts+2 /* , totv=numcuts*4+4 */;
+
+ lines = MEM_callocN(sizeof(BMVert*)*(numcuts+2)*(numcuts+2),
+ "q_4edge_split");
+ /*build a 2-dimensional array of verts,
+ containing every vert (and all new ones)
+ in the face.*/
+
+ /*first line*/
+ for (i=0; i<numcuts+2; i++) {
+ lines[i] = verts[numcuts*3+2+(numcuts-i+1)];
+ }
+
+ /*last line*/
+ for (i=0; i<numcuts+2; i++) {
+ lines[(s-1)*s+i] = verts[numcuts+i];
+ }
+
+ /*first and last members of middle lines*/
+ for (i=0; i<numcuts; i++) {
+ a = i;
+ b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
+
+ e = connect_smallest_face(bm, verts[a], verts[b], &nf);
+ if (!e)
+ continue;
+
+ BMO_SetFlag(bm, e, ELE_INNER);
+ BMO_SetFlag(bm, nf, ELE_INNER);
+
+
+ v1 = lines[(i+1)*s] = verts[a];
+ v2 = lines[(i+1)*s + s-1] = verts[b];
+
+ temp = *e;
+ for (a=0; a<numcuts; a++) {
+ v = subdivideedgenum(bm, e, &temp, a, numcuts, params, &ne,
+ v1, v2);
+ if (!v)
+ bmesh_error();
+
+ BMO_SetFlag(bm, ne, ELE_INNER);
+ lines[(i+1)*s+a+1] = v;
+ }
+ }
+
+ for (i=1; i<numcuts+2; i++) {
+ for (j=1; j<numcuts+1; j++) {
+ a = i*s + j;
+ b = (i-1)*s + j;
+ e = connect_smallest_face(bm, lines[a], lines[b], &nf);
+ if (!e)
+ continue;
+
+ BMO_SetFlag(bm, e, ELE_INNER);
+ BMO_SetFlag(bm, nf, ELE_INNER);
+ }
+ }
+
+ MEM_freeN(lines);
+}
+
+/* v3
+ / \
+ / \
+ / \
+ / \
+ / \
+v4--v0--v1--v2
+ s s
+*/
+static void tri_1edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ int i, numcuts = params->numcuts;
+
+ for (i=0; i<numcuts; i++) {
+ connect_smallest_face(bm, verts[i], verts[numcuts+1], &nf);
+ }
+}
+
+static subdpattern tri_1edge = {
+ {1, 0, 0},
+ tri_1edge_split,
+ 3,
+};
+
+/* v5
+ / \
+ s v6/---\ v4 s
+ / \ / \
+sv7/---v---\ v3 s
+ / \/ \/ \
+ v8--v0--v1--v2
+ s s
+*/
+static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+ subdparams *params)
+{
+ BMFace *nf;
+ BMEdge *e, *ne, temp;
+ BMVert ***lines, *v, ov1, ov2;
+ void *stackarr[1];
+ int i, j, a, b, numcuts = params->numcuts;
+
+ /*number of verts in each line*/
+ lines = MEM_callocN(sizeof(void*)*(numcuts+2), "triangle vert table");
+
+ lines[0] = (BMVert**) stackarr;
+ lines[0][0] = verts[numcuts*2+1];
+
+ lines[1+numcuts] = MEM_callocN(sizeof(void*)*(numcuts+2),
+ "triangle vert table 2");
+ for (i=0; i<numcuts; i++) {
+ lines[1+numcuts][1+i] = verts[i];
+ }
+ lines[1+numcuts][0] = verts[numcuts*3+2];
+ lines[1+numcuts][1+numcuts] = verts[numcuts];
+
+ for (i=0; i<numcuts; i++) {
+ lines[i+1] = MEM_callocN(sizeof(void*)*(2+i),
+ "triangle vert table row");
+ a = numcuts*2 + 2 + i;
+ b = numcuts + numcuts - i;
+ e = connect_smallest_face(bm, verts[a], verts[b], &nf);
+ if (!e) goto cleanup;
+
+ BMO_SetFlag(bm, e, ELE_INNER);
+ BMO_SetFlag(bm, nf, ELE_INNER);
+
+ lines[i+1][0] = verts[a];
+ lines[i+1][1+i] = verts[b];
+
+ temp = *e;
+ ov1 = *verts[a];
+ ov2 = *verts[b];
+ temp.v1 = &ov1;
+ temp.v2 = &ov2;
+ for (j=0; j<i; j++) {
+ v = subdivideedgenum(bm, e, &temp, j, i, params, &ne,
+ verts[a], verts[b]);
+ lines[i+1][j+1] = v;
+
+ BMO_SetFlag(bm, ne, ELE_INNER);
+ }
+ }
+
+
+/* v5
+ / \
+ s v6/---\ v4 s
+ / \ / \
+sv7/---v---\ v3 s
+ / \/ \/ \
+ v8--v0--v1--v2
+ s s
+*/
+ for (i=1; i<numcuts+1; i++) {
+ for (j=0; j<i; j++) {
+ e= connect_smallest_face(bm, lines[i][j], lines[i+1][j+1],
+ &nf);
+
+ BMO_SetFlag(bm, e, ELE_INNER);
+ BMO_SetFlag(bm, nf, ELE_INNER);
+
+ e= connect_smallest_face(bm,lines[i][j+1],lines[i+1][j+1],
+ &nf);
+
+ BMO_SetFlag(bm, e, ELE_INNER);
+ BMO_SetFlag(bm, nf, ELE_INNER);
+ }
+ }
+
+cleanup:
+ for (i=1; i<numcuts+2; i++) {
+ if (lines[i]) MEM_freeN(lines[i]);
+ }
+
+ MEM_freeN(lines);
+}
+
+static subdpattern tri_3edge = {
+ {1, 1, 1},
+ tri_3edge_subdivide,
+ 3,
+};
+
+
+static subdpattern quad_4edge = {
+ {1, 1, 1, 1},
+ quad_4edge_subdivide,
+ 4,
+};
+
+static subdpattern *patterns[] = {
+ NULL, //quad single edge pattern is inserted here
+ NULL, //quad corner vert pattern is inserted here
+ NULL, //tri single edge pattern is inserted here
+ NULL,
+ &quad_3edge,
+ NULL,
+};
+
+#define PLEN (sizeof(patterns) / sizeof(void*))
+
+typedef struct subd_facedata {
+ BMVert *start; subdpattern *pat;
+ int totedgesel; //only used if pat was NULL, e.g. no pattern was found
+ BMFace *face;
+} subd_facedata;
+
+void esubdivide_exec(BMesh *bmesh, BMOperator *op)
+{
+ BMOpSlot *einput;
+ subdpattern *pat;
+ subdparams params;
+ subd_facedata *facedata = NULL;
+ BMIter viter, fiter, liter;
+ BMVert *v, **verts = NULL;
+ BMEdge *edge, **edges = NULL;
+ BMLoop *nl, *l, **splits = NULL, **loops = NULL;
+ BMFace *face;
+ BLI_array_declare(splits);
+ BLI_array_declare(loops);
+ BLI_array_declare(facedata);
+ BLI_array_declare(edges);
+ BLI_array_declare(verts);
+ float smooth, fractal;
+ int beauty, cornertype, singleedge, gridfill;
+ int skey, seed, i, j, matched, a, b, numcuts, totesel;
+
+ BMO_Flag_Buffer(bmesh, op, "edges", SUBD_SPLIT, BM_EDGE);
+
+ numcuts = BMO_Get_Int(op, "numcuts");
+ seed = BMO_Get_Int(op, "seed");
+ smooth = BMO_Get_Float(op, "smooth");
+ fractal = BMO_Get_Float(op, "fractal");
+ beauty = BMO_Get_Int(op, "beauty");
+ cornertype = BMO_Get_Int(op, "quadcornertype");
+ singleedge = BMO_Get_Int(op, "singleedge");
+ gridfill = BMO_Get_Int(op, "gridfill");
+
+ BLI_srandom(seed);
+
+ patterns[1] = NULL;
+ //straight cut is patterns[1] == NULL
+ switch (cornertype) {
+ case SUBD_PATH:
+ patterns[1] = &quad_2edge_path;
+ break;
+ case SUBD_INNERVERT:
+ patterns[1] = &quad_2edge_innervert;
+ break;
+ case SUBD_FAN:
+ patterns[1] = &quad_2edge_fan;
+ break;
+ }
+
+ if (singleedge) {
+ patterns[0] = &quad_1edge;
+ patterns[2] = &tri_1edge;
+ } else {
+ patterns[0] = NULL;
+ patterns[2] = NULL;
+ }
+
+ if (gridfill) {
+ patterns[3] = &quad_4edge;
+ patterns[5] = &tri_3edge;
+ } else {
+ patterns[3] = NULL;
+ patterns[5] = NULL;
+ }
+
+ /*add a temporary shapekey layer to store displacements on current geometry*/
+ BM_add_data_layer(bmesh, &bmesh->vdata, CD_SHAPEKEY);
+ skey = CustomData_number_of_layers(&bmesh->vdata, CD_SHAPEKEY)-1;
+
+ BM_ITER(v, &viter, bmesh, BM_VERTS_OF_MESH, NULL) {
+ float *co = CustomData_bmesh_get_n(&bmesh->vdata, v->head.data, CD_SHAPEKEY, skey);
+ copy_v3_v3(co, v->co);
+ }
+
+ /*first go through and tag edges*/
+ BMO_Flag_To_Slot(bmesh, op, "edges",
+ SUBD_SPLIT, BM_EDGE);
+
+ params.numcuts = numcuts;
+ params.op = op;
+ params.smooth = smooth;
+ params.seed = seed;
+ params.fractal = fractal;
+ params.beauty = beauty;
+ params.origkey = skey;
+ params.off[0] = (float)BLI_drand()*200.0f;
+ params.off[1] = (float)BLI_drand()*200.0f;
+ params.off[2] = (float)BLI_drand()*200.0f;
+
+ BMO_Mapping_To_Flag(bmesh, op, "custompatterns",
+ FACE_CUSTOMFILL);
+
+ BMO_Mapping_To_Flag(bmesh, op, "edgepercents",
+ EDGE_PERCENT);
+
+ for (face=BMIter_New(&fiter, bmesh, BM_FACES_OF_MESH, NULL);
+ face; face=BMIter_Step(&fiter)) {
+ BMEdge *e1 = NULL, *e2 = NULL;
+ float vec1[3], vec2[3];
+
+ /*figure out which pattern to use*/
+
+ BLI_array_empty(edges);
+ BLI_array_empty(verts);
+ matched = 0;
+
+ i = 0;
+ totesel = 0;
+ for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
+ nl; nl=BMIter_Step(&liter)) {
+ BLI_array_growone(edges);
+ BLI_array_growone(verts);
+ edges[i] = nl->e;
+ verts[i] = nl->v;
+
+ if (BMO_TestFlag(bmesh, edges[i], SUBD_SPLIT)) {
+ if (!e1) e1 = edges[i];
+ else e2 = edges[i];
+
+ totesel++;
+ }
+
+ i++;
+ }
+
+ /*make sure the two edges have a valid angle to each other*/
+ if (totesel == 2 && (e1->v1 == e2->v1 || e1->v1 == e2->v2
+ || e1->v2 == e2->v1 || e1->v2 == e2->v1)) {
+ float angle;
+
+ sub_v3_v3v3(vec1, e1->v2->co, e1->v1->co);
+ sub_v3_v3v3(vec2, e2->v2->co, e2->v1->co);
+ normalize_v3(vec1);
+ normalize_v3(vec2);
+
+ angle = INPR(vec1, vec2);
+ angle = ABS(angle);
+ if (ABS(angle - 1.0f) < 0.01f)
+ totesel = 0;
+ }
+
+ if (BMO_TestFlag(bmesh, face, FACE_CUSTOMFILL)) {
+ pat = BMO_Get_MapData(bmesh, op,
+ "custompatterns", face);
+ for (i=0; i<pat->len; i++) {
+ matched = 1;
+ for (j=0; j<pat->len; j++) {
+ a = (j + i) % pat->len;
+ if ((!!BMO_TestFlag(bmesh, edges[a], SUBD_SPLIT))
+ != (!!pat->seledges[j])) {
+ matched = 0;
+ break;
+ }
+ }
+ if (matched) {
+ BLI_array_growone(facedata);
+ b = BLI_array_count(facedata)-1;
+ facedata[b].pat = pat;
+ facedata[b].start = verts[i];
+ facedata[b].face = face;
+ facedata[b].totedgesel = totesel;
+ BMO_SetFlag(bmesh, face, SUBD_SPLIT);
+ break;
+ }
+ }
+
+ /*obvously don't test for other patterns matching*/
+ continue;
+ }
+
+ for (i=0; i<PLEN; i++) {
+ pat = patterns[i];
+ if (!pat) continue;
+
+ if (pat->len == face->len) {
+ for (a=0; a<pat->len; a++) {
+ matched = 1;
+ for (b=0; b<pat->len; b++) {
+ j = (b + a) % pat->len;
+ if ((!!BMO_TestFlag(bmesh, edges[j], SUBD_SPLIT))
+ != (!!pat->seledges[b])) {
+ matched = 0;
+ break;
+ }
+ }
+ if (matched) break;
+ }
+ if (matched) {
+ BLI_array_growone(facedata);
+ j = BLI_array_count(facedata) - 1;
+
+ BMO_SetFlag(bmesh, face, SUBD_SPLIT);
+
+ facedata[j].pat = pat;
+ facedata[j].start = verts[a];
+ facedata[j].face = face;
+ facedata[j].totedgesel = totesel;
+ break;
+ }
+ }
+
+ }
+
+ if (!matched && totesel) {
+ BLI_array_growone(facedata);
+ j = BLI_array_count(facedata) - 1;
+
+ BMO_SetFlag(bmesh, face, SUBD_SPLIT);
+ facedata[j].totedgesel = totesel;
+ facedata[j].face = face;
+ }
+ }
+
+ einput = BMO_GetSlot(op, "edges");
+
+ /*go through and split edges*/
+ for (i=0; i<einput->len; i++) {
+ edge = ((BMEdge**)einput->data.p)[i];
+ bm_subdivide_multicut(bmesh, edge, &params, edge->v1, edge->v2);
+ }
+
+ i = 0;
+ for (i=0; i<BLI_array_count(facedata); i++) {
+ face = facedata[i].face;
+
+ /*figure out which pattern to use*/
+ BLI_array_empty(verts);
+
+ pat = facedata[i].pat;
+
+ if (!pat && facedata[i].totedgesel == 2) {
+ int vlen;
+
+ /*ok, no pattern. we still may be able to do something.*/
+ BLI_array_empty(loops);
+ BLI_array_empty(splits);
+
+ /*for case of two edges, connecting them shouldn't be too hard*/
+ BM_ITER(l, &liter, bmesh, BM_LOOPS_OF_FACE, face) {
+ BLI_array_growone(loops);
+ loops[BLI_array_count(loops)-1] = l;
+ }
+
+ vlen = BLI_array_count(loops);
+
+ /*find the boundary of one of the split edges*/
+ for (a=1; a<vlen; a++) {
+ if (!BMO_TestFlag(bmesh, loops[a-1]->v, ELE_INNER)
+ && BMO_TestFlag(bmesh, loops[a]->v, ELE_INNER))
+ break;
+ }
+
+ if (BMO_TestFlag(bmesh, loops[(a+numcuts+1)%vlen]->v, ELE_INNER)) {
+ b = (a+numcuts+1)%vlen;
+ } else {
+ /*find the boundary of the other edge.*/
+ for (j=0; j<vlen; j++) {
+ b = (j + a + numcuts + 1) % vlen;
+ if (!BMO_TestFlag(bmesh, loops[b==0 ? vlen-1 : b-1]->v, ELE_INNER)
+ && BMO_TestFlag(bmesh, loops[b]->v, ELE_INNER))
+ break;
+ }
+ }
+
+ b += numcuts - 1;
+
+ for (j=0; j<numcuts; j++) {
+ BLI_array_growone(splits);
+ splits[BLI_array_count(splits)-1] = loops[a];
+
+ BLI_array_growone(splits);
+ splits[BLI_array_count(splits)-1] = loops[b];
+
+ b = (b-1) % vlen;
+ a = (a+1) % vlen;
+ }
+
+ //BM_LegalSplits(bmesh, face, splits, BLI_array_count(splits)/2);
+
+ for (j=0; j<BLI_array_count(splits)/2; j++) {
+ if (splits[j*2]) {
+ /* BMFace *nf= */ /* UNUSED */
+ BM_Split_Face(bmesh, face, splits[j*2]->v, splits[j*2+1]->v, &nl, NULL);
+ }
+ }
+
+ continue;
+ } else if (!pat) {
+ continue;
+ }
+
+ j = a = 0;
+ for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
+ nl; nl=BMIter_Step(&liter)) {
+ if (nl->v == facedata[i].start) {
+ a = j+1;
+ break;
+ }
+ j++;
+ }
+
+ for (j=0; j<face->len; j++) {
+ BLI_array_growone(verts);
+ }
+
+ j = 0;
+ for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
+ nl; nl=BMIter_Step(&liter)) {
+ b = (j-a+face->len) % face->len;
+ verts[b] = nl->v;
+ j += 1;
+ }
+
+ CHECK_ELEMENT(bmesh, face);
+ pat->connectexec(bmesh, face, verts, &params);
+ }
+
+ /*copy original-geometry displacements to current coordinates*/
+ BM_ITER(v, &viter, bmesh, BM_VERTS_OF_MESH, NULL) {
+ float *co = CustomData_bmesh_get_n(&bmesh->vdata, v->head.data, CD_SHAPEKEY, skey);
+ copy_v3_v3(v->co, co);
+ }
+
+ BM_free_data_layer_n(bmesh, &bmesh->vdata, CD_SHAPEKEY, skey);
+
+ if (facedata) BLI_array_free(facedata);
+ if (edges) BLI_array_free(edges);
+ if (verts) BLI_array_free(verts);
+ BLI_array_free(splits);
+ BLI_array_free(loops);
+
+ BMO_Flag_To_Slot(bmesh, op, "outinner",
+ ELE_INNER, BM_ALL);
+ BMO_Flag_To_Slot(bmesh, op, "outsplit",
+ ELE_SPLIT, BM_ALL);
+
+ BMO_Flag_To_Slot(bmesh, op, "geomout",
+ ELE_INNER|ELE_SPLIT|SUBD_SPLIT, BM_ALL);
+}
+
+/*editmesh-emulating function*/
+void BM_esubdivideflag(Object *UNUSED(obedit), BMesh *bm, int flag, float smooth,
+ float fractal, int beauty, int numcuts,
+ int seltype, int cornertype, int singleedge,
+ int gridfill, int seed)
+{
+ BMOperator op;
+
+ BMO_InitOpf(bm, &op, "esubd edges=%he smooth=%f fractal=%f "
+ "beauty=%d numcuts=%d quadcornertype=%d singleedge=%d "
+ "gridfill=%d seed=%d",
+ flag, smooth, fractal, beauty, numcuts,
+ cornertype, singleedge, gridfill, seed);
+
+ BMO_Exec_Op(bm, &op);
+
+ if (seltype == SUBDIV_SELECT_INNER) {
+ BMOIter iter;
+ BMHeader *ele;
+ // int i;
+
+ ele = BMO_IterNew(&iter, bm, &op, "outinner", BM_EDGE|BM_VERT);
+ for (; ele; ele=BMO_IterStep(&iter)) {
+ BM_Select(bm, ele, 1);
+ }
+ } else if (seltype == SUBDIV_SELECT_LOOPCUT) {
+ BMOIter iter;
+ BMHeader *ele;
+ // int i;
+
+ /*deselect input*/
+ BM_clear_flag_all(bm, BM_SELECT);
+
+ ele = BMO_IterNew(&iter, bm, &op, "outinner", BM_EDGE|BM_VERT);
+ for (; ele; ele=BMO_IterStep(&iter)) {
+ BM_Select(bm, ele, 1);
+
+ if (ele->type == BM_VERT) {
+ BMEdge *e;
+ BMIter eiter;
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, ele) {
+ if (!BM_TestHFlag(e, BM_SELECT) && BM_TestHFlag(e->v1, BM_SELECT)
+ && BM_TestHFlag(e->v2, BM_SELECT)) {
+ BM_Select(bm, e, 1);
+ bm->totedgesel += 1;
+ } else if (BM_TestHFlag(e, BM_SELECT) && (!BM_TestHFlag(e->v1, BM_SELECT)
+ || !BM_TestHFlag(e->v2, BM_SELECT))) {
+ BM_Select(bm, e, 0);
+ bm->totedgesel -= 1;
+ }
+ }
+ }
+ }
+ }
+
+ BMO_Finish_Op(bm, &op);
+}
+
+void esplit_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMEdge *e;
+ subdparams params;
+ int skey;
+
+ params.numcuts = BMO_GetSlot(op, "numcuts")->data.i;
+ params.op = op;
+
+ BM_add_data_layer(bm, &bm->vdata, CD_SHAPEKEY);
+ skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY)-1;
+
+ params.origkey = skey;
+
+ /*go through and split edges*/
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ bm_subdivide_multicut(bm, e, &params, e->v1, e->v2);
+ }
+
+ BMO_Flag_To_Slot(bm, op, "outsplit",
+ ELE_SPLIT, BM_ALL);
+
+ BM_free_data_layer_n(bm, &bm->vdata, CD_SHAPEKEY, skey);
+}
diff --git a/source/blender/bmesh/operators/subdivideop.h b/source/blender/bmesh/operators/subdivideop.h
new file mode 100644
index 00000000000..966cd90cbde
--- /dev/null
+++ b/source/blender/bmesh/operators/subdivideop.h
@@ -0,0 +1,41 @@
+#ifndef _SUBDIVIDEOP_H
+#define _SUBDIVIDEOP_H
+
+typedef struct subdparams {
+ int numcuts;
+ float smooth;
+ float fractal;
+ int beauty;
+ int seed;
+ int origkey; /*shapekey holding displaced vertex coordinates for current geometry*/
+ BMOperator *op;
+ float off[3];
+} subdparams;
+
+typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts,
+ subdparams *params);
+
+/*
+note: this is a pattern-based edge subdivider.
+it tries to match a pattern to edge selections on faces,
+then executes functions to cut them.
+*/
+typedef struct subdpattern {
+ int seledges[20]; //selected edges mask, for splitting
+
+ /*verts starts at the first new vert cut, not the first vert in the
+ face*/
+ subd_pattern_fill_fp connectexec;
+ int len; /*total number of verts, before any subdivision*/
+} subdpattern;
+
+/*generic subdivision rules:
+
+ * two selected edges in a face should make a link
+ between them.
+
+ * one edge should do, what? make pretty topology, or just
+ split the edge only?
+*/
+
+#endif /* _SUBDIVIDEOP_H */
diff --git a/source/blender/bmesh/operators/triangulateop.c b/source/blender/bmesh/operators/triangulateop.c
new file mode 100644
index 00000000000..51423eb9229
--- /dev/null
+++ b/source/blender/bmesh/operators/triangulateop.c
@@ -0,0 +1,194 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_scanfill.h"
+#include "BLI_math.h"
+#include "BLI_array.h"
+#include "BLI_editVert.h"
+#include "BLI_smallhash.h"
+
+#include "bmesh.h"
+#include "bmesh_private.h"
+
+#define EDGE_NEW 1
+#define FACE_NEW 1
+
+#define ELE_NEW 1
+#define FACE_MARK 2
+#define EDGE_MARK 4
+
+void triangulate_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMFace *face, **newfaces = NULL;
+ BLI_array_declare(newfaces);
+ float (*projectverts)[3] = NULL;
+ BLI_array_declare(projectverts);
+ int i, lastlen=0 /* , count = 0 */;
+
+ face = BMO_IterNew(&siter, bm, op, "faces", BM_FACE);
+ for (; face; face=BMO_IterStep(&siter)) {
+ if (lastlen < face->len) {
+ BLI_array_empty(projectverts);
+ BLI_array_empty(newfaces);
+ for (lastlen=0; lastlen<face->len; lastlen++) {
+ BLI_array_growone(projectverts);
+ BLI_array_growone(projectverts);
+ BLI_array_growone(projectverts);
+ BLI_array_growone(newfaces);
+ }
+ }
+
+ BM_Triangulate_Face(bm, face, projectverts, EDGE_NEW,
+ FACE_NEW, newfaces);
+
+ BMO_Insert_MapPointer(bm, op, "facemap",
+ face, face);
+ for (i=0; newfaces[i]; i++) {
+ BMO_Insert_MapPointer(bm, op, "facemap",
+ newfaces[i], face);
+
+ }
+ }
+
+ BMO_Flag_To_Slot(bm, op, "edgeout", EDGE_NEW, BM_EDGE);
+ BMO_Flag_To_Slot(bm, op, "faceout", FACE_NEW, BM_FACE);
+
+ BLI_array_free(projectverts);
+ BLI_array_free(newfaces);
+}
+
+void bmesh_beautify_fill_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMIter iter;
+ BMFace *f;
+ BMEdge *e;
+ int stop=0;
+
+ BMO_Flag_Buffer(bm, op, "constrain_edges", EDGE_MARK, BM_EDGE);
+
+ BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
+ if (f->len == 3)
+ BMO_SetFlag(bm, f, FACE_MARK);
+ }
+
+ while (!stop) {
+ stop = 1;
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ BMVert *v1, *v2, *v3, *v4;
+
+ if (BM_Edge_FaceCount(e) != 2 || BMO_TestFlag(bm, e, EDGE_MARK))
+ continue;
+ if (!BMO_TestFlag(bm, e->l->f, FACE_MARK) || !BMO_TestFlag(bm, e->l->radial_next->f, FACE_MARK))
+ continue;
+
+ v1 = e->l->prev->v;
+ v2 = e->l->v;
+ v3 = e->l->radial_next->prev->v;
+ v4 = e->l->next->v;
+
+ if (is_quad_convex_v3(v1->co, v2->co, v3->co, v4->co)) {
+ float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
+ /* testing rule:
+ * the area divided by the total edge lengths
+ */
+ len1= len_v3v3(v1->co, v2->co);
+ len2= len_v3v3(v2->co, v3->co);
+ len3= len_v3v3(v3->co, v4->co);
+ len4= len_v3v3(v4->co, v1->co);
+ len5= len_v3v3(v1->co, v3->co);
+ len6= len_v3v3(v2->co, v4->co);
+
+ opp1= area_tri_v3(v1->co, v2->co, v3->co);
+ opp2= area_tri_v3(v1->co, v3->co, v4->co);
+
+ fac1= opp1/(len1+len2+len5) + opp2/(len3+len4+len5);
+
+ opp1= area_tri_v3(v2->co, v3->co, v4->co);
+ opp2= area_tri_v3(v2->co, v4->co, v1->co);
+
+ fac2= opp1/(len2+len3+len6) + opp2/(len4+len1+len6);
+
+ if (fac1 > fac2) {
+ e = BM_Rotate_Edge(bm, e, 0);
+ BMO_SetFlag(bm, e, ELE_NEW);
+
+ BMO_SetFlag(bm, e->l->f, FACE_MARK|ELE_NEW);
+ BMO_SetFlag(bm, e->l->radial_next->f, FACE_MARK|ELE_NEW);
+ stop = 0;
+ }
+ }
+ }
+ }
+
+ BMO_Flag_To_Slot(bm, op, "geomout", ELE_NEW, BM_EDGE|BM_FACE);
+}
+
+void bmesh_triangle_fill_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMEdge *e;
+ BMOperator bmop;
+ EditEdge *eed;
+ EditVert *eve, *v1, *v2;
+ EditFace *efa;
+ SmallHash hash;
+
+ BLI_smallhash_init(&hash);
+
+ BLI_begin_edgefill();
+
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+
+ if (!BLI_smallhash_haskey(&hash, (uintptr_t)e->v1)) {
+ eve = BLI_addfillvert(e->v1->co);
+ eve->tmp.p = e->v1;
+ BLI_smallhash_insert(&hash, (uintptr_t)e->v1, eve);
+ }
+
+ if (!BLI_smallhash_haskey(&hash, (uintptr_t)e->v2)) {
+ eve = BLI_addfillvert(e->v2->co);
+ eve->tmp.p = e->v2;
+ BLI_smallhash_insert(&hash, (uintptr_t)e->v2, eve);
+ }
+
+ v1 = BLI_smallhash_lookup(&hash, (uintptr_t)e->v1);
+ v2 = BLI_smallhash_lookup(&hash, (uintptr_t)e->v2);
+ eed = BLI_addfilledge(v1, v2);
+ eed->tmp.p = e;
+ }
+
+ BLI_edgefill(0);
+
+ for (efa=fillfacebase.first; efa; efa=efa->next) {
+ BMFace *f = BM_Make_QuadTri(bm, efa->v1->tmp.p, efa->v2->tmp.p, efa->v3->tmp.p, NULL, NULL, 1);
+ BMLoop *l;
+ BMIter liter;
+
+ BMO_SetFlag(bm, f, ELE_NEW);
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ if (!BMO_TestFlag(bm, l->e, EDGE_MARK)) {
+ BMO_SetFlag(bm, l->e, ELE_NEW);
+ }
+ }
+ }
+
+ BLI_end_edgefill();
+ BLI_smallhash_release(&hash);
+
+ /*clean up fill*/
+ BMO_InitOpf(bm, &bmop, "beautify_fill faces=%ff constrain_edges=%fe", ELE_NEW, EDGE_MARK);
+ BMO_Exec_Op(bm, &bmop);
+ BMO_Flag_Buffer(bm, &bmop, "geomout", ELE_NEW, BM_FACE|BM_EDGE);
+ BMO_Finish_Op(bm, &bmop);
+
+ BMO_Flag_To_Slot(bm, op, "geomout", ELE_NEW, BM_EDGE|BM_FACE);
+}
diff --git a/source/blender/bmesh/operators/utils.c b/source/blender/bmesh/operators/utils.c
new file mode 100644
index 00000000000..daa60c640cd
--- /dev/null
+++ b/source/blender/bmesh/operators/utils.c
@@ -0,0 +1,1292 @@
+#include "MEM_guardedalloc.h"
+#include "BKE_customdata.h"
+#include "DNA_listBase.h"
+#include "DNA_customdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include <string.h>
+#include "BKE_utildefines.h"
+#include "BKE_mesh.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+
+#include "BLI_editVert.h"
+#include "mesh_intern.h"
+#include "ED_mesh.h"
+
+#include "BLI_math.h"
+#include "BLI_array.h"
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+
+#include "BLI_heap.h"
+
+#include "bmesh.h"
+
+#include "bmesh_operators_private.h" /* own include */
+
+/*
+ * UTILS.C
+ *
+ * utility bmesh operators, e.g. transform,
+ * translate, rotate, scale, etc.
+ *
+*/
+
+void bmesh_makevert_exec(BMesh *bm, BMOperator *op)
+{
+ float vec[3];
+
+ BMO_Get_Vec(op, "co", vec);
+
+ BMO_SetFlag(bm, BM_Make_Vert(bm, vec, NULL), 1);
+ BMO_Flag_To_Slot(bm, op, "newvertout", 1, BM_VERT);
+}
+
+void bmesh_transform_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter iter;
+ BMVert *v;
+ float mat[4][4];
+
+ BMO_Get_Mat4(op, "mat", mat);
+
+ BMO_ITER(v, &iter, bm, op, "verts", BM_VERT) {
+ mul_m4_v3(mat, v->co);
+ }
+}
+
+void bmesh_translate_exec(BMesh *bm, BMOperator *op)
+{
+ float mat[4][4], vec[3];
+
+ BMO_Get_Vec(op, "vec", vec);
+
+ unit_m4(mat);
+ copy_v3_v3(mat[3], vec);
+
+ BMO_CallOpf(bm, "transform mat=%m4 verts=%s", mat, op, "verts");
+}
+
+void bmesh_scale_exec(BMesh *bm, BMOperator *op)
+{
+ float mat[3][3], vec[3];
+
+ BMO_Get_Vec(op, "vec", vec);
+
+ unit_m3(mat);
+ mat[0][0] = vec[0];
+ mat[1][1] = vec[1];
+ mat[2][2] = vec[2];
+
+ BMO_CallOpf(bm, "transform mat=%m3 verts=%s", mat, op, "verts");
+}
+
+void bmesh_rotate_exec(BMesh *bm, BMOperator *op)
+{
+ float vec[3];
+
+ BMO_Get_Vec(op, "cent", vec);
+
+ /*there has to be a proper matrix way to do this, but
+ this is how editmesh did it and I'm too tired to think
+ through the math right now.*/
+ mul_v3_fl(vec, -1);
+ BMO_CallOpf(bm, "translate verts=%s vec=%v", op, "verts", vec);
+
+ BMO_CallOpf(bm, "transform mat=%s verts=%s", op, "mat", op, "verts");
+
+ mul_v3_fl(vec, -1);
+ BMO_CallOpf(bm, "translate verts=%s vec=%v", op, "verts", vec);
+}
+
+void bmesh_reversefaces_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMFace *f;
+
+ BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
+ BM_flip_normal(bm, f);
+ }
+}
+
+void bmesh_edgerotate_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMEdge *e, *e2;
+ int ccw = BMO_Get_Int(op, "ccw");
+
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ if (!(e2 = BM_Rotate_Edge(bm, e, ccw))) {
+ BMO_RaiseError(bm, op, BMERR_INVALID_SELECTION, "Could not rotate edge");
+ return;
+ }
+
+ BMO_SetFlag(bm, e2, 1);
+ }
+
+ BMO_Flag_To_Slot(bm, op, "edgeout", 1, BM_EDGE);
+}
+
+#define SEL_FLAG 1
+#define SEL_ORIG 2
+
+static void bmesh_regionextend_extend(BMesh *bm, BMOperator *op, int usefaces)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMIter eiter;
+ BMOIter siter;
+
+ if (!usefaces) {
+ BMO_ITER(v, &siter, bm, op, "geom", BM_VERT) {
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ if (!BMO_TestFlag(bm, e, SEL_ORIG))
+ break;
+ }
+
+ if (e) {
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ BMO_SetFlag(bm, e, SEL_FLAG);
+ BMO_SetFlag(bm, BM_OtherEdgeVert(e, v), SEL_FLAG);
+ }
+ }
+ }
+ } else {
+ BMIter liter, fiter;
+ BMFace *f, *f2;
+ BMLoop *l;
+
+ BMO_ITER(f, &siter, bm, op, "geom", BM_FACE) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BM_ITER(f2, &fiter, bm, BM_FACES_OF_EDGE, l->e) {
+ if (!BMO_TestFlag(bm, f2, SEL_ORIG))
+ BMO_SetFlag(bm, f2, SEL_FLAG);
+ }
+ }
+ }
+ }
+}
+
+static void bmesh_regionextend_constrict(BMesh *bm, BMOperator *op, int usefaces)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMIter eiter;
+ BMOIter siter;
+
+ if (!usefaces) {
+ BMO_ITER(v, &siter, bm, op, "geom", BM_VERT) {
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ if (!BMO_TestFlag(bm, e, SEL_ORIG))
+ break;
+ }
+
+ if (e) {
+ BMO_SetFlag(bm, v, SEL_FLAG);
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ BMO_SetFlag(bm, e, SEL_FLAG);
+ }
+ }
+ }
+ } else {
+ BMIter liter, fiter;
+ BMFace *f, *f2;
+ BMLoop *l;
+
+ BMO_ITER(f, &siter, bm, op, "geom", BM_FACE) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BM_ITER(f2, &fiter, bm, BM_FACES_OF_EDGE, l->e) {
+ if (!BMO_TestFlag(bm, f2, SEL_ORIG)) {
+ BMO_SetFlag(bm, f, SEL_FLAG);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void bmesh_regionextend_exec(BMesh *bm, BMOperator *op)
+{
+ int usefaces = BMO_Get_Int(op, "usefaces");
+ int constrict = BMO_Get_Int(op, "constrict");
+
+ BMO_Flag_Buffer(bm, op, "geom", SEL_ORIG, BM_ALL);
+
+ if (constrict)
+ bmesh_regionextend_constrict(bm, op, usefaces);
+ else
+ bmesh_regionextend_extend(bm, op, usefaces);
+
+ BMO_Flag_To_Slot(bm, op, "geomout", SEL_FLAG, BM_ALL);
+}
+
+/********* righthand faces implementation ********/
+
+#define FACE_VIS 1
+#define FACE_FLAG 2
+#define FACE_MARK 4
+#define FACE_FLIP 8
+
+/* NOTE: these are the original righthandfaces comment in editmesh_mods.c,
+ * copied here for reference. */
+
+ /* based at a select-connected to witness loose objects */
+
+/* count per edge the amount of faces
+ * find the ultimate left, front, upper face (not manhattan dist!!)
+ * also evaluate both triangle cases in quad, since these can be non-flat
+ *
+ * put normal to the outside, and set the first direction flags in edges
+ *
+ * then check the object, and set directions / direction-flags: but only for edges with 1 or 2 faces
+ * this is in fact the 'select connected'
+ *
+ * in case (selected) faces were not done: start over with 'find the ultimate ...' */
+
+/* NOTE: this function uses recursion, which is a little unusual for a bmop
+ function, but acceptable I think. */
+
+void bmesh_righthandfaces_exec(BMesh *bm, BMOperator *op)
+{
+ BMIter liter, liter2;
+ BMOIter siter;
+ BMFace *f, *startf, **fstack = NULL;
+ BLI_array_declare(fstack);
+ BMLoop *l, *l2;
+ float maxx, cent[3];
+ int i, maxi, flagflip = BMO_Get_Int(op, "doflip");
+
+ startf= NULL;
+ maxx= -1.0e10;
+
+ BMO_Flag_Buffer(bm, op, "faces", FACE_FLAG, BM_FACE);
+
+ /*find a starting face*/
+ BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
+ if (BMO_TestFlag(bm, f, FACE_VIS))
+ continue;
+
+ if (!startf) startf = f;
+
+ BM_Compute_Face_Center(bm, f, cent);
+
+ cent[0] = cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
+ if (cent[0] > maxx) {
+ maxx = cent[0];
+ startf = f;
+ }
+ }
+
+ if (!startf) return;
+
+ BM_Compute_Face_Center(bm, startf, cent);
+
+ /*make sure the starting face has the correct winding*/
+ if (dot_v3v3(cent, startf->no) < 0.0f) {
+ BM_flip_normal(bm, startf);
+ BMO_ToggleFlag(bm, startf, FACE_FLIP);
+
+ if (flagflip)
+ BM_ToggleHFlag(startf, BM_FLIPPED);
+ }
+
+ /*now that we've found our starting face, make all connected faces
+ have the same winding. this is done recursively, using a manual
+ stack (if we use simple function recursion, we'd end up overloading
+ the stack on large meshes).*/
+
+ BLI_array_growone(fstack);
+ fstack[0] = startf;
+ BMO_SetFlag(bm, startf, FACE_VIS);
+
+ i = 0;
+ maxi = 1;
+ while (i >= 0) {
+ f = fstack[i];
+ i--;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ BM_ITER(l2, &liter2, bm, BM_LOOPS_OF_LOOP, l) {
+ if (!BMO_TestFlag(bm, l2->f, FACE_FLAG) || l2 == l)
+ continue;
+
+ if (!BMO_TestFlag(bm, l2->f, FACE_VIS)) {
+ BMO_SetFlag(bm, l2->f, FACE_VIS);
+ i++;
+
+ if (l2->v == l->v) {
+ BM_flip_normal(bm, l2->f);
+
+ BMO_ToggleFlag(bm, l2->f, FACE_FLIP);
+ if (flagflip)
+ BM_ToggleHFlag(l2->f, BM_FLIPPED);
+ } else if (BM_TestHFlag(l2->f, BM_FLIPPED) || BM_TestHFlag(l->f, BM_FLIPPED)) {
+ if (flagflip) {
+ BM_ClearHFlag(l->f, BM_FLIPPED);
+ BM_ClearHFlag(l2->f, BM_FLIPPED);
+ }
+ }
+
+ if (i == maxi) {
+ BLI_array_growone(fstack);
+ maxi++;
+ }
+
+ fstack[i] = l2->f;
+ }
+ }
+ }
+ }
+
+ BLI_array_free(fstack);
+
+ /*check if we have faces yet to do. if so, recurse.*/
+ BMO_ITER(f, &siter, bm, op, "faces", BM_FACE) {
+ if (!BMO_TestFlag(bm, f, FACE_VIS)) {
+ bmesh_righthandfaces_exec(bm, op);
+ break;
+ }
+ }
+}
+
+void bmesh_vertexsmooth_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter siter;
+ BMIter iter;
+ BMVert *v;
+ BMEdge *e;
+ BLI_array_declare(cos);
+ float (*cos)[3] = NULL;
+ float *co, *co2, clipdist = BMO_Get_Float(op, "clipdist");
+ int i, j, clipx, clipy, clipz;
+
+ clipx = BMO_Get_Int(op, "mirror_clip_x");
+ clipy = BMO_Get_Int(op, "mirror_clip_y");
+ clipz = BMO_Get_Int(op, "mirror_clip_z");
+
+ i = 0;
+ BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+ BLI_array_growone(cos);
+ co = cos[i];
+
+ j = 0;
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
+ co2 = BM_OtherEdgeVert(e, v)->co;
+ add_v3_v3v3(co, co, co2);
+ j += 1;
+ }
+
+ if (!j) {
+ copy_v3_v3(co, v->co);
+ i++;
+ continue;
+ }
+
+ mul_v3_fl(co, 1.0f / (float)j);
+ mid_v3_v3v3(co, co, v->co);
+
+ if (clipx && fabsf(v->co[0]) < clipdist)
+ co[0] = 0.0f;
+ if (clipy && fabsf(v->co[1]) < clipdist)
+ co[1] = 0.0f;
+ if (clipz && fabsf(v->co[2]) < clipdist)
+ co[2] = 0.0f;
+
+ i++;
+ }
+
+ i = 0;
+ BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+ copy_v3_v3(v->co, cos[i]);
+ i++;
+ }
+
+ BLI_array_free(cos);
+}
+
+/*
+** compute the centroid of an ngon
+**
+** NOTE: This should probably go to bmesh_polygon.c and replace the function that compute its center
+** basing on bounding box
+*/
+static void ngon_center(float *v, BMesh *bm, BMFace *f)
+{
+ BMIter liter;
+ BMLoop *l;
+ v[0] = v[1] = v[2] = 0;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ add_v3_v3v3(v, v, l->v->co);
+ }
+
+ if( f->len ) mul_v3_fl(v, 1.0f / (float)f->len);
+}
+
+/*
+** compute the perimeter of an ngon
+**
+** NOTE: This should probably go to bmesh_polygon.c
+*/
+static float ngon_perimeter(BMesh *bm, BMFace *f)
+{
+ BMIter liter;
+ BMLoop *l;
+ int num_verts = 0;
+ float v[3], sv[3];
+ float perimeter = 0.0f;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ if( num_verts == 0 ) {
+ copy_v3_v3(v, l->v->co);
+ copy_v3_v3(sv, l->v->co);
+ } else {
+ perimeter += len_v3v3(v, l->v->co);
+ copy_v3_v3(v, l->v->co);
+ }
+ num_verts++;
+ }
+
+ perimeter += len_v3v3(v, sv);
+
+ return perimeter;
+}
+
+/*
+** compute the fake surface of an ngon
+** This is done by decomposing the ngon into triangles who share the centroid of the ngon
+** while this method is far from being exact, it should garantee an invariance.
+**
+** NOTE: This should probably go to bmesh_polygon.c
+*/
+static float ngon_fake_area(BMesh *bm, BMFace *f)
+{
+ BMIter liter;
+ BMLoop *l;
+ int num_verts = 0;
+ float v[3], sv[3], c[3];
+ float area = 0.0f;
+
+ ngon_center(c, bm, f);
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ if( num_verts == 0 ) {
+ copy_v3_v3(v, l->v->co);
+ copy_v3_v3(sv, l->v->co);
+ num_verts++;
+ } else {
+ area += area_tri_v3(v, c, l->v->co);
+ copy_v3_v3(v, l->v->co);
+ num_verts++;
+ }
+ }
+
+ area += area_tri_v3(v, c, sv);
+
+ return area;
+}
+
+/*
+** extra face data (computed data)
+*/
+typedef struct tmp_face_ext {
+ BMFace *f; /* the face */
+ float c[3]; /* center */
+ union {
+ float area; /* area */
+ float perim; /* perimeter */
+ float d; /* 4th component of plane (the first three being the normal) */
+ struct Image *t; /* image pointer */
+ };
+} tmp_face_ext;
+
+/*
+** Select similar faces, the choices are in the enum in source/blender/bmesh/bmesh_operators.h
+** We select either similar faces based on material, image, area, perimeter, normal, or the coplanar faces
+*/
+void bmesh_similarfaces_exec(BMesh *bm, BMOperator *op)
+{
+ BMIter fm_iter;
+ BMFace *fs, *fm;
+ BMOIter fs_iter;
+ int num_sels = 0, num_total = 0, i = 0, idx = 0;
+ float angle = 0.0f;
+ tmp_face_ext *f_ext = NULL;
+ int *indices = NULL;
+ float t_no[3]; /* temporary normal */
+ int type = BMO_Get_Int(op, "type");
+ float thresh = BMO_Get_Float(op, "thresh");
+
+ num_total = BM_Count_Element(bm, BM_FACE);
+
+ /*
+ ** The first thing to do is to iterate through all the the selected items and mark them since
+ ** they will be in the selection anyway.
+ ** This will increase performance, (especially when the number of originaly selected faces is high)
+ ** so the overall complexity will be less than $O(mn)$ where is the total number of selected faces,
+ ** and n is the total number of faces
+ */
+ BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) {
+ if (!BMO_TestFlag(bm, fs, FACE_MARK)) { /* is this really needed ? */
+ BMO_SetFlag(bm, fs, FACE_MARK);
+ num_sels++;
+ }
+ }
+
+ /* allocate memory for the selected faces indices and for all temporary faces */
+ indices = (int*)MEM_callocN(sizeof(int) * num_sels, "face indices util.c");
+ f_ext = (tmp_face_ext*)MEM_callocN(sizeof(tmp_face_ext) * num_total, "f_ext util.c");
+
+ /* loop through all the faces and fill the faces/indices structure */
+ BM_ITER(fm, &fm_iter, bm, BM_FACES_OF_MESH, NULL) {
+ f_ext[i].f = fm;
+ if (BMO_TestFlag(bm, fm, FACE_MARK)) {
+ indices[idx] = i;
+ idx++;
+ }
+ i++;
+ }
+
+ /*
+ ** Save us some computation burden: In case of perimeter/area/coplanar selection we compute
+ ** only once.
+ */
+ if( type == SIMFACE_PERIMETER || type == SIMFACE_AREA || type == SIMFACE_COPLANAR || type == SIMFACE_IMAGE ) {
+ for( i = 0; i < num_total; i++ ) {
+ switch( type ) {
+ case SIMFACE_PERIMETER:
+ /* set the perimeter */
+ f_ext[i].perim = ngon_perimeter(bm, f_ext[i].f);
+ break;
+
+ case SIMFACE_COPLANAR:
+ /* compute the center of the polygon */
+ ngon_center(f_ext[i].c, bm, f_ext[i].f);
+
+ /* normalize the polygon normal */
+ copy_v3_v3(t_no, f_ext[i].f->no);
+ normalize_v3(t_no);
+
+ /* compute the plane distance */
+ f_ext[i].d = dot_v3v3(t_no, f_ext[i].c);
+ break;
+
+ case SIMFACE_AREA:
+ f_ext[i].area = ngon_fake_area(bm, f_ext[i].f);
+ break;
+
+ case SIMFACE_IMAGE:
+ f_ext[i].t = NULL;
+ if( CustomData_has_layer(&(bm->pdata), CD_MTEXPOLY) ) {
+ MTexPoly *mtpoly = CustomData_bmesh_get(&bm->pdata, f_ext[i].f->head.data, CD_MTEXPOLY);
+ f_ext[i].t = mtpoly->tpage;
+ }
+ break;
+ }
+ }
+ }
+
+ /* now select the rest (if any) */
+ for( i = 0; i < num_total; i++ ) {
+ fm = f_ext[i].f;
+ if( !BMO_TestFlag(bm, fm, FACE_MARK) && !BM_TestHFlag(fm, BM_HIDDEN) ) {
+ int cont = 1;
+ for( idx = 0; idx < num_sels && cont == 1; idx++ ) {
+ fs = f_ext[indices[idx]].f;
+ switch( type ) {
+ case SIMFACE_MATERIAL:
+ if( fm->mat_nr == fs->mat_nr ) {
+ BMO_SetFlag(bm, fm, FACE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMFACE_IMAGE:
+ if( f_ext[i].t == f_ext[indices[idx]].t ) {
+ BMO_SetFlag(bm, fm, FACE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMFACE_NORMAL:
+ angle = RAD2DEGF(angle_v3v3(fs->no, fm->no)); /* if the angle between the normals -> 0 */
+ if( angle / 180.0f <= thresh ) {
+ BMO_SetFlag(bm, fm, FACE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMFACE_COPLANAR:
+ angle = RAD2DEGF(angle_v3v3(fs->no, fm->no)); /* angle -> 0 */
+ if( angle / 180.0f <= thresh ) { /* and dot product difference -> 0 */
+ if( fabsf(f_ext[i].d - f_ext[indices[idx]].d) <= thresh ) {
+ BMO_SetFlag(bm, fm, FACE_MARK);
+ cont = 0;
+ }
+ }
+ break;
+
+ case SIMFACE_AREA:
+ if( fabsf(f_ext[i].area - f_ext[indices[idx]].area) <= thresh ) {
+ BMO_SetFlag(bm, fm, FACE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMFACE_PERIMETER:
+ if( fabsf(f_ext[i].perim - f_ext[indices[idx]].perim) <= thresh ) {
+ BMO_SetFlag(bm, fm, FACE_MARK);
+ cont = 0;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ MEM_freeN(f_ext);
+ MEM_freeN(indices);
+
+ /* transfer all marked faces to the output slot */
+ BMO_Flag_To_Slot(bm, op, "faceout", FACE_MARK, BM_FACE);
+}
+
+/******************************************************************************
+** Similar Edges
+******************************************************************************/
+#define EDGE_MARK 1
+
+/*
+** compute the angle of an edge (i.e. the angle between two faces)
+*/
+static float edge_angle(BMesh *bm, BMEdge *e)
+{
+ BMIter fiter;
+ BMFace *f, *f_prev = NULL;
+
+ /* first edge faces, dont account for 3+ */
+
+ BM_ITER(f, &fiter, bm, BM_FACES_OF_EDGE, e) {
+ if(f_prev == NULL) {
+ f_prev= f;
+ }
+ else {
+ return angle_v3v3(f_prev->no, f->no);
+ }
+ }
+
+ return 0.0f;
+}
+/*
+** extra edge information
+*/
+typedef struct tmp_edge_ext {
+ BMEdge *e;
+ union {
+ float dir[3];
+ float angle; /* angle between the faces*/
+ };
+
+ union {
+ float length; /* edge length */
+ int faces; /* faces count */
+ };
+} tmp_edge_ext;
+
+/*
+** select similar edges: the choices are in the enum in source/blender/bmesh/bmesh_operators.h
+** choices are length, direction, face, ...
+*/
+void bmesh_similaredges_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter es_iter; /* selected edges iterator */
+ BMIter e_iter; /* mesh edges iterator */
+ BMEdge *es; /* selected edge */
+ BMEdge *e; /* mesh edge */
+ int idx = 0, i = 0 /* , f = 0 */;
+ int *indices = NULL;
+ tmp_edge_ext *e_ext = NULL;
+ // float *angles = NULL;
+ float angle;
+
+ int num_sels = 0, num_total = 0;
+ int type = BMO_Get_Int(op, "type");
+ float thresh = BMO_Get_Float(op, "thresh");
+
+ num_total = BM_Count_Element(bm, BM_EDGE);
+
+ /* iterate through all selected edges and mark them */
+ BMO_ITER(es, &es_iter, bm, op, "edges", BM_EDGE) {
+ BMO_SetFlag(bm, es, EDGE_MARK);
+ num_sels++;
+ }
+
+ /* allocate memory for the selected edges indices and for all temporary edges */
+ indices = (int*)MEM_callocN(sizeof(int) * num_sels, "indices util.c");
+ e_ext = (tmp_edge_ext*)MEM_callocN(sizeof(tmp_edge_ext) * num_total, "e_ext util.c");
+
+ /* loop through all the edges and fill the edges/indices structure */
+ BM_ITER(e, &e_iter, bm, BM_EDGES_OF_MESH, NULL) {
+ e_ext[i].e = e;
+ if (BMO_TestFlag(bm, e, EDGE_MARK)) {
+ indices[idx] = i;
+ idx++;
+ }
+ i++;
+ }
+
+ /* save us some computation time by doing heavy computation once */
+ if( type == SIMEDGE_LENGTH || type == SIMEDGE_FACE || type == SIMEDGE_DIR ||
+ type == SIMEDGE_FACE_ANGLE ) {
+ for( i = 0; i < num_total; i++ ) {
+ switch( type ) {
+ case SIMEDGE_LENGTH: /* compute the length of the edge */
+ e_ext[i].length = len_v3v3(e_ext[i].e->v1->co, e_ext[i].e->v2->co);
+ break;
+
+ case SIMEDGE_DIR: /* compute the direction */
+ sub_v3_v3v3(e_ext[i].dir, e_ext[i].e->v1->co, e_ext[i].e->v2->co);
+ break;
+
+ case SIMEDGE_FACE: /* count the faces around the edge */
+ e_ext[i].faces = BM_Edge_FaceCount(e_ext[i].e);
+ break;
+
+ case SIMEDGE_FACE_ANGLE:
+ e_ext[i].faces = BM_Edge_FaceCount(e_ext[i].e);
+ if( e_ext[i].faces == 2 )
+ e_ext[i].angle = edge_angle(bm, e_ext[i].e);
+ break;
+ }
+ }
+ }
+
+ /* select the edges if any */
+ for( i = 0; i < num_total; i++ ) {
+ e = e_ext[i].e;
+ if( !BMO_TestFlag(bm, e, EDGE_MARK) && !BM_TestHFlag(e, BM_HIDDEN) ) {
+ int cont = 1;
+ for( idx = 0; idx < num_sels && cont == 1; idx++ ) {
+ es = e_ext[indices[idx]].e;
+ switch( type ) {
+ case SIMEDGE_LENGTH:
+ if( fabsf(e_ext[i].length - e_ext[indices[idx]].length) <= thresh ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMEDGE_DIR:
+ /* compute the angle between the two edges */
+ angle = RAD2DEGF(angle_v3v3(e_ext[i].dir, e_ext[indices[idx]].dir));
+
+ if( angle > 90.0f ) /* use the smallest angle between the edges */
+ angle = fabsf(angle - 180.0f);
+
+ if( angle / 90.0f <= thresh ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMEDGE_FACE:
+ if( e_ext[i].faces == e_ext[indices[idx]].faces ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMEDGE_FACE_ANGLE:
+ if( e_ext[i].faces == 2 ) {
+ if( e_ext[indices[idx]].faces == 2 ) {
+ if( fabsf(e_ext[i].angle - e_ext[indices[idx]].angle) <= thresh ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ }
+ } else cont = 0;
+ break;
+
+ case SIMEDGE_CREASE:
+ if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
+ float *c1, *c2;
+
+ c1 = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE);
+ c2 = CustomData_bmesh_get(&bm->edata, es->head.data, CD_CREASE);
+
+ if( c1&&c2 && fabsf(*c1 - *c2) <= thresh ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ }
+ break;
+
+ case SIMEDGE_SEAM:
+ if( BM_TestHFlag(e, BM_SEAM) == BM_TestHFlag(es, BM_SEAM) ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMEDGE_SHARP:
+ if( BM_TestHFlag(e, BM_SHARP) == BM_TestHFlag(es, BM_SHARP) ) {
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ cont = 0;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ MEM_freeN(e_ext);
+ MEM_freeN(indices);
+
+ /* transfer all marked edges to the output slot */
+ BMO_Flag_To_Slot(bm, op, "edgeout", EDGE_MARK, BM_EDGE);
+}
+
+/******************************************************************************
+** Similar Vertices
+******************************************************************************/
+#define VERT_MARK 1
+
+typedef struct tmp_vert_ext {
+ BMVert *v;
+ union {
+ int num_faces; /* adjacent faces */
+ MDeformVert *dvert; /* deform vertex */
+ };
+} tmp_vert_ext;
+
+/*
+** select similar vertices: the choices are in the enum in source/blender/bmesh/bmesh_operators.h
+** choices are normal, face, vertex group...
+*/
+void bmesh_similarverts_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter vs_iter; /* selected verts iterator */
+ BMIter v_iter; /* mesh verts iterator */
+ BMVert *vs; /* selected vertex */
+ BMVert *v; /* mesh vertex */
+ tmp_vert_ext *v_ext = NULL;
+ int *indices = NULL;
+ int num_total = 0, num_sels = 0, i = 0, idx = 0;
+ int type = BMO_Get_Int(op, "type");
+ float thresh = BMO_Get_Float(op, "thresh");
+
+ num_total = BM_Count_Element(bm, BM_VERT);
+
+ /* iterate through all selected edges and mark them */
+ BMO_ITER(vs, &vs_iter, bm, op, "verts", BM_VERT) {
+ BMO_SetFlag(bm, vs, VERT_MARK);
+ num_sels++;
+ }
+
+ /* allocate memory for the selected vertices indices and for all temporary vertices */
+ indices = (int*)MEM_mallocN(sizeof(int) * num_sels, "vertex indices");
+ v_ext = (tmp_vert_ext*)MEM_mallocN(sizeof(tmp_vert_ext) * num_total, "vertex extra");
+
+ /* loop through all the vertices and fill the vertices/indices structure */
+ BM_ITER(v, &v_iter, bm, BM_VERTS_OF_MESH, NULL) {
+ v_ext[i].v = v;
+ if (BMO_TestFlag(bm, v, VERT_MARK)) {
+ indices[idx] = i;
+ idx++;
+ }
+
+ switch( type ) {
+ case SIMVERT_FACE:
+ /* calling BM_Vert_FaceCount every time is time consumming, so call it only once per vertex */
+ v_ext[i].num_faces = BM_Vert_FaceCount(v);
+ break;
+
+ case SIMVERT_VGROUP:
+ if( CustomData_has_layer(&(bm->vdata),CD_MDEFORMVERT) ) {
+ v_ext[i].dvert = CustomData_bmesh_get(&bm->vdata, v_ext[i].v->head.data, CD_MDEFORMVERT);
+ } else v_ext[i].dvert = NULL;
+ break;
+ }
+
+ i++;
+ }
+
+ /* select the vertices if any */
+ for( i = 0; i < num_total; i++ ) {
+ v = v_ext[i].v;
+ if( !BMO_TestFlag(bm, v, VERT_MARK) && !BM_TestHFlag(v, BM_HIDDEN) ) {
+ int cont = 1;
+ for( idx = 0; idx < num_sels && cont == 1; idx++ ) {
+ vs = v_ext[indices[idx]].v;
+ switch( type ) {
+ case SIMVERT_NORMAL:
+ /* compare the angle between the normals */
+ if( RAD2DEGF(angle_v3v3(v->no, vs->no)) / 180.0f <= thresh ) {
+ BMO_SetFlag(bm, v, VERT_MARK);
+ cont = 0;
+ }
+ break;
+ case SIMVERT_FACE:
+ /* number of adjacent faces */
+ if( v_ext[i].num_faces == v_ext[indices[idx]].num_faces ) {
+ BMO_SetFlag(bm, v, VERT_MARK);
+ cont = 0;
+ }
+ break;
+
+ case SIMVERT_VGROUP:
+ if( v_ext[i].dvert != NULL && v_ext[indices[idx]].dvert != NULL ) {
+ int v1, v2;
+ for( v1 = 0; v1 < v_ext[i].dvert->totweight && cont == 1; v1++ ) {
+ for( v2 = 0; v2 < v_ext[indices[idx]].dvert->totweight; v2++ ) {
+ if( v_ext[i].dvert->dw[v1].def_nr == v_ext[indices[idx]].dvert->dw[v2].def_nr ) {
+ BMO_SetFlag(bm, v, VERT_MARK);
+ cont = 0;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ MEM_freeN(indices);
+ MEM_freeN(v_ext);
+
+ BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT);
+}
+
+/******************************************************************************
+** Cycle UVs for a face
+******************************************************************************/
+
+void bmesh_rotateuvs_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter fs_iter; /* selected faces iterator */
+ BMFace *fs; /* current face */
+ BMIter l_iter; /* iteration loop */
+ // int n;
+
+ int dir = BMO_Get_Int(op, "dir");
+
+ BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) {
+ if( CustomData_has_layer(&(bm->ldata), CD_MLOOPUV) ) {
+ if( dir == DIRECTION_CW ) { /* same loops direction */
+ BMLoop *lf; /* current face loops */
+ MLoopUV *f_luv; /* first face loop uv */
+ float p_uv[2]; /* previous uvs */
+ float t_uv[2]; /* tmp uvs */
+
+ int n = 0;
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ /* current loop uv is the previous loop uv */
+ MLoopUV *luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPUV);
+ if( n == 0 ) {
+ f_luv = luv;
+ p_uv[0] = luv->uv[0];
+ p_uv[1] = luv->uv[1];
+ } else {
+ t_uv[0] = luv->uv[0];
+ t_uv[1] = luv->uv[1];
+ luv->uv[0] = p_uv[0];
+ luv->uv[1] = p_uv[1];
+ p_uv[0] = t_uv[0];
+ p_uv[1] = t_uv[1];
+ }
+ n++;
+ }
+
+ f_luv->uv[0] = p_uv[0];
+ f_luv->uv[1] = p_uv[1];
+ } else if( dir == DIRECTION_CCW ) { /* counter loop direction */
+ BMLoop *lf; /* current face loops */
+ MLoopUV *p_luv; /*previous loop uv */
+ MLoopUV *luv;
+ float t_uv[2]; /* current uvs */
+
+ int n = 0;
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ /* previous loop uv is the current loop uv */
+ luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPUV);
+ if( n == 0 ) {
+ p_luv = luv;
+ t_uv[0] = luv->uv[0];
+ t_uv[1] = luv->uv[1];
+ } else {
+ p_luv->uv[0] = luv->uv[0];
+ p_luv->uv[1] = luv->uv[1];
+ p_luv = luv;
+ }
+ n++;
+ }
+
+ luv->uv[0] = t_uv[0];
+ luv->uv[1] = t_uv[1];
+ }
+ }
+ }
+
+}
+
+/******************************************************************************
+** Reverse UVs for a face
+******************************************************************************/
+
+void bmesh_reverseuvs_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter fs_iter; /* selected faces iterator */
+ BMFace *fs; /* current face */
+ BMIter l_iter; /* iteration loop */
+ BLI_array_declare(uvs);
+ float (*uvs)[2] = NULL;
+
+ BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) {
+ if( CustomData_has_layer(&(bm->ldata), CD_MLOOPUV) ) {
+ BMLoop *lf; /* current face loops */
+ int i = 0;
+
+ BLI_array_empty(uvs);
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ MLoopUV *luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPUV);
+
+ /* current loop uv is the previous loop uv */
+ BLI_array_growone(uvs);
+ uvs[i][0] = luv->uv[0];
+ uvs[i][1] = luv->uv[1];
+ i++;
+ }
+
+ /* now that we have the uvs in the array, reverse! */
+ i = 0;
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ /* current loop uv is the previous loop uv */
+ MLoopUV *luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPUV);
+ luv->uv[0] = uvs[(fs->len - i - 1)][0];
+ luv->uv[1] = uvs[(fs->len - i - 1)][1];
+ i++;
+ }
+ }
+ }
+
+ BLI_array_free(uvs);
+}
+
+/******************************************************************************
+** Cycle colors for a face
+******************************************************************************/
+
+void bmesh_rotatecolors_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter fs_iter; /* selected faces iterator */
+ BMFace *fs; /* current face */
+ BMIter l_iter; /* iteration loop */
+ // int n;
+
+ int dir = BMO_Get_Int(op, "dir");
+
+ BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) {
+ if( CustomData_has_layer(&(bm->ldata), CD_MLOOPCOL) ) {
+ if( dir == DIRECTION_CW ) { /* same loops direction */
+ BMLoop *lf; /* current face loops */
+ MLoopCol *f_lcol; /* first face loop color */
+ MLoopCol p_col; /* previous color */
+ MLoopCol t_col; /* tmp color */
+
+ int n = 0;
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ /* current loop color is the previous loop color */
+ MLoopCol *luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPCOL);
+ if( n == 0 ) {
+ f_lcol = luv;
+ p_col = *luv;
+ } else {
+ t_col = *luv;
+ *luv = p_col;
+ p_col = t_col;
+ }
+ n++;
+ }
+
+ *f_lcol = p_col;
+ } else if( dir == DIRECTION_CCW ) { /* counter loop direction */
+ BMLoop *lf; /* current face loops */
+ MLoopCol *p_lcol; /*previous loop color */
+ MLoopCol *lcol;
+ MLoopCol t_col; /* current color */
+
+ int n = 0;
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ /* previous loop color is the current loop color */
+ lcol = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPCOL);
+ if( n == 0 ) {
+ p_lcol = lcol;
+ t_col = *lcol;
+ } else {
+ *p_lcol = *lcol;
+ p_lcol = lcol;
+ }
+ n++;
+ }
+
+ *lcol = t_col;
+ }
+ }
+ }
+}
+
+/******************************************************************************
+** Reverse colors for a face
+******************************************************************************/
+
+void bmesh_reversecolors_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter fs_iter; /* selected faces iterator */
+ BMFace *fs; /* current face */
+ BMIter l_iter; /* iteration loop */
+ BLI_array_declare(cols);
+ MLoopCol *cols = NULL;
+
+ BMO_ITER(fs, &fs_iter, bm, op, "faces", BM_FACE) {
+ if( CustomData_has_layer(&(bm->ldata), CD_MLOOPCOL) ) {
+ BMLoop *lf; /* current face loops */
+ int i = 0;
+
+ BLI_array_empty(cols);
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ MLoopCol *lcol = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPCOL);
+
+ /* current loop uv is the previous loop color */
+ BLI_array_growone(cols);
+ cols[i] = *lcol;
+ i++;
+ }
+
+ /* now that we have the uvs in the array, reverse! */
+ i = 0;
+ BM_ITER(lf, &l_iter, bm, BM_LOOPS_OF_FACE, fs) {
+ /* current loop uv is the previous loop color */
+ MLoopCol *lcol = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPCOL);
+ *lcol = cols[(fs->len - i - 1)];
+ i++;
+ }
+ }
+ }
+
+ BLI_array_free(cols);
+}
+
+
+/******************************************************************************
+** shortest vertex path select
+******************************************************************************/
+
+typedef struct element_node {
+ BMVert *v; /* vertex */
+ BMVert *parent; /* node parent id */
+ float weight; /* node weight */
+ HeapNode *hn; /* heap node */
+} element_node;
+
+void bmesh_vertexshortestpath_exec(BMesh *bm, BMOperator *op)
+{
+ BMOIter vs_iter /* , vs2_iter */; /* selected verts iterator */
+ BMIter v_iter; /* mesh verts iterator */
+ BMVert *vs, *sv, *ev; /* starting vertex, ending vertex */
+ BMVert *v; /* mesh vertex */
+ Heap *h = NULL;
+
+ element_node *vert_list = NULL;
+
+ int num_total = 0 /*, num_sels = 0 */, i = 0;
+ int type = BMO_Get_Int(op, "type");
+
+ BMO_ITER(vs, &vs_iter, bm, op, "startv", BM_VERT)
+ sv = vs;
+ BMO_ITER(vs, &vs_iter, bm, op, "endv", BM_VERT)
+ ev = vs;
+
+ num_total = BM_Count_Element(bm, BM_VERT);
+
+ /* allocate memory for the nodes */
+ vert_list = (element_node*)MEM_mallocN(sizeof(element_node) * num_total, "vertex nodes");
+
+ /* iterate through all the mesh vertices */
+ /* loop through all the vertices and fill the vertices/indices structure */
+ i = 0;
+ BM_ITER(v, &v_iter, bm, BM_VERTS_OF_MESH, NULL) {
+ vert_list[i].v = v;
+ vert_list[i].parent = NULL;
+ vert_list[i].weight = FLT_MAX;
+ BM_SetIndex(v, i);
+ i++;
+ }
+
+ /*
+ ** we now have everything we need, start Dijkstra path finding algorithm
+ */
+
+ /* set the distance/weight of the start vertex to 0 */
+ vert_list[BM_GetIndex(sv)].weight = 0.0f;
+
+ h = BLI_heap_new();
+
+ for( i = 0; i < num_total; i++ )
+ vert_list[i].hn = BLI_heap_insert(h, vert_list[i].weight, vert_list[i].v);
+
+ while( !BLI_heap_empty(h) ) {
+ BMEdge *e;
+ BMIter e_i;
+ float v_weight;
+
+ /* take the vertex with the lowest weight out of the heap */
+ BMVert *v = (BMVert*)BLI_heap_popmin(h);
+
+ if( vert_list[BM_GetIndex(v)].weight == FLT_MAX ) /* this means that there is no path */
+ break;
+
+ v_weight = vert_list[BM_GetIndex(v)].weight;
+
+ BM_ITER(e, &e_i, bm, BM_EDGES_OF_VERT, v) {
+ BMVert *u;
+ float e_weight = v_weight;
+
+ if( type == VPATH_SELECT_EDGE_LENGTH )
+ e_weight += len_v3v3(e->v1->co, e->v2->co);
+ else e_weight += 1.0f;
+
+ u = ( e->v1 == v ) ? e->v2 : e->v1;
+
+ if( e_weight < vert_list[BM_GetIndex(u)].weight ) { /* is this path shorter ? */
+ /* add it if so */
+ vert_list[BM_GetIndex(u)].parent = v;
+ vert_list[BM_GetIndex(u)].weight = e_weight;
+
+ /* we should do a heap update node function!!! :-/ */
+ BLI_heap_remove(h, vert_list[BM_GetIndex(u)].hn);
+ BLI_heap_insert(h, e_weight, u);
+ }
+ }
+ }
+
+ /* now we trace the path (if it exists) */
+ v = ev;
+
+ while( vert_list[BM_GetIndex(v)].parent != NULL ) {
+ BMO_SetFlag(bm, v, VERT_MARK);
+ v = vert_list[BM_GetIndex(v)].parent;
+ }
+
+ BLI_heap_free(h, NULL);
+ MEM_freeN(vert_list);
+
+ BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT);
+}
diff --git a/source/blender/bmesh/tools/BME_bevel.c b/source/blender/bmesh/tools/BME_bevel.c
new file mode 100644
index 00000000000..05c6fcd766d
--- /dev/null
+++ b/source/blender/bmesh/tools/BME_bevel.c
@@ -0,0 +1,918 @@
+/**
+ * BME_tools.c jan 2007
+ *
+ * Functions for changing the topology of a mesh.
+ *
+ * $Id: BME_eulers.c,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle and Levi Schooley.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_bmesh.h"
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+
+#include "MTC_matrixops.h"
+#include "MTC_vectorops.h"
+
+#include "blendef.h"
+
+/* ------- Bevel code starts here -------- */
+
+BME_TransData_Head *BME_init_transdata(int bufsize) {
+ BME_TransData_Head *td;
+
+ td = MEM_callocN(sizeof(BME_TransData_Head), "BM transdata header");
+ td->gh = BLI_ghash_new(BLI_ghashutil_ptrhash,BLI_ghashutil_ptrcmp);
+ td->ma = BLI_memarena_new(bufsize);
+ BLI_memarena_use_calloc(td->ma);
+
+ return td;
+}
+
+void BME_free_transdata(BME_TransData_Head *td) {
+ BLI_ghash_free(td->gh,NULL,NULL);
+ BLI_memarena_free(td->ma);
+ MEM_freeN(td);
+}
+
+BME_TransData *BME_assign_transdata(BME_TransData_Head *td, BMesh *bm, BMVert *v,
+ float *co, float *org, float *vec, float *loc,
+ float factor, float weight, float maxfactor, float *max) {
+ BME_TransData *vtd;
+ int is_new = 0;
+
+ if (v == NULL) return NULL;
+
+ if ((vtd = BLI_ghash_lookup(td->gh, v)) == NULL && bm != NULL) {
+ vtd = BLI_memarena_alloc(td->ma, sizeof(*vtd));
+ BLI_ghash_insert(td->gh, v, vtd);
+ td->len++;
+ is_new = 1;
+ }
+
+ vtd->bm = bm;
+ vtd->v = v;
+ if (co != NULL) VECCOPY(vtd->co,co);
+ if (org == NULL && is_new) { VECCOPY(vtd->org,v->co); } /* default */
+ else if (org != NULL) VECCOPY(vtd->org,org);
+ if (vec != NULL) {
+ VECCOPY(vtd->vec,vec);
+ normalize_v3(vtd->vec);
+ }
+ vtd->loc = loc;
+
+ vtd->factor = factor;
+ vtd->weight = weight;
+ vtd->maxfactor = maxfactor;
+ vtd->max = max;
+
+ return vtd;
+}
+
+BME_TransData *BME_get_transdata(BME_TransData_Head *td, BMVert *v) {
+ BME_TransData *vtd;
+ vtd = BLI_ghash_lookup(td->gh, v);
+ return vtd;
+}
+
+/* a hack (?) to use the transdata memarena to allocate floats for use with the max limits */
+float *BME_new_transdata_float(BME_TransData_Head *td) {
+ return BLI_memarena_alloc(td->ma, sizeof(float));
+}
+
+static int BME_bevel_is_split_vert(BMLoop *l) {
+ /* look for verts that have already been added to the edge when
+ * beveling other polys; this can be determined by testing the
+ * vert and the edges around it for originality
+ */
+ if ((l->v->tflag1 & BME_BEVEL_ORIG)==0
+ && (l->e->tflag1 & BME_BEVEL_ORIG)
+ && (l->prev->e->tflag1 & BME_BEVEL_ORIG))
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/* get a vector, vec, that points from v1->co to wherever makes sense to
+ * the bevel operation as a whole based on the relationship between v1 and v2
+ * (won't necessarily be a vec from v1->co to v2->co, though it probably will be);
+ * the return value is -1 for failure, 0 if we used vert co's, and 1 if we used transform origins */
+static int BME_bevel_get_vec(float *vec, BMVert *v1, BMVert *v2, BME_TransData_Head *td) {
+ BME_TransData *vtd1, *vtd2;
+
+ vtd1 = BME_get_transdata(td,v1);
+ vtd2 = BME_get_transdata(td,v2);
+ if (!vtd1 || !vtd2) {
+ //printf("BME_bevel_get_vec() got called without proper BME_TransData\n");
+ return -1;
+ }
+
+ /* compare the transform origins to see if we can use the vert co's;
+ * if they belong to different origins, then we will use the origins to determine
+ * the vector */
+ if (compare_v3v3(vtd1->org,vtd2->org,0.000001f)) {
+ VECSUB(vec,v2->co,v1->co);
+ if (len_v3(vec) < 0.000001f) {
+ mul_v3_fl(vec,0);
+ }
+ return 0;
+ }
+ else {
+ VECSUB(vec,vtd2->org,vtd1->org);
+ if (len_v3(vec) < 0.000001f) {
+ mul_v3_fl(vec,0);
+ }
+ return 1;
+ }
+}
+
+/* "Projects" a vector perpendicular to vec2 against vec1, such that
+ * the projected vec1 + vec2 has a min distance of 1 from the "edge" defined by vec2.
+ * note: the direction, is_forward, is used in conjunction with up_vec to determine
+ * whether this is a convex or concave corner. If it is a concave corner, it will
+ * be projected "backwards." If vec1 is before vec2, is_forward should be 0 (we are projecting backwards).
+ * vec1 is the vector to project onto (expected to be normalized)
+ * vec2 is the direction of projection (pointing away from vec1)
+ * up_vec is used for orientation (expected to be normalized)
+ * returns the length of the projected vector that lies along vec1 */
+static float BME_bevel_project_vec(float *vec1, float *vec2, float *up_vec, int is_forward, BME_TransData_Head *td) {
+ float factor, vec3[3], tmp[3],c1,c2;
+
+ cross_v3_v3v3(tmp,vec1,vec2);
+ normalize_v3(tmp);
+ factor = dot_v3v3(up_vec,tmp);
+ if ((factor > 0 && is_forward) || (factor < 0 && !is_forward)) {
+ cross_v3_v3v3(vec3,vec2,tmp); /* hmm, maybe up_vec should be used instead of tmp */
+ }
+ else {
+ cross_v3_v3v3(vec3,tmp,vec2); /* hmm, maybe up_vec should be used instead of tmp */
+ }
+ normalize_v3(vec3);
+ c1 = dot_v3v3(vec3,vec1);
+ c2 = dot_v3v3(vec1,vec1);
+ if (fabs(c1) < 0.000001f || fabs(c2) < 0.000001f) {
+ factor = 0.0f;
+ }
+ else {
+ factor = c2/c1;
+ }
+
+ return factor;
+}
+
+/* BME_bevel_split_edge() is the main math work-house; its responsibilities are:
+ * using the vert and the loop passed, get or make the split vert, set its coordinates
+ * and transform properties, and set the max limits.
+ * Finally, return the split vert. */
+static BMVert *BME_bevel_split_edge(BMesh *bm, BMVert *v, BMVert *v1, BMLoop *l, float *up_vec, float value, BME_TransData_Head *td) {
+ BME_TransData *vtd, *vtd1, *vtd2;
+ BMVert *sv, *v2, *v3, *ov;
+ BMLoop *lv1, *lv2;
+ BMEdge *ne, *e1, *e2;
+ float maxfactor, scale, len, dis, vec1[3], vec2[3], t_up_vec[3];
+ int is_edge, forward, is_split_vert;
+
+ if (l == NULL) {
+ /* what you call operator overloading in C :)
+ * I wanted to use the same function for both wire edges and poly loops
+ * so... here we walk around edges to find the needed verts */
+ forward = 1;
+ is_split_vert = 0;
+ if (v->e == NULL) {
+ //printf("We can't split a loose vert's edge!\n");
+ return NULL;
+ }
+ e1 = v->e; /* we just use the first two edges */
+ e2 = bmesh_disk_nextedge(v->e, v);
+ if (e1 == e2) {
+ //printf("You need at least two edges to use BME_bevel_split_edge()\n");
+ return NULL;
+ }
+ v2 = BM_OtherEdgeVert(e1, v);
+ v3 = BM_OtherEdgeVert(e2, v);
+ if (v1 != v2 && v1 != v3) {
+ //printf("Error: more than 2 edges in v's disk cycle, or v1 does not share an edge with v\n");
+ return NULL;
+ }
+ if (v1 == v2) {
+ v2 = v3;
+ }
+ else {
+ e1 = e2;
+ }
+ ov = BM_OtherEdgeVert(e1,v);
+ sv = BM_Split_Edge(bm,v,e1,&ne,0);
+ //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/
+ //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25);
+ //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25);
+ BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */
+ sv->tflag1 |= BME_BEVEL_BEVEL;
+ ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */
+ BME_bevel_get_vec(vec1,v1,v,td);
+ BME_bevel_get_vec(vec2,v2,v,td);
+ cross_v3_v3v3(t_up_vec,vec1,vec2);
+ normalize_v3(t_up_vec);
+ up_vec = t_up_vec;
+ }
+ else {
+ /* establish loop direction */
+ if (l->v == v) {
+ forward = 1;
+ lv1 = l->next;
+ lv2 = l->prev;
+ v1 = l->next->v;
+ v2 = l->prev->v;
+ }
+ else if (l->next->v == v) {
+ forward = 0;
+ lv1 = l;
+ lv2 = l->next->next;
+ v1 = l->v;
+ v2 = l->next->next->v;
+ }
+ else {
+ //printf("ERROR: BME_bevel_split_edge() - v must be adjacent to l\n");
+ return NULL;
+ }
+
+ if (BME_bevel_is_split_vert(lv1)) {
+ is_split_vert = 1;
+ sv = v1;
+ if (forward) v1 = l->next->next->v;
+ else v1 = l->prev->v;
+ }
+ else {
+ is_split_vert = 0;
+ ov = BM_OtherEdgeVert(l->e,v);
+ sv = BM_Split_Edge(bm,v,l->e,&ne,0);
+ //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/
+ //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25);
+ //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25);
+ BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */
+ sv->tflag1 |= BME_BEVEL_BEVEL;
+ ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */
+ }
+
+ if (BME_bevel_is_split_vert(lv2)) {
+ if (forward) v2 = lv2->prev->v;
+ else v2 = lv2->next->v;
+ }
+ }
+
+ is_edge = BME_bevel_get_vec(vec1,v,v1,td); /* get the vector we will be projecting onto */
+ BME_bevel_get_vec(vec2,v,v2,td); /* get the vector we will be projecting parallel to */
+ len = len_v3(vec1);
+ normalize_v3(vec1);
+
+ vtd = BME_get_transdata(td, sv);
+ vtd1 = BME_get_transdata(td, v);
+ vtd2 = BME_get_transdata(td,v1);
+
+ if (vtd1->loc == NULL) {
+ /* this is a vert with data only for calculating initial weights */
+ if (vtd1->weight < 0) {
+ vtd1->weight = 0;
+ }
+ scale = vtd1->weight/vtd1->factor;
+ if (!vtd1->max) {
+ vtd1->max = BME_new_transdata_float(td);
+ *vtd1->max = -1;
+ }
+ }
+ else {
+ scale = vtd1->weight;
+ }
+ vtd->max = vtd1->max;
+
+ if (is_edge && vtd1->loc != NULL) {
+ maxfactor = vtd1->maxfactor;
+ }
+ else {
+ maxfactor = scale*BME_bevel_project_vec(vec1,vec2,up_vec,forward,td);
+ if (vtd->maxfactor > 0 && vtd->maxfactor < maxfactor) {
+ maxfactor = vtd->maxfactor;
+ }
+ }
+
+ dis = (v1->tflag1 & BME_BEVEL_ORIG)? len/3 : len/2;
+ if (is_edge || dis > maxfactor*value) {
+ dis = maxfactor*value;
+ }
+ VECADDFAC(sv->co,v->co,vec1,dis);
+ VECSUB(vec1,sv->co,vtd1->org);
+ dis = len_v3(vec1);
+ normalize_v3(vec1);
+ BME_assign_transdata(td, bm, sv, vtd1->org, vtd1->org, vec1, sv->co, dis, scale, maxfactor, vtd->max);
+
+ return sv;
+}
+
+static float BME_bevel_set_max(BMVert *v1, BMVert *v2, float value, BME_TransData_Head *td) {
+ BME_TransData *vtd1, *vtd2;
+ float max, fac1, fac2, vec1[3], vec2[3], vec3[3];
+
+ BME_bevel_get_vec(vec1,v1,v2,td);
+ vtd1 = BME_get_transdata(td,v1);
+ vtd2 = BME_get_transdata(td,v2);
+
+ if (vtd1->loc == NULL) {
+ fac1 = 0;
+ }
+ else {
+ VECCOPY(vec2,vtd1->vec);
+ mul_v3_fl(vec2,vtd1->factor);
+ if (dot_v3v3(vec1, vec1)) {
+ project_v3_v3v3(vec2,vec2,vec1);
+ fac1 = len_v3(vec2)/value;
+ }
+ else {
+ fac1 = 0;
+ }
+ }
+
+ if (vtd2->loc == NULL) {
+ fac2 = 0;
+ }
+ else {
+ VECCOPY(vec3,vtd2->vec);
+ mul_v3_fl(vec3,vtd2->factor);
+ if (dot_v3v3(vec1, vec1)) {
+ project_v3_v3v3(vec2,vec3,vec1);
+ fac2 = len_v3(vec2)/value;
+ }
+ else {
+ fac2 = 0;
+ }
+ }
+
+ if (fac1 || fac2) {
+ max = len_v3(vec1)/(fac1 + fac2);
+ if (vtd1->max && (*vtd1->max < 0 || max < *vtd1->max)) {
+ *vtd1->max = max;
+ }
+ if (vtd2->max && (*vtd2->max < 0 || max < *vtd2->max)) {
+ *vtd2->max = max;
+ }
+ }
+ else {
+ max = -1;
+ }
+
+ return max;
+}
+
+static BMVert *BME_bevel_wire(BMesh *bm, BMVert *v, float value, int res, int options, BME_TransData_Head *td) {
+ BMVert *ov1, *ov2, *v1, *v2;
+
+ ov1 = BM_OtherEdgeVert(v->e, v);
+ ov2 = BM_OtherEdgeVert(bmesh_disk_nextedge(v->e, v), v);
+
+ /* split the edges */
+ v1 = BME_bevel_split_edge(bm,v,ov1,NULL,NULL,value,td);
+ v1->tflag1 |= BME_BEVEL_NONMAN;
+ v2 = BME_bevel_split_edge(bm,v,ov2,NULL,NULL,value,td);
+ v2->tflag1 |= BME_BEVEL_NONMAN;
+
+ if (value > 0.5) {
+ BME_bevel_set_max(v1,ov1,value,td);
+ BME_bevel_set_max(v2,ov2,value,td);
+ }
+
+ /* remove the original vert */
+ if (res) {
+ bmesh_jekv;
+
+ //void BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, int calcnorm){
+ //hrm, why is there a fac here? it just removes a vert
+ BM_Collapse_Vert(bm, v->e, v, 1.0, 0);
+ //bmesh_jekv(bm,v->e,v);
+ }
+
+ return v1;
+}
+
+static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int options, float *up_vec, BME_TransData_Head *td) {
+ BMVert *v1, *v2, *kv;
+ BMLoop *kl=NULL, *nl;
+ BMEdge *e;
+ BMFace *f;
+
+ f = l->f;
+ e = l->e;
+
+ if ((l->e->tflag1 & BME_BEVEL_BEVEL) == 0
+ && ((l->v->tflag1 & BME_BEVEL_BEVEL) || (l->next->v->tflag1 & BME_BEVEL_BEVEL)))
+ { /* sanity check */
+ return l;
+ }
+
+ /* checks and operations for prev edge */
+ /* first, check to see if this edge was inset previously */
+ if ((l->prev->e->tflag1 & BME_BEVEL_ORIG) == 0
+ && (l->v->tflag1 & BME_BEVEL_NONMAN) == 0) {
+ kl = l->prev->radial_next;
+ if (kl->v == l->v) kl = kl->prev;
+ else kl = kl->next;
+ kv = l->v;
+ }
+ else {
+ kv = NULL;
+ }
+ /* get/make the first vert to be used in SFME */
+ if (l->v->tflag1 & BME_BEVEL_NONMAN){
+ v1 = l->v;
+ }
+ else { /* we'll need to split the previous edge */
+ v1 = BME_bevel_split_edge(bm,l->v,NULL,l->prev,up_vec,value,td);
+ }
+ /* if we need to clean up geometry... */
+ if (kv) {
+ l = l->next;
+ if (kl->v == kv) {
+ BM_Split_Face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e);
+ bmesh_jfke(bm, kl->prev->radial_next->f,kl->f,kl->prev->e);
+ BM_Collapse_Vert(bm, kl->e, kv, 1.0);
+ //BME_JEKV(bm,kl->e,kv);
+
+ }
+ else {
+ BM_Split_Face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e);
+ bmesh_jfke(bm, kl->next->radial_next->f,kl->f,kl->next->e);
+ BM_Collapse_Vert(bm, kl->e, kv, 1.0);
+ //BME_JEKV(bm,kl->e,kv);
+ }
+ l = l->prev;
+ }
+
+ /* checks and operations for the next edge */
+ /* first, check to see if this edge was inset previously */
+ if ((l->next->e->tflag1 & BME_BEVEL_ORIG) == 0
+ && (l->next->v->tflag1 & BME_BEVEL_NONMAN) == 0) {
+ kl = l->next->radial_next;
+ if (kl->v == l->next->v) kl = kl->prev;
+ else kl = kl->next;
+ kv = l->next->v;
+ }
+ else {
+ kv = NULL;
+ }
+ /* get/make the second vert to be used in SFME */
+ if (l->next->v->tflag1 & BME_BEVEL_NONMAN) {
+ v2 = l->next->v;
+ }
+ else { /* we'll need to split the next edge */
+ v2 = BME_bevel_split_edge(bm,l->next->v,NULL,l->next,up_vec,value,td);
+ }
+ /* if we need to clean up geometry... */
+ if (kv) {
+ if (kl->v == kv) {
+ BM_Split_Face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e);
+ bmesh_jfke(bm,kl->prev->radial_next->f,kl->f,kl->prev->e);
+ BM_Collapse_Vert(bm, kl->e, kv, 1.0);
+ //BME_JEKV(bm,kl->e,kv);
+ }
+ else {
+ BM_Split_Face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e);
+ bmesh_jfke(bm, kl->next->radial_next->f,kl->f,kl->next->e);
+ BM_Collapse_Vert(bm, kl->e, kv, 1.0);
+ //BME_JEKV(bm,kl->e,kv);
+ }
+ }
+
+ if ((v1->tflag1 & BME_BEVEL_NONMAN)==0 || (v2->tflag1 & BME_BEVEL_NONMAN)==0) {
+ BM_Split_Face(bm,f,v2,v1,&l,e);
+ l->e->tflag1 = BME_BEVEL_BEVEL;
+ l = l->radial_next;
+ }
+
+ if (l->f != f){
+ //printf("Whoops! You got something out of order in BME_bevel_edge()!\n");
+ }
+
+ return l;
+}
+
+static BMLoop *BME_bevel_vert(BMesh *bm, BMLoop *l, float value, int options, float *up_vec, BME_TransData_Head *td) {
+ BMVert *v1, *v2;
+ BMFace *f;
+
+ /* get/make the first vert to be used in SFME */
+ /* may need to split the previous edge */
+ v1 = BME_bevel_split_edge(bm,l->v,NULL,l->prev,up_vec,value,td);
+
+ /* get/make the second vert to be used in SFME */
+ /* may need to split this edge (so move l) */
+ l = l->prev;
+ v2 = BME_bevel_split_edge(bm,l->next->v,NULL,l->next,up_vec,value,td);
+ l = l->next->next;
+
+ /* "cut off" this corner */
+ f = BM_Split_Face(bm,l->f,v2,v1,NULL,l->e);
+
+ return l;
+}
+
+/**
+ * BME_bevel_poly
+ *
+ * Polygon inset tool:
+ *
+ * Insets a polygon/face based on the tflag1's of its vertices
+ * and edges. Used by the bevel tool only, for now.
+ * The parameter "value" is the distance to inset (should be negative).
+ * The parameter "options" is not currently used.
+ *
+ * Returns -
+ * A BMFace pointer to the resulting inner face.
+*/
+static BMFace *BME_bevel_poly(BMesh *bm, BMFace *f, float value, int options, BME_TransData_Head *td) {
+ BMLoop *l, *ol;
+ BME_TransData *vtd1, *vtd2;
+ float up_vec[3], vec1[3], vec2[3], vec3[3], fac1, fac2, max = -1;
+ int len, i;
+
+ up_vec[0] = 0.0f;
+ up_vec[1] = 0.0f;
+ up_vec[2] = 0.0f;
+ /* find a good normal for this face (there's better ways, I'm sure) */
+ ol = f->loopbase;
+ l = ol->next;
+ for (i=0,ol=f->loopbase,l=ol->next; l->next!=ol; l=l->next) {
+ BME_bevel_get_vec(vec1,l->next->v,ol->v,td);
+ BME_bevel_get_vec(vec2,l->v,ol->v,td);
+ cross_v3_v3v3(vec3,vec2,vec1);
+ VECADD(up_vec,up_vec,vec3);
+ i++;
+ }
+ mul_v3_fl(up_vec,1.0f/i);
+ normalize_v3(up_vec);
+
+ for (i=0,len=f->len; i<len; i++,l=l->next) {
+ if ((l->e->tflag1 & BME_BEVEL_BEVEL) && (l->e->tflag1 & BME_BEVEL_ORIG)) {
+ max = 1.0f;
+ l = BME_bevel_edge(bm, l, value, options, up_vec, td);
+ }
+
+ else if ((l->v->tflag1 & BME_BEVEL_BEVEL) && (l->v->tflag1 & BME_BEVEL_ORIG) && (l->prev->e->tflag1 & BME_BEVEL_BEVEL) == 0) {
+ max = 1.0f;
+ l = BME_bevel_vert(bm, l, value, options, up_vec, td);
+ }
+ }
+
+ /* max pass */
+ if (value > 0.5 && max > 0) {
+ max = -1;
+ for (i=0,len=f->len; i<len; i++,l=l->next) {
+ if ((l->e->tflag1 & BME_BEVEL_BEVEL) || (l->e->tflag1 & BME_BEVEL_ORIG)) {
+ BME_bevel_get_vec(vec1,l->v,l->next->v,td);
+ vtd1 = BME_get_transdata(td,l->v);
+ vtd2 = BME_get_transdata(td,l->next->v);
+ if (vtd1->loc == NULL) {
+ fac1 = 0;
+ }
+ else {
+ VECCOPY(vec2,vtd1->vec);
+ mul_v3_fl(vec2,vtd1->factor);
+ if (dot_v3v3(vec1, vec1)) {
+ project_v3_v3v3(vec2,vec2,vec1);
+ fac1 = len_v3(vec2)/value;
+ }
+ else {
+ fac1 = 0;
+ }
+ }
+ if (vtd2->loc == NULL) {
+ fac2 = 0;
+ }
+ else {
+ VECCOPY(vec3,vtd2->vec);
+ mul_v3_fl(vec3,vtd2->factor);
+ if (dot_v3v3(vec1, vec1)) {
+ project_v3_v3v3(vec2,vec3,vec1);
+ fac2 = len_v3(vec2)/value;
+ }
+ else {
+ fac2 = 0;
+ }
+ }
+ if (fac1 || fac2) {
+ max = len_v3(vec1)/(fac1 + fac2);
+ if (vtd1->max && (*vtd1->max < 0 || max < *vtd1->max)) {
+ *vtd1->max = max;
+ }
+ if (vtd2->max && (*vtd2->max < 0 || max < *vtd2->max)) {
+ *vtd2->max = max;
+ }
+ }
+ }
+ }
+ }
+
+ return l->f;
+}
+
+static void BME_bevel_add_vweight(BME_TransData_Head *td, BMesh *bm, BMVert *v, float weight, float factor, int options) {
+ BME_TransData *vtd;
+
+ if (v->tflag1 & BME_BEVEL_NONMAN) return;
+ v->tflag1 |= BME_BEVEL_BEVEL;
+ if ( (vtd = BME_get_transdata(td, v)) ) {
+ if (options & BME_BEVEL_EMIN) {
+ vtd->factor = 1.0;
+ if (vtd->weight < 0 || weight < vtd->weight) {
+ vtd->weight = weight;
+ }
+ }
+ else if (options & BME_BEVEL_EMAX) {
+ vtd->factor = 1.0;
+ if (weight > vtd->weight) {
+ vtd->weight = weight;
+ }
+ }
+ else if (vtd->weight < 0) {
+ vtd->factor = factor;
+ vtd->weight = weight;
+ }
+ else {
+ vtd->factor += factor; /* increment number of edges with weights (will be averaged) */
+ vtd->weight += weight; /* accumulate all the weights */
+ }
+ }
+ else {
+ /* we'll use vtd->loc == NULL to mark that this vert is not moving */
+ vtd = BME_assign_transdata(td, bm, v, v->co, NULL, NULL, NULL, factor, weight, -1, NULL);
+ }
+}
+
+
+static bevel_init_verts(BMesh *bm, int options, BME_TransData_Head *td){
+ BMVert *v;
+ float weight;
+ for(v=bm->verts.first; v; v=v->next){
+ weight = 0.0;
+ if(!(v->tflag1 & BME_BEVEL_NONMAN)){
+ if(options & BME_BEVEL_SELECT){
+ if(v->flag & SELECT) weight = 1.0;
+ }
+ else if(options & BME_BEVEL_WEIGHT) weight = v->bweight;
+ else weight = 1.0;
+ if(weight > 0.0){
+ v->tflag1 |= BME_BEVEL_BEVEL;
+ BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 1.0,weight, -1, NULL);
+ }
+ }
+ }
+}
+static bevel_init_edges(BMesh *bm, int options, BME_TransData_Head *td){
+ BMEdge *e;
+ int count;
+ float weight;
+ for( e = BM_first_element(bm, BME_EDGE); e; e = BM_next_element(bm, BME_EDGE, e)){
+ weight = 0.0;
+ if(!(e->tflag1 & BME_BEVEL_NONMAN)){
+ if(options & BME_BEVEL_SELECT){
+ if(e->flag & SELECT) weight = 1.0;
+ }
+ else if(options & BME_BEVEL_WEIGHT){
+ weight = e->bweight;
+ }
+ else{
+ weight = 1.0;
+ }
+ if(weight > 0.0){
+ e->tflag1 |= BME_BEVEL_BEVEL;
+ e->v1->tflag1 |= BME_BEVEL_BEVEL;
+ e->v2->tflag1 |= BME_BEVEL_BEVEL;
+ BME_bevel_add_vweight(td, bm, e->v1, weight, 1.0, options);
+ BME_bevel_add_vweight(td, bm, e->v2, weight, 1.0, options);
+ }
+ }
+ }
+
+ /*clean up edges with 2 faces that share more than one edge*/
+ for( e = BM_first_element(bm, BME_EDGE); e; e = BM_next_element(bm, BME_EDGE, e)){
+ if(e->tflag1 & BME_BEVEL_BEVEL){
+ count = BM_face_sharededges(e->l->f, e->l->radial_next->f);
+ if(count > 1) e->tflag1 &= ~BME_BEVEL_BEVEL;
+ }
+ }
+}
+static BMesh *BME_bevel_initialize(BMesh *bm, int options, int defgrp_index, float angle, BME_TransData_Head *td){
+
+ BMVert *v, *v2;
+ BMEdge *e, *curedge;
+ BMFace *f;
+ BMIter iter;
+ int wire, len;
+
+ for (v = BMIter_New(&iter, bm, BM_VERTS, nm); v; v = BMIter_Step(&iter)) v->tflag1 = 0;
+ for (e = BMIter_New(&iter, bm, BM_EDGES, nm); e; e = BMIter_Step(&iter)) e->tflag1 = 0;
+ for (f = BMIter_New(&iter, bm, BM_FACES, nm); f; f = BMIter_Step(&iter)) f->tflag1 = 0;
+
+ /*tag non-manifold geometry*/
+ for (v = BMIter_New(&iter, bm, BM_VERTS, nm); v; v = BMIter_Step(&iter)) {
+ v->tflag1 = BME_BEVEL_ORIG;
+ if(v->e){
+ BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 0, -1, -1, NULL);
+ if (BM_Nonmanifold_Vert(bm,v)) v->tflag1 |= BME_BEVEL_NONMAN;
+ /*test wire vert*/
+ len = bmesh_cycle_length(bmesh_disk_getpointer(v->e,v));
+ if(len == 2 && BME_wirevert(bm, v)) v->tflag1 &= ~BME_BEVEL_NONMAN;
+ }else v->tflag1 |= BME_BEVEL_NONMAN;
+ }
+
+ for (e = BMIter_New(&iter, bm, BM_EDGES, nm); e; e = BMIter_Step(&iter)) {
+ e->tflag1 = BME_BEVEL_ORIG;
+ if (e->l == NULL || BME_cycle_length(&(e->l->radial)) > 2){
+ e->v1->tflag1 |= BME_BEVEL_NONMAN;
+ e->v2->tflag1 |= BME_BEVEL_NONMAN;
+ e->tflag1 |= BME_BEVEL_NONMAN;
+ }
+ if((e->v1->tflag1 & BME_BEVEL_NONMAN) || (e->v2->tflag1 & BME_BEVEL_NONMAN)) e->tflag1 |= BME_BEVEL_NONMAN;
+ }
+
+ for (f = BMIter_New(&iter, bm, BM_FACES, nm); f; f = BMIter_Step(&iter))
+ f->tflag1 = BME_BEVEL_ORIG;
+ if(options & BME_BEVEL_VERT) bevel_init_verts(bm, options, td);
+ else bevel_init_edges(bm, options, td);
+ return bm;
+
+}
+static BMesh *BME_bevel_reinitialize(BMesh *bm)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ for (v = BMIter_New(bm, BM_VERTS, NULL); v; v = BMIter_Step(bm)){
+ v->tflag1 |= BME_BEVEL_ORIG;
+ v->tflag2 = 0;
+ }
+ for (e = BMIter_New(bm, BM_EDGES, NULL); e; e = BMIter_Step(bm)){
+ e->tflag1 |= BME_BEVEL_ORIG;
+ }
+ for (f = BMIter_New(bm, BM_FACES, NULL); f; f = BMIter_Step(bm)){
+ f->tflag1 |= BME_BEVEL_ORIG;
+ }
+ return bm;
+
+}
+
+/**
+ * BME_bevel_mesh
+ *
+ * Mesh beveling tool:
+ *
+ * Bevels an entire mesh. It currently uses the tflag1's of
+ * its vertices and edges to track topological changes.
+ * The parameter "value" is the distance to inset (should be negative).
+ * The parameter "options" is not currently used.
+ *
+ * Returns -
+ * A BMesh pointer to the BM passed as a parameter.
+*/
+
+static BMMesh *BME_bevel_mesh(BMMesh *bm, float value, int res, int options, int defgrp_index, BME_TransData_Head *td) {
+ BMVert *v, *nv;
+ BMEdge *e, *curedge, *ne;
+ BMLoop *l, *l2;
+ BMFace *f, *nf;
+
+ BMeshIter verts;
+ BMeshIter edges;
+ BMeshIter loops;
+ BMeshIter faces;
+
+ unsigned int i, len;
+
+ /*bevel polys*/
+ for(f = BMeshIter_init(faces, BM_FACES, bm, 0); f; f = BMeshIter_step(faces)){
+ if(bmesh_test_flag(f, BME_BEVEL_ORIG){
+ bevel_poly(bm,f,value,options,td);
+ }
+ }
+ /*get rid of beveled edges*/
+ for(e = BMeshIter_init(edges, BM_EDGES, bm, 0); e;){
+ ne = BMeshIter_step(edges);
+ if( bmesh_test_flag(e, BME_BEVEL_BEVEL) && bmesh_test_flag(e, BME_BEVEL_ORIG) ) bmesh_join_faces(bm, e->l->f, e->l->radial_next->f, e, 1);
+ e = ne;
+ }
+ /*link up corners and clip*/
+ for(v = BMeshIter_init(verts, BM_VERTS, bm, 0); v;){
+ nv = BMeshIter_step(verts)
+ if( bmesh_test_flag(v, BME_BEVEL_ORIG) && bmesh_test_flag(v, BME_BEVEL_BEVEL)){
+ curedge = v->e;
+ do{
+ l = curedge->l;
+ l2 = l->radial_next;
+ if(l->v != v) l = l->next;
+ if(l2->v != v) l2 = l2->next;
+ if(l->f->len > 3) BM_split_face(bm,l->f,l->next->v,l->prev->v,&l,l->e); /* clip this corner off */
+ if(l2->f->len > 3) BM_split_face(bm,l2->f,l2->next->v,l2->prev->v,&l,l2->e); /* clip this corner off */
+ curedge = BM_edge_of_vert(curedge, v);
+ }while(curedge != v->e);
+ BM_dissolve_disk(bm,v);
+ }
+ v = nv;
+ }
+
+ /*Debug print, remove*/
+ for(f = BMeshIter_init(faces, BM_FACES, bm, 0); f;){
+ if(f->len == 2){
+ printf("warning");
+ }
+ }
+
+ return bm;
+}
+
+BMesh *BME_bevel(BMMesh *bm, float value, int res, int options, int defgrp_index, float angle, BME_TransData_Head **rtd) {
+ BMVert *v;
+ BMEdge *e;
+ BMIter *verts;
+
+ BME_TransData_Head *td;
+ BME_TransData *vtd;
+ int i;
+ double fac=1, d;
+
+
+ td = BME_init_transdata(BLI_MEMARENA_STD_BUFSIZE);
+ /* recursion math courtesy of Martin Poirier (theeth) */
+ for (i=0; i<res-1; i++) {
+ if (i==0) fac += 1.0f/3.0f; else fac += 1.0f/(3 * i * 2.0f);
+ }
+ d = 1.0f/fac;
+
+
+ for (i=0; i<res || (res==0 && i==0); i++) {
+ BME_bevel_initialize(bm, options, defgrp_index, angle, td);
+ //if (i != 0) BME_bevel_reinitialize(bm);
+ bmesh_begin_edit(bm);
+ BME_bevel_mesh(bm,(float)d,res,options,defgrp_index,td);
+ bmesh_end_edit(bm);
+ if (i==0) d /= 3; else d /= 2;
+ }
+
+ BME_model_begin(bm);
+ BME_tesselate(bm);
+ BME_model_end(bm);
+
+
+ /*interactive preview?*/
+ if (rtd) {
+ *rtd = td;
+ return bm;
+ }
+
+ /* otherwise apply transforms */
+ for( v = BMeshIter_init(verts); v; v = BMeshIter_step(verts)){
+ if ( (vtd = BME_get_transdata(td, v)) ) {
+ if (vtd->max && (*vtd->max > 0 && value > *vtd->max)) {
+ d = *vtd->max;
+ }
+ else {
+ d = value;
+ }
+ VECADDFAC(v->co,vtd->org,vtd->vec,vtd->factor*d);
+ }
+ v->tflag1 = 0;
+ }
+
+ BME_free_transdata(td);
+ return bm;
+}
diff --git a/source/blender/bmesh/tools/BME_dupe_ops.c b/source/blender/bmesh/tools/BME_dupe_ops.c
new file mode 100644
index 00000000000..ad5739e9abc
--- /dev/null
+++ b/source/blender/bmesh/tools/BME_dupe_ops.c
@@ -0,0 +1,318 @@
+/*
+ * BME_DUPLICATE.C
+ *
+ * This file contains functions for duplicating, copying, and splitting
+ * elements from a bmesh.
+ *
+ */
+
+/*
+ * COPY VERTEX
+ *
+ * Copy an existing vertex from one bmesh to another.
+ *
+*/
+
+static BMVert *copy_vertex(BMMesh *source_mesh, BMVert *source_vertex, BMMesh *target_mesh, GHash *vhash)
+{
+ BMVert *target_vertex = NULL;
+
+ /*create a new vertex*/
+ target_vertex = BM_Make_Vert(target, source_vertex->co, NULL);
+
+ /*insert new vertex into the vert hash*/
+ BLI_ghash_insert(vhash, source_vertex, target_vertex);
+
+ /*copy custom data in this function since we cannot be assured that byte layout is same between meshes*/
+ CustomData_bmesh_copy_data(&source_mesh->vdata, &target_mesh->vdata, source_vertex->data, &target_vertex->data);
+
+ /*Copy Markings*/
+ if(BM_Is_Selected((BMHeader*)source_vertex)) BM_Select_Vert(target_mesh, target_vertex, 1);
+ if(BM_Is_Hidden((BMHeader*)source_vertex)) BM_Mark_Hidden((BMHeader*)target_vertex, 1);
+
+ BMO_SetFlag(target_mesh, (BMHeader*)target_vertex, DUPE_NEW);
+
+ return target_vertex;
+}
+
+/*
+ * COPY EDGE
+ *
+ * Copy an existing edge from one bmesh to another.
+ *
+*/
+
+static BMEdge *copy_edge(BMMesh *source_mesh, BMEdge *source_edge, BMMesh *target_mesh, GHash *vhash, GHash *ehash)
+{
+ BMEdge *target_edge = NULL;
+ BMVert *target_vert1, *target_vert2;
+
+ /*lookup v1 and v2*/
+ target_vert1 = BLI_ghash_lookup(vhash, source_edge->v1);
+ target_vert2 = BLI_ghash_lookup(vhash, source_edge->v2);
+
+ /*create a new edge*/
+ target_edge = BM_Make_Edge(target_mesh, target_vert1, target_vert2, NULL, 0);
+
+ /*insert new edge into the edge hash*/
+ BLI_ghash_insert(ehash, source_edge, target_edge);
+
+ /*copy custom data in this function since we cannot be assured that byte layout is same between meshes*/
+ CustomData_bmesh_copy_data(&source_mesh->edata, &target_mesh->edata, source_edge->data, &target_edge->data);
+
+ /*copy flags*/
+ if(BM_Is_Selected((BMHeader*) source_edge)) BM_Select_Edge(target_mesh, target_edge, 1);
+ if(BM_Is_Hidden((BMHeader*) source_edge)) BM_Mark_Hidden(target_mesh, target_edge, 1);
+ if(BM_Is_Sharp((BMHeader*) source_edge)) BM_Mark_Sharp(target_edge, 1);
+ if(BM_Is_Seam((BMHeader*) source_edge)) BM_Mark_Seam(target_edge, 1);
+ if(BM_Is_Fgon((BMHeader*) source_edge)) BM_Mark_Fgon(target_edge, 1);
+
+ BMO_SetFlag(target_mesh, (BMHeader*)target_edge, DUPE_NEW);
+
+ return target_edge;
+}
+
+/*
+ * COPY FACE
+ *
+ * Copy an existing face from one bmesh to another.
+ *
+*/
+
+static BMFace *copy_face(BMMesh *source_mesh, BMFace *source_face, BMMesh *target_mesh, BMEdge **edar, GHash *verthash, GHash *ehash)
+{
+ BMEdge *target_edge;
+ BMVert *target_vert1, *target_vert2;
+ BMLoop *source_loop, *target_loop;
+ BMFace *target_face = NULL;
+ int i;
+
+ /*lookup the first and second verts*/
+ target_vert1 = BLI_ghash_lookup(vhash, source_face->lbase->v);
+ target_vert2 = BLI_ghash_lookup(vhash, source_face->lbase->next->v);
+
+ /*lookup edges*/
+ i = 0;
+ source_loop = source_face->lbase;
+ do{
+ edar[i] = BLI_ghash_lookup(ehash, source_loop->e);
+ i++;
+ source_loop = source_loop->next;
+ }while(source_loop != source_face->lbase);
+
+ /*create new face*/
+ target_face = BM_Make_Ngon(target_mesh, target_vert1, target_vert2, edar, source_face->len, 0);
+
+ /*we copy custom data by hand, we cannot assume that customdata byte layout will be exactly the same....*/
+ CustomData_bmesh_copy_data(&source_mesh->pdata, &target_mesh->pdata, source_face->data, &target_face->data);
+
+ /*copy flags*/
+ if(BM_Is_Selected((BMHeader*)source_face)) BM_Select_face(target, target_face, 1);
+ if(BM_Is_Hidden((BMHeader*)source_face)) BM_Mark_Hidden((BMHeader*)target_face, 1);
+
+ /*mark the face for output*/
+ BMO_SetFlag(target_mesh, (BMHeader*)target_face, DUPE_NEW);
+
+ /*copy per-loop custom data*/
+ source_loop = source_face->lbase;
+ target_loop = target_face->lbase;
+ do{
+ CustomData_bmesh_copy_data(&source_mesh->ldata, &target_mesh->ldata, source_loop->data, &target_loop->data);
+ source_loop = source_loop->next;
+ target_loop = target_loop->next;
+ }while(source_loop != source_face->lbase);
+
+ return target_face;
+}
+
+/*
+ * COPY MESH
+ *
+ * Internal Copy function.
+*/
+
+/*local flag defines*/
+
+#define DUPE_INPUT 1 /*input from operator*/
+#define DUPE_NEW 2
+#define DUPE_DONE 3
+
+static void copy_mesh(BMMesh *source, BMMesh *target)
+{
+
+ BMVert *v = NULL;
+ BMEdge *e = NULL, **edar = NULL;
+ BMLoop *l = NULL;
+ BMFace *f = NULL;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+ BMIter loops;
+
+ GHash *vhash;
+ GHash *ehash;
+
+ int maxlength = 0, flag;
+
+ /*initialize pointer hashes*/
+ vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ ehash = BLI_ghash_new(BLI_ghashutil_ptrrhash, BLI_ghashutil_ptrcmp);
+
+ /*initialize edge pointer array*/
+ for(f = BMIter_New(&faces, source, BM_FACES, source, 0, NULL); f; f = BMIter_Step(&faces)){
+ if(f->len > maxlength) maxlength = f->len;
+ }
+ edar = MEM_callocN(sizeof(BMEdge*) * maxlength, "BM copy mesh edge pointer array");
+
+
+ /*first we dupe all flagged faces and their elements from source*/
+ for(f = BMIter_New(&faces, source, BM_FACES, source, 0, NULL); f; f= BMIter_Step(&faces)){
+ if(BMO_TestFlag(source, (BMHeader*)f, DUPE_INPUT)){
+ /*vertex pass*/
+ for(v = BMIter_New(&verts, source, BM_VERT_OF_FACE, f, 0, NULL); v; v = BMIter_Step(&verts)){
+ if(!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE)){
+ copy_vertex(source,v, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
+ }
+ }
+
+ /*edge pass*/
+ for(e = BMIter_New(&edges, source, BM_EDGE_OF_FACE, f, 0, NULL); e; e = BMeshIter_step(&edges)){
+ if(!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE)){
+ copy_edge(source, e, target, vhash, ehash);
+ BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE);
+ }
+ }
+ copy_face(source, f, target, edar, vhash, ehash);
+ BMO_SetFlag(source, (BMHeader*)f, DUPE_DONE);
+ }
+ }
+
+ /*now we dupe all the edges*/
+ for(e = BMIter_New(&edges, source, BM_EDGES, source, 0, NULL); e; e = BMIter_Step(&edges)){
+ if(BMO_TestFlag(source, (BMHeader*)e, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE))){
+ /*make sure that verts are copied*/
+ if(!BMO_TestFlag(source, (BMHeader*)e->v1, DUPE_DONE){
+ copy_vertex(source, e->v1, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)e->v1, DUPE_DONE);
+ }
+ if(!BMO_TestFlag(source, (BMHeader*)e->v2, DUPE_DONE){
+ copy_vertex(source, e->v2, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)e->v2, DUPE_DONE);
+ }
+ /*now copy the actual edge*/
+ copy_edge(source, e, target, vhash, ehash);
+ BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE);
+ }
+ }
+
+ /*finally dupe all loose vertices*/
+ for(v = BMIter_New(&verts, source, BM_VERTS, source, 0, NULL); v; v = BMIter_Step(&verts)){
+ if(BMO_TestFlag(source, (BMHeader*)v, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE))){
+ copy_vertex(source, v, target, vhash);
+ BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
+ }
+ }
+
+ /*free pointer hashes*/
+ BLI_ghash_free(vhash, NULL, NULL);
+ BLI_ghash_free(ehash, NULL, NULL);
+
+ /*free edge pointer array*/
+ if(edar)
+ MEM_freeN(edar);
+}
+/*
+BMMesh *bmesh_make_mesh_from_mesh(BMMesh *bm, int allocsize[4])
+{
+ BMMesh *target = NULL;
+ target = bmesh_make_mesh(allocsize);
+
+
+ CustomData_copy(&bm->vdata, &target->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->edata, &target->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->ldata, &target->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->pdata, &target->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+
+ CustomData_bmesh_init_pool(&target->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&target->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&target->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&target->pdata, allocsize[3]);
+
+ bmesh_begin_edit(bm);
+ bmesh_begin_edit(target);
+
+ bmesh_copy_mesh(bm, target, 0);
+
+ bmesh_end_edit(bm);
+ bmesh_end_edit(target);
+
+ return target;
+
+}
+*/
+
+void dupeop_exec(BMMesh *bm, BMOperator *op)
+{
+ BMOperator *dupeop = op;
+ BMOpSlot *vinput, *einput, *finput, *vnew, *enew, *fnew;
+ int i;
+
+ vinput = BMO_Get_Slot(dupeop, BMOP_DUPE_VINPUT);
+ einput = BMO_Get_Slot(dupeop, BMOP_DUPE_EINPUT);
+ finput = BMO_Get_Slot(dupeop, BMOP_DUPE_FINPUT);
+
+ /*go through vinput, einput, and finput and flag elements with private flags*/
+ BMO_Flag_Buffer(bm, dupeop, BMOP_DUPE_VINPUT, DUPE_INPUT);
+ BMO_Flag_Buffer(bm, dupeop, BMOP_DUPE_EINPUT, DUPE_INPUT);
+ BMO_Flag_Buffer(bm, dupeop, BMOP_DUPE_FINPUT, DUPE_INPUT);
+
+ /*use the internal copy function*/
+ copy_mesh(bm, bm);
+
+ /*Output*/
+ /*First copy the input buffers to output buffers - original data*/
+ BMO_Copy_Opslot_Buffer_Alloc(dupeop, vinput, BMO_Get_Slot(dupeop, BMOP_DUPE_VORIGINAL));
+ BMO_Copy_Opslot_Buffer_Alloc(dupeop, einput, BMO_Get_Slot(dupeop, BMOP_DUPE_EORIGINAL));
+ BMO_Copy_Opslot_Buffer_Alloc(dupeop, finput, BMO_Get_Slot(dupeop, BMOP_DUPE_FORIGINAL));
+
+ /*Now alloc the new output buffers*/
+ BMO_Flag_To_Slot(bm, dupeop, BMOP_DUPE_VNEW, DUPE_NEW, BMESH_VERT);
+ BMO_Flag_To_Slot(bm, dupeop, BMOP_DUPE_ENEW, DUPE_NEW, BMESH_EDGE);
+ BMO_Flag_To_Slot(bm, dupeop, BMOP_DUPE_FNEW, DUPE_NEW, BMESH_FACE);
+}
+
+void splitop_exec(BMMesh *bm, BMOperator *op)
+{
+ BMOperator *splitop = op;
+ BMOperator dupeop;
+ BMOperator delop;
+
+ /*initialize our sub-operators*/
+ BMO_Init_Op(&dupeop, BMOP_DUPE);
+ BMO_Init_Op(&delop, BMOP_DEL);
+
+ BMO_Connect(BMO_Get_Slot(splitop, BMOP_SPLIT_VINPUT),BMO_Get_Slot(&dupeop, BMOP_DUPE_VINPUT));
+ BMO_Connect(BMO_Get_Slot(splitop, BMOP_SPLIT_EINPUT),BMO_Get_Slot(&dupeop, BMOP_DUPE_EINPUT));
+ BMO_Connect(BMO_Get_Slot(splitop, BMOP_SPLIT_FINPUT),BMO_Get_Slot(&dupeop, BMOP_DUPE_FINPUT));
+
+ BMO_Exec_Op(&dupeop);
+
+ /*connect outputs of dupe to delete*/
+ BMO_Connect(BMO_Get_Slot(&dupeop, BMOP_DUPE_VORIGINAL), BMO_Get_Slot(&delop, BMOP_DEL_VINPUT));
+ BMO_Connect(BMO_Get_Slot(&dupeop, BMOP_DUPE_EORIGINAL), BMO_Get_Slot(&delop, BMOP_DEL_EINPUT));
+ BMO_Connect(BMO_Get_Slot(&dupeop, BMOP_DUPE_FORIGINAL), BMO_Get_Slot(&delop, BMOP_DEL_FINPUT));
+
+ BMO_Exec_Op(&delop);
+
+ /*now we make our outputs by copying the dupe outputs*/
+ BMO_Copy_Buffer_Alloc(BMO_Get_Slot(&dupeop, BMOP_DUPE_VNEW), BMO_Get_Slot(splitop, BMOP_SPLIT_VOUTPUT));
+ BMO_Copy_Buffer_Alloc(BMO_Get_Slot(&dupeop, BMOP_DUPE_ENEW), BMO_Get_Slot(splitop, BMOP_SPLIT_EOUTPUT));
+ BMO_Copy_Buffer_Alloc(BMO_Get_Slot(&dupeop, BMOP_DUPE_FNEW), BMO_Get_Slot(splitop, BMOP_SPLIT_FOUTPUT));
+
+ /*cleanup*/
+ BMO_Finish_Op(&dupeop);
+ BMO_Finish_Op(&delop);
+} \ No newline at end of file
diff --git a/source/blender/bmesh/tools/BME_duplicate.c b/source/blender/bmesh/tools/BME_duplicate.c
new file mode 100644
index 00000000000..ec3cfe56fc9
--- /dev/null
+++ b/source/blender/bmesh/tools/BME_duplicate.c
@@ -0,0 +1,307 @@
+/*
+ * BME_DUPLICATE.C
+ *
+ * This file contains functions for duplicating, copying, and splitting
+ * elements from a bmesh.
+ *
+ */
+
+/*
+ * BMESH COPY VERTEX
+ *
+ * Copy an existing vertex from one bmesh to another.
+ *
+*/
+
+static BMVert *bmesh_copy_vertex(BMMesh *source_mesh, BMVert *source_vertex, BMMesh *target_mesh, GHash *vhash)
+{
+ BMVert *target_vertex = NULL;
+
+ /*create a new vertex*/
+ target_vertex = bmesh_make_vert(target, source_vertex->co, NULL);
+
+ /*insert new vertex into the vert hash*/
+ BLI_ghash_insert(vhash, source_vertex, target_vertex);
+
+ /*copy custom data in this function since we cannot be assured that byte layout is same between meshes*/
+ CustomData_bmesh_copy_data(&source_mesh->vdata, &target_mesh->vdata, source_vertex->data, &target_vertex->data);
+
+ /*copy flags*/
+ if(bmesh_test_flag(source_vertex, BMESH_SELECT)) bmesh_set_flag(target_vertex, BMESH_SELECT);
+ if(bmesh_test_flag(source_vertex, BMESH_HIDDEN)) bmesh_set_flag(target_vertex, BMESH_HIDDEN);
+
+ return target_vertex;
+}
+
+/*
+ * BMESH COPY EDGE
+ *
+ * Copy an existing edge from one bmesh to another.
+ *
+*/
+
+static BMEdge *bmesh_copy_edge(BMMesh *source_mesh, BMEdge *source_edge, BMMesh *target_mesh, GHash *vhash, GHash *ehash)
+{
+ BMEdge *target_edge = NULL;
+ BMVert *target_vert1, *target_vert2;
+
+ /*lookup v1 and v2*/
+ target_vert1 = BLI_ghash_lookup(vhash, source_edge->v1);
+ target_vert2 = BLI_ghash_lookup(vhash, source_edge->v2);
+
+ /*create a new edge*/
+ target_edge = bmesh_make_edge(target_mesh, target_vert1, target_vert2, NULL, 0);
+
+ /*insert new edge into the edge hash*/
+ BLI_ghash_insert(ehash, source_edge, target_edge);
+
+ /*copy custom data in this function since we cannot be assured that byte layout is same between meshes*/
+ CustomData_bmesh_copy_data(&source_mesh->edata, &target_mesh->edata, source_edge->data, &target_edge->data);
+
+ /*copy flags*/
+ if(bmesh_test_flag(source_edge, BMESH_SELECT)) bmesh_set_flag(target_edge, BMESH_SELECT);
+ if(bmesh_test_flag(source_edge, BMESH_HIDDEN)) bmesh_set_flag(target_edge, BMESH_SELECT);
+ if(bmesh_test_flag(source_edge, BMESH_SHARP)) bmesh_set_flag(target_edge, BMESH_SHARP);
+ if(bmesh_test_flag(source_edge, BMESH_SEAM)) bmesh_set_flag(target_edge, BMESH_SEAM);
+ if(bmesh_test_flag(source_edge, BMESH_FGON)) bmesh_set_flag(target_edge, BMESH_FGON);
+
+ return target_edge;
+}
+
+/*
+ * BMESH COPY FACE
+ *
+ * Copy an existing face from one bmesh to another.
+ *
+*/
+
+static BMFace *bmesh_copy_face(BMMesh *source_mesh, BMFace *source_face, BMMesh *target_mesh, BMEdge **edar, GHash *verthash, GHash *ehash)
+{
+ BMEdge *target_edge;
+ BMVert *target_vert1, *target_vert2;
+ BMLoop *source_loop, *target_loop;
+ BMFace *target_face = NULL;
+ int i;
+
+
+ /*lookup the first and second verts*/
+ target_vert1 = BLI_ghash_lookup(vhash, source_face->lbase->v);
+ target_vert2 = BLI_ghash_lookup(vhash, source_face->lbase->next->v);
+
+ /*lookup edges*/
+ i = 0;
+ source_loop = source_face->lbase;
+ do{
+ edar[i] = BLI_ghash_lookup(ehash, source_loop->e);
+ i++;
+ source_loop = source_loop->next;
+ }while(source_loop != source_face->lbase);
+
+ /*create new face*/
+ target_face = bmesh_make_ngon(target_mesh, target_vert1, target_vert2, edar, source_face->len, 0);
+
+ /*we copy custom data by hand, we cannot assume that customdata byte layout will be exactly the same....*/
+ CustomData_bmesh_copy_data(&source_mesh->pdata, &target_mesh->pdata, source_face->data, &target_face->data);
+
+ /*copy flags*/
+ if(bmesh_test_flag(source_face, BMESH_SELECT)) bmesh_set_flag(target_face, BMESH_SELECT);
+ if(bmesh_test_flag(source_face, BMESH_HIDDEN)) bmesh_set_flag(target_face, BMESH_HIDDEN);
+
+ /*mark the face as dirty for normal and tesselation calcs*/
+ bmesh_set_flag(target_face, BMESH_DIRTY);
+
+ /*copy per-loop custom data*/
+ source_loop = source_face->lbase;
+ target_loop = target_face->lbase;
+ do{
+ CustomData_bmesh_copy_data(&source_mesh->ldata, &target_mesh->ldata, source_loop->data, &target_loop->data);
+ source_loop = source_loop->next;
+ target_loop = target_loop->next;
+ }while(source_loop != source_face->lbase);
+
+ return target_face;
+}
+
+/*
+ * BMESH COPY MESH
+ *
+ * Internal Copy function. copies flagged elements from
+ * source to target, which may in fact be the same mesh.
+ * Note that if __flag is 0, all elements will be copied.
+ *
+*/
+
+static void bmesh_copy_mesh(BMMesh *source, BMMesh *target, int __flag)
+{
+
+ BMVert *v;
+ BMEdge *e, **edar;
+ BMLoop *l;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+ BMIter loops;
+
+ GHash *vhash;
+ GHash *ehash;
+
+ int maxlength = 0, flag;
+
+ /*initialize pointer hashes*/
+ vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ ehash = BLI_ghash_new(BLI_ghashutil_ptrrhash, BLI_ghashutil_ptrcmp);
+
+ /*initialize edge pointer array*/
+ for(f = BMeshIter_init(faces, BM_FACES, source, 0); f; f = BMeshIter_step(faces)){
+ if(f->len > maxlength) maxlength = f->len;
+ }
+ edar = MEM_callocN(sizeof(BMEdge*) * maxlength, "BM copy mesh edge pointer array");
+
+ /*begin modelling loop for target*/
+ bmesh_begin_edit(target);
+
+ /*we make special exception for __flag == 0... we copy all*/
+ if(!__flag){
+ flag = BMESH_DUPE;
+ for(v = BMeshIter_init(verts, BM_VERTS, source, 0); v; v = BMeshIter_step(verts)) bmesh_set_flag(v, BMESH_DUPE);
+ for(e = BMeshIter_init(verts, BM_EDGES, source, 0); e; e = BMeshIter_step(edges)) bmesh_set_flag(e, BMESH_DUPE);
+ for(f = BMeshIter_init(faces, BM_FACES, source, 0); f; f = BMeshIter_step(faces)) bmesh_set_flag(f, BMESH_DUPE);
+ } else{
+ flag = __flag;
+ }
+
+ /*first we dupe all flagged faces and their elements from source*/
+ for(f = BMeshIter_init(faces, BM_FACES, source, 0); f; f= BMeshIter_step(faces)){
+ if(bmesh_test_flag(f, flag)){
+ /*vertex pass*/
+ for(l = BMeshIter_init(loops, BMESH_LOOP_OF_MESH, f, 0); l; l = BMeshIter_step(loops)){
+ if(!bmesh_test_flag(l->v, BMESH_DUPED)){
+ bmesh_copy_vertex(source,l->v, target, vhash);
+ bmesh_set_flag(l->v, BMESH_DUPED);
+ }
+ }
+
+ /*edge pass*/
+ for(l = BMeshIter_init(loops, BMESH_LOOP_OF_MESH, f, 0); l; l = BMeshIter_step(loops)){
+ if(!bmesh_test_flag(l->e, BMESH_DUPED)){
+ bmesh_copy_edge(source, l->e, target, vhash, ehash);
+ bmesh_set_flag(l->e, BMESH_DUPED);
+ }
+ }
+ bmesh_copy_face(source, f, target, edar, vhash, ehash);
+ bmesh_set_flag(f, BMESH_DUPED);
+ }
+ }
+
+ /*now we dupe all the edges*/
+ for(e = BMeshIter_init(edges, BM_EDGES, source, 0); e; e = BMeshIter_step(edges)){
+ if(bmesh_test_flag(e, flag) && (!bmesh_test_flag(e, BMESH_DUPED))){
+ /*make sure that verts are copied*/
+ if(!bmesh_test_flag(e->v1, BMESH_DUPED)){
+ bmesh_copy_vertex(source, e->v1, target, vhash);
+ bmesh_set_flag(e->v1, BMESH_DUPED);
+ }
+ if(!bmesh_test_flag(e->v2, BMESH_DUPED)){
+ bmesh_copy_vertex(source, e->v2, target, vhash);
+ bmesh_set_flag(e->v2, BMESH_DUPED);
+ }
+ /*now copy the actual edge*/
+ bmesh_copy_edge(source, e, target, vhash, ehash);
+ bmesh_set_flag(e, BMESH_DUPED);
+ }
+ }
+
+ /*finally dupe all loose vertices*/
+ for(v = BMeshIter_init(verts, BM_VERTS, bm, 0); v; v = BMeshIter_step(verts)){
+ if(bmesh_test_flag(v, flag) && (!bmesh_test_flag(v, BMESH_DUPED))){
+ bmesh_copy_vertex(source, v, target, vhash);
+ bmesh_set_flag(v, BMESH_DUPED);
+ }
+ }
+
+ /*finish*/
+ bmesh_end_edit(target, BMESH_CALC_NORM | BMESH_CALC_TESS);
+
+ /*free pointer hashes*/
+ BLI_ghash_free(vhash, NULL, NULL);
+ BLI_ghash_free(ehash, NULL, NULL);
+
+ /*free edge pointer array*/
+ MEM_freeN(edar);
+}
+
+/*
+ * BMESH MAKE MESH FROM MESH
+ *
+ * Creates a new mesh by duplicating an existing one.
+ *
+*/
+
+BMMesh *bmesh_make_mesh_from_mesh(BMMesh *bm, int allocsize[4])
+{
+ BMMesh *target = NULL;
+ target = bmesh_make_mesh(allocsize);
+
+ /*copy custom data layout*/
+ CustomData_copy(&bm->vdata, &target->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->edata, &target->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->ldata, &target->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm->pdata, &target->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+ /*initialize memory pools*/
+ CustomData_bmesh_init_pool(&target->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&target->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&target->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&target->pdata, allocsize[3]);
+
+ bmesh_begin_edit(bm);
+ bmesh_begin_edit(target);
+
+ bmesh_copy_mesh(bm, target, 0); /*copy all elements*/
+
+ bmesh_end_edit(bm);
+ bmesh_end_edit(target);
+
+ return target;
+
+}
+
+/*
+ * BMESH SPLIT MESH
+ *
+ * Copies flagged elements then deletes them.
+ *
+*/
+
+void bmesh_split_mesh(BMMesh *bm, int flag){
+
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter verts;
+ BMIter edges;
+ BMIter faces;
+
+ bmesh_begin_edit(bm);
+ bmesh_copy_mesh(bm, bm, flag);
+
+ /*mark verts for deletion*/
+ for(v = BMeshIter_init(verts, BM_VERTS, bm, 0); v; v = BMeshIter_step(verts)){
+ if(bmesh_test_flag(v, flag)) bmesh_delete_vert(bm, v);
+ }
+ /*mark edges for deletion*/
+ for(e = BMeshIter_init(edges, BM_EDGES, bm, 0); e; e = BMeshIter_step(edges)){
+ if(bmesh_test_flag(e, flag)) bmesh_delete_edge(bm, e);
+
+ }
+ /*mark faces for deletion*/
+ for(f = BMeshIter_init(faces, BM_FACES, bm, 0); f; f= BMeshIter_step(faces)){
+ if(bmesh_tes t_flag(f, flag)) bmesh_delete_face(bm, f);
+
+ }
+ bmesh_end_edit(bm);
+}
+
diff --git a/source/blender/bmesh/tools/BME_extrude.c b/source/blender/bmesh/tools/BME_extrude.c
new file mode 100644
index 00000000000..70baff2adf6
--- /dev/null
+++ b/source/blender/bmesh/tools/BME_extrude.c
@@ -0,0 +1,216 @@
+/**
+ * BMESH EXTRUDE TOOL
+ *
+ * A rewrite of the old editmesh extrude code with the
+ * redundant parts broken into multiple functions
+ * in an effort to reduce code. This works with multiple
+ * selection modes, and is intended to build the
+ * extrusion in steps, depending on what elements are selected.
+ * Also decoupled the calculation of transform normal
+ * and put it in UI where it probably is more appropriate
+ * for the moment.
+ *
+ * TODO:
+ * -Fit this into the new 'easy' API.
+*/
+
+void BME_extrude_verts(BME_Mesh *bm, GHash *vhash){
+ BMVert *v, *nv = NULL;
+ BMEdge *ne = NULL;
+ float vec[3];
+
+ //extrude the vertices
+ for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
+ if(BME_SELECTED(v)){
+ VECCOPY(vec,v->co);
+ nv = BME_MV(bm,vec);
+ nv->tflag2 =1; //mark for select
+ ne = BME_ME(bm,v,nv);
+ ne->tflag1 = 2; //mark as part of skirt 'ring'
+ BLI_ghash_insert(vhash,v,nv);
+ BME_VISIT(v);
+ }
+ }
+}
+
+void BME_extrude_skirt(BME_Mesh *bm, GHash *ehash){
+
+ BMFace *nf=NULL;
+ BMEdge *e, *l=NULL, *r=NULL, *edar[4], *ne;
+ BMVert *v, *v1, *v2, *lv, *rv, *nv;
+
+ for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
+ if(BME_SELECTED(e)){
+ /*find one face incident upon e and use it for winding of new face*/
+ if(e->l){
+ v1 = e->l->next->v;
+ v2 = e->l->v;
+ }
+ else{
+ v1 = e->v1;
+ v2 = e->v2;
+ }
+
+ if(v1->e->tflag1 == 2) l = v1->e;
+ else l = BME_disk_next_edgeflag(v1->e, v1, 0, 2);
+ if(v2->e->tflag1 == 2) r = v2->e;
+ else r = BME_disk_next_edgeflag(v2->e, v2, 0, 2);
+
+ lv = BME_edge_getothervert(l,v1);
+ rv = BME_edge_getothervert(r,v2);
+
+ ne = BME_ME(bm,lv,rv);
+ ne->tflag2 = 1; //mark for select
+ BLI_ghash_insert(ehash,e,ne);
+ BME_VISIT(e);
+
+ edar[0] = e;
+ edar[1] = l;
+ edar[2] = ne;
+ edar[3] = r;
+ BME_MF(bm,v1,v2,edar,4);
+ }
+ }
+}
+
+void BME_cap_skirt(BME_Mesh *bm, GHash *vhash, GHash *ehash){
+ BMVert *v, *nv, *v1, *v2;
+ BMEdge *e, **edar, *ne;
+ BME_Loop *l;
+ BMFace *f, *nf;
+ MemArena *edgearena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+ float vec[3];
+ int i, j, del_old =0;
+
+
+ //loop through faces, then loop through their verts. If the verts havnt been visited yet, duplicate these.
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
+ if(BME_SELECTED(f)){
+ l = f->loopbase;
+ do{
+ if(!(BME_ISVISITED(l->v))){ //interior vertex
+ //dupe vert
+ VECCOPY(vec,l->v->co);
+ nv = BME_MV(bm,vec);
+ BLI_ghash_insert(vhash,l->v,nv);
+ //mark for delete
+ l->v->tflag1 = 1;
+ BME_VISIT(l->v); //we dont want to dupe it again.
+ }
+ l=l->next;
+ }while(l!=f->lbase);
+ }
+ }
+
+ //find out if we delete old faces or not. This needs to be improved a lot.....
+ for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
+ if(BME_SELECTED(e) && e->l){
+ i= BME_cycle_length(&(e->l->radial));
+ if(i > 2){
+ del_old = 1;
+ break;
+ }
+ }
+ }
+
+
+ //build a new edge net, insert the new edges into the edge hash
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
+ if(BME_SELECTED(f)){
+ l=f->loopbase;
+ do{
+ if(!(BME_ISVISITED(l->e))){ //interior edge
+ //dupe edge
+ ne = BME_ME(bm,BLI_ghash_lookup(vhash,l->e->v1),BLI_ghash_lookup(vhash,l->e->v2));
+ BLI_ghash_insert(ehash,l->e,ne);
+ //mark for delete
+ l->e->tflag1 = 1;
+ BME_VISIT(l->e); //we dont want to dupe it again.
+ }
+ l=l->next;
+ }while(l!=f->lbase);
+ }
+ }
+
+ //build new faces. grab edges from edge hash.
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
+ if(BME_SELECTED(f)){
+ edar = MEM_callocN(sizeof(BMEdge*)*f->len,"Extrude array");
+ v1 = BLI_ghash_lookup(vhash,f->loopbase->v);
+ v2 = BLI_ghash_lookup(vhash,f->loopbase->next->v);
+ for(i=0,l=f->loopbase; i < f->len; i++,l=l->next){
+ ne = BLI_ghash_lookup(ehash,l->e);
+ edar[i] = ne;
+ }
+ nf=BME_MF(bm,v1,v2,edar,f->len);
+ nf->tflag2 = 1; // mark for select
+ if(del_old) f->tflag1 = 1; //mark for delete
+ MEM_freeN(edar);
+ }
+ }
+ BLI_memarena_free(edgearena);
+}
+
+/*unified extrude code*/
+void BME_extrude_mesh(BME_Mesh *bm, int type){
+
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+ BME_Loop *l;
+
+ struct GHash *vhash, *ehash;
+ /*Build a hash table of old pointers and new pointers.*/
+ vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ BME_selectmode_flush(bm); //ensure consistent selection. contains hack to make sure faces get consistent select.
+ if(type & BME_EXTRUDE_FACES){ //Find selected edges with more than one incident face that is also selected. deselect them.
+ for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
+ int totsel=0;
+ if(e->l){
+ l= e->l;
+ do{
+ if(BME_SELECTED(l->f)) totsel++;
+ l=BME_radial_nextloop(l);
+ }while(l!=e->l);
+ }
+ if(totsel > 1) BME_select_edge(bm,e,0);
+ }
+ }
+
+ /*another hack to ensure consistent selection.....*/
+ for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
+ if(BME_SELECTED(e)) BME_select_edge(bm,e,1);
+ }
+
+ /*now we are ready to extrude*/
+ if(type & BME_EXTRUDE_VERTS) BME_extrude_verts(bm,vhash);
+ if(type & BME_EXTRUDE_EDGES) BME_extrude_skirt(bm,ehash);
+ if(type & BME_EXTRUDE_FACES) BME_cap_skirt(bm,vhash,ehash);
+
+ /*clear all selection flags*/
+ BME_clear_flag_all(bm, SELECT|BME_VISITED);
+ /*go through and fix up selection flags. Anything with BME_NEW should be selected*/
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
+ if(f->tflag2 == 1) BME_select_poly(bm,f,1);
+ if(f->tflag1 == 1) BME_VISIT(f); //mark for delete
+ }
+ for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
+ if(e->tflag2 == 1) BME_select_edge(bm,e,1);
+ if(e->tflag1 == 1) BME_VISIT(e); // mark for delete
+ }
+ for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
+ if(v->tflag2 == 1) BME_select_vert(bm,v,1);
+ if(v->tflag1 == 1) BME_VISIT(v); //mark for delete
+ }
+ /*go through and delete all of our old faces , edges and vertices.*/
+ remove_tagged_polys(bm);
+ remove_tagged_edges(bm);
+ remove_tagged_verts(bm);
+ /*free our hash tables*/
+ BLI_ghash_free(vhash,NULL, NULL); //check usage!
+ BLI_ghash_free(ehash,NULL, NULL); //check usage!
+ BME_selectmode_flush(bm);
+}
+
diff --git a/source/blender/bmesh/tools/BME_weld.c b/source/blender/bmesh/tools/BME_weld.c
new file mode 100644
index 00000000000..a17c07addbc
--- /dev/null
+++ b/source/blender/bmesh/tools/BME_weld.c
@@ -0,0 +1,333 @@
+/*
+ * BME_WELD.C
+ *
+ * This file contains functions for welding
+ * elements in a mesh togather (remove doubles,
+ * collapse, ect).
+ *
+ * TODO:
+ * -Rewrite this to fit into the new API
+ * -Seperate out find doubles code and put it in
+ * BME_queries.c
+ *
+*/
+
+
+/********* qsort routines *********/
+
+
+typedef struct xvertsort {
+ float x;
+ BMVert *v1;
+} xvertsort;
+
+static int vergxco(const void *v1, const void *v2)
+{
+ const xvertsort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+
+struct facesort {
+ unsigned long x;
+ struct BMFace *f;
+};
+
+
+static int vergface(const void *v1, const void *v2)
+{
+ const struct facesort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+
+
+
+/*break this into two functions.... 'find doubles' and 'remove doubles'?*/
+
+static void BME_remove_doubles__splitface(BME_Mesh *bm,BMFace *f,GHash *vhash){
+ BMVert *doub=NULL, *target=NULL;
+ BME_Loop *l;
+ BMFace *f2=NULL;
+ int split=0;
+
+ l=f->loopbase;
+ do{
+ if(l->v->tflag1 == 2){
+ target = BLI_ghash_lookup(vhash,l->v);
+ if((BME_vert_in_face(target,f)) && (target != l->next->v) && (target != l->prev->v)){
+ doub = l->v;
+ split = 1;
+ break;
+ }
+ }
+
+ l= l->next;
+ }while(l!= f->loopbase);
+
+ if(split){
+ f2 = BME_SFME(bm,f,doub,target,NULL);
+ BME_remove_doubles__splitface(bm,f,vhash);
+ BME_remove_doubles__splitface(bm,f2,vhash);
+ }
+}
+
+int BME_remove_doubles(BME_Mesh *bm, float limit)
+{
+
+ /* all verts with (flag & 'flag') are being evaluated */
+ BMVert *v, *v2, *target;
+ BMEdge *e, **edar, *ne;
+ BME_Loop *l;
+ BMFace *f, *nf;
+ xvertsort *sortblock, *sb, *sb1;
+ struct GHash *vhash;
+ struct facesort *fsortblock, *vsb, *vsb1;
+ int a, b, test, amount=0, found;
+ float dist;
+
+ /*Build a hash table of doubles to thier target vert/edge.*/
+ vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ /*count amount of selected vertices*/
+ for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
+ if(BME_SELECTED(v))amount++;
+ }
+
+ /*qsort vertices based upon average of coordinate. We test this way first.*/
+ sb= sortblock= MEM_mallocN(sizeof(xvertsort)*amount,"sortremovedoub");
+
+ for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
+ if(BME_SELECTED(v)){
+ sb->x = v->co[0]+v->co[1]+v->co[2];
+ sb->v1 = v;
+ sb++;
+ }
+ }
+ qsort(sortblock, amount, sizeof(xvertsort), vergxco);
+
+ /* test for doubles */
+ sb= sortblock;
+ for(a=0; a<amount; a++) {
+ v= sb->v1;
+ if(!(v->tflag1)) { //have we tested yet?
+ sb1= sb+1;
+ for(b=a+1; b<amount; b++) {
+ /* first test: simple distance. Simple way to discard*/
+ dist= sb1->x - sb->x;
+ if(dist > limit) break;
+
+ /* second test: have we already done this vertex?
+ (eh this should be swapped, simple equality test should be cheaper than math above... small savings
+ though) */
+ v2= sb1->v1;
+ if(!(v2->tflag1)) {
+ dist= (float)fabs(v2->co[0]-v->co[0]);
+ if(dist<=limit) {
+ dist= (float)fabs(v2->co[1]-v->co[1]);
+ if(dist<=limit) {
+ dist= (float)fabs(v2->co[2]-v->co[2]);
+ if(dist<=limit) {
+ /*v2 is a double of v. We want to throw out v1 and relink everything to v*/
+ BLI_ghash_insert(vhash,v2, v);
+ v->tflag1 = 1; //mark this vertex as a target
+ v->tflag2++; //increase user count for this vert.
+ v2->tflag1 = 2; //mark this vertex as a double.
+ BME_VISIT(v2); //mark for delete
+ }
+ }
+ }
+ }
+ sb1++;
+ }
+ }
+ sb++;
+ }
+ MEM_freeN(sortblock);
+
+
+ /*todo... figure out what this is for...
+ for(eve = em->verts.first; eve; eve=eve->next)
+ if((eve->f & flag) && (eve->f & 128))
+ EM_data_interp_from_verts(eve, eve->tmp.v, eve->tmp.v, 0.5f);
+ */
+
+ /*We cannot collapse a vertex onto another vertex if they share a face and are not connected via a collapsable edge.
+ so to deal with this we simply find these offending vertices and split the faces. Note that this is not optimal, but works.
+ */
+
+
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
+ if(!(BME_NEWELEM(f))){
+ BME_remove_doubles__splitface(bm,f,vhash);
+ }
+ }
+
+ for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
+ /*If either vertices of this edge are a double, we must mark it for removal and we create a new one.*/
+ if(e->v1->tflag1 == 2 || e->v2->tflag1 == 2){
+ v = v2 = NULL;
+ /*For each vertex in the edge, test to find out what it should equal now.*/
+ if(e->v1->tflag1 == 2) v= BLI_ghash_lookup(vhash,e->v1);
+ else v = e->v1;
+ if(e->v2->tflag1 == 2) v2 = BLI_ghash_lookup(vhash,e->v2);
+ else v2 = e->v2;
+
+ /*small optimization, test to see if the edge needs to be rebuilt at all*/
+ if((e->v1 != v) || (e->v2 != v2)){ /*will this always be true of collapsed edges?*/
+ if(v == v2) e->tflag1 = 2; /*mark as a collapsed edge*/
+ else if(!BME_disk_existedge(v,v2)) ne = BME_ME(bm,v,v2);
+ BME_VISIT(e); /*mark for delete*/
+ }
+ }
+ }
+
+
+ /*need to remove double edges as well. To do this we decide on one edge to keep, and if its inserted into hash then we need to remove all other
+ edges incident upon and relink.*/
+ /*
+ * REBUILD FACES
+ *
+ * Loop through double faces and if they have vertices that have been flagged, they need to be rebuilt.
+ * We do this by looking up the face
+ *rebuild faces. loop through original face, for each loop, if the edge it is attached to is marked for delete and has no
+ *other edge in the hash edge, then we know to skip that loop on face recreation. Simple.
+ */
+
+ /*1st loop through, just marking elements*/
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){ //insert bit here about double edges, mark with a flag (e->tflag2) so that we can nuke it later.
+ l = f->loopbase;
+ do{
+ if(l->v->tflag1 == 2) f->tflag1 = 1; //double, mark for rebuild
+ if(l->e->tflag1 != 2) f->tflag2++; //count number of edges in the new face.
+ l=l->next;
+ }while(l!=f->loopbase);
+ }
+
+ /*now go through and create new faces*/
+ for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
+ if(f->tflag1 && f->tflag2 < 3) BME_VISIT(f); //mark for delete
+ else if (f->tflag1 == 1){ /*is the face marked for rebuild*/
+ edar = MEM_callocN(sizeof(BMEdge *)*f->tflag2,"Remove doubles face creation array.");
+ a=0;
+ l = f->loopbase;
+ do{
+ v = l->v;
+ v2 = l->next->v;
+ if(l->v->tflag1 == 2) v = BLI_ghash_lookup(vhash,l->v);
+ if(l->next->v->tflag1 == 2) v2 = BLI_ghash_lookup(vhash,l->next->v);
+ ne = BME_disk_existedge(v,v2); //use BME_disk_next_edgeflag here or something to find the edge that is marked as 'target'.
+ //add in call here to edge doubles hash array... then bobs your uncle.
+ if(ne){
+ edar[a] = ne;
+ a++;
+ }
+ l=l->next;
+ }while(l!=f->loopbase);
+
+ if(BME_vert_in_edge(edar[1],edar[0]->v2)){
+ v = edar[0]->v1;
+ v2 = edar[0]->v2;
+ }
+ else{
+ v = edar[0]->v2;
+ v2 = edar[0]->v1;
+ }
+
+ nf = BME_MF(bm,v,v2,edar,f->tflag2);
+
+ /*copy per loop data here*/
+ if(nf){
+ BME_VISIT(f); //mark for delete
+ }
+ MEM_freeN(edar);
+ }
+ }
+
+ /*count amount of removed vert doubles*/
+ a = 0;
+ for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
+ if(v->tflag1 == 2) a++;
+ }
+
+ /*free memory and return amount removed*/
+ remove_tagged_polys(bm);
+ remove_tagged_edges(bm);
+ remove_tagged_verts(bm);
+ BLI_ghash_free(vhash,NULL, NULL);
+ BME_selectmode_flush(bm);
+ return a;
+}
+
+static void BME_MeshWalk__collapsefunc(void *userData, BMEdge *applyedge){
+ int index;
+ GHash *collected = userData;
+ index = BLI_ghash_size(collected);
+ if(!BLI_ghash_lookup(collected,applyedge->v1)){
+ BLI_ghash_insert(collected,index,applyedge->v1);
+ index++;
+ }
+ if(!BLI_ghash_lookup(collected,applyedge->v2)){
+ BLI_ghash_insert(collected,index,applyedge->v2);
+ }
+}
+
+void BME_collapse_edges(BME_Mesh *bm){
+
+ BMVert *v, *cvert;
+ GHash *collected;
+ float min[3], max[3], cent[3];
+ int size, i=0, j, num=0;
+
+ for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
+ if(!(BME_ISVISITED(v)) && v->edge){
+ /*initiate hash table*/
+ collected = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ /*do the walking.*/
+ BME_MeshWalk(bm,v,BME_MeshWalk__collapsefunc,collected,BME_RESTRICTSELECT);
+ /*now loop through the hash table twice, once to calculate bounding box, second time to do the actual collapse*/
+ size = BLI_ghash_size(collected);
+ /*initial values*/
+ VECCOPY(min,v->co);
+ VECCOPY(max,v->co);
+ cent[0] = cent[1] = cent[2]=0;
+ for(i=0; i<size; i++){
+ cvert = BLI_ghash_lookup(collected,i);
+ cent[0] = cent[0] + cvert->co[0];
+ cent[1] = cent[1] + cvert->co[1];
+ cent[2] = cent[2] + cvert->co[2];
+ }
+
+ cent[0] = cent[0] / size;
+ cent[1] = cent[1] / size;
+ cent[2] = cent[2] / size;
+
+ for(i=0; i<size; i++){
+ cvert = BLI_ghash_lookup(collected,i);
+ VECCOPY(cvert->co,cent);
+ num++;
+ }
+ /*free the hash table*/
+ BLI_ghash_free(collected,NULL, NULL);
+ }
+ }
+ /*if any collapsed, call remove doubles*/
+ if(num){
+ //need to change selection mode here, OR do something else? Or does tool change selection mode?
+ //selectgrep
+ //first clear flags
+ BMEdge *e;
+ BMFace *f;
+ BME_clear_flag_all(bm,BME_VISITED);
+ for(v=BME_first(bm,BME_VERT); v; v=BME_next(bm,BME_VERT,v)) v->tflag1 = v->tflag2 = 0;
+ for(e=BME_first(bm,BME_EDGE); e; e=BME_next(bm,BME_EDGE,e)) e->tflag1 = e->tflag2 = 0;
+ for(f=BME_first(bm,BME_POLY); f; f=BME_next(bm,BME_POLY,f)) f->tflag1 = f->tflag2 = 0;
+ /*now call remove doubles*/
+ BME_remove_doubles(bm,0.0000001);
+ }
+ BME_selectmode_flush(bm);
+} \ No newline at end of file
diff --git a/source/blender/editors/animation/SConscript b/source/blender/editors/animation/SConscript
index 96b05b8bccc..3e5133c1174 100644
--- a/source/blender/editors/animation/SConscript
+++ b/source/blender/editors/animation/SConscript
@@ -4,6 +4,6 @@ Import ('env')
sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf'
-incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include ../../blenloader'
+incs += ' ../../bmesh ../../windowmanager #/intern/guardedalloc #/extern/glew/include ../../blenloader'
env.BlenderLib ( 'bf_editors_animation', sources, Split(incs), [], libtype=['core'], priority=[125] )
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index 3b65e777200..95324554a06 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -731,10 +731,10 @@ EnumPropertyItem *ANIM_keying_sets_enum_itemf (bContext *C, PointerRNA *UNUSED(p
* - these are listed in the order in which they were defined for the active scene
*/
if (scene->keyingsets.first) {
- for (ks= scene->keyingsets.first; ks; ks= ks->next, i++) {
+ for (ks= scene->keyingsets.first; ks; ks= ks->next) {
if (ANIM_keyingset_context_ok_poll(C, ks)) {
item_tmp.identifier= item_tmp.name= ks->name;
- item_tmp.value= i;
+ item_tmp.value= i++;
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
}
@@ -745,11 +745,11 @@ EnumPropertyItem *ANIM_keying_sets_enum_itemf (bContext *C, PointerRNA *UNUSED(p
/* builtin Keying Sets */
i= -1;
- for (ks= builtin_keyingsets.first; ks; ks= ks->next, i--) {
+ for (ks= builtin_keyingsets.first; ks; ks= ks->next) {
/* only show KeyingSet if context is suitable */
if (ANIM_keyingset_context_ok_poll(C, ks)) {
item_tmp.identifier= item_tmp.name= ks->name;
- item_tmp.value= i;
+ item_tmp.value= i--;
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
}
diff --git a/source/blender/editors/armature/SConscript b/source/blender/editors/armature/SConscript
index ded82b3dfb7..b85a13ced85 100644
--- a/source/blender/editors/armature/SConscript
+++ b/source/blender/editors/armature/SConscript
@@ -5,6 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna ../../imbuf ../../blenloader'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../render/extern/include ../../bmesh'
incs += ' ../../gpu ../../makesrna #/intern/opennl/extern'
if env['OURPLATFORM'] == 'linux':
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c
index 15c8868f9b9..34ec2605cdd 100644
--- a/source/blender/editors/armature/editarmature.c
+++ b/source/blender/editors/armature/editarmature.c
@@ -2126,7 +2126,7 @@ typedef struct UndoArmature {
ListBase lb;
} UndoArmature;
-static void undoBones_to_editBones(void *uarmv, void *armv)
+static void undoBones_to_editBones(void *uarmv, void *armv, void *UNUSED(data))
{
UndoArmature *uarm= uarmv;
bArmature *arm= armv;
@@ -2159,7 +2159,7 @@ static void undoBones_to_editBones(void *uarmv, void *armv)
}
}
-static void *editBones_to_undoBones(void *armv)
+static void *editBones_to_undoBones(void *armv, void *UNUSED(obdata))
{
bArmature *arm= armv;
UndoArmature *uarm;
@@ -4524,7 +4524,8 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
/* for each vertex in the mesh */
for (i=0; i < mesh->totvert; i++) {
- iflip = (dgroupflip)? mesh_get_x_mirror_vert(ob, i): 0;
+ /*BMESH_TODO*/
+ iflip = 0; //(dgroupflip)? mesh_get_x_mirror_vert(ob, i): 0;
/* for each skinnable bone */
for (j=0; j < numbones; ++j) {
@@ -4717,7 +4718,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
}
/* only generated in some cases but can call anyway */
- mesh_octree_table(ob, NULL, NULL, 'e');
+ //BMESH_TODO mesh_octree_table(ob, NULL, NULL, 'e');
/* free the memory allocated */
MEM_freeN(bonelist);
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 53d0141f44d..86720a9bbf4 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -41,10 +41,10 @@
#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
+#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
#include "BLI_memarena.h"
-#include "BLI_utildefines.h"
#include "BKE_DerivedMesh.h"
#include "BKE_modifier.h"
@@ -709,12 +709,16 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
laplacian_system_construct_end(sys);
+#if 0 /*BMESH_TODO*/
if(dgroupflip) {
vertsflipped = MEM_callocN(sizeof(int)*me->totvert, "vertsflipped");
for(a=0; a<me->totvert; a++)
vertsflipped[a] = mesh_get_x_mirror_vert(ob, a);
}
-
+#else
+ dgroupflip = 0;
+#endif
+
/* compute weights per bone */
for(j=0; j<numsource; j++) {
if(!selected[j])
@@ -1187,8 +1191,8 @@ static int meshdeform_intersect(MeshDeformBind *mdb, MeshDeformIsect *isec)
isec->labda= 1e10;
- mface= mdb->cagedm->getFaceArray(mdb->cagedm);
- totface= mdb->cagedm->getNumFaces(mdb->cagedm);
+ mface= mdb->cagedm->getTessFaceArray(mdb->cagedm);
+ totface= mdb->cagedm->getNumTessFaces(mdb->cagedm);
add_v3_v3v3(end, isec->start, isec->vec);
@@ -1877,7 +1881,7 @@ static void harmonic_coordinates_bind(Scene *UNUSED(scene), MeshDeformModifierDa
static void heat_weighting_bind(Scene *scene, DerivedMesh *dm, MeshDeformModifierData *mmd, MeshDeformBind *mdb)
{
LaplacianSystem *sys;
- MFace *mface= dm->getFaceArray(dm), *mf;
+ MFace *mface= dm->getTessFaceArray(dm), *mf;
int totvert= dm->getNumVerts(dm);
int totface= dm->getNumFaces(dm);
float solution, weight;
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c
index 0b214e48b6a..2e5dafeb507 100644
--- a/source/blender/editors/armature/reeb.c
+++ b/source/blender/editors/armature/reeb.c
@@ -55,6 +55,7 @@
//#include "BIF_toolbox.h"
//#include "BIF_graphics.h"
+#include "BKE_mesh.h"
//#include "blendef.h"
@@ -3381,9 +3382,12 @@ static int iteratorStopped(void *arg)
ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C)
{
+ (void)C;
+ return NULL;
+#if 0
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
- EditMesh *em =( (Mesh*)obedit->data)->edit_mesh;
+ EditMesh *em =BKE_mesh_get_editmesh(((Mesh*)obedit->data));
EdgeIndex indexed_edges;
VertexData *data;
ReebGraph *rg = NULL;
@@ -3479,7 +3483,14 @@ ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C)
MEM_freeN(data);
+ /*no need to load the editmesh back into the object, just
+ free it (avoids ngon conversion issues too going back the
+ other way)*/
+ free_editMesh(em);
+ MEM_freeN(em);
+
return rg;
+#endif
}
#if 0
diff --git a/source/blender/editors/curve/SConscript b/source/blender/editors/curve/SConscript
index efb56ce5466..95dd7fc6233 100644
--- a/source/blender/editors/curve/SConscript
+++ b/source/blender/editors/curve/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
-incs += ' ../../gpu ../../blenloader'
+incs += ' ../../bmesh ../../gpu ../../blenloader'
incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
env.BlenderLib ( 'bf_editors_curve', sources, Split(incs), [], libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 4087002598e..4f6519bad5b 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -6541,12 +6541,12 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
ListBase *editnurb;
Nurb *nu;
int newob= 0;
- int enter_editmode;
+ int enter_editmode, is_aligned;
unsigned int layer;
float loc[3], rot[3];
float mat[4][4];
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+ if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, &is_aligned))
return OPERATOR_CANCELLED;
if (!isSurf) { /* adding curve */
@@ -6941,7 +6941,7 @@ static void *undo_check_lastsel(void *lastsel, Nurb *nu, Nurb *newnu)
return NULL;
}
-static void undoCurve_to_editCurve(void *ucu, void *obe)
+static void undoCurve_to_editCurve(void *ucu, void *UNUSED(edata), void *obe)
{
Object *obedit= obe;
Curve *cu= (Curve*)obedit->data;
@@ -6991,10 +6991,9 @@ static void undoCurve_to_editCurve(void *ucu, void *obe)
ED_curve_updateAnimPaths(obedit);
}
-static void *editCurve_to_undoCurve(void *obe)
+static void *editCurve_to_undoCurve(void *UNUSED(edata), void *obdata)
{
- Object *obedit= obe;
- Curve *cu= (Curve*)obedit->data;
+ Curve *cu= obdata;
ListBase *nubase= curve_editnurbs(cu);
UndoCurve *undoCurve;
EditNurb *editnurb= cu->editnurb, tmpEditnurb;
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 1ac920b048a..14c687cc8b1 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -1784,7 +1784,7 @@ void FONT_OT_unlink(wmOperatorType *ot)
/* **************** undo for font object ************** */
-static void undoFont_to_editFont(void *strv, void *ecu)
+static void undoFont_to_editFont(void *strv, void *ecu, void *UNUSED(obdata))
{
Curve *cu= (Curve *)ecu;
EditFont *ef= cu->editfont;
@@ -1801,7 +1801,7 @@ static void undoFont_to_editFont(void *strv, void *ecu)
update_string(cu);
}
-static void *editFont_to_undoFont(void *ecu)
+static void *editFont_to_undoFont(void *ecu, void *UNUSED(obdata))
{
Curve *cu= (Curve *)ecu;
EditFont *ef= cu->editfont;
diff --git a/source/blender/editors/datafiles/SConscript b/source/blender/editors/datafiles/SConscript
index dd0db90af44..0cbeb96ffdb 100644
--- a/source/blender/editors/datafiles/SConscript
+++ b/source/blender/editors/datafiles/SConscript
@@ -4,6 +4,6 @@ Import ('env')
sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
-incs += ' #/intern/guardedalloc'
+incs += ' ../../bmesh #/intern/guardedalloc'
env.BlenderLib ( 'bf_editor_datafiles', sources, Split(incs), [], libtype=['core', 'player'], priority=[235, 30] )
diff --git a/source/blender/editors/gpencil/SConscript b/source/blender/editors/gpencil/SConscript
index d2fd9e5fe9d..6c23e77208a 100644
--- a/source/blender/editors/gpencil/SConscript
+++ b/source/blender/editors/gpencil/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
-incs += ' ../../gpu ../../blenloader'
+incs += ' ../../gpu ../../blenloader ../../bmesh'
incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
env.BlenderLib ( 'bf_editors_gpencil', sources, Split(incs), [], libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 1bab362fe55..4ec90d210ad 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -48,7 +48,6 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_gpencil_types.h"
-#include "DNA_windowmanager_types.h"
#include "UI_view2d.h"
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 5d1e02a6cab..f0fc62c07b1 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -43,7 +43,6 @@ struct EditVert;
struct EditEdge;
struct EditFace;
struct bContext;
-struct wmOperator;
struct wmWindowManager;
struct wmKeyConfig;
struct ReportList;
@@ -61,132 +60,176 @@ struct MCol;
struct UvVertMap;
struct UvMapVert;
struct CustomData;
+struct BMEditMesh;
+struct BMEditSelection;
+struct BMesh;
+struct BMVert;
+struct MLoopCol;
+struct BMEdge;
+struct BMFace;
+struct UvVertMap;
+struct UvMapVert;
struct Material;
struct Object;
struct rcti;
+struct wmOperator;
+struct ToolSettings;
-#define EM_FGON_DRAW 1 // face flag
-#define EM_FGON 2 // edge and face flag both
+// edge and face flag both
+#define EM_FGON 2
+// face flag
+#define EM_FGON_DRAW 1
/* editbutflag */
-#define B_CLOCKWISE 1
-#define B_KEEPORIG 2
-#define B_BEAUTY 4
-#define B_SMOOTH 8
-#define B_BEAUTY_SHORT 0x10
-#define B_AUTOFGON 0x20
-#define B_KNIFE 0x80
+#define B_CLOCKWISE 1
+#define B_KEEPORIG 2
+#define B_BEAUTY 4
+#define B_SMOOTH 8
+#define B_BEAUTY_SHORT 16
+#define B_AUTOFGON 32
+#define B_KNIFE 0x80
#define B_PERCENTSUBD 0x40
//#define B_MESH_X_MIRROR 0x100 // deprecated, use mesh
#define B_JOINTRIA_UV 0x200
#define B_JOINTRIA_VCOL 0X400
#define B_JOINTRIA_SHARP 0X800
#define B_JOINTRIA_MAT 0X1000
-#define B_FRACTAL 0x2000
-#define B_SPHERE 0x4000
+#define B_FRACTAL 0x2000
+#define B_SPHERE 0x4000
-/* meshtools.c */
+float *bm_get_cd_float(struct CustomData *cdata, void *data, int type);
-intptr_t mesh_octree_table(struct Object *ob, struct EditMesh *em, float *co, char mode);
-long mesh_mirrtopo_table(struct Object *ob, char mode);
+/* bmeshutils.c */
-struct EditVert *editmesh_get_x_mirror_vert(struct Object *ob, struct EditMesh *em, struct EditVert *eve, float *co, int index);
-int mesh_get_x_mirror_vert(struct Object *ob, int index);
-int *mesh_get_x_mirror_faces(struct Object *ob, struct EditMesh *em);
-
-int join_mesh_exec(struct bContext *C, struct wmOperator *op);
-int join_mesh_shapes_exec(struct bContext *C, struct wmOperator *op);
-
-/* mesh_ops.c */
-void ED_operatortypes_mesh(void);
-void ED_operatormacros_mesh(void);
-void ED_keymap_mesh(struct wmKeyConfig *keyconf);
+/*
+ [note: I've decided to use ideasman's code for non-editmode stuff, but since
+ it has a big "not for editmode!" disclaimer, I'm going to keep what I have here
+ - joeedh]
+
+ x-mirror editing api. usage:
+
+ EDBM_CacheMirrorVerts(em);
+ ...
+ ...
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ mirrorv = EDBM_GetMirrorVert(em, v);
+ }
+ ...
+ ...
+ EDBM_EndMirrorCache(em);
+
+ note: why do we only allow x axis mirror editing?
+ */
+void EDBM_CacheMirrorVerts(struct BMEditMesh *em);
+
+/*retrieves mirrored cache vert, or NULL if there isn't one.
+ note: calling this without ensuring the mirror cache state
+ is bad.*/
+struct BMVert *EDBM_GetMirrorVert(struct BMEditMesh *em, struct BMVert *v);
+void EDBM_EndMirrorCache(struct BMEditMesh *em);
+
+void EDBM_RecalcNormals(struct BMEditMesh *em);
+
+void EDBM_MakeEditBMesh(struct ToolSettings *ts, struct Scene *scene, struct Object *ob);
+void EDBM_FreeEditBMesh(struct BMEditMesh *tm);
+void EDBM_LoadEditBMesh(struct Scene *scene, struct Object *ob);
+
+void EDBM_init_index_arrays(struct BMEditMesh *em, int forvert, int foredge, int forface);
+void EDBM_free_index_arrays(struct BMEditMesh *em);
+struct BMVert *EDBM_get_vert_for_index(struct BMEditMesh *em, int index);
+struct BMEdge *EDBM_get_edge_for_index(struct BMEditMesh *em, int index);
+struct BMFace *EDBM_get_face_for_index(struct BMEditMesh *em, int index);
+
+int EDBM_CallAndSelectOpf(struct BMEditMesh *em, struct wmOperator *op,
+ const char *selectslot, const char *fmt, ...);
+
+/*flushes based on the current select mode. if in vertex select mode,
+ verts select/deselect edges and faces, if in edge select mode,
+ edges select/deselect faces and vertices, and in face select mode faces select/deselect
+ edges and vertices.*/
+void EDBM_selectmode_flush(struct BMEditMesh *em);
+
+int EDBM_get_actSelection(struct BMEditMesh *em, struct BMEditSelection *ese);
+
+/*exactly the same as EDBM_selectmode_flush, but you pass in the selectmode
+ instead of using the current one*/
+void EDBM_select_flush(struct BMEditMesh *em, int selectmode);
+void EDBM_deselect_flush(struct BMEditMesh *em);
+
+void EDBM_selectmode_set(struct BMEditMesh *em);
+void EDBM_convertsel(struct BMEditMesh *em, short oldmode, short selectmode);
+void undo_push_mesh(struct bContext *C, const char *name);
+void EDBM_editselection_center(struct BMEditMesh *em, float *center, struct BMEditSelection *ese);
+void EDBM_editselection_plane(struct BMEditMesh *em, float *plane, struct BMEditSelection *ese);
+void EDBM_editselection_normal(float *normal, struct BMEditSelection *ese);
+int EDBM_vertColorCheck(struct BMEditMesh *em);
+void EDBM_validate_selections(struct BMEditMesh *em);
-/* editmesh.c */
-void make_editMesh(struct Scene *scene, struct Object *ob);
-void load_editMesh(struct Scene *scene, struct Object *ob);
-void remake_editMesh(struct Scene *scene, struct Object *ob);
-void free_editMesh(struct EditMesh *em);
+void EDBM_hide_mesh(struct BMEditMesh *em, int swap);
+void EDBM_reveal_mesh(struct BMEditMesh *em);
-void recalc_editnormals(struct EditMesh *em);
+int EDBM_check_backbuf(unsigned int index);
+int EDBM_mask_init_backbuf_border(struct ViewContext *vc, int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax);
+void EDBM_free_backbuf(void);
+int EDBM_init_backbuf_border(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
+int EDBM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short rads);
-void EM_init_index_arrays(struct EditMesh *em, int forVert, int forEdge, int forFace);
-void EM_free_index_arrays(void);
-struct EditVert *EM_get_vert_for_index(int index);
-struct EditEdge *EM_get_edge_for_index(int index);
-struct EditFace *EM_get_face_for_index(int index);
-int EM_texFaceCheck(struct EditMesh *em);
-int EM_vertColorCheck(struct EditMesh *em);
+void EDBM_deselect_by_material(struct BMEditMesh *em, const short index, const short select);
-void undo_push_mesh(struct bContext *C, const char *name);
+void EDBM_select_swap(struct BMEditMesh *em); /* exported for UV */
-void paintvert_flush_flags(struct Object *ob);
-void paintvert_deselect_all_visible(struct Object *ob, int action, short flush_flags);
+int EDBM_texFaceCheck(struct BMEditMesh *em);
+struct MTexPoly *EDBM_get_active_mtexpoly(struct BMEditMesh *em, struct BMFace **act_efa, int sloppy);
-/* editmesh_lib.c */
+void EDBM_free_uv_vert_map(struct UvVertMap *vmap);
+struct UvMapVert *EDBM_get_uv_map_vert(struct UvVertMap *vmap, unsigned int v);
+struct UvVertMap *EDBM_make_uv_vert_map(struct BMEditMesh *em, int selected, int do_face_idx_array, float *limit);
+void EM_add_data_layer(struct BMEditMesh *em, struct CustomData *data, int type, const char *name);
+void EM_free_data_layer(struct BMEditMesh *em, struct CustomData *data, int type);
-struct EditFace *EM_get_actFace(struct EditMesh *em, int sloppy);
-void EM_set_actFace(struct EditMesh *em, struct EditFace *efa);
-float EM_face_area(struct EditFace *efa);
+void EDBM_toggle_select_all(struct BMEditMesh *em);
+void EDBM_set_flag_all(struct BMEditMesh *em, int flag);
+void EDBM_clear_flag_all(struct BMEditMesh *em, int flag);
+void EDBM_automerge(struct Scene *scene, struct Object *ob, int update);
-void EM_select_edge(struct EditEdge *eed, int sel);
-void EM_select_face(struct EditFace *efa, int sel);
-void EM_select_face_fgon(struct EditMesh *em, struct EditFace *efa, int val);
-void EM_select_swap(struct EditMesh *em);
-void EM_toggle_select_all(struct EditMesh *em);
-void EM_select_all(struct EditMesh *em);
-void EM_deselect_all(struct EditMesh *em);
-void EM_selectmode_flush(struct EditMesh *em);
-void EM_deselect_flush(struct EditMesh *em);
-void EM_selectmode_set(struct EditMesh *em);
-void EM_select_flush(struct EditMesh *em);
-void EM_convertsel(struct EditMesh *em, short oldmode, short selectmode);
-void EM_validate_selections(struct EditMesh *em);
-void EM_selectmode_to_scene(struct Scene *scene, struct Object *obedit);
+/* editmesh_mods.c */
+extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs;
- /* exported to transform */
-int EM_get_actSelection(struct EditMesh *em, struct EditSelection *ese);
-void EM_editselection_normal(float *normal, struct EditSelection *ese);
-void EM_editselection_plane(float *plane, struct EditSelection *ese);
-void EM_editselection_center(float *center, struct EditSelection *ese);
+intptr_t mesh_octree_table(struct Object *ob, struct BMEditMesh *em, float *co, char mode);
+long mesh_mirrtopo_table(struct Object *ob, char mode);
-struct UvVertMap *EM_make_uv_vert_map(struct EditMesh *em, int selected, int do_face_idx_array, float *limit);
-struct UvMapVert *EM_get_uv_map_vert(struct UvVertMap *vmap, unsigned int v);
-void EM_free_uv_vert_map(struct UvVertMap *vmap);
+//BMESH_TODO void EM_cache_x_mirror_vert(struct Object *ob, struct BMEditMesh *em);
-void EM_add_data_layer(struct EditMesh *em, struct CustomData *data, int type, const char *name);
-void EM_free_data_layer(struct EditMesh *em, struct CustomData *data, int type);
+int mouse_mesh(struct bContext *C, const int mval[2], short extend);
-void EM_make_hq_normals(struct EditMesh *em);
-void EM_solidify(struct EditMesh *em, float dist);
+struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em, struct BMVert *eve, float *co, int index);
+int mesh_get_x_mirror_vert(struct Object *ob, int index);
+int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em);
-int EM_deselect_nth(struct EditMesh *em, int nth);
+int join_mesh_exec(struct bContext *C, struct wmOperator *op);
+int join_mesh_shapes_exec(struct bContext *C, struct wmOperator *op);
-void EM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct Object *obedit, struct EditMesh *em);
+/* mesh_ops.c */
+void ED_operatortypes_mesh(void);
+void ED_operatormacros_mesh(void);
+void ED_keymap_mesh(struct wmKeyConfig *keyconf);
-/* editmesh_mods.c */
-extern unsigned int em_vertoffs, em_solidoffs, em_wireoffs;
-void EM_cache_x_mirror_vert(struct Object *ob, struct EditMesh *em);
-int mouse_mesh(struct bContext *C, const int mval[2], short extend);
-int EM_check_backbuf(unsigned int index);
-int EM_mask_init_backbuf_border(struct ViewContext *vc, int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax);
-void EM_free_backbuf(void);
-int EM_init_backbuf_border(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
-int EM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short rads);
+/* editmesh.c */
-void EM_hide_mesh(struct EditMesh *em, int swap);
-void EM_reveal_mesh(struct EditMesh *em);
+void ED_spacetypes_init(void);
+void ED_keymap_mesh(struct wmKeyConfig *keyconf);
-void EM_select_by_material(struct EditMesh *em, int index);
-void EM_deselect_by_material(struct EditMesh *em, int index);
+/* bmesh_mods.c */
+extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs;
-void EM_automerge(struct Scene *scene, struct Object *obedit, int update);
+/* bmesh_tools.c (could be moved) */
+void EMBM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct Object *obedit, struct BMEditMesh *em);
/* editface.c */
void paintface_flush_flags(struct Object *ob);
-struct MTFace *EM_get_active_mtface(struct EditMesh *em, struct EditFace **act_efa, struct MCol **mcol, int sloppy);
+struct MTexPoly *EM_get_active_mtexpoly(struct BMEditMesh *em, struct BMFace **act_efa, struct MLoopCol **col, int sloppy);
int paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], int extend);
int do_paintface_box_select(struct ViewContext *vc, struct rcti *rect, int select, int extend);
void paintface_deselect_all_visible(struct Object *ob, int action, short flush_flags);
@@ -196,6 +239,9 @@ int paintface_minmax(struct Object *ob, float *min, float *max);
void paintface_hide(struct Object *ob, const int unselected);
void paintface_reveal(struct Object *ob);
+void paintvert_deselect_all_visible(struct Object *ob, int action, short flush_flags);
+void paintvert_flush_flags(struct Object *ob);
+
/* object_vgroup.c */
#define WEIGHT_REPLACE 1
@@ -217,18 +263,26 @@ void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum
void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum);
float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum);
-/*needed by edge slide*/
-struct EditVert *editedge_getOtherVert(struct EditEdge *eed, struct EditVert *eve);
-struct EditVert *editedge_getSharedVert(struct EditEdge *eed, struct EditEdge *eed2);
-int editedge_containsVert(struct EditEdge *eed, struct EditVert *eve);
-int editface_containsVert(struct EditFace *efa, struct EditVert *eve);
-int editface_containsEdge(struct EditFace *efa, struct EditEdge *eed);
-short sharesFace(struct EditMesh *em, struct EditEdge *e1, struct EditEdge *e2);
+/**
+ * findnearestvert
+ *
+ * dist (in/out): minimal distance to the nearest and at the end, actual distance
+ * sel: selection bias
+ * if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
+ * if 0, unselected vertice are given the bias
+ * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased
+ */
+
+struct BMVert *EDBM_findnearestvert(struct ViewContext *vc, int *dist, short sel, short strict);
+struct BMEdge *EDBM_findnearestedge(struct ViewContext *vc, int *dist);
+struct BMFace *EDBM_findnearestface(struct ViewContext *vc, int *dist);
/* mesh_data.c */
// void ED_mesh_geometry_add(struct Mesh *mesh, struct ReportList *reports, int verts, int edges, int faces);
+void ED_mesh_polys_add(struct Mesh *mesh, struct ReportList *reports, int count);
void ED_mesh_faces_add(struct Mesh *mesh, struct ReportList *reports, int count);
void ED_mesh_edges_add(struct Mesh *mesh, struct ReportList *reports, int count);
+void ED_mesh_loops_add(struct Mesh *mesh, struct ReportList *reports, int count);
void ED_mesh_vertices_add(struct Mesh *mesh, struct ReportList *reports, int count);
void ED_mesh_transform(struct Mesh *me, float *mat);
@@ -241,9 +295,12 @@ int ED_mesh_uv_texture_remove(struct bContext *C, struct Object *ob, struct Mesh
int ED_mesh_color_add(struct bContext *C, struct Scene *scene, struct Object *ob, struct Mesh *me, const char *name, int active_set);
int ED_mesh_color_remove(struct bContext *C, struct Object *ob, struct Mesh *me);
+void EDBM_selectmode_to_scene(struct bContext *C);
+
+#include "../mesh/editbmesh_bvh.h"
+
#ifdef __cplusplus
}
#endif
#endif /* ED_MESH_H */
-
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 4e0f59afc15..3ae3876c18a 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -102,8 +102,11 @@ float ED_object_new_primitive_matrix(struct bContext *C, struct Object *editob,
void ED_object_add_generic_props(struct wmOperatorType *ot, int do_editmode);
int ED_object_add_generic_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op, float *loc, float *rot, int *enter_editmode, unsigned int *layer);
-struct Object *ED_object_add_type(struct bContext *C, int type, float *loc, float *rot, int enter_editmode, unsigned int layer);
+int ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op,
+ float *loc, float *rot, int *enter_editmode, unsigned int *layer, int *is_view_aligned);
+
+struct Object *ED_object_add_type(struct bContext *C, int type, float *loc,
+ float *rot, int enter_editmode, unsigned int layer);
void ED_object_single_users(struct Main *bmain, struct Scene *scene, int full);
void ED_object_single_user(struct Scene *scene, struct Object *ob);
diff --git a/source/blender/editors/include/ED_toolmode.h b/source/blender/editors/include/ED_toolmode.h
new file mode 100755
index 00000000000..733ca6c74fc
--- /dev/null
+++ b/source/blender/editors/include/ED_toolmode.h
@@ -0,0 +1,80 @@
+#if 0
+/**
+ * $Id:
+ *
+ * ***** 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) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_TOOLMODE_H
+#define ED_TOOLMODE_H
+
+struct ID;
+struct View3D;
+struct ARegion;
+struct bContext;
+struct wmWindowManager;
+struct wmKeyConfig;
+struct ReportList;
+struct ViewContext;
+struct bDeformGroup;
+struct MDeformWeight;
+struct MDeformVert;
+struct Scene;
+struct Mesh;
+struct MCol;
+struct UvVertMap;
+struct UvMapVert;
+struct CustomData;
+struct BMEditMesh;
+struct BMEditSelection;
+struct BMesh;
+struct BMVert;
+struct BMEdge;
+struct BMFace;
+struct UvVertMap;
+struct UvMapVert;
+struct Material;
+struct Object;
+struct rcti;
+struct wmOperator;
+
+typedef struct ToolModeDefine {
+ short idtype, icon;
+ char *name;
+ void (*create)(void *args);
+ void (*free)(void *self);
+
+ /*called when mode is set active*/
+ void (*enter)(void *self, struct bContext *C);
+ void (*exit)(void *self, struct bContext *C);
+
+ /*called on draw*/
+ void (*draw)(void *self, struct bContext *C);
+ /*modal is option, and should be used carefully*/
+ void (*modal)(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+
+ /*keymap stuff*/
+ void (*create_keymap)(struct wmKeyConfig *km);
+ void (*keymap_poll)(struct bContext *C);
+};
+#endif
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index c08e5eabbd3..db7b736e3eb 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -38,7 +38,7 @@ struct ARegion;
struct uiBlock;
struct wmOperator;
struct wmOperatorType;
-struct EditMesh;
+struct BMEditMesh;
struct Mesh;
/* ed_util.c */
@@ -70,8 +70,8 @@ int ED_undo_valid (const struct bContext *C, const char *undoname);
void undo_editmode_push(struct bContext *C, const char *name,
void * (*getdata)(struct bContext *C),
void (*freedata)(void *),
- void (*to_editmode)(void *, void *),
- void *(*from_editmode)(void *),
+ void (*to_editmode)(void *, void *, void *),
+ void *(*from_editmode)(void *, void *),
int (*validate_undo)(void *, void *));
@@ -79,7 +79,7 @@ void undo_editmode_clear (void);
/* crazyspace.c */
float *crazyspace_get_mapped_editverts(struct Scene *scene, struct Object *obedit);
-void crazyspace_set_quats_editmesh(struct EditMesh *em, float *origcos, float *mappedcos, float *quats);
+void crazyspace_set_quats_editmesh(struct BMEditMesh *em, float *origcos, float *mappedcos, float *quats);
void crazyspace_set_quats_mesh(struct Mesh *me, float *origcos, float *mappedcos, float *quats);
int sculpt_get_first_deform_matrices(struct Scene *scene, struct Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]);
void crazyspace_build_sculpt(struct Scene *scene, struct Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]);
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 2b4c213bc52..44c5113413d 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -38,6 +38,10 @@ struct Object;
struct Scene;
struct bContext;
struct wmKeyConfig;
+struct BMEditMesh;
+struct BMLoop;
+struct BMFace;
+struct MTexPoly;
/* uvedit_ops.c */
void ED_operatortypes_uvedit(void);
@@ -50,18 +54,17 @@ int ED_uvedit_test_silent(struct Object *obedit);
int ED_uvedit_test(struct Object *obedit);
/* visibility and selection */
-int uvedit_edge_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
-int uvedit_face_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf);
-int uvedit_face_visible_nolocal(struct Scene *scene, struct EditFace *efa);
-int uvedit_face_visible(struct Scene *scene, struct Image *ima, struct EditFace *efa, struct MTFace *tf);
-int uvedit_uv_selected(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
-void uvedit_edge_deselect(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
-void uvedit_edge_select(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
-void uvedit_face_deselect(struct Scene *scene, struct EditFace *efa, struct MTFace *tf);
-void uvedit_face_select(struct Scene *scene, struct EditFace *efa, struct MTFace *tf);
-void uvedit_uv_deselect(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
-void uvedit_uv_select(struct Scene *scene, struct EditFace *efa, struct MTFace *tf, int i);
+int uvedit_face_visible(struct Scene *scene, struct Image *ima, struct BMFace *efa, struct MTexPoly *tf);
+int uvedit_face_selected(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa);
+int uvedit_edge_selected(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l);
+int uvedit_uv_selected(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l);
+int uvedit_face_select(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa);
+int uvedit_face_deselect(struct Scene *scene, struct BMEditMesh *em, struct BMFace *efa);
+void uvedit_edge_select(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l);
+void uvedit_edge_deselect(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l);
+void uvedit_uv_select(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l);
+void uvedit_uv_deselect(struct BMEditMesh *em, struct Scene *scene, struct BMLoop *l);
int ED_uvedit_nearest_uv(struct Scene *scene, struct Object *obedit, struct Image *ima, float co[2], float uv[2]);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index f69abb0996a..884992d8765 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -38,8 +38,11 @@ struct BezTriple;
struct bglMats;
struct BoundBox;
struct BPoint;
-struct EditEdge;
-struct EditFace;
+struct Nurb;
+struct BezTriple;
+struct BMVert;
+struct BMEdge;
+struct BMFace;
struct EditVert;
struct ImBuf;
struct Main;
@@ -62,7 +65,7 @@ typedef struct ViewContext {
struct ARegion *ar;
struct View3D *v3d;
struct RegionView3D *rv3d;
- struct EditMesh *em;
+ struct BMEditMesh *em;
int mval[2];
} ViewContext;
@@ -183,9 +186,9 @@ void ED_view3d_from_object(struct Object *ob, float ofs[3], float quat[4], float
*/
void ED_view3d_to_object(struct Object *ob, const float ofs[3], const float quat[4], const float dist);
-#if 0 /* UNUSED */
+//#if 0 /* UNUSED */
void view3d_unproject(struct bglMats *mats, float out[3], const short x, const short y, const float z);
-#endif
+//#endif
/* Depth buffer */
void ED_view3d_depth_update(struct ARegion *ar);
@@ -211,12 +214,13 @@ int ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d, floa
int ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, struct rctf *viewplane, float *clipsta, float *clipend, float *pixsize);
void ED_view3d_ob_project_mat_get(struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]);
void ED_view3d_project_float(struct ARegion *a, const float vec[3], float adr[2], float mat[4][4]);
+void ED_view3d_project_float_v3(struct ARegion *a, float *vec, float *adr, float mat[4][4]);
void ED_view3d_calc_camera_border(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, struct rctf *viewborder_r, short do_shift);
/* drawobject.c iterators */
-void mesh_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct EditVert *eve, int x, int y, int index), void *userData, int clipVerts);
-void mesh_foreachScreenEdge(struct ViewContext *vc, void (*func)(void *userData, struct EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts);
-void mesh_foreachScreenFace(struct ViewContext *vc, void (*func)(void *userData, struct EditFace *efa, int x, int y, int index), void *userData);
+void mesh_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct BMVert *eve, int x, int y, int index), void *userData, int clipVerts);
+void mesh_foreachScreenEdge(struct ViewContext *vc, void (*func)(void *userData, struct BMEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts);
+void mesh_foreachScreenFace(struct ViewContext *vc, void (*func)(void *userData, struct BMFace *efa, int x, int y, int index), void *userData);
void nurbs_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct Nurb *nu, struct BPoint *bp, struct BezTriple *bezt, int beztindex, int x, int y), void *userData);
void lattice_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct BPoint *bp, int x, int y), void *userData);
diff --git a/source/blender/editors/interface/SConscript b/source/blender/editors/interface/SConscript
index ec5ae99755d..2d6d5cd235e 100644
--- a/source/blender/editors/interface/SConscript
+++ b/source/blender/editors/interface/SConscript
@@ -8,7 +8,7 @@ for source in env.Glob('*_api.c'):
incs = '../include ../../blenlib ../../blenfont ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc ../../gpu'
-incs += ' #/extern/glew/include ../../blenloader'
+incs += ' #/extern/glew/include ../../blenloader ../../bmesh'
incs += ' ../../python/' # python button eval
defs = []
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index e49cb4898d9..9f77317292c 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -1437,11 +1437,8 @@ static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data,
ui_check_but(but);
}
-/* this is used for both utf8 and ascii, its meant to be used for single keys,
- * notie the buffer is either copied or not, so its not suitable for pasting in
- * - campbell */
-static int ui_textedit_type_buf(uiBut *but, uiHandleButtonData *data,
- const char *utf8_buf, int utf8_buf_len)
+/* note: utf8 & ascii funcs should be merged */
+static int ui_textedit_type_utf8(uiBut *but, uiHandleButtonData *data, const char utf8_buf[6])
{
char *str;
int len, changed= 0;
@@ -1450,7 +1447,7 @@ static int ui_textedit_type_buf(uiBut *but, uiHandleButtonData *data,
len= strlen(str);
if(len-(but->selend - but->selsta)+1 <= data->maxlen) {
- int step= utf8_buf_len;
+ int step= BLI_str_utf8_size(utf8_buf);
/* type over the current selection */
if ((but->selend - but->selsta) > 0) {
@@ -1471,17 +1468,8 @@ static int ui_textedit_type_buf(uiBut *but, uiHandleButtonData *data,
static int ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char ascii)
{
- char buf[2]= {ascii, '\0'};
-
- if (ui_is_but_utf8(but) && (BLI_str_utf8_size(buf) == -1)) {
- printf("%s: entering invalid ascii char into an ascii key (%d)\n",
- __func__, (int)(unsigned char)ascii);
-
- return 0;
- }
-
- /* in some cases we want to allow invalid utf8 chars */
- return ui_textedit_type_buf(but, data, buf, 1);
+ char utf8_buf[6]= {ascii, '\0'};
+ return ui_textedit_type_utf8(but, data, utf8_buf);
}
static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, int direction, int select, uiButtonJumpType jump)
@@ -1944,26 +1932,18 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
if((event->ascii || event->utf8_buf[0]) && (retval == WM_UI_HANDLER_CONTINUE)) {
char ascii = event->ascii;
- const char *utf8_buf= event->utf8_buf;
/* exception that's useful for number buttons, some keyboard
numpads have a comma instead of a period */
- if(ELEM3(but->type, NUM, NUMABS, NUMSLI)) { /* could use data->min*/
- if(event->type == PADPERIOD && ascii == ',') {
+ if(ELEM3(but->type, NUM, NUMABS, NUMSLI))
+ if(event->type == PADPERIOD && ascii == ',')
ascii = '.';
- utf8_buf= NULL; /* force ascii fallback */
- }
- }
- if(utf8_buf && utf8_buf[0]) {
- int utf8_buf_len= BLI_str_utf8_size(utf8_buf);
+ if(event->utf8_buf[0]) {
/* keep this printf until utf8 is well tested */
- if (utf8_buf_len != 1) {
- printf("%s: utf8 char '%.*s'\n", __func__, utf8_buf_len, utf8_buf);
- }
-
- // strcpy(utf8_buf, "12345");
- changed= ui_textedit_type_buf(but, data, event->utf8_buf, utf8_buf_len);
+ printf("%s: utf8 char '%s'\n", __func__, event->utf8_buf);
+ // strcpy(event->utf8_buf, "12345");
+ changed= ui_textedit_type_utf8(but, data, event->utf8_buf);
}
else {
changed= ui_textedit_type_ascii(but, data, ascii);
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index 7849b71307b..c57ef4f5690 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -20,9 +20,11 @@
set(INC
../include
+ ../uvedit
../../blenkernel
../../blenlib
../../blenloader
+ ../../bmesh
../../imbuf
../../makesdna
../../makesrna
@@ -36,18 +38,20 @@ set(INC_SYS
)
set(SRC
- editface.c
- editmesh.c
- editmesh_add.c
- editmesh_lib.c
- editmesh_loop.c
- editmesh_mods.c
- editmesh_tools.c
+ meshtools.c
loopcut.c
- mesh_data.c
mesh_ops.c
- meshtools.c
+ editbmesh_bvh.c
+ editbmesh_add.c
+ bmeshutils.c
+ bmesh_selecthistory.c
+ bmesh_select.c
+ mesh_data.c
+ bmesh_tools.c
+ knifetool.c
+ editface.c
+ editbmesh_bvh.h
mesh_intern.h
)
diff --git a/source/blender/editors/mesh/SConscript b/source/blender/editors/mesh/SConscript
index 6546a44adeb..8142faf67a1 100644
--- a/source/blender/editors/mesh/SConscript
+++ b/source/blender/editors/mesh/SConscript
@@ -9,6 +9,7 @@ incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../gpu ../../blenloader'
incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
+incs += ' ../../bmesh ../uvedit '
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'
diff --git a/source/blender/editors/mesh/bmesh_select.c b/source/blender/editors/mesh/bmesh_select.c
new file mode 100644
index 00000000000..c63fd6796a9
--- /dev/null
+++ b/source/blender/editors/mesh/bmesh_select.c
@@ -0,0 +1,2678 @@
+/**
+ * $Id:
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+
+BMEditMesh_mods.c, UI level access, no geometry changes
+
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_rand.h"
+#include "BLI_array.h"
+#include "BLI_smallhash.h"
+#include "BLI_heap.h"
+
+#include "BKE_context.h"
+#include "BKE_displist.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_texture.h"
+#include "BKE_report.h"
+#include "BKE_tessmesh.h"
+#include "BKE_paint.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "RE_render_ext.h" /* externtex */
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "bmesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_resources.h"
+
+#include "mesh_intern.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+/* ****************************** MIRROR **************** */
+
+static void EDBM_select_mirrored(Object *obedit, BMEditMesh *em)
+{
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ BMVert *eve, *v1;
+ BMIter iter;
+ int i;
+
+ i= 0;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_SELECT) && !BM_TestHFlag(eve, BM_HIDDEN)) {
+ v1= editbmesh_get_x_mirror_vert(obedit, em, eve, eve->co, i);
+ if(v1) {
+ BM_Select(em->bm, eve, 0);
+ BM_Select(em->bm, v1, 1);
+ }
+ }
+ i++;
+ }
+ }
+}
+
+void EDBM_automerge(Scene *scene, Object *obedit, int update)
+{
+ BMEditMesh *em;
+
+ if ((scene->toolsettings->automerge) &&
+ (obedit && obedit->type==OB_MESH))
+ {
+ em = ((Mesh*)obedit->data)->edit_btmesh;
+ if (!em)
+ return;
+
+ BMO_CallOpf(em->bm, "automerge verts=%hv dist=%f", BM_SELECT, scene->toolsettings->doublimit);
+ if (update) {
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ }
+ }
+}
+
+/* ****************************** SELECTION ROUTINES **************** */
+
+unsigned int bm_solidoffs=0, bm_wireoffs=0, bm_vertoffs=0; /* set in drawobject.c ... for colorindices */
+
+/* facilities for border select and circle select */
+static char *selbuf= NULL;
+
+/* opengl doesn't support concave... */
+static void draw_triangulated(int mcords[][2], short tot)
+{
+ ListBase lb={NULL, NULL};
+ DispList *dl;
+ float *fp;
+ int a;
+
+ /* make displist */
+ dl= MEM_callocN(sizeof(DispList), "poly disp");
+ dl->type= DL_POLY;
+ dl->parts= 1;
+ dl->nr= tot;
+ dl->verts= fp= MEM_callocN(tot*3*sizeof(float), "poly verts");
+ BLI_addtail(&lb, dl);
+
+ for(a=0; a<tot; a++, fp+=3) {
+ fp[0]= (float)mcords[a][0];
+ fp[1]= (float)mcords[a][1];
+ }
+
+ /* do the fill */
+ filldisplist(&lb, &lb, 0);
+
+ /* do the draw */
+ dl= lb.first; /* filldisplist adds in head of list */
+ if(dl->type==DL_INDEX3) {
+ int *index;
+
+ a= dl->parts;
+ fp= dl->verts;
+ index= dl->index;
+ glBegin(GL_TRIANGLES);
+ while(a--) {
+ glVertex3fv(fp+3*index[0]);
+ glVertex3fv(fp+3*index[1]);
+ glVertex3fv(fp+3*index[2]);
+ index+= 3;
+ }
+ glEnd();
+ }
+
+ freedisplist(&lb);
+}
+
+
+/* reads rect, and builds selection array for quick lookup */
+/* returns if all is OK */
+int EDBM_init_backbuf_border(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
+{
+ struct ImBuf *buf;
+ unsigned int *dr;
+ int a;
+
+ if(vc->obedit==NULL || vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
+
+ buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ if(buf==NULL) return 0;
+ if(bm_vertoffs==0) return 0;
+
+ dr = buf->rect;
+
+ /* build selection lookup */
+ selbuf= MEM_callocN(bm_vertoffs+1, "selbuf");
+
+ a= (xmax-xmin+1)*(ymax-ymin+1);
+ while(a--) {
+ if(*dr>0 && *dr<=bm_vertoffs)
+ selbuf[*dr]= 1;
+ dr++;
+ }
+ IMB_freeImBuf(buf);
+ return 1;
+}
+
+int EDBM_check_backbuf(unsigned int index)
+{
+ if(selbuf==NULL) return 1;
+ if(index>0 && index<=bm_vertoffs)
+ return selbuf[index];
+ return 0;
+}
+
+void EDBM_free_backbuf(void)
+{
+ if(selbuf) MEM_freeN(selbuf);
+ selbuf= NULL;
+}
+
+/* mcords is a polygon mask
+ - grab backbuffer,
+ - draw with black in backbuffer,
+ - grab again and compare
+ returns 'OK'
+*/
+int EDBM_mask_init_backbuf_border(ViewContext *vc, int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
+{
+ unsigned int *dr, *drm;
+ struct ImBuf *buf, *bufmask;
+ int a;
+
+ /* method in use for face selecting too */
+ if(vc->obedit==NULL) {
+ if(paint_facesel_test(vc->obact));
+ else if(paint_vertsel_test(vc->obact));
+ else return 0;
+ }
+ else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
+
+ buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ if(buf==NULL) return 0;
+ if(bm_vertoffs==0) return 0;
+
+ dr = buf->rect;
+
+ /* draw the mask */
+ glDisable(GL_DEPTH_TEST);
+
+ glColor3ub(0, 0, 0);
+
+ /* yah, opengl doesn't do concave... tsk! */
+ ED_region_pixelspace(vc->ar);
+ draw_triangulated(mcords, tot);
+
+ glBegin(GL_LINE_LOOP); /* for zero sized masks, lines */
+ for(a=0; a<tot; a++) glVertex2iv(mcords[a]);
+ glEnd();
+
+ glFinish(); /* to be sure readpixels sees mask */
+
+ /* grab mask */
+ bufmask= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ drm = bufmask->rect;
+ if(bufmask==NULL) return 0; /* only when mem alloc fails, go crash somewhere else! */
+
+ /* build selection lookup */
+ selbuf= MEM_callocN(bm_vertoffs+1, "selbuf");
+
+ a= (xmax-xmin+1)*(ymax-ymin+1);
+ while(a--) {
+ if(*dr>0 && *dr<=bm_vertoffs && *drm==0) selbuf[*dr]= 1;
+ dr++; drm++;
+ }
+ IMB_freeImBuf(buf);
+ IMB_freeImBuf(bufmask);
+ return 1;
+
+}
+
+/* circle shaped sample area */
+int EDBM_init_backbuf_circle(ViewContext *vc, short xs, short ys, short rads)
+{
+ struct ImBuf *buf;
+ unsigned int *dr;
+ short xmin, ymin, xmax, ymax, xc, yc;
+ int radsq;
+
+ /* method in use for face selecting too */
+ if(vc->obedit==NULL) {
+ if(paint_facesel_test(vc->obact));
+ else if(paint_vertsel_test(vc->obact));
+ else return 0;
+ }
+ else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
+
+ xmin= xs-rads; xmax= xs+rads;
+ ymin= ys-rads; ymax= ys+rads;
+ buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ if(bm_vertoffs==0) return 0;
+ if(buf==NULL) return 0;
+
+ dr = buf->rect;
+
+ /* build selection lookup */
+ selbuf= MEM_callocN(bm_vertoffs+1, "selbuf");
+ radsq= rads*rads;
+ for(yc= -rads; yc<=rads; yc++) {
+ for(xc= -rads; xc<=rads; xc++, dr++) {
+ if(xc*xc + yc*yc < radsq) {
+ if(*dr>0 && *dr<=bm_vertoffs) selbuf[*dr]= 1;
+ }
+ }
+ }
+
+ IMB_freeImBuf(buf);
+ return 1;
+
+}
+
+static void findnearestvert__doClosest(void *userData, BMVert *eve, int x, int y, int index)
+{
+ struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; BMVert *closest; } *data = userData;
+
+ if (data->pass==0) {
+ if (index<=data->lastIndex)
+ return;
+ } else {
+ if (index>data->lastIndex)
+ return;
+ }
+
+ if (data->dist>3) {
+ int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y);
+ if (BM_TestHFlag(eve, BM_SELECT) == data->select) {
+ if (data->strict == 1)
+ return;
+ else
+ temp += 5;
+ }
+
+ if (temp<data->dist) {
+ data->dist = temp;
+ data->closest = eve;
+ data->closestIndex = index;
+ }
+ }
+}
+
+
+
+
+static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int index)
+{
+ BMEditMesh *em= (BMEditMesh *)handle;
+ BMVert *eve = BMIter_AtIndex(em->bm, BM_VERTS_OF_MESH, NULL, index-1);
+
+ if(eve && BM_TestHFlag(eve, BM_SELECT)) return 0;
+ return 1;
+}
+/**
+ * findnearestvert
+ *
+ * dist (in/out): minimal distance to the nearest and at the end, actual distance
+ * sel: selection bias
+ * if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
+ * if 0, unselected vertice are given the bias
+ * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased
+ */
+BMVert *EDBM_findnearestvert(ViewContext *vc, int *dist, short sel, short strict)
+{
+ if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)){
+ int distance;
+ unsigned int index;
+ BMVert *eve;
+
+ if(strict) index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, strict, vc->em, findnearestvert__backbufIndextest);
+ else index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, 0, NULL, NULL);
+
+ eve = BMIter_AtIndex(vc->em->bm, BM_VERTS_OF_MESH, NULL, index-1);
+
+ if(eve && distance < *dist) {
+ *dist = distance;
+ return eve;
+ } else {
+ return NULL;
+ }
+
+ }
+ else {
+ struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; BMVert *closest; } data;
+ static int lastSelectedIndex=0;
+ static BMVert *lastSelected=NULL;
+
+ if (lastSelected && BMIter_AtIndex(vc->em->bm, BM_VERTS_OF_MESH, NULL, lastSelectedIndex)!=lastSelected) {
+ lastSelectedIndex = 0;
+ lastSelected = NULL;
+ }
+
+ data.lastIndex = lastSelectedIndex;
+ data.mval[0] = vc->mval[0];
+ data.mval[1] = vc->mval[1];
+ data.select = sel;
+ data.dist = *dist;
+ data.strict = strict;
+ data.closest = NULL;
+ data.closestIndex = 0;
+
+ data.pass = 0;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
+
+ if (data.dist>3) {
+ data.pass = 1;
+ mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
+ }
+
+ *dist = data.dist;
+ lastSelected = data.closest;
+ lastSelectedIndex = data.closestIndex;
+
+ return data.closest;
+ }
+}
+
+/* returns labda for closest distance v1 to line-piece v2-v3 */
+float labda_PdistVL2Dfl(const float v1[3], const float v2[3], const float v3[3])
+{
+ float rc[2], len;
+
+ rc[0]= v3[0]-v2[0];
+ rc[1]= v3[1]-v2[1];
+ len= rc[0]*rc[0]+ rc[1]*rc[1];
+ if(len==0.0f)
+ return 0.0f;
+
+ return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
+}
+
+/* note; uses v3d, so needs active 3d window */
+static void findnearestedge__doClosest(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int UNUSED(index))
+{
+ struct { ViewContext vc; float mval[2]; int dist; BMEdge *closest; } *data = userData;
+ float v1[2], v2[2];
+ int distance;
+
+ v1[0] = x0;
+ v1[1] = y0;
+ v2[0] = x1;
+ v2[1] = y1;
+
+ distance= dist_to_line_segment_v2(data->mval, v1, v2);
+
+ if(BM_TestHFlag(eed, BM_SELECT)) distance+=5;
+ if(distance < data->dist) {
+ if(data->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float labda= labda_PdistVL2Dfl(data->mval, v1, v2);
+ float vec[3];
+
+ vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]);
+ vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]);
+ vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]);
+ mul_m4_v3(data->vc.obedit->obmat, vec);
+
+ if(ED_view3d_test_clipping(data->vc.rv3d, vec, 1)==0) {
+ data->dist = distance;
+ data->closest = eed;
+ }
+ }
+ else {
+ data->dist = distance;
+ data->closest = eed;
+ }
+ }
+}
+BMEdge *EDBM_findnearestedge(ViewContext *vc, int *dist)
+{
+
+ if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
+ int distance;
+ unsigned int index;
+ BMEdge *eed;
+
+ view3d_validate_backbuf(vc);
+
+ index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_solidoffs, bm_wireoffs, &distance,0, NULL, NULL);
+ eed = BMIter_AtIndex(vc->em->bm, BM_EDGES_OF_MESH, NULL, index-1);
+
+ if (eed && distance<*dist) {
+ *dist = distance;
+ return eed;
+ } else {
+ return NULL;
+ }
+ }
+ else {
+ struct { ViewContext vc; float mval[2]; int dist; BMEdge *closest; } data;
+
+ data.vc= *vc;
+ data.mval[0] = vc->mval[0];
+ data.mval[1] = vc->mval[1];
+ data.dist = *dist;
+ data.closest = NULL;
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, 2);
+
+ *dist = data.dist;
+ return data.closest;
+ }
+}
+
+static void findnearestface__getDistance(void *userData, BMFace *efa, int x, int y, int UNUSED(index))
+{
+ struct { short mval[2]; int dist; BMFace *toFace; } *data = userData;
+
+ if (efa==data->toFace) {
+ int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
+
+ if (temp<data->dist)
+ data->dist = temp;
+ }
+}
+static void findnearestface__doClosest(void *userData, BMFace *efa, int x, int y, int index)
+{
+ struct { short mval[2], pass; int dist, lastIndex, closestIndex; BMFace *closest; } *data = userData;
+
+ if (data->pass==0) {
+ if (index<=data->lastIndex)
+ return;
+ } else {
+ if (index>data->lastIndex)
+ return;
+ }
+
+ if (data->dist>3) {
+ int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
+
+ if (temp<data->dist) {
+ data->dist = temp;
+ data->closest = efa;
+ data->closestIndex = index;
+ }
+ }
+}
+
+BMFace *EDBM_findnearestface(ViewContext *vc, int *dist)
+{
+
+ if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
+ unsigned int index;
+ BMFace *efa;
+
+ view3d_validate_backbuf(vc);
+
+ index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]);
+ efa = BMIter_AtIndex(vc->em->bm, BM_FACES_OF_MESH, NULL, index-1);
+
+ if (efa) {
+ struct { short mval[2]; int dist; BMFace *toFace; } data;
+
+ data.mval[0] = vc->mval[0];
+ data.mval[1] = vc->mval[1];
+ data.dist = 0x7FFF; /* largest short */
+ data.toFace = efa;
+
+ mesh_foreachScreenFace(vc, findnearestface__getDistance, &data);
+
+ if(vc->em->selectmode == SCE_SELECT_FACE || data.dist<*dist) { /* only faces, no dist check */
+ *dist= data.dist;
+ return efa;
+ }
+ }
+
+ return NULL;
+ }
+ else {
+ struct { short mval[2], pass; int dist, lastIndex, closestIndex; BMFace *closest; } data;
+ static int lastSelectedIndex=0;
+ static BMFace *lastSelected=NULL;
+
+ if (lastSelected && BMIter_AtIndex(vc->em->bm, BM_FACES_OF_MESH, NULL, lastSelectedIndex)!=lastSelected) {
+ lastSelectedIndex = 0;
+ lastSelected = NULL;
+ }
+
+ data.lastIndex = lastSelectedIndex;
+ data.mval[0] = vc->mval[0];
+ data.mval[1] = vc->mval[1];
+ data.dist = *dist;
+ data.closest = NULL;
+ data.closestIndex = 0;
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ data.pass = 0;
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
+
+ if (data.dist>3) {
+ data.pass = 1;
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
+ }
+
+ *dist = data.dist;
+ lastSelected = data.closest;
+ lastSelectedIndex = data.closestIndex;
+
+ return data.closest;
+ }
+}
+
+/* best distance based on screen coords.
+ use em->selectmode to define how to use
+ selected vertices and edges get disadvantage
+ return 1 if found one
+*/
+static int unified_findnearest(ViewContext *vc, BMVert **eve, BMEdge **eed, BMFace **efa)
+{
+ BMEditMesh *em= vc->em;
+ int dist= 75;
+
+ *eve= NULL;
+ *eed= NULL;
+ *efa= NULL;
+
+ /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
+ view3d_validate_backbuf(vc);
+
+ if(em->selectmode & SCE_SELECT_VERTEX)
+ *eve= EDBM_findnearestvert(vc, &dist, BM_SELECT, 0);
+ if(em->selectmode & SCE_SELECT_FACE)
+ *efa= EDBM_findnearestface(vc, &dist);
+
+ dist-= 20; /* since edges select lines, we give dots advantage of 20 pix */
+ if(em->selectmode & SCE_SELECT_EDGE)
+ *eed= EDBM_findnearestedge(vc, &dist);
+
+ /* return only one of 3 pointers, for frontbuffer redraws */
+ if(*eed) {
+ *efa= NULL; *eve= NULL;
+ }
+ else if(*efa) {
+ *eve= NULL;
+ }
+
+ return (*eve || *eed || *efa);
+}
+
+/* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */
+
+static EnumPropertyItem prop_similar_types[] = {
+ {SIMVERT_NORMAL, "NORMAL", 0, "Normal", ""},
+ {SIMVERT_FACE, "FACE", 0, "Amount of Adjacent Faces", ""},
+ {SIMVERT_VGROUP, "VGROUP", 0, "Vertex Groups", ""},
+
+ {SIMEDGE_LENGTH, "LENGTH", 0, "Length", ""},
+ {SIMEDGE_DIR, "DIR", 0, "Direction", ""},
+ {SIMEDGE_FACE, "FACE", 0, "Amount of Faces Around an Edge", ""},
+ {SIMEDGE_FACE_ANGLE, "FACE_ANGLE", 0, "Face Angles", ""},
+ {SIMEDGE_CREASE, "CREASE", 0, "Crease", ""},
+ {SIMEDGE_SEAM, "SEAM", 0, "Seam", ""},
+ {SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""},
+
+ {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""},
+ {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""},
+ {SIMFACE_AREA, "AREA", 0, "Area", ""},
+ {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
+ {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
+ {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""},
+
+ {0, NULL, 0, NULL, NULL}
+};
+
+/* selects new faces/edges/verts based on the existing selection */
+
+static int similar_face_select_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ /* get the type from RNA */
+ int type = RNA_enum_get(op->ptr, "type");
+
+ float thresh = CTX_data_tool_settings(C)->select_thresh;
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "similarfaces faces=%hf type=%d thresh=%f", BM_SELECT, type, thresh);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* clear the existing selection */
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ /* select the output */
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "faceout", BM_SELECT, BM_ALL);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+ /* dependencies graph and notification stuff */
+ DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
+
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+/* ***************************************************** */
+
+/* EDGE GROUP */
+
+/* wrap the above function but do selection flushing edge to face */
+static int similar_edge_select_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ /* get the type from RNA */
+ int type = RNA_enum_get(op->ptr, "type");
+
+ float thresh = CTX_data_tool_settings(C)->select_thresh;
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "similaredges edges=%he type=%d thresh=%f", BM_SELECT, type, thresh);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* clear the existing selection */
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ /* select the output */
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "edgeout", BM_SELECT, BM_ALL);
+ EDBM_selectmode_flush(em);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+ /* dependencies graph and notification stuff */
+ DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
+
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+/* ********************************* */
+
+/*
+VERT GROUP
+ mode 1: same normal
+ mode 2: same number of face users
+ mode 3: same vertex groups
+*/
+
+
+static int similar_vert_select_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+ /* get the type from RNA */
+ int type = RNA_enum_get(op->ptr, "type");
+ float thresh = CTX_data_tool_settings(C)->select_thresh;
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "similarverts verts=%hv type=%d thresh=%f", BM_SELECT, type, thresh);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* clear the existing selection */
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ /* select the output */
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "vertout", BM_SELECT, BM_ALL);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+ EDBM_selectmode_flush(em);
+
+ /* dependencies graph and notification stuff */
+ DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
+
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+static int select_similar_exec(bContext *C, wmOperator *op)
+{
+ int type= RNA_enum_get(op->ptr, "type");
+
+ if(type < 100)
+ return similar_vert_select_exec(C, op);
+ else if(type < 200)
+ return similar_edge_select_exec(C, op);
+ else
+ return similar_face_select_exec(C, op);
+}
+
+static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
+{
+ Object *obedit = CTX_data_edit_object(C);
+
+ if(obedit && obedit->type == OB_MESH) {
+ EnumPropertyItem *item= NULL;
+ int a, totitem= 0;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ for (a=SIMVERT_NORMAL; a<SIMEDGE_LENGTH; a++) {
+ RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
+ }
+ } else if(em->selectmode & SCE_SELECT_EDGE) {
+ for (a=SIMEDGE_LENGTH; a<SIMFACE_MATERIAL; a++) {
+ RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
+ }
+ } else if(em->selectmode & SCE_SELECT_FACE) {
+ for (a=SIMFACE_MATERIAL; a<=SIMFACE_COPLANAR; a++) {
+ RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
+ }
+ }
+ RNA_enum_item_end(&item, &totitem);
+
+ *free= 1;
+
+ return item;
+ }
+
+ return NULL;
+}
+
+void MESH_OT_select_similar(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Select Similar";
+ ot->idname= "MESH_OT_select_similar";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= select_similar_exec;
+ ot->poll= ED_operator_editmesh;
+ ot->description= "Select similar vertices, edges or faces by property types";
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ prop= ot->prop= RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", "");
+ RNA_def_enum_funcs(prop, select_similar_type_itemf);
+}
+
+/* ***************************************************** */
+
+/* **************** LOOP SELECTS *************** */
+
+static void walker_select(BMEditMesh *em, int walkercode, void *start, int select)
+{
+ BMesh *bm = em->bm;
+ BMHeader *h;
+ BMWalker walker;
+
+ BMW_Init(&walker, bm, walkercode, 0, 0);
+ h = BMW_Begin(&walker, start);
+ for (; h; h=BMW_Step(&walker)) {
+ if (!select)
+ BM_remove_selection(bm, h);
+ BM_Select(bm, h, select);
+ }
+ BMW_End(&walker);
+}
+
+static int loop_multiselect(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
+ BMEdge *eed;
+ BMEdge **edarray;
+ int edindex;
+ int looptype= RNA_boolean_get(op->ptr, "ring");
+
+ BMIter iter;
+ int totedgesel = 0;
+
+ for(eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ eed; eed = BMIter_Step(&iter)){
+
+ if(BM_TestHFlag(eed, BM_SELECT)){
+ totedgesel++;
+ }
+ }
+
+
+ edarray = MEM_mallocN(sizeof(BMEdge*)*totedgesel,"edge array");
+ edindex = 0;
+
+ for(eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ eed; eed = BMIter_Step(&iter)){
+
+ if(BM_TestHFlag(eed, BM_SELECT)){
+ edarray[edindex] = eed;
+ edindex++;
+ }
+ }
+
+ if(looptype){
+ for(edindex = 0; edindex < totedgesel; edindex +=1){
+ eed = edarray[edindex];
+ walker_select(em, BMW_EDGERING, eed, 1);
+ }
+ EDBM_selectmode_flush(em);
+ }
+ else{
+ for(edindex = 0; edindex < totedgesel; edindex +=1){
+ eed = edarray[edindex];
+ walker_select(em, BMW_LOOP, eed, 1);
+ }
+ EDBM_selectmode_flush(em);
+ }
+ MEM_freeN(edarray);
+// if (EM_texFaceCheck())
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_loop_multi_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Multi Select Loops";
+ ot->idname= "MESH_OT_loop_multi_select";
+
+ /* api callbacks */
+ ot->exec= loop_multiselect;
+ ot->poll= ED_operator_editmesh;
+ ot->description= "Select a loop of connected edges by connection type";
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "ring", 0, "Ring", "");
+}
+
+
+/* ***************** MAIN MOUSE SELECTION ************** */
+
+
+/* ***************** loop select (non modal) ************** */
+
+static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring)
+{
+ ViewContext vc;
+ BMEditMesh *em;
+ BMEdge *eed;
+ int select= 1;
+ int dist = 50;
+
+ em_setup_viewcontext(C, &vc);
+ vc.mval[0]= mval[0];
+ vc.mval[1]= mval[1];
+ em= vc.em;
+
+ /* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */
+ view3d_validate_backbuf(&vc);
+
+ eed = EDBM_findnearestedge(&vc, &dist);
+ if (eed) {
+ if(extend==0) EDBM_clear_flag_all(em, BM_SELECT);
+
+ if (BM_TestHFlag(eed, BM_SELECT)==0) {
+ select=1;
+ }
+ else if (extend) {
+ select=0;
+ }
+
+ if(em->selectmode & SCE_SELECT_FACE) {
+ walker_select(em, BMW_FACELOOP, eed, select);
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ if(ring)
+ walker_select(em, BMW_EDGERING, eed, select);
+ else
+ walker_select(em, BMW_LOOP, eed, select);
+ }
+ else if(em->selectmode & SCE_SELECT_VERTEX) {
+ if(ring)
+ walker_select(em, BMW_EDGERING, eed, select);
+
+ else
+ walker_select(em, BMW_LOOP, eed, select);
+ }
+
+ EDBM_selectmode_flush(em);
+// if (EM_texFaceCheck())
+
+ /* sets as active, useful for other tools */
+ if (select) {
+ if (em->selectmode & SCE_SELECT_VERTEX) {
+ /* TODO: would be nice if the edge vertex chosen here
+ was the one closer to the selection pointer, instead
+ of arbitrarily selecting the first one */
+ EDBM_store_selection(em, eed->v1);
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ EDBM_store_selection(em, eed);
+ }
+ /* TODO: would be nice if the nearest face that
+ belongs to the selected edge could be set to
+ active here in face select mode */
+ }
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit);
+ }
+}
+
+static int mesh_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+
+ view3d_operator_needs_opengl(C);
+
+ mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"),
+ RNA_boolean_get(op->ptr, "ring"));
+
+ /* cannot do tweaks for as long this keymap is after transform map */
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_loop_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Loop Select";
+ ot->idname= "MESH_OT_loop_select";
+ ot->description= "Select a loop";
+
+ /* api callbacks */
+ ot->invoke= mesh_select_loop_invoke;
+ ot->poll= ED_operator_editmesh;
+ ot->description= "Select a loop of connected edges";
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Extend the selection");
+ RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "Select ring");
+}
+
+void MESH_OT_edgering_select (wmOperatorType *ot)
+{
+ /* description */
+ ot->name= "Edge Ring Select";
+ ot->idname= "MESH_OT_edgering_select";
+ ot->description= "Select an edge ring";
+
+ /* callbacks */
+ ot->invoke= mesh_select_loop_invoke;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
+ RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring");
+}
+
+/* ******************* edgetag_shortest_path and helpers ****************** */
+
+static float edgetag_cut_cost(BMEditMesh *UNUSED(em), BMEdge *e1, BMEdge *e2, BMVert* v)
+{
+ BMVert *v1 = (e1->v1 == v) ? e1->v2 : e1->v1;
+ BMVert *v2 = (e2->v1 == v) ? e2->v2 : e2->v1;
+ float cost, d1[3], d2[3];
+
+ /*The cost is based on the simple sum of the length of the two edgees...*/
+ sub_v3_v3v3(d1, v->co, v1->co);
+ sub_v3_v3v3(d2, v2->co, v->co);
+ cost = len_v3(d1);
+ cost += len_v3(d2);
+
+ /*...but is biased to give higher values to sharp turns, so that it will take
+ paths with fewer "turns" when selecting between equal-weighted paths between
+ the two edges*/
+ cost = cost + 0.5f*cost*(2.0f - sqrt(fabs(dot_v3v3(d1, d2))));
+
+ return cost;
+}
+
+static void edgetag_add_adjacent(BMEditMesh *em, SmallHash *visithash, Heap *heap, int mednum, int vertnum,
+ int *nedges, int *edges, int *prevedge, float *cost)
+{
+ BMEdge *e1 = EDBM_get_edge_for_index(em, mednum);
+ BMVert *v = EDBM_get_vert_for_index(em, vertnum);
+ int startadj, endadj = nedges[vertnum+1];
+
+ for (startadj = nedges[vertnum]; startadj < endadj; startadj++) {
+ int adjnum = edges[startadj];
+ BMEdge *e2 = EDBM_get_edge_for_index(em, adjnum);
+ float newcost;
+ float cutcost;
+
+ if (BLI_smallhash_haskey(visithash, (uintptr_t)e2))
+ continue;
+
+ cutcost = edgetag_cut_cost(em, e1, e2, v);
+ newcost = cost[mednum] + cutcost;
+
+ if (cost[adjnum] > newcost) {
+ cost[adjnum] = newcost;
+ prevedge[adjnum] = mednum;
+ BLI_heap_insert(heap, newcost, SET_INT_IN_POINTER(adjnum));
+ }
+ }
+}
+
+static void edgetag_context_set(BMEditMesh *em, Scene *scene, BMEdge *e, int val)
+{
+
+ switch (scene->toolsettings->edge_mode) {
+ case EDGE_MODE_SELECT:
+ BM_Select(em->bm, e, val);
+ break;
+ case EDGE_MODE_TAG_SEAM:
+ if (val) {BM_SetHFlag(e, BM_SEAM);}
+ else {BM_ClearHFlag(e, BM_SEAM);}
+ break;
+ case EDGE_MODE_TAG_SHARP:
+ if (val) {BM_SetHFlag(e, BM_SEAM);}
+ else {BM_ClearHFlag(e, BM_SEAM);}
+ break;
+ case EDGE_MODE_TAG_CREASE:
+ {
+ float *crease = CustomData_bmesh_get(&em->bm->edata, e->head.data, CD_CREASE);
+
+ if (val) {*crease = 1.0f;}
+ else {*crease = 0.0f;}
+ break;
+ }
+ case EDGE_MODE_TAG_BEVEL:
+ {
+ float *bweight = CustomData_bmesh_get(&em->bm->edata, e->head.data, CD_BWEIGHT);
+
+ if (val) {*bweight = 1.0f;}
+ else {*bweight = 0.0f;}
+ break;
+ }
+ }
+}
+
+static float bm_cdata_get_single_float(BMesh *UNUSED(bm), CustomData *cdata, void *element, int type)
+{
+ BMHeader *ele = element;
+ float *f;
+
+ if (!CustomData_has_layer(cdata, type))
+ return 0.0f;
+
+ f = CustomData_bmesh_get(cdata, ele->data, type);
+
+ return *f;
+}
+
+static int edgetag_context_check(Scene *scene, BMEditMesh *em, BMEdge *e)
+{
+ switch (scene->toolsettings->edge_mode) {
+ case EDGE_MODE_SELECT:
+ return BM_TestHFlag(e, BM_SELECT) ? 1 : 0;
+ case EDGE_MODE_TAG_SEAM:
+ return BM_TestHFlag(e, BM_SEAM);
+ case EDGE_MODE_TAG_SHARP:
+ return BM_TestHFlag(e, BM_SHARP);
+ case EDGE_MODE_TAG_CREASE:
+ return bm_cdata_get_single_float(em->bm, &em->bm->edata, e, CD_CREASE) ? 1 : 0;
+ case EDGE_MODE_TAG_BEVEL:
+ return bm_cdata_get_single_float(em->bm, &em->bm->edata, e, CD_BWEIGHT) ? 1 : 0;
+ }
+ return 0;
+}
+
+static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, BMEdge *target)
+{
+ BMEdge *e;
+ BMVert *v;
+ BMIter iter;
+ Heap *heap;
+ SmallHash visithash;
+ float *cost;
+ int i, totvert=0, totedge=0, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0;
+ int targetnum;
+
+ BLI_smallhash_init(&visithash);
+
+ /* we need the vert */
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(v, totvert);
+ totvert++;
+ }
+
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ e->head.flags[0].f = 0;
+ if (BM_TestHFlag(e, BM_HIDDEN)) {
+ BLI_smallhash_insert(&visithash, (uintptr_t)e, NULL);
+ }
+ BM_SetIndex(e, totedge);
+ totedge++;
+ }
+
+ /* alloc */
+ nedges = MEM_callocN(sizeof(*nedges)*totvert+1, "SeamPathNEdges");
+ edges = MEM_mallocN(sizeof(*edges)*totedge*2, "SeamPathEdges");
+ prevedge = MEM_mallocN(sizeof(*prevedge)*totedge, "SeamPathPrevious");
+ cost = MEM_mallocN(sizeof(*cost)*totedge, "SeamPathCost");
+
+ /* count edges, compute adjacent edges offsets and fill adjacent */
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ nedges[BM_GetIndex(e->v1)+1]++;
+ nedges[BM_GetIndex(e->v2)+1]++;
+ }
+
+ for (i = 1; i < totvert; i++) {
+ int newswap = nedges[i+1];
+ nedges[i+1] = nedgeswap + nedges[i];
+ nedgeswap = newswap;
+ }
+ nedges[0] = nedges[1] = 0;
+
+ i = 0;
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ edges[nedges[BM_GetIndex(e->v1)+1]++] = i;
+ edges[nedges[BM_GetIndex(e->v2)+1]++] = i;
+
+ cost[i] = 1e20f;
+ prevedge[i] = -1;
+ i++;
+ }
+
+ /*
+ * Arrays are now filled as follows:
+ *
+ * nedges[n] = sum of the # of edges incident to all vertices numbered 0 thru n-1
+ * edges[edges[n]..edges[n-1]] = the indices of of the edges incident to vertex n
+ *
+ * As the search continues, prevedge[n] will be the previous edge on the shortest
+ * path found so far to edge n. The visitedhash will of course contain entries
+ * for edges that have been visited, cost[n] will contain the length of the shortest
+ * path to edge n found so far, Finally, heap is a priority heap which is built on the
+ * the same data as the cost arry, but inverted: it is a worklist of edges prioritized
+ * by the shortest path found so far to the edge.
+ */
+
+#if 0 /* UNUSED */ /* this block does nothing, not sure why its here? - campbell */
+ for (i = 0; i < totvert; i++) {
+ int start = nedges[i], end = nedges[i+1], cur;
+ for (cur = start; cur < end; cur++) {
+ BMEdge* e = EDBM_get_edge_for_index(em, edges[cur]);
+ }
+ }
+#endif
+
+ /* regular dijkstra shortest path, but over edges instead of vertices */
+ heap = BLI_heap_new();
+ BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(BM_GetIndex(source)));
+ cost[BM_GetIndex(source)] = 0.0f;
+ EDBM_init_index_arrays(em, 1, 1, 0);
+ targetnum = BM_GetIndex(target);
+
+ while (!BLI_heap_empty(heap)) {
+ mednum = GET_INT_FROM_POINTER(BLI_heap_popmin(heap));
+ e = EDBM_get_edge_for_index(em, mednum);
+
+ if (mednum == targetnum)
+ break;
+
+ if (BLI_smallhash_haskey(&visithash, (uintptr_t)e))
+ continue;
+
+ BLI_smallhash_insert(&visithash, (uintptr_t)e, NULL);
+
+ edgetag_add_adjacent(em, &visithash, heap, mednum, BM_GetIndex(e->v1), nedges, edges, prevedge, cost);
+ edgetag_add_adjacent(em, &visithash, heap, mednum, BM_GetIndex(e->v2), nedges, edges, prevedge, cost);
+ }
+
+ if (mednum == targetnum) {
+ short allseams = 1;
+
+ /*Check whether the path is already completely tagged.
+ if it is, the tags will be cleared instead of set.*/
+ mednum = targetnum;
+ do {
+ e = EDBM_get_edge_for_index(em, mednum);
+ if (!edgetag_context_check(scene, em, e)) {
+ allseams = 0;
+ break;
+ }
+ mednum = prevedge[mednum];
+ } while (mednum != BM_GetIndex(source));
+
+ /*Follow path back and source and add or remove tags*/
+ mednum = targetnum;
+ do {
+ e = EDBM_get_edge_for_index(em, mednum);
+ if (allseams)
+ edgetag_context_set(em, scene, e, 0);
+ else
+ edgetag_context_set(em, scene, e, 1);
+ mednum = prevedge[mednum];
+ } while (mednum != -1);
+ }
+
+ EDBM_free_index_arrays(em);
+ MEM_freeN(nedges);
+ MEM_freeN(edges);
+ MEM_freeN(prevedge);
+ MEM_freeN(cost);
+ BLI_heap_free(heap, NULL);
+ BLI_smallhash_release(&visithash);
+
+ return 1;
+}
+
+/* ******************* mesh shortest path select, uses prev-selected edge ****************** */
+
+/* since you want to create paths with multiple selects, it doesn't have extend option */
+static void mouse_mesh_shortest_path(bContext *C, int mval[2])
+{
+ Object *ob = CTX_data_edit_object(C);
+ ViewContext vc;
+ BMEditMesh *em;
+ BMEdge *e;
+ int dist= 50;
+
+ em_setup_viewcontext(C, &vc);
+ vc.mval[0]= mval[0];
+ vc.mval[1]= mval[1];
+ em= vc.em;
+
+ e= EDBM_findnearestedge(&vc, &dist);
+ if(e) {
+ Mesh *me= vc.obedit->data;
+ int path = 0;
+
+ if (em->bm->selected.last) {
+ EditSelection *ese = em->bm->selected.last;
+
+ if(ese && ese->type == BM_EDGE) {
+ BMEdge *e_act;
+ e_act = (BMEdge*)ese->data;
+ if (e_act != e) {
+ if (edgetag_shortest_path(vc.scene, em, e_act, e)) {
+ EDBM_remove_selection(em, e_act);
+ path = 1;
+ }
+ }
+ }
+ }
+ if (path==0) {
+ int act = (edgetag_context_check(vc.scene, em, e)==0);
+ edgetag_context_set(em, vc.scene, e, act); /* switch the edge option */
+ }
+
+ EDBM_selectmode_flush(em);
+
+ /* even if this is selected it may not be in the selection list */
+ if(edgetag_context_check(vc.scene, em, e)==0)
+ EDBM_remove_selection(em, e);
+ else
+ EDBM_store_selection(em, e);
+
+ /* force drawmode for mesh */
+ switch (CTX_data_tool_settings(C)->edge_mode) {
+
+ case EDGE_MODE_TAG_SEAM:
+ me->drawflag |= ME_DRAWSEAMS;
+ break;
+ case EDGE_MODE_TAG_SHARP:
+ me->drawflag |= ME_DRAWSHARP;
+ break;
+ case EDGE_MODE_TAG_CREASE:
+ me->drawflag |= ME_DRAWCREASES;
+ break;
+ case EDGE_MODE_TAG_BEVEL:
+ me->drawflag |= ME_DRAWBWEIGHTS;
+ break;
+ }
+
+ DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
+ }
+}
+
+
+static int mesh_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+{
+
+ view3d_operator_needs_opengl(C);
+
+ mouse_mesh_shortest_path(C, event->mval);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_shortest_path(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Shortest Path Select";
+ ot->idname= "MESH_OT_select_shortest_path";
+
+ /* api callbacks */
+ ot->invoke= mesh_shortest_path_select_invoke;
+ ot->poll= ED_operator_editmesh;
+ ot->description= "Select shortest path between two selections";
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
+}
+
+/* ************************************************** */
+/* here actual select happens */
+/* gets called via generic mouse select operator */
+int mouse_mesh(bContext *C, const int mval[2], short extend)
+{
+ ViewContext vc;
+ BMVert *eve = NULL;
+ BMEdge *eed = NULL;
+ BMFace *efa = NULL;
+
+ /* setup view context for argument to callbacks */
+ em_setup_viewcontext(C, &vc);
+ vc.mval[0]= mval[0];
+ vc.mval[1]= mval[1];
+
+ if(unified_findnearest(&vc, &eve, &eed, &efa)) {
+
+ if(extend==0) EDBM_clear_flag_all(vc.em, BM_SELECT);
+
+ if(efa) {
+ /* set the last selected face */
+ BM_set_actFace(vc.em->bm, efa);
+
+ if(!BM_TestHFlag(efa, BM_SELECT)) {
+ EDBM_store_selection(vc.em, efa);
+ BM_Select(vc.em->bm, efa, 1);
+ }
+ else if(extend) {
+ EDBM_remove_selection(vc.em, efa);
+ BM_Select(vc.em->bm, efa, 0);
+ }
+ }
+ else if(eed) {
+ if(!BM_TestHFlag(eed, BM_SELECT)) {
+ EDBM_store_selection(vc.em, eed);
+ BM_Select(vc.em->bm, eed, 1);
+ }
+ else if(extend) {
+ EDBM_remove_selection(vc.em, eed);
+ BM_Select(vc.em->bm, eed, 0);
+ }
+ }
+ else if(eve) {
+ if(!BM_TestHFlag(eve, BM_SELECT)) {
+ EDBM_store_selection(vc.em, eve);
+ BM_Select(vc.em->bm, eve, 1);
+ }
+ else if(extend){
+ EDBM_remove_selection(vc.em, eve);
+ BM_Select(vc.em->bm, eve, 0);
+ }
+ }
+
+ EDBM_selectmode_flush(vc.em);
+
+// if (EM_texFaceCheck()) {
+
+ if (efa && efa->mat_nr != vc.obedit->actcol-1) {
+ vc.obedit->actcol= efa->mat_nr+1;
+ vc.em->mat_nr= efa->mat_nr;
+// BIF_preview_changed(ID_MA);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit);
+ return 1;
+ }
+
+ return 0;
+}
+
+static void EDBM_strip_selections(BMEditMesh *em)
+{
+ BMEditSelection *ese, *nextese;
+
+ if(!(em->selectmode & SCE_SELECT_VERTEX)){
+ ese = em->bm->selected.first;
+ while(ese){
+ nextese = ese->next;
+ if(ese->type == BM_VERT) BLI_freelinkN(&(em->bm->selected),ese);
+ ese = nextese;
+ }
+ }
+ if(!(em->selectmode & SCE_SELECT_EDGE)){
+ ese=em->bm->selected.first;
+ while(ese){
+ nextese = ese->next;
+ if(ese->type == BM_EDGE) BLI_freelinkN(&(em->bm->selected), ese);
+ ese = nextese;
+ }
+ }
+ if(!(em->selectmode & SCE_SELECT_FACE)){
+ ese=em->bm->selected.first;
+ while(ese){
+ nextese = ese->next;
+ if(ese->type == BM_FACE) BLI_freelinkN(&(em->bm->selected), ese);
+ ese = nextese;
+ }
+ }
+}
+
+/* when switching select mode, makes sure selection is consistant for editing */
+/* also for paranoia checks to make sure edge or face mode works */
+void EDBM_selectmode_set(BMEditMesh *em)
+{
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+ BMIter iter;
+
+ em->bm->selectmode = em->selectmode;
+
+ EDBM_strip_selections(em); /*strip BMEditSelections from em->selected that are not relevant to new mode*/
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ /*BMIter iter;
+
+ eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; eed; eed=BMIter_Step(&iter)) BM_Select(em->bm, eed, 0);
+
+ efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for ( ; efa; efa=BMIter_Step(&iter)) BM_Select(em->bm, efa, 0);*/
+
+ EDBM_selectmode_flush(em);
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ /* deselect vertices, and select again based on edge select */
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for ( ; eve; eve=BMIter_Step(&iter)) BM_Select(em->bm, eve, 0);
+
+ eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; eed; eed=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(eed, BM_SELECT))
+ BM_Select(em->bm, eed, 1);
+ }
+
+ /* selects faces based on edge status */
+ EDBM_selectmode_flush(em);
+ }
+ else if(em->selectmode & SCE_SELECT_FACE) {
+ /* deselect eges, and select again based on face select */
+ eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; eed; eed=BMIter_Step(&iter)) BM_Select(em->bm, eed, 0);
+
+ efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for ( ; efa; efa=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(efa, BM_SELECT))
+ BM_Select(em->bm, efa, 1);
+ }
+ }
+}
+
+void EDBM_convertsel(BMEditMesh *em, short oldmode, short selectmode)
+{
+ BMEdge *eed;
+ BMFace *efa;
+ BMIter iter;
+
+ /*have to find out what the selectionmode was previously*/
+ if(oldmode == SCE_SELECT_VERTEX) {
+ if(selectmode == SCE_SELECT_EDGE) {
+ /*select all edges associated with every selected vertex*/
+ eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; eed; eed=BMIter_Step(&iter)) {
+ if(BM_TestHFlag(eed->v1, BM_SELECT)) BM_Select(em->bm, eed, 1);
+ else if(BM_TestHFlag(eed->v2, BM_SELECT)) BM_Select(em->bm, eed, 1);
+ }
+ }
+ else if(selectmode == SCE_SELECT_FACE) {
+ BMIter liter;
+ BMLoop *l;
+
+ /*select all faces associated with every selected vertex*/
+ efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for ( ; efa; efa=BMIter_Step(&iter)) {
+ l = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
+ for (; l; l=BMIter_Step(&liter)) {
+ if (BM_TestHFlag(l->v, BM_SELECT)) {
+ BM_Select(em->bm, efa, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if(oldmode == SCE_SELECT_EDGE){
+ if(selectmode == SCE_SELECT_FACE) {
+ BMIter liter;
+ BMLoop *l;
+
+ /*select all faces associated with every selected vertex*/
+ efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for ( ; efa; efa=BMIter_Step(&iter)) {
+ l = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
+ for (; l; l=BMIter_Step(&liter)) {
+ if (BM_TestHFlag(l->v, BM_SELECT)) {
+ BM_Select(em->bm, efa, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void EDBM_deselect_by_material(struct BMEditMesh *em, const short index, const short select)
+{
+ BMIter iter;
+ BMFace *efa;
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(efa, BM_HIDDEN))
+ continue;
+ if(efa->mat_nr == index) {
+ BM_Select(em->bm, efa, select);
+ }
+ }
+}
+
+
+void EDBM_select_swap(BMEditMesh *em) /* exported for UV */
+{
+ BMIter iter;
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+
+ if(em->bm->selectmode & SCE_SELECT_VERTEX) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_HIDDEN))
+ continue;
+ BM_Select(em->bm, eve, !BM_TestHFlag(eve, BM_SELECT));
+ }
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(eed, BM_HIDDEN))
+ continue;
+ BM_Select(em->bm, eed, !BM_TestHFlag(eed, BM_SELECT));
+ }
+ }
+ else {
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(efa, BM_HIDDEN))
+ continue;
+ BM_Select(em->bm, efa, !BM_TestHFlag(efa, BM_SELECT));
+ }
+
+ }
+// if (EM_texFaceCheck())
+}
+
+static int select_inverse_mesh_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ EDBM_select_swap(em);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_inverse(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Inverse";
+ ot->idname= "MESH_OT_select_inverse";
+ ot->description= "Select inverse of (un)selected vertices, edges or faces";
+
+ /* api callbacks */
+ ot->exec= select_inverse_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ViewContext vc;
+ BMWalker walker;
+ BMEditMesh *em;
+ BMVert *eve;
+ BMEdge *e, *eed;
+ BMFace *efa;
+ int sel= !RNA_boolean_get(op->ptr, "deselect");
+
+ /* unified_finednearest needs ogl */
+ view3d_operator_needs_opengl(C);
+
+ /* setup view context for argument to callbacks */
+ em_setup_viewcontext(C, &vc);
+ em = vc.em;
+
+ if(vc.em->bm->totedge==0)
+ return OPERATOR_CANCELLED;
+
+ vc.mval[0]= event->mval[0];
+ vc.mval[1]= event->mval[1];
+
+ /* return warning! */
+
+ /*if(limit) {
+ int retval= select_linked_limited_invoke(&vc, 0, sel);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+ return retval;
+ }*/
+
+ if( unified_findnearest(&vc, &eve, &eed, &efa)==0 ) {
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_CANCELLED;
+ }
+
+ if (efa) {
+ eed = bm_firstfaceloop(efa)->e;
+ } else if (!eed) {
+ if (!eve || !eve->e)
+ return OPERATOR_CANCELLED;
+
+ eed = eve->e;
+ }
+
+ BMW_Init(&walker, em->bm, BMW_SHELL, 0, 0);
+ e = BMW_Begin(&walker, eed->v1);
+ for (; e; e=BMW_Step(&walker)) {
+ BM_Select(em->bm, e->v1, sel);
+ BM_Select(em->bm, e->v2, sel);
+ }
+ BMW_End(&walker);
+ EDBM_select_flush(em, SCE_SELECT_VERTEX);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_linked_pick(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Linked";
+ ot->idname= "MESH_OT_select_linked_pick";
+
+ /* api callbacks */
+ ot->invoke= select_linked_pick_invoke;
+ ot->poll= ED_operator_editmesh;
+ ot->description= "select/deselect all vertices linked to the edge under the mouse cursor";
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
+ RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "");
+}
+
+
+static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BLI_array_declare(verts);
+ BMVert **verts = NULL;
+ BMIter iter;
+ BMVert *v;
+ BMEdge *e;
+ BMWalker walker;
+ int i, tot;
+
+ tot = 0;
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(v, BM_SELECT) && !BM_TestHFlag(v, BM_HIDDEN)) {
+ BLI_array_growone(verts);
+ verts[tot++] = v;
+ }
+ }
+
+ BMW_Init(&walker, em->bm, BMW_SHELL, 0, 0);
+ for (i=0; i<tot; i++) {
+ e = BMW_Begin(&walker, verts[i]);
+ for (; e; e=BMW_Step(&walker)) {
+ BM_Select(em->bm, e->v1, 1);
+ BM_Select(em->bm, e->v2, 1);
+ }
+ }
+ BMW_End(&walker);
+ EDBM_select_flush(em, SCE_SELECT_VERTEX);
+
+ BLI_array_free(verts);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Linked All";
+ ot->idname= "MESH_OT_select_linked";
+
+ /* api callbacks */
+ ot->exec= select_linked_exec;
+ ot->poll= ED_operator_editmesh;
+ ot->description= "Select all vertices linked to the active mesh";
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "");
+}
+
+/* ******************** **************** */
+
+static int select_more(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
+ BMOperator bmop;
+ int usefaces = em->selectmode > SCE_SELECT_EDGE;
+
+ EDBM_InitOpf(em, &bmop, op, "regionextend geom=%hvef constrict=%d usefaces=%d",
+ BM_SELECT, 0, usefaces);
+
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
+
+ EDBM_selectmode_flush(em);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_more(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select More";
+ ot->idname= "MESH_OT_select_more";
+ ot->description= "Select more vertices, edges or faces connected to initial selection";
+
+ /* api callbacks */
+ ot->exec= select_more;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int select_less(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
+ BMOperator bmop;
+ int usefaces = em->selectmode > SCE_SELECT_EDGE;
+
+ EDBM_InitOpf(em, &bmop, op, "regionextend geom=%hvef constrict=%d usefaces=%d",
+ BM_SELECT, 1, usefaces);
+
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_UnHeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
+
+ EDBM_selectmode_flush(em);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_less(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Less";
+ ot->idname= "MESH_OT_select_less";
+ ot->description= "Deselect vertices, edges or faces at the boundary of each selection region";
+
+ /* api callbacks */
+ ot->exec= select_less;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* Walk all reachable elements of the same type as h_act in breadth-first
+ order, starting from h_act. Deselects elements if the depth when they
+ are reached is not a multiple of "nth". */
+static void walker_deselect_nth(BMEditMesh *em, int nth, int offset, BMHeader *h_act)
+{
+ BMHeader *h;
+ BMesh *bm = em->bm;
+ BMWalker walker;
+ BMIter iter;
+ int walktype = 0, itertype = 0, flushtype = 0;
+
+ /* No active element from which to start - nothing to do */
+ if(h_act==NULL) {
+ return;
+ }
+
+ /* Determine which type of iter, walker, and select flush to use
+ based on type of the elements being deselected */
+ switch (h_act->type) {
+ case BM_VERT:
+ itertype = BM_VERTS_OF_MESH;
+ walktype = BMW_CONNECTED_VERTEX;
+ flushtype = SCE_SELECT_VERTEX;
+ break;
+ case BM_EDGE:
+ itertype = BM_EDGES_OF_MESH;
+ walktype = BMW_SHELL;
+ flushtype = SCE_SELECT_EDGE;
+ break;
+ case BM_FACE:
+ itertype = BM_FACES_OF_MESH;
+ walktype = BMW_ISLAND;
+ flushtype = SCE_SELECT_FACE;
+ break;
+ }
+
+ /* Walker restrictions uses BMO flags, not header flags,
+ so transfer BM_SELECT from HFlags onto a BMO flag layer. */
+ BMO_push(bm, NULL);
+ BM_ITER(h, &iter, bm, itertype, NULL) {
+ if (BM_TestHFlag(h, BM_SELECT)) {
+ BMO_SetFlag(bm, h, BM_SELECT);
+ }
+ }
+
+ /* Walk over selected elements starting at active */
+ BMW_Init(&walker, bm, walktype, BM_SELECT, 0);
+ BLI_assert(walker.order == BMW_BREADTH_FIRST);
+ for (h = BMW_Begin(&walker, h_act); h != NULL; h = BMW_Step(&walker)) {
+ /* Deselect elements that aren't at "nth" depth from active */
+ if ((offset + BMW_CurrentDepth(&walker)) % nth) {
+ BM_Select(bm, h, 0);
+ }
+ }
+ BMW_End(&walker);
+
+ BMO_pop(bm);
+
+ /* Flush selection up */
+ EDBM_select_flush(em, flushtype);
+}
+
+static void deselect_nth_active(BMEditMesh *em, BMVert **v_p, BMEdge **e_p, BMFace **f_p)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+ BMIter iter;
+ BMEditSelection *ese;
+
+ *v_p= NULL;
+ *e_p= NULL;
+ *f_p= NULL;
+
+ EDBM_selectmode_flush(em);
+ ese= (BMEditSelection*)em->bm->selected.last;
+
+ if(ese) {
+ switch(ese->type) {
+ case BM_VERT:
+ *v_p= (BMVert *)ese->data;
+ return;
+ case BM_EDGE:
+ *e_p= (BMEdge *)ese->data;
+ return;
+ case BM_FACE:
+ *f_p= (BMFace *)ese->data;
+ return;
+ }
+ }
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(v, BM_SELECT)) {
+ *v_p = v;
+ return;
+ }
+ }
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(e, BM_SELECT)) {
+ *e_p = e;
+ return;
+ }
+ }
+ }
+ else if(em->selectmode & SCE_SELECT_FACE) {
+ f= BM_get_actFace(em->bm, 1);
+ if(f) {
+ *f_p= f;
+ return;
+ }
+ }
+}
+
+static int EM_deselect_nth(BMEditMesh *em, int nth, int offset)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ deselect_nth_active(em, &v, &e, &f);
+
+ if (v) {
+ walker_deselect_nth(em, nth, offset, &v->head);
+ return 1;
+ }
+ else if(e) {
+ walker_deselect_nth(em, nth, offset, &e->head);
+ return 1;
+ }
+ else if(f) {
+ walker_deselect_nth(em, nth, offset, &f->head);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int mesh_select_nth_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ int nth= RNA_int_get(op->ptr, "nth");
+ int offset= RNA_int_get(op->ptr, "offset");
+
+ offset = MIN2(nth, offset);
+
+ if(EM_deselect_nth(em, nth, offset) == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face");
+ return OPERATOR_CANCELLED;
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void MESH_OT_select_nth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Nth";
+ ot->description= "";
+ ot->idname= "MESH_OT_select_nth";
+
+ /* api callbacks */
+ ot->exec= mesh_select_nth_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "nth", 2, 2, 100, "Nth Selection", "", 1, INT_MAX);
+ RNA_def_int(ot->srna, "offset", 0, 0, 100, "Offset", "", 0, INT_MAX);
+}
+
+void em_setup_viewcontext(bContext *C, ViewContext *vc)
+{
+ view3d_set_viewcontext(C, vc);
+
+ if(vc->obedit) {
+ Mesh *me= vc->obedit->data;
+ vc->em= me->edit_btmesh;
+ }
+}
+
+/* poll call for mesh operators requiring a view3d context */
+int EM_view3d_poll(bContext *C)
+{
+ if(ED_operator_editmesh(C) && ED_operator_view3d_active(C))
+ return 1;
+ return 0;
+}
+
+
+static int select_sharp_edges_exec(bContext *C, wmOperator *op)
+{
+ /* Find edges that have exactly two neighboring faces,
+ * check the angle between those faces, and if angle is
+ * small enough, select the edge
+ */
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMIter iter;
+ BMEdge *e;
+ BMLoop *l1, *l2;
+ float sharp = RNA_float_get(op->ptr, "sharpness"), angle;
+
+ sharp = DEG2RADF(sharp);
+
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(e, BM_HIDDEN) || !e->l)
+ continue;
+
+ l1 = e->l;
+ l2 = l1->radial_next;
+
+ if (l1 == l2)
+ continue;
+
+ /* edge has exactly two neighboring faces, check angle */
+ angle = saacos(l1->f->no[0]*l2->f->no[0]+l1->f->no[1]*l2->f->no[1]+l1->f->no[2]*l2->f->no[2]);
+
+ if (fabsf(angle) < sharp) {
+ BM_Select(em->bm, e, 1);
+ }
+
+ }
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_edges_select_sharp(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Sharp Edges";
+ ot->description= "Marked selected edges as sharp";
+ ot->idname= "MESH_OT_edges_select_sharp";
+
+ /* api callbacks */
+ ot->exec= select_sharp_edges_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_float(ot->srna, "sharpness", 1.0f, 0.01f, FLT_MAX, "sharpness", "", 1.0f, 180.0f);
+}
+
+static int select_linked_flat_faces_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMIter iter, liter, liter2;
+ BMFace *f, **stack = NULL;
+ BLI_array_declare(stack);
+ BMLoop *l, *l2;
+ float sharp = RNA_float_get(op->ptr, "sharpness");
+ int i;
+
+ sharp = (sharp * M_PI) / 180.0;
+
+ BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BM_SetIndex(f, 0);
+ }
+
+ BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(f, BM_HIDDEN) || !BM_TestHFlag(f, BM_SELECT) || BM_GetIndex(f))
+ continue;
+
+ BLI_array_empty(stack);
+ i = 1;
+
+ BLI_array_growone(stack);
+ stack[i-1] = f;
+
+ while (i) {
+ f = stack[i-1];
+ i--;
+
+ BM_Select(em->bm, f, 1);
+
+ BM_SetIndex(f, 1);
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
+ BM_ITER(l2, &liter2, em->bm, BM_LOOPS_OF_LOOP, l) {
+ float angle;
+
+ if (BM_GetIndex(l2->f) || BM_TestHFlag(l2->f, BM_HIDDEN))
+ continue;
+
+ /* edge has exactly two neighboring faces, check angle */
+ angle = saacos(f->no[0]*l2->f->no[0]+f->no[1]*l2->f->no[1]+f->no[2]*l2->f->no[2]);
+
+ /* invalidate: edge too sharp */
+ if (fabs(angle) < sharp) {
+ BLI_array_growone(stack);
+ stack[i] = l2->f;
+ i++;
+ }
+ }
+ }
+ }
+ }
+
+ BLI_array_free(stack);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_faces_select_linked_flat(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Linked Flat Faces";
+ ot->description= "Select linked faces by angle";
+ ot->idname= "MESH_OT_faces_select_linked_flat";
+
+ /* api callbacks */
+ ot->exec= select_linked_flat_faces_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_float(ot->srna, "sharpness", 1.0f, 0.01f, FLT_MAX, "sharpness", "", 1.0f, 180.0f);
+}
+
+static int select_non_manifold_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMVert *v;
+ BMEdge *e;
+ BMIter iter;
+
+ /* Selects isolated verts, and edges that do not have 2 neighboring
+ * faces
+ */
+
+ if(em->selectmode==SCE_SELECT_FACE) {
+ BKE_report(op->reports, RPT_ERROR, "Doesn't work in face selection mode");
+ return OPERATOR_CANCELLED;
+ }
+
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (!BM_TestHFlag(em->bm, BM_HIDDEN) && BM_Nonmanifold_Vert(em->bm, v))
+ BM_Select(em->bm, v, 1);
+ }
+
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(em->bm, BM_HIDDEN) && BM_Edge_FaceCount(e) != 2)
+ BM_Select(em->bm, e, 1);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_non_manifold(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Non Manifold";
+ ot->description= "Select all non-manifold vertices or edges";
+ ot->idname= "MESH_OT_select_non_manifold";
+
+ /* api callbacks */
+ ot->exec= select_non_manifold_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int mesh_select_random_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+ BMIter iter;
+ float randfac = RNA_float_get(op->ptr, "percent")/100.0f;
+
+ BLI_srand( BLI_rand() ); /* random seed */
+
+ if(!RNA_boolean_get(op->ptr, "extend"))
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (!BM_TestHFlag(eve, BM_HIDDEN) && BLI_frand() < randfac)
+ BM_Select(em->bm, eve, 1);
+ }
+ EDBM_selectmode_flush(em);
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(eed, BM_HIDDEN) && BLI_frand() < randfac)
+ BM_Select(em->bm, eed, 1);
+ }
+ EDBM_selectmode_flush(em);
+ }
+ else {
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN) && BLI_frand() < randfac)
+ BM_Select(em->bm, efa, 1);
+ }
+ EDBM_selectmode_flush(em);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_random(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Random";
+ ot->description= "Randomly select vertices";
+ ot->idname= "MESH_OT_select_random";
+
+ /* api callbacks */
+ ot->exec= mesh_select_random_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of elements to select randomly", 0.f, 100.0f);
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend Selection", "Extend selection instead of deselecting everything first");
+}
+
+static int select_next_loop(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
+ BMFace *f;
+ BMVert *v;
+ BMIter iter;
+
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(v, 0);
+ }
+
+ BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BMLoop *l;
+ BMIter liter;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
+ if (BM_TestHFlag(l->v, BM_SELECT) && !BM_TestHFlag(l->v, BM_HIDDEN)) {
+ BM_SetIndex(l->next->v, 1);
+ BM_Select(em->bm, l->v, 0);
+ }
+ }
+ }
+
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_GetIndex(v)) {
+ BM_Select(em->bm, v, 1);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_next_loop(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Next Loop";
+ ot->idname= "MESH_OT_select_next_loop";
+ ot->description= "";
+
+ /* api callbacks */
+ ot->exec= select_next_loop;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+static int region_to_loop(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *f;
+ BMEdge *e;
+ BMIter iter;
+ ViewContext vc;
+
+ em_setup_viewcontext(C, &vc);
+
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ BM_SetIndex(e, 0);
+ }
+
+ BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BMLoop *l1, *l2;
+ BMIter liter1, liter2;
+
+ BM_ITER(l1, &liter1, em->bm, BM_LOOPS_OF_FACE, f) {
+ int tot=0, totsel=0;
+
+ BM_ITER(l2, &liter2, em->bm, BM_LOOPS_OF_EDGE, l1->e) {
+ tot++;
+ totsel += BM_TestHFlag(l2->f, BM_SELECT) != 0;
+ }
+
+ if ((tot != totsel && totsel > 0) || (totsel == 1 && tot == 1))
+ BM_SetIndex(l1->e, 1);
+ }
+ }
+
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_GetIndex(e) && !BM_TestHFlag(e, BM_HIDDEN))
+ BM_Select_Edge(em->bm, e, 1);
+ }
+
+ /* If in face-only select mode, switch to edge select mode so that
+ an edge-only selection is not inconsistent state */
+ if (em->selectmode == SCE_SELECT_FACE) {
+ em->selectmode = SCE_SELECT_EDGE;
+ EDBM_selectmode_set(em);
+ EDBM_selectmode_to_scene(C);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_region_to_loop(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Boundary Loop";
+ ot->idname= "MESH_OT_region_to_loop";
+
+ /* api callbacks */
+ ot->exec= region_to_loop;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int loop_find_region(BMEditMesh *em, BMLoop *l, int flag,
+ SmallHash *fhash, BMFace ***region_out)
+{
+ BLI_array_declare(region);
+ BLI_array_declare(stack);
+ BMFace **region = NULL, *f;
+ BMFace **stack = NULL;
+
+ BLI_array_append(stack, l->f);
+ BLI_smallhash_insert(fhash, (uintptr_t)l->f, NULL);
+
+ while (BLI_array_count(stack) > 0) {
+ BMIter liter1, liter2;
+ BMLoop *l1, *l2;
+
+ f = BLI_array_pop(stack);
+ BLI_array_append(region, f);
+
+ BM_ITER(l1, &liter1, em->bm, BM_LOOPS_OF_FACE, f) {
+ if (BM_TestHFlag(l1->e, flag))
+ continue;
+
+ BM_ITER(l2, &liter2, em->bm, BM_LOOPS_OF_EDGE, l1->e) {
+ if (BLI_smallhash_haskey(fhash, (uintptr_t)l2->f))
+ continue;
+
+ BLI_array_append(stack, l2->f);
+ BLI_smallhash_insert(fhash, (uintptr_t)l2->f, NULL);
+ }
+ }
+ }
+
+ BLI_array_free(stack);
+
+ *region_out = region;
+ return BLI_array_count(region);
+}
+
+static int verg_radial(const void *va, const void *vb)
+{
+ BMEdge *e1 = *((void**)va);
+ BMEdge *e2 = *((void**)vb);
+ int a, b;
+
+ a = BM_Edge_FaceCount(e1);
+ b = BM_Edge_FaceCount(e2);
+
+ if (a > b) return -1;
+ if (a == b) return 0;
+ if (a < b) return 1;
+
+ return -1;
+}
+
+static int loop_find_regions(BMEditMesh *em, int selbigger)
+{
+ SmallHash visithash;
+ BMIter iter;
+ BMEdge *e, **edges=NULL;
+ BLI_array_declare(edges);
+ BMFace *f;
+ int count = 0, i;
+
+ BLI_smallhash_init(&visithash);
+
+ BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BM_SetIndex(f, 0);
+ }
+
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(e, BM_SELECT)) {
+ BLI_array_append(edges, e);
+ BM_SetIndex(e, 1);
+ } else {
+ BM_SetIndex(e, 0);
+ }
+ }
+
+ /*sort edges by radial cycle length*/
+ qsort(edges, BLI_array_count(edges), sizeof(void*), verg_radial);
+
+ for (i=0; i<BLI_array_count(edges); i++) {
+ BMIter liter;
+ BMLoop *l;
+ BMFace **region=NULL, **r;
+ int c, tot=0;
+
+ e = edges[i];
+
+ if (!BM_GetIndex(e))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_EDGE, e) {
+ if (BLI_smallhash_haskey(&visithash, (uintptr_t)l->f))
+ continue;
+
+ c = loop_find_region(em, l, BM_SELECT, &visithash, &r);
+
+ if (!region || (selbigger ? c >= tot : c < tot)) {
+ /* this region is the best seen so far */
+ tot = c;
+ if (region) {
+ /* free the previous best */
+ MEM_freeN(region);
+ }
+ /* track the current region as the new best */
+ region = r;
+ }
+ else {
+ /* this region is not as good as best so far, just free it */
+ MEM_freeN(r);
+ }
+ }
+
+ if (region) {
+ int j;
+
+ for (j=0; j<tot; j++) {
+ BM_SetIndex(region[j], 1);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, region[j]) {
+ BM_SetIndex(l->e, 0);
+ }
+ }
+
+ count += tot;
+
+ MEM_freeN(region);
+ }
+ }
+
+ BLI_array_free(edges);
+ BLI_smallhash_release(&visithash);
+
+ return count;
+}
+
+static int loop_to_region(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
+ BMIter iter;
+ BMFace *f;
+ int selbigger = RNA_boolean_get(op->ptr, "select_bigger");
+ int a, b;
+
+ /*find the set of regions with smallest number of total faces*/
+ a = loop_find_regions(em, selbigger);
+ b = loop_find_regions(em, !selbigger);
+
+ if ((a <= b) ^ selbigger) {
+ loop_find_regions(em, selbigger);
+ }
+
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_GetIndex(f) && !BM_TestHFlag(f, BM_HIDDEN)) {
+ BM_Select_Face(em->bm, f, 1);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_loop_to_region(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Loop Inner-Region";
+ ot->idname= "MESH_OT_loop_to_region";
+
+ /* api callbacks */
+ ot->exec= loop_to_region;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "select_bigger", 0, "Select Bigger", "Select bigger regions instead of smaller ones");
+}
diff --git a/source/blender/editors/mesh/bmesh_selecthistory.c b/source/blender/editors/mesh/bmesh_selecthistory.c
new file mode 100644
index 00000000000..b517b34880f
--- /dev/null
+++ b/source/blender/editors/mesh/bmesh_selecthistory.c
@@ -0,0 +1,126 @@
+/**
+ * $Id:
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* ********* Selection History ************ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_rand.h"
+#include "BLI_array.h"
+
+#include "BKE_context.h"
+#include "BKE_displist.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+#include "BKE_report.h"
+#include "BKE_tessmesh.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "RE_render_ext.h" /* externtex */
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "bmesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "mesh_intern.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+/*these wrap equivilent bmesh functions. I'm in two minds of it we should
+ just use the bm functions directly; on the one hand, there's no real
+ need (at the moment) to wrap them, but on the other hand having these
+ wrapped avoids a confusing mess of mixing BM_ and EDBM_ namespaces.*/
+
+void EDBM_editselection_center(BMEditMesh *em, float *center, BMEditSelection *ese)
+{
+ BM_editselection_center(em->bm, center, ese);
+}
+
+void EDBM_editselection_normal(float *normal, BMEditSelection *ese)
+{
+ BM_editselection_normal(normal, ese);
+}
+
+/* Calculate a plane that is rightangles to the edge/vert/faces normal
+also make the plane run along an axis that is related to the geometry,
+because this is used for the manipulators Y axis.*/
+void EDBM_editselection_plane(BMEditMesh *em, float *plane, BMEditSelection *ese)
+{
+ BM_editselection_plane(em->bm, plane, ese);
+}
+
+void EDBM_remove_selection(BMEditMesh *em, void *data)
+{
+ BM_remove_selection(em->bm, data);
+}
+
+void EDBM_store_selection(BMEditMesh *em, void *data)
+{
+ BM_store_selection(em->bm, data);
+}
+
+void EDBM_validate_selections(BMEditMesh *em)
+{
+ BM_validate_selections(em->bm);
+}
diff --git a/source/blender/editors/mesh/bmesh_tools.c b/source/blender/editors/mesh/bmesh_tools.c
new file mode 100644
index 00000000000..b69c948a29a
--- /dev/null
+++ b/source/blender/editors/mesh/bmesh_tools.c
@@ -0,0 +1,4845 @@
+ /* $Id: bmesh_tools.c
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_key_types.h"
+
+#include "RNA_types.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_heap.h"
+#include "BLI_array.h"
+#include "BLI_smallhash.h"
+
+#include "BKE_material.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_bmesh.h"
+#include "BKE_report.h"
+#include "BKE_tessmesh.h"
+#include "BKE_texture.h"
+#include "BKE_main.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_view3d.h"
+#include "ED_util.h"
+#include "ED_screen.h"
+#include "ED_transform.h"
+#include "ED_object.h"
+
+#include "UI_interface.h"
+
+#include "RE_render_ext.h"
+
+#include "mesh_intern.h"
+#include "bmesh.h"
+
+#include "editbmesh_bvh.h"
+
+static void add_normal_aligned(float *nor, float *add)
+{
+ if( INPR(nor, add) < -0.9999f)
+ sub_v3_v3v3(nor, nor, add);
+ else
+ add_v3_v3v3(nor, nor, add);
+}
+
+
+static int subdivide_exec(bContext *C, wmOperator *op)
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ int cuts= RNA_int_get(op->ptr,"number_cuts");
+ float fractal= RNA_float_get(op->ptr, "fractal")/2.5;
+ int flag= 0;
+
+ if(fractal != 0.0f)
+ flag |= B_FRACTAL;
+
+ if (RNA_boolean_get(op->ptr, "quadtri") &&
+ RNA_enum_get(op->ptr, "quadcorner") == SUBD_STRAIGHT_CUT)
+ {
+ RNA_enum_set(op->ptr, "quadcorner", SUBD_INNERVERT);
+ }
+
+ BM_esubdivideflag(obedit, em->bm, BM_SELECT,
+ 0.0f, fractal,
+ ts->editbutflag|flag,
+ cuts, 0, RNA_enum_get(op->ptr, "quadcorner"),
+ RNA_boolean_get(op->ptr, "quadtri"),
+ 1, RNA_int_get(op->ptr, "seed"));
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+/* Note, these values must match delete_mesh() event values */
+static EnumPropertyItem prop_mesh_cornervert_types[] = {
+ {SUBD_INNERVERT, "INNERVERT", 0, "Inner Vert", ""},
+ {SUBD_PATH, "PATH", 0, "Path", ""},
+ {SUBD_STRAIGHT_CUT, "STRAIGHT_CUT", 0, "Straight Cut", ""},
+ {SUBD_FAN, "FAN", 0, "Fan", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+void MESH_OT_subdivide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Subdivide";
+ ot->description= "Subdivide selected edges";
+ ot->idname= "MESH_OT_subdivide";
+
+ /* api callbacks */
+ ot->exec= subdivide_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of Cuts", "", 1, 10);
+
+ RNA_def_boolean(ot->srna, "quadtri", 0, "Quad/Tri Mode", "Tries to prevent ngons");
+ RNA_def_enum(ot->srna, "quadcorner", prop_mesh_cornervert_types, SUBD_STRAIGHT_CUT, "Quad Corner Type", "How to subdivide quad corners (anything other then Straight Cut will prevent ngons)");
+
+ RNA_def_float(ot->srna, "fractal", 0.0f, 0.0f, FLT_MAX, "Fractal", "Fractal randomness factor", 0.0f, 1000.0f);
+ RNA_def_int(ot->srna, "seed", 0, 0, 10000, "Random Seed", "Seed for the random number generator", 0, 50);
+}
+
+
+void EMBM_project_snap_verts(bContext *C, ARegion *ar, Object *obedit, BMEditMesh *em)
+{
+ BMIter iter;
+ BMVert *eve;
+
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_SELECT)) {
+ float mval[2], vec[3], no_dummy[3];
+ int dist_dummy;
+ mul_v3_m4v3(vec, obedit->obmat, eve->co);
+ project_float_noclip(ar, vec, mval);
+ if(snapObjectsContext(C, mval, &dist_dummy, vec, no_dummy, SNAP_NOT_OBEDIT)) {
+ mul_v3_m4v3(eve->co, obedit->imat, vec);
+ }
+ }
+ }
+}
+
+
+/* individual face extrude */
+/* will use vertex normals for extrusion directions, so *nor is unaffected */
+static short EDBM_Extrude_face_indiv(BMEditMesh *em, wmOperator *op, short flag, float *UNUSED(nor))
+{
+ BMOIter siter;
+ BMIter liter;
+ BMFace *f;
+ BMLoop *l;
+ BMOperator bmop;
+
+ EDBM_InitOpf(em, &bmop, op, "extrude_face_indiv faces=%hf", flag);
+
+ /*deselect original verts*/
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ BMO_Exec_Op(em->bm, &bmop);
+
+ BMO_ITER(f, &siter, em->bm, &bmop, "faceout", BM_FACE) {
+ BM_Select(em->bm, f, 1);
+
+ /*set face vertex normals to face normal*/
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
+ copy_v3_v3(l->v->no, f->no);
+ }
+ }
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1)) return 0;
+
+ return 's'; // s is shrink/fatten
+}
+
+/* extrudes individual edges */
+static short EDBM_Extrude_edges_indiv(BMEditMesh *em, wmOperator *op, short flag, float *UNUSED(nor))
+{
+ BMOperator bmop;
+
+ EDBM_InitOpf(em, &bmop, op, "extrude_edge_only edges=%he", flag);
+
+ /*deselect original verts*/
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_VERT|BM_EDGE);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1)) return 0;
+
+ return 'n'; // n is normal grab
+}
+
+/* extrudes individual vertices */
+static short EDBM_Extrude_verts_indiv(BMEditMesh *em, wmOperator *op, short flag, float *UNUSED(nor))
+{
+ BMOperator bmop;
+
+ EDBM_InitOpf(em, &bmop, op, "extrude_vert_indiv verts=%hv", flag);
+
+ /*deselect original verts*/
+ BMO_UnHeaderFlag_Buffer(em->bm, &bmop, "verts", BM_SELECT, BM_VERT);
+
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "vertout", BM_SELECT, BM_VERT);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1)) return 0;
+
+ return 'g'; // g is grab
+}
+
+static short EDBM_Extrude_edge(Object *obedit, BMEditMesh *em, int flag, float *nor)
+{
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMOIter siter;
+ BMOperator extop;
+ BMEdge *edge;
+ BMFace *f;
+ ModifierData *md;
+ BMHeader *el;
+
+ BMO_Init_Op(&extop, "extrudefaceregion");
+ BMO_HeaderFlag_To_Slot(bm, &extop, "edgefacein",
+ flag, BM_VERT|BM_EDGE|BM_FACE);
+
+ /* If a mirror modifier with clipping is on, we need to adjust some
+ * of the cases above to handle edges on the line of symmetry.
+ */
+ md = obedit->modifiers.first;
+ for (; md; md=md->next) {
+ if ((md->type==eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ if(mmd->flag & MOD_MIR_CLIPPING) {
+ float mtx[4][4];
+ if (mmd->mirror_ob) {
+ float imtx[4][4];
+ invert_m4_m4(imtx, mmd->mirror_ob->obmat);
+ mul_m4_m4m4(mtx, obedit->obmat, imtx);
+ }
+
+ for (edge=BMIter_New(&iter,bm,BM_EDGES_OF_MESH,NULL);
+ edge; edge=BMIter_Step(&iter))
+ {
+ if(edge->head.flag & flag) {
+ float co1[3], co2[3];
+
+ copy_v3_v3(co1, edge->v1->co);
+ copy_v3_v3(co2, edge->v2->co);
+
+ if (mmd->mirror_ob) {
+ mul_v3_m4v3(co1, mtx, co1);
+ mul_v3_m4v3(co2, mtx, co2);
+ }
+
+ if (mmd->flag & MOD_MIR_AXIS_X)
+ if ( (fabs(co1[0]) < mmd->tolerance) &&
+ (fabs(co2[0]) < mmd->tolerance) )
+ BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL);
+
+ if (mmd->flag & MOD_MIR_AXIS_Y)
+ if ( (fabs(co1[1]) < mmd->tolerance) &&
+ (fabs(co2[1]) < mmd->tolerance) )
+ BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL);
+
+ if (mmd->flag & MOD_MIR_AXIS_Z)
+ if ( (fabs(co1[2]) < mmd->tolerance) &&
+ (fabs(co2[2]) < mmd->tolerance) )
+ BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL);
+ }
+ }
+ }
+ }
+ }
+
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ BMO_Exec_Op(bm, &extop);
+
+ nor[0] = nor[1] = nor[2] = 0.0f;
+
+ BMO_ITER(el, &siter, bm, &extop, "geomout", BM_ALL) {
+ BM_Select(bm, el, 1);
+
+ if (el->type == BM_FACE) {
+ f = (BMFace*)el;
+ add_normal_aligned(nor, f->no);
+ };
+ }
+
+ normalize_v3(nor);
+
+ BMO_Finish_Op(bm, &extop);
+
+ if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // grab
+ return 'n'; // normal constraint
+
+}
+static short EDBM_Extrude_vert(Object *obedit, BMEditMesh *em, short flag, float *nor)
+{
+ BMIter iter;
+ BMEdge *eed;
+
+ /*ensure vert flags are consistent for edge selections*/
+ eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; eed; eed=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(eed, flag)) {
+ if (flag & BM_SELECT) {
+ BM_Select(em->bm, eed->v1, 1);
+ BM_Select(em->bm, eed->v2, 1);
+ }
+
+ BM_SetHFlag(eed->v1, flag & ~BM_SELECT);
+ BM_SetHFlag(eed->v2, flag & ~BM_SELECT);
+ } else {
+ if (BM_TestHFlag(eed->v1, flag) && BM_TestHFlag(eed->v2, flag)) {
+ if (flag & BM_SELECT) {
+ BM_Select(em->bm, eed, 1);
+ }
+
+ BM_SetHFlag(eed, flag & ~BM_SELECT);
+ }
+ }
+ }
+
+ return EDBM_Extrude_edge(obedit, em, flag, nor);
+}
+
+static int extrude_repeat_mesh(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh *)obedit->data)->edit_btmesh;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+
+ int steps = RNA_int_get(op->ptr,"steps");
+
+ float offs = RNA_float_get(op->ptr,"offset");
+ float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0};
+ short a;
+
+ /* dvec */
+ dvec[0]= rv3d->persinv[2][0];
+ dvec[1]= rv3d->persinv[2][1];
+ dvec[2]= rv3d->persinv[2][2];
+ normalize_v3(dvec);
+ dvec[0]*= offs;
+ dvec[1]*= offs;
+ dvec[2]*= offs;
+
+ /* base correction */
+ copy_m3_m4(bmat, obedit->obmat);
+ invert_m3_m3(tmat, bmat);
+ mul_m3_v3(tmat, dvec);
+
+ for(a=0; a<steps; a++) {
+ EDBM_Extrude_edge(obedit, em, BM_SELECT, nor);
+ //BMO_CallOpf(em->bm, "extrudefaceregion edgefacein=%hef", BM_SELECT);
+ BMO_CallOpf(em->bm, "translate vec=%v verts=%hv", (float*)dvec, BM_SELECT);
+ //extrudeflag(obedit, em, SELECT, nor);
+ //translateflag(em, SELECT, dvec);
+ }
+
+ EDBM_RecalcNormals(em);
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_extrude_repeat(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude Repeat Mesh";
+ ot->description= "Extrude selected vertices, edges or faces repeatedly";
+ ot->idname= "MESH_OT_extrude_repeat";
+
+ /* api callbacks */
+ ot->exec= extrude_repeat_mesh;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, FLT_MAX);
+ RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, INT_MAX);
+}
+
+/* generic extern called extruder */
+static int EDBM_Extrude_Mesh(Scene *scene, Object *obedit, BMEditMesh *em, wmOperator *op, float *norin)
+{
+ short nr, transmode= 0;
+ float stacknor[3] = {0.0f, 0.0f, 0.0f};
+ float *nor = norin ? norin : stacknor;
+
+ nor[0] = nor[1] = nor[2] = 0.0f;
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ if(em->bm->totvertsel==0) nr= 0;
+ else if(em->bm->totvertsel==1) nr= 4;
+ else if(em->bm->totedgesel==0) nr= 4;
+ else if(em->bm->totfacesel==0)
+ nr= 3; // pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4");
+ else if(em->bm->totfacesel==1)
+ nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4");
+ else
+ nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4");
+ }
+ else if(em->selectmode & SCE_SELECT_EDGE) {
+ if (em->bm->totedgesel==0) nr = 0;
+
+ nr = 1;
+ /*else if (em->totedgesel==1) nr = 3;
+ else if(em->totfacesel==0) nr = 3;
+ else if(em->totfacesel==1)
+ nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3");
+ else
+ nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
+ */
+ }
+ else {
+ if (em->bm->totfacesel == 0) nr = 0;
+ else if (em->bm->totfacesel == 1) nr = 1;
+ else
+ nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
+ }
+
+ if(nr<1) return 'g';
+
+ if(nr==1 && em->selectmode & SCE_SELECT_VERTEX)
+ transmode= EDBM_Extrude_vert(obedit, em, BM_SELECT, nor);
+ else if (nr == 1) transmode= EDBM_Extrude_edge(obedit, em, BM_SELECT, nor);
+ else if(nr==4) transmode= EDBM_Extrude_verts_indiv(em, op, BM_SELECT, nor);
+ else if(nr==3) transmode= EDBM_Extrude_edges_indiv(em, op, BM_SELECT, nor);
+ else transmode= EDBM_Extrude_face_indiv(em, op, BM_SELECT, nor);
+
+ if(transmode==0) {
+ BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude");
+ }
+ else {
+
+ /* We need to force immediate calculation here because
+ * transform may use derived objects (which are now stale).
+ *
+ * This shouldn't be necessary, derived queries should be
+ * automatically building this data if invalid. Or something.
+ */
+// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+ object_handle_update(scene, obedit);
+
+ /* individual faces? */
+// BIF_TransformSetUndo("Extrude");
+ if(nr==2) {
+// initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR);
+// Transform();
+ }
+ else {
+// initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR);
+ if(transmode=='n') {
+ mul_m4_v3(obedit->obmat, nor);
+ sub_v3_v3v3(nor, nor, obedit->obmat[3]);
+// BIF_setSingleAxisConstraint(nor, "along normal");
+ }
+// Transform();
+ }
+ }
+
+ return transmode;
+}
+
+/* extrude without transform */
+static int mesh_extrude_region_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+
+ EDBM_Extrude_Mesh(scene, obedit, em, op, NULL);
+
+ /*This normally happens when pushing undo but modal operators
+ like this one don't push undo data until after modal mode is
+ done.*/
+ EDBM_RecalcNormals(em);
+ BMEdit_RecalcTesselation(em);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_extrude_region(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude Region";
+ ot->idname= "MESH_OT_extrude_region";
+
+ /* api callbacks */
+ //ot->invoke= mesh_extrude_region_invoke;
+ ot->exec= mesh_extrude_region_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+}
+
+static int mesh_extrude_verts_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ float nor[3];
+
+ EDBM_Extrude_verts_indiv(em, op, BM_SELECT, nor);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_extrude_verts_indiv(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude Only Vertices";
+ ot->idname= "MESH_OT_extrude_verts_indiv";
+
+ /* api callbacks */
+ ot->exec= mesh_extrude_verts_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+}
+
+static int mesh_extrude_edges_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ float nor[3];
+
+ EDBM_Extrude_edges_indiv(em, op, BM_SELECT, nor);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_extrude_edges_indiv(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude Only Edges";
+ ot->idname= "MESH_OT_extrude_edges_indiv";
+
+ /* api callbacks */
+ ot->exec= mesh_extrude_edges_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+}
+
+static int mesh_extrude_faces_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ float nor[3];
+
+ EDBM_Extrude_face_indiv(em, op, BM_SELECT, nor);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_extrude_faces_indiv(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Extrude Individual Faces";
+ ot->idname= "MESH_OT_extrude_faces_indiv";
+
+ /* api callbacks */
+ ot->exec= mesh_extrude_faces_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+}
+
+/* ******************** (de)select all operator **************** */
+
+void EDBM_toggle_select_all(BMEditMesh *em) /* exported for UV */
+{
+ if(em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel)
+ EDBM_clear_flag_all(em, BM_SELECT);
+ else
+ EDBM_set_flag_all(em, BM_SELECT);
+}
+
+static int toggle_select_all_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ EDBM_toggle_select_all(em);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select/Deselect All";
+ ot->idname= "MESH_OT_select_all";
+ ot->description= "(de)select all vertices, edges or faces";
+
+ /* api callbacks */
+ ot->exec= toggle_select_all_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* *************** add-click-mesh (extrude) operator ************** */
+/* in trunk see: 'editmesh_add.c' */
+static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ViewContext vc;
+ BMVert *v1;
+ BMIter iter;
+ float min[3], max[3];
+ int done= 0;
+ short use_proj;
+
+ em_setup_viewcontext(C, &vc);
+
+ use_proj= (vc.scene->toolsettings->snap_flag & SCE_SNAP) && (vc.scene->toolsettings->snap_mode==SCE_SNAP_MODE_FACE);
+
+ INIT_MINMAX(min, max);
+
+ BM_ITER(v1, &iter, vc.em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(v1, BM_SELECT)) {
+ DO_MINMAX(v1->co, min, max);
+ done= 1;
+ }
+ }
+
+ /* call extrude? */
+ if(done) {
+ const short rot_src= RNA_boolean_get(op->ptr, "rotate_source");
+ BMEdge *eed;
+ float vec[3], cent[3], mat[3][3];
+ float nor[3]= {0.0, 0.0, 0.0};
+
+ /* 2D normal calc */
+ float mval_f[2];
+
+ mval_f[0]= (float)event->mval[0];
+ mval_f[1]= (float)event->mval[1];
+
+ /* check for edges that are half selected, use for rotation */
+ done= 0;
+ BM_ITER(eed, &iter, vc.em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(eed, BM_SELECT)) {
+ float co1[3], co2[3];
+ mul_v3_m4v3(co1, vc.obedit->obmat, eed->v1->co);
+ mul_v3_m4v3(co2, vc.obedit->obmat, eed->v2->co);
+ project_float_noclip(vc.ar, co1, co1);
+ project_float_noclip(vc.ar, co2, co2);
+
+ /* 2D rotate by 90d while adding.
+ * (x, y) = (y, -x)
+ *
+ * accumulate the screenspace normal in 2D,
+ * with screenspace edge length weighting the result. */
+ if(line_point_side_v2(co1, co2, mval_f) >= 0.0f) {
+ nor[0] += (co1[1] - co2[1]);
+ nor[1] += -(co1[0] - co2[0]);
+ }
+ else {
+ nor[0] += (co2[1] - co1[1]);
+ nor[1] += -(co2[0] - co1[0]);
+ }
+ }
+ done= 1;
+ }
+
+ if(done) {
+ float view_vec[3], cross[3];
+
+ /* convert the 2D nomal into 3D */
+ mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* worldspace */
+ mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */
+
+ /* correct the normal to be aligned on the view plane */
+ copy_v3_v3(view_vec, vc.rv3d->viewinv[2]);
+ mul_mat3_m4_v3(vc.obedit->imat, view_vec);
+ cross_v3_v3v3(cross, nor, view_vec);
+ cross_v3_v3v3(nor, view_vec, cross);
+ normalize_v3(nor);
+ }
+
+ /* center */
+ mid_v3_v3v3(cent, min, max);
+ copy_v3_v3(min, cent);
+
+ mul_m4_v3(vc.obedit->obmat, min); // view space
+ view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE);
+ mul_m4_v3(vc.obedit->imat, min); // back in object space
+
+ sub_v3_v3(min, cent);
+
+ /* calculate rotation */
+ unit_m3(mat);
+ if(done) {
+ float dot;
+
+ copy_v3_v3(vec, min);
+ normalize_v3(vec);
+ dot= INPR(vec, nor);
+
+ if( fabs(dot)<0.999) {
+ float cross[3], si, q1[4];
+
+ cross_v3_v3v3(cross, nor, vec);
+ normalize_v3(cross);
+ dot= 0.5f*saacos(dot);
+
+ /* halve the rotation if its applied twice */
+ if(rot_src) dot *= 0.5f;
+
+ si= (float)sin(dot);
+ q1[0]= (float)cos(dot);
+ q1[1]= cross[0]*si;
+ q1[2]= cross[1]*si;
+ q1[3]= cross[2]*si;
+ quat_to_mat3( mat,q1);
+ }
+ }
+
+ if(rot_src) {
+ EDBM_CallOpf(vc.em, op, "rotate verts=%hv cent=%v mat=%m3",
+ BM_SELECT, cent, mat);
+
+ /* also project the source, for retopo workflow */
+ if(use_proj)
+ EMBM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);
+ }
+
+ EDBM_Extrude_edge(vc.obedit, vc.em, BM_SELECT, nor);
+ EDBM_CallOpf(vc.em, op, "rotate verts=%hv cent=%v mat=%m3",
+ BM_SELECT, cent, mat);
+ EDBM_CallOpf(vc.em, op, "translate verts=%hv vec=%v",
+ BM_SELECT, min);
+ }
+ else {
+ float *curs= give_cursor(vc.scene, vc.v3d);
+ BMOperator bmop;
+ BMOIter oiter;
+
+ copy_v3_v3(min, curs);
+ view3d_get_view_aligned_coordinate(&vc, min, event->mval, 0);
+
+ invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ mul_m4_v3(vc.obedit->imat, min); // back in object space
+
+ EDBM_InitOpf(vc.em, &bmop, op, "makevert co=%v", min);
+ BMO_Exec_Op(vc.em->bm, &bmop);
+
+ BMO_ITER(v1, &oiter, vc.em->bm, &bmop, "newvertout", BM_VERT) {
+ BM_Select(vc.em->bm, v1, 1);
+ }
+
+ if (!EDBM_FinishOp(vc.em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+ }
+
+ if(use_proj)
+ EMBM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, vc.obedit->data);
+ DAG_id_tag_update(vc.obedit->data, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Duplicate or Extrude at 3D Cursor";
+ ot->idname= "MESH_OT_dupli_extrude_cursor";
+
+ /* api callbacks */
+ ot->invoke= dupli_extrude_cursor;
+ ot->description= "Duplicate and extrude selected vertices, edges or faces towards the mouse cursor";
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "rotate_source", 1, "Rotate Source", "Rotate initial selection giving better shape");
+}
+
+static int delete_mesh(bContext *C, Object *obedit, wmOperator *op, int event, Scene *UNUSED(scene))
+{
+ BMEditMesh *bem = ((Mesh*)obedit->data)->edit_btmesh;
+
+ if(event<1) return OPERATOR_CANCELLED;
+
+ if(event==10 ) {
+ //"Erase Vertices";
+
+ if (!EDBM_CallOpf(bem, op, "del geom=%hv context=%i", BM_SELECT, DEL_VERTS))
+ return OPERATOR_CANCELLED;
+ }
+ else if(event==11) {
+ //"Edge Loop"
+ if (!EDBM_CallOpf(bem, op, "dissolveedgeloop edges=%he", BM_SELECT))
+ return OPERATOR_CANCELLED;
+ }
+ else if(event==7) {
+ //"Dissolve"
+ if (bem->selectmode & SCE_SELECT_FACE) {
+ if (!EDBM_CallOpf(bem, op, "dissolvefaces faces=%hf",BM_SELECT))
+ return OPERATOR_CANCELLED;
+ } else if (bem->selectmode & SCE_SELECT_EDGE) {
+ if (!EDBM_CallOpf(bem, op, "dissolveedges edges=%he",BM_SELECT))
+ return OPERATOR_CANCELLED;
+ } else if (bem->selectmode & SCE_SELECT_VERTEX) {
+ if (!EDBM_CallOpf(bem, op, "dissolveverts verts=%hv",BM_SELECT))
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if(event==4) {
+ //Edges and Faces
+ if (!EDBM_CallOpf(bem, op, "del geom=%hef context=%i", BM_SELECT, DEL_EDGESFACES))
+ return OPERATOR_CANCELLED;
+ }
+ else if(event==1) {
+ //"Erase Edges"
+ if (!EDBM_CallOpf(bem, op, "del geom=%he context=%i", BM_SELECT, DEL_EDGES))
+ return OPERATOR_CANCELLED;
+ }
+ else if(event==2) {
+ //"Erase Faces";
+ if (!EDBM_CallOpf(bem, op, "del geom=%hf context=%i", BM_SELECT, DEL_FACES))
+ return OPERATOR_CANCELLED;
+ }
+ else if(event==5) {
+ //"Erase Only Faces";
+ if (!EDBM_CallOpf(bem, op, "del geom=%hf context=%d",
+ BM_SELECT, DEL_ONLYFACES))
+ return OPERATOR_CANCELLED;
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+/* Note, these values must match delete_mesh() event values */
+static EnumPropertyItem prop_mesh_delete_types[] = {
+ {7, "DISSOLVE", 0, "Dissolve", ""},
+ {12, "COLLAPSE", 0, "Collapse", ""},
+ {10,"VERT", 0, "Vertices", ""},
+ {1, "EDGE", 0, "Edges", ""},
+ {2, "FACE", 0, "Faces", ""},
+ {11, "EDGE_LOOP", 0, "Edge Loop", ""},
+ {4, "EDGE_FACE", 0, "Edges & Faces", ""},
+ {5, "ONLY_FACE", 0, "Only Faces", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int delete_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
+ Scene *scene = CTX_data_scene(C);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ if (type != 12) {
+ if (delete_mesh(C, obedit, op, type, scene) == OPERATOR_CANCELLED)
+ return OPERATOR_CANCELLED;
+ EDBM_clear_flag_all(em, BM_SELECT);
+ } else {
+ if (!EDBM_CallOpf(em, op, "collapse edges=%he", BM_SELECT))
+ return OPERATOR_CANCELLED;
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete";
+ ot->description= "Delete selected vertices, edges or faces";
+ ot->idname= "MESH_OT_delete";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= delete_mesh_exec;
+
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /*props */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, 10, "Type", "Method used for deleting mesh data");
+}
+
+
+static int addedgeface_mesh_exec(bContext *C, wmOperator *op)
+{
+ BMOperator bmop;
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ if (!EDBM_InitOpf(em, &bmop, op, "contextual_create geom=%hfev", BM_SELECT))
+ return OPERATOR_CANCELLED;
+
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "faceout", BM_SELECT, BM_FACE);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_edge_face_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make Edge/Face";
+ ot->description= "Add an edge or face to selected";
+ ot->idname= "MESH_OT_edge_face_add";
+
+ /* api callbacks */
+ ot->exec= addedgeface_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+}
+
+static EnumPropertyItem prop_mesh_edit_types[] = {
+ {1, "VERT", 0, "Vertices", ""},
+ {2, "EDGE", 0, "Edges", ""},
+ {3, "FACE", 0, "Faces", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int mesh_selection_type_exec(bContext *C, wmOperator *op)
+{
+
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ int type = RNA_enum_get(op->ptr,"type");
+
+ switch (type) {
+ case 1:
+ em->selectmode = SCE_SELECT_VERTEX;
+ break;
+ case 2:
+ em->selectmode = SCE_SELECT_EDGE;
+ break;
+ case 3:
+ em->selectmode = SCE_SELECT_FACE;
+ break;
+ }
+
+ EDBM_selectmode_set(em);
+ CTX_data_tool_settings(C)->selectmode = em->selectmode;
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static void MESH_OT_selection_type(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Selection Mode";
+ ot->description= "Set the selection mode type";
+ ot->idname= "MESH_OT_selection_type";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= mesh_selection_type_exec;
+
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "type", prop_mesh_edit_types, 0, "Type", "Set the mesh selection type");
+ RNA_def_boolean(ot->srna, "inclusive", 0, "Inclusive", "Selects geometry around selected geometry, occording to selection mode");
+}
+
+/* ************************* SEAMS AND EDGES **************** */
+
+static int editbmesh_mark_seam(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Mesh *me= ((Mesh *)obedit->data);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMEdge *eed;
+ BMIter iter;
+ int clear = RNA_boolean_get(op->ptr, "clear");
+
+ /* auto-enable seams drawing */
+ if(clear==0) {
+ me->drawflag |= ME_DRAWSEAMS;
+ }
+
+ if(clear) {
+ BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(eed, BM_SELECT) || BM_TestHFlag(eed, BM_HIDDEN))
+ continue;
+
+ BM_ClearHFlag(eed, BM_SEAM);
+ }
+ }
+ else {
+ BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(eed, BM_SELECT) || BM_TestHFlag(eed, BM_HIDDEN))
+ continue;
+ BM_SetHFlag(eed, BM_SEAM);
+ }
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_mark_seam(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mark Seam";
+ ot->idname= "MESH_OT_mark_seam";
+ ot->description= "(un)mark selected edges as a seam";
+
+ /* api callbacks */
+ ot->exec= editbmesh_mark_seam;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
+}
+
+static int editbmesh_mark_sharp(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Mesh *me= ((Mesh *)obedit->data);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMEdge *eed;
+ BMIter iter;
+ int clear = RNA_boolean_get(op->ptr, "clear");
+
+ /* auto-enable sharp edge drawing */
+ if(clear == 0) {
+ me->drawflag |= ME_DRAWSHARP;
+ }
+
+ if(!clear) {
+ BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(eed, BM_SELECT) || BM_TestHFlag(eed, BM_HIDDEN))
+ continue;
+
+ BM_SetHFlag(eed, BM_SHARP);
+ }
+ } else {
+ BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(eed, BM_SELECT) || BM_TestHFlag(eed, BM_HIDDEN))
+ continue;
+
+ BM_ClearHFlag(eed, BM_SHARP);
+ }
+ }
+
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_mark_sharp(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Mark Sharp";
+ ot->idname= "MESH_OT_mark_sharp";
+ ot->description= "(un)mark selected edges as sharp";
+
+ /* api callbacks */
+ ot->exec= editbmesh_mark_sharp;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
+}
+
+
+static int editbmesh_vert_connect(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+ int len = 0;
+
+ if (!EDBM_InitOpf(em, &bmop, op, "connectverts verts=%hv", BM_SELECT)) {
+ return OPERATOR_CANCELLED;
+ }
+ BMO_Exec_Op(bm, &bmop);
+ len = BMO_GetSlot(&bmop, "edgeout")->len;
+ if (!EDBM_FinishOp(em, &bmop, op, 1)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
+
+void MESH_OT_vert_connect(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Vertex Connect";
+ ot->idname= "MESH_OT_vert_connect";
+
+ /* api callbacks */
+ ot->exec= editbmesh_vert_connect;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int editbmesh_edge_split(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+ int len = 0;
+
+ if (!EDBM_InitOpf(em, &bmop, op, "edgesplit edges=%he numcuts=%d",
+ BM_SELECT, RNA_int_get(op->ptr,"number_cuts"))) {
+ return OPERATOR_CANCELLED;
+ }
+ BMO_Exec_Op(bm, &bmop);
+ len = BMO_GetSlot(&bmop, "outsplit")->len;
+ if (!EDBM_FinishOp(em, &bmop, op, 1)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
+
+void MESH_OT_edge_split(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Edge Split";
+ ot->idname= "MESH_OT_edge_split";
+
+ /* api callbacks */
+ ot->exec= editbmesh_edge_split;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, INT_MAX);
+}
+
+/****************** add duplicate operator ***************/
+
+static int mesh_duplicate_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ EDBM_InitOpf(em, &bmop, op, "dupe geom=%hvef", BM_SELECT);
+
+ BMO_Exec_Op(em->bm, &bmop);
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "newout", BM_SELECT, BM_ALL);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+
+ return OPERATOR_FINISHED;
+}
+
+static int mesh_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+{
+ WM_cursor_wait(1);
+ mesh_duplicate_exec(C, op);
+ WM_cursor_wait(0);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Duplicate";
+ ot->description= "Duplicate selected vertices, edges or faces";
+ ot->idname= "MESH_OT_duplicate";
+
+ /* api callbacks */
+ ot->invoke= mesh_duplicate_invoke;
+ ot->exec= mesh_duplicate_exec;
+
+ ot->poll= ED_operator_editmesh;
+
+ /* to give to transform */
+ RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+}
+
+static int flip_normals(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
+
+ if (!EDBM_CallOpf(em, op, "reversefaces faces=%hf", BM_SELECT))
+ return OPERATOR_CANCELLED;
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_flip_normals(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Flip Normals";
+ ot->description= "Flip the direction of selected face's vertex and face normals";
+ ot->idname= "MESH_OT_flip_normals";
+
+ /* api callbacks */
+ ot->exec= flip_normals;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+float *bm_get_cd_float(CustomData *cdata, void *data, int type)
+{
+ float *f = CustomData_bmesh_get(cdata, data, type);
+
+ return f;
+}
+
+static const EnumPropertyItem direction_items[]= {
+ {DIRECTION_CW, "CW", 0, "Clockwise", ""},
+ {DIRECTION_CCW, "CCW", 0, "Counter Clockwise", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+/* only accepts 1 selected edge, or 2 selected faces */
+static int edge_rotate_selected(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMOperator bmop;
+ BMEdge *eed;
+ BMIter iter;
+ const int do_ccw = RNA_enum_get(op->ptr, "direction") == 1;
+ int do_deselect= FALSE; /* do we deselect */
+
+ if (!(em->bm->totfacesel == 2 || em->bm->totedgesel == 1)) {
+ BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces");
+ return OPERATOR_CANCELLED;
+ }
+
+ /*first see if we have two adjacent faces*/
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_Edge_FaceCount(eed) == 2) {
+ if ((BM_TestHFlag(eed->l->f, BM_SELECT) && BM_TestHFlag(eed->l->radial_next->f, BM_SELECT))
+ && !(BM_TestHFlag(eed->l->f, BM_HIDDEN) || BM_TestHFlag(eed->l->radial_next->f, BM_HIDDEN)))
+ {
+ break;
+ }
+ }
+ }
+
+ /*ok, we don't have two adjacent faces, but we do have two selected ones.
+ that's an error condition.*/
+ if (!eed && em->bm->totfacesel == 2) {
+ BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!eed) {
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(eed, BM_SELECT) && !BM_TestHFlag(eed, BM_HIDDEN)) {
+ /* de-select the edge before */
+ do_deselect = TRUE;
+ break;
+ }
+ }
+ }
+
+ /*this should never happen*/
+ if (!eed)
+ return OPERATOR_CANCELLED;
+
+ EDBM_InitOpf(em, &bmop, op, "edgerotate edges=%e ccw=%d", eed, do_ccw);
+
+ /* avoid adding to the selection if we start off with only a selected edge,
+ * we could also just deselect the single edge easily but use the BMO api
+ * since it seems this is more 'correct' */
+ if(do_deselect) BMO_UnHeaderFlag_Buffer(em->bm, &bmop, "edges", BM_SELECT, BM_EDGE);
+
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "edgeout", BM_SELECT, BM_EDGE);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_edge_rotate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Rotate Selected Edge";
+ ot->description= "Rotate selected edge or adjoining faces";
+ ot->idname= "MESH_OT_edge_rotate";
+
+ /* api callbacks */
+ ot->exec= edge_rotate_selected;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "direction", "direction to rotate edge around");
+}
+
+/* swap is 0 or 1, if 1 it hides not selected */
+void EDBM_hide_mesh(BMEditMesh *em, int swap)
+{
+ BMIter iter;
+ BMHeader *h;
+ int itermode;
+
+ if(em==NULL) return;
+
+ if (em->selectmode & SCE_SELECT_VERTEX)
+ itermode = BM_VERTS_OF_MESH;
+ else if (em->selectmode & SCE_SELECT_EDGE)
+ itermode = BM_EDGES_OF_MESH;
+ else
+ itermode = BM_FACES_OF_MESH;
+
+ BM_ITER(h, &iter, em->bm, itermode, NULL) {
+ if (BM_TestHFlag(h, BM_SELECT) ^ swap)
+ BM_Hide(em->bm, h, 1);
+ }
+
+ EDBM_selectmode_flush(em);
+
+ /*original hide flushing comment (OUTDATED):
+ hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */
+ /* - vertex hidden, always means edge is hidden too
+ - edge hidden, always means face is hidden too
+ - face hidden, only set face hide
+ - then only flush back down what's absolute hidden
+ */
+
+}
+
+static int hide_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
+
+ EDBM_hide_mesh(em, RNA_boolean_get(op->ptr, "unselected"));
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_hide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Hide Selection";
+ ot->idname= "MESH_OT_hide";
+
+ /* api callbacks */
+ ot->exec= hide_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+ ot->description= "Hide (un)selected vertices, edges or faces";
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
+}
+
+
+void EDBM_reveal_mesh(BMEditMesh *em)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int i, types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+ int sels[3] = {
+ (em->selectmode & SCE_SELECT_VERTEX),
+ (em->selectmode & SCE_SELECT_EDGE),
+ (em->selectmode & SCE_SELECT_FACE),
+ };
+
+ /* Use index field to remember what was hidden before all is revealed. */
+ for (i=0; i<3; i++) {
+ BM_ITER(ele, &iter, em->bm, types[i], NULL) {
+ BM_SetIndex(ele, BM_TestHFlag(ele, BM_HIDDEN) ? 1 : 0);
+ }
+ }
+
+ /* Reveal everything */
+ EDBM_clear_flag_all(em, BM_HIDDEN);
+
+ /* Select relevant just-revealed elements */
+ for (i=0; i<3; i++) {
+ if (!sels[i]) {
+ continue;
+ }
+
+ BM_ITER(ele, &iter, em->bm, types[i], NULL) {
+ if (BM_GetIndex(ele)) {
+ BM_Select(em->bm, ele, 1);
+ }
+ }
+ }
+
+ EDBM_selectmode_flush(em);
+}
+
+static int reveal_mesh_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
+
+ EDBM_reveal_mesh(em);
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_reveal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reveal Hidden";
+ ot->idname= "MESH_OT_reveal";
+ ot->description= "Reveal all hidden vertices, edges and faces";
+
+ /* api callbacks */
+ ot->exec= reveal_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int normals_make_consistent_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ /* doflip has to do with bmesh_rationalize_normals, it's an internal
+ * thing*/
+ if (!EDBM_CallOpf(em, op, "righthandfaces faces=%hf doflip=%d", BM_SELECT, 1))
+ return OPERATOR_CANCELLED;
+
+ if (RNA_boolean_get(op->ptr, "inside"))
+ EDBM_CallOpf(em, op, "reversefaces faces=%hf", BM_SELECT);
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_normals_make_consistent(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Make Normals Consistent";
+ ot->description= "Make face and vertex normals point either outside or inside the mesh";
+ ot->idname= "MESH_OT_normals_make_consistent";
+
+ /* api callbacks */
+ ot->exec= normals_make_consistent_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "inside", 0, "Inside", "");
+}
+
+
+
+static int do_smooth_vertex(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ ModifierData *md;
+ int mirrx=0, mirry=0, mirrz=0;
+ int i, repeat;
+
+ /* if there is a mirror modifier with clipping, flag the verts that
+ * are within tolerance of the plane(s) of reflection
+ */
+ for(md=obedit->modifiers.first; md; md=md->next) {
+ if(md->type==eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
+ MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+ if(mmd->flag & MOD_MIR_CLIPPING) {
+ if (mmd->flag & MOD_MIR_AXIS_X)
+ mirrx = 1;
+ if (mmd->flag & MOD_MIR_AXIS_Y)
+ mirry = 1;
+ if (mmd->flag & MOD_MIR_AXIS_Z)
+ mirrz = 1;
+ }
+ }
+ }
+
+ repeat = RNA_int_get(op->ptr,"repeat");
+ if (!repeat)
+ repeat = 1;
+
+ for (i=0; i<repeat; i++) {
+ if (!EDBM_CallOpf(em, op, "vertexsmooth verts=%hv mirror_clip_x=%d mirror_clip_y=%d mirror_clip_z=%d",
+ BM_SELECT, mirrx, mirry, mirrz))
+ {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ //BMESH_TODO: need to handle the x-axis editing option here properly.
+ //should probably make a helper function for that? I dunno.
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_vertices_smooth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Smooth Vertex";
+ ot->description= "Flatten angles of selected vertices";
+ ot->idname= "MESH_OT_vertices_smooth";
+
+ /* api callbacks */
+ ot->exec= do_smooth_vertex;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Number of times to smooth the mesh", "", 1, INT_MAX);
+}
+
+
+static int bm_test_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMBVHTree *tree = BMBVH_NewBVH(em, 0, NULL, NULL);
+ BMIter iter;
+ BMEdge *e;
+
+ /*hide all back edges*/
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(e, BM_SELECT))
+ continue;
+
+ if (!BMBVH_EdgeVisible(tree, e, ar, v3d, obedit))
+ BM_Select(em->bm, e, 0);
+ }
+
+ BMBVH_FreeBVH(tree);
+
+#if 0 //uv island walker test
+ BMIter iter, liter;
+ BMFace *f;
+ BMLoop *l, *l2;
+ MLoopUV *luv;
+ BMWalker walker;
+ int i=0;
+
+ BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ }
+ }
+
+ BMW_Init(&walker, em->bm, BMW_UVISLAND, 0);
+
+ BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ l2 = BMW_Begin(&walker, l);
+ for (; l2; l2=BMW_Step(&walker)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l2->head.data, CD_MLOOPUV);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+ }
+ }
+ }
+
+ BMW_End(&walker);
+#endif
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_bm_test(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "BMesh Test Operator";
+ ot->idname= "MESH_OT_bm_test";
+
+ /* api callbacks */
+ ot->exec= bm_test_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ //RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Number of times to smooth the mesh", "", 1, INT_MAX);
+}
+
+/********************** Smooth/Solid Operators *************************/
+
+static void mesh_set_smooth_faces(BMEditMesh *em, short smooth)
+{
+ BMIter iter;
+ BMFace *efa;
+
+ if(em==NULL) return;
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (BM_TestHFlag(efa, BM_SELECT)) {
+ if (smooth)
+ BM_SetHFlag(efa, BM_SMOOTH);
+ else
+ BM_ClearHFlag(efa, BM_SMOOTH);
+ }
+ }
+}
+
+static int mesh_faces_shade_smooth_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ mesh_set_smooth_faces(em, 1);
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_faces_shade_smooth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Shade Smooth";
+ ot->description= "Display faces smooth (using vertex normals)";
+ ot->idname= "MESH_OT_faces_shade_smooth";
+
+ /* api callbacks */
+ ot->exec= mesh_faces_shade_smooth_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int mesh_faces_shade_flat_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ mesh_set_smooth_faces(em, 0);
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_faces_shade_flat(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Shade Flat";
+ ot->description= "Display faces flat";
+ ot->idname= "MESH_OT_faces_shade_flat";
+
+ /* api callbacks */
+ ot->exec= mesh_faces_shade_flat_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/********************** UV/Color Operators *************************/
+
+
+static const EnumPropertyItem axis_items[]= {
+ {OPUVC_AXIS_X, "X", 0, "X", ""},
+ {OPUVC_AXIS_Y, "Y", 0, "Y", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+static int mesh_rotate_uvs(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ /* get the direction from RNA */
+ int dir = RNA_enum_get(op->ptr, "direction");
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "meshrotateuvs faces=%hf dir=%d", BM_SELECT, dir);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+
+ /* dependencies graph and notification stuff */
+ DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+/* DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+*/
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+static int mesh_reverse_uvs(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "meshreverseuvs faces=%hf", BM_SELECT);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+ /* dependencies graph and notification stuff */
+ DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+/* DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+*/
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+static int mesh_rotate_colors(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ /* get the direction from RNA */
+ int dir = RNA_enum_get(op->ptr, "direction");
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "meshrotatecolors faces=%hf dir=%d", BM_SELECT, dir);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+
+ /* dependencies graph and notification stuff */
+ DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+/* DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_GEOM_SELECT, ob);
+*/
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+
+static int mesh_reverse_colors(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "meshreversecolors faces=%hf", BM_SELECT);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+ DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_uvs_rotate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Rotate UVs";
+ ot->idname= "MESH_OT_uvs_rotate";
+
+ /* api callbacks */
+ ot->exec= mesh_rotate_uvs;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate UVs around");
+}
+
+//void MESH_OT_uvs_mirror(wmOperatorType *ot)
+void MESH_OT_uvs_reverse(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reverse UVs";
+ ot->idname= "MESH_OT_uvs_reverse";
+
+ /* api callbacks */
+ ot->exec= mesh_reverse_uvs;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ //RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror UVs around");
+}
+
+void MESH_OT_colors_rotate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Rotate Colors";
+ ot->idname= "MESH_OT_colors_rotate";
+
+ /* api callbacks */
+ ot->exec= mesh_rotate_colors;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate edge around");
+}
+
+void MESH_OT_colors_reverse(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Reverse Colors";
+ ot->idname= "MESH_OT_colors_reverse";
+
+ /* api callbacks */
+ ot->exec= mesh_reverse_colors;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ //RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around");
+}
+
+
+static int merge_firstlast(BMEditMesh *em, int first, int uvmerge, wmOperator *wmop)
+{
+ BMVert *mergevert;
+ BMEditSelection *ese;
+
+ /* do sanity check in mergemenu in edit.c ?*/
+ if(first == 0){
+ ese = em->bm->selected.last;
+ mergevert= (BMVert*)ese->data;
+ }
+ else{
+ ese = em->bm->selected.first;
+ mergevert = (BMVert*)ese->data;
+ }
+
+ if (!BM_TestHFlag(mergevert, BM_SELECT))
+ return OPERATOR_CANCELLED;
+
+ if (uvmerge) {
+ if (!EDBM_CallOpf(em, wmop, "pointmerge_facedata verts=%hv snapv=%e", BM_SELECT, mergevert))
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!EDBM_CallOpf(em, wmop, "pointmerge verts=%hv mergeco=%v", BM_SELECT, mergevert->co))
+ return OPERATOR_CANCELLED;
+
+ return OPERATOR_FINISHED;
+}
+
+static int merge_target(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob,
+ int target, int uvmerge, wmOperator *wmop)
+{
+ BMIter iter;
+ BMVert *v;
+ float *vco=NULL, co[3], cent[3] = {0.0f, 0.0f, 0.0f};
+
+ if (target) {
+ vco = give_cursor(scene, v3d);
+ copy_v3_v3(co, vco);
+ mul_m4_v3(ob->imat, co);
+ }
+ else {
+ float fac;
+ int i = 0;
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (!BM_TestHFlag(v, BM_SELECT))
+ continue;
+ VECADD(cent, cent, v->co);
+ i++;
+ }
+
+ if (!i)
+ return OPERATOR_CANCELLED;
+
+ fac = 1.0f / (float)i;
+ mul_v3_fl(cent, fac);
+ copy_v3_v3(co, cent);
+ vco = co;
+ }
+
+ if (!vco)
+ return OPERATOR_CANCELLED;
+
+ if (uvmerge) {
+ if (!EDBM_CallOpf(em, wmop, "vert_average_facedata verts=%hv", BM_SELECT))
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!EDBM_CallOpf(em, wmop, "pointmerge verts=%hv mergeco=%v", BM_SELECT, co))
+ return OPERATOR_CANCELLED;
+
+ return OPERATOR_FINISHED;
+}
+
+static int merge_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ int status= 0, uvs= RNA_boolean_get(op->ptr, "uvs");
+
+ switch(RNA_enum_get(op->ptr, "type")) {
+ case 3:
+ status = merge_target(em, scene, v3d, obedit, 0, uvs, op);
+ break;
+ case 4:
+ status = merge_target(em, scene, v3d, obedit, 1, uvs, op);
+ break;
+ case 1:
+ status = merge_firstlast(em, 0, uvs, op);
+ break;
+ case 6:
+ status = merge_firstlast(em, 1, uvs, op);
+ break;
+ case 5:
+ status = 1;
+ if (!EDBM_CallOpf(em, op, "collapse edges=%he", BM_SELECT))
+ status = 0;
+ break;
+ }
+
+ if(!status)
+ return OPERATOR_CANCELLED;
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+static EnumPropertyItem merge_type_items[]= {
+ {6, "FIRST", 0, "At First", ""},
+ {1, "LAST", 0, "At Last", ""},
+ {3, "CENTER", 0, "At Center", ""},
+ {4, "CURSOR", 0, "At Cursor", ""},
+ {5, "COLLAPSE", 0, "Collapse", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+static EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
+{
+ Object *obedit;
+ EnumPropertyItem *item= NULL;
+ int totitem= 0;
+
+ if(!C) /* needed for docs */
+ return merge_type_items;
+
+ obedit= CTX_data_edit_object(C);
+ if(obedit && obedit->type == OB_MESH) {
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+
+ if(em->selectmode & SCE_SELECT_VERTEX) {
+ if(em->bm->selected.first && em->bm->selected.last &&
+ ((BMEditSelection*)em->bm->selected.first)->type == BM_VERT && ((BMEditSelection*)em->bm->selected.last)->type == BM_VERT) {
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
+ }
+ else if(em->bm->selected.first && ((BMEditSelection*)em->bm->selected.first)->type == BM_VERT)
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
+ else if(em->bm->selected.last && ((BMEditSelection*)em->bm->selected.last)->type == BM_VERT)
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
+ }
+
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 3);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 4);
+ RNA_enum_items_add_value(&item, &totitem, merge_type_items, 5);
+ RNA_enum_item_end(&item, &totitem);
+
+ *free= 1;
+
+ return item;
+ }
+
+ return NULL;
+}
+
+void MESH_OT_merge(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Merge";
+ ot->idname= "MESH_OT_merge";
+
+ /* api callbacks */
+ ot->exec= merge_exec;
+ ot->invoke= WM_menu_invoke;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop= RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use");
+ RNA_def_enum_funcs(ot->prop, merge_type_itemf);
+ RNA_def_boolean(ot->srna, "uvs", 1, "UVs", "Move UVs according to merge");
+}
+
+
+static int removedoublesflag_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMOperator bmop;
+ /* int count; */ /* UNUSED */
+
+ EDBM_InitOpf(em, &bmop, op, "finddoubles verts=%hv dist=%f",
+ BM_SELECT, RNA_float_get(op->ptr, "mergedist"));
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* count = BMO_CountSlotMap(em->bm, &bmop, "targetmapout"); */ /* UNUSED */
+
+ if (!EDBM_CallOpf(em, op, "weldverts targetmap=%s", &bmop, "targetmapout")) {
+ BMO_Finish_Op(em->bm, &bmop);
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ /*we need a better way of reporting this, since this doesn't work
+ with the last operator panel correctly.
+ if(count)
+ {
+ sprintf(msg, "Removed %d vertices", count);
+ BKE_report(op->reports, RPT_INFO, msg);
+ }
+ */
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_remove_doubles(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Remove Doubles";
+ ot->idname= "MESH_OT_remove_doubles";
+
+ /* api callbacks */
+ ot->exec= removedoublesflag_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_float(ot->srna, "mergedist", 0.0001f, 0.000001f, 50.0f,
+ "Merge Distance",
+ "Minimum distance between elements to merge", 0.00001, 10.0);
+}
+
+/************************ Vertex Path Operator *************************/
+
+typedef struct PathNode {
+ int u;
+ int visited;
+ ListBase edges;
+} PathNode;
+
+typedef struct PathEdge {
+ struct PathEdge *next, *prev;
+ int v;
+ float w;
+} PathEdge;
+
+
+
+static int select_vertex_path_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+ BMEditSelection *sv, *ev;
+
+ /* get the type from RNA */
+ int type = RNA_enum_get(op->ptr, "type");
+
+ sv = em->bm->selected.last;
+ if( sv != NULL )
+ ev = sv->prev;
+ else return OPERATOR_CANCELLED;
+ if( ev == NULL )
+ return OPERATOR_CANCELLED;
+
+ if( sv->type != BM_VERT || ev->type != BM_VERT )
+ return OPERATOR_CANCELLED;
+
+ /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
+ EDBM_InitOpf(em, &bmop, op, "vertexshortestpath startv=%e endv=%e type=%d", sv->data, ev->data, type);
+
+ /* execute the operator */
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /* DO NOT clear the existing selection */
+ /* EDBM_clear_flag_all(em, BM_SELECT); */
+
+ /* select the output */
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "vertout", BM_SELECT, BM_ALL);
+
+ /* finish the operator */
+ if( !EDBM_FinishOp(em, &bmop, op, 1) )
+ return OPERATOR_CANCELLED;
+
+ EDBM_selectmode_flush(em);
+
+ /* dependencies graph and notification stuff */
+/* DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_GEOM_SELECT, ob);
+*/
+ DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+
+
+ /* we succeeded */
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_vertex_path(wmOperatorType *ot)
+{
+ static const EnumPropertyItem type_items[] = {
+ {VPATH_SELECT_EDGE_LENGTH, "EDGE_LENGTH", 0, "Edge Length", NULL},
+ {VPATH_SELECT_TOPOLOGICAL, "TOPOLOGICAL", 0, "Topological", NULL},
+ {0, NULL, 0, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Select Vertex Path";
+ ot->idname= "MESH_OT_select_vertex_path";
+
+ /* api callbacks */
+ ot->exec= select_vertex_path_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", type_items, VPATH_SELECT_EDGE_LENGTH, "Type", "Method to compute distance");
+}
+/********************** Rip Operator *************************/
+
+/* helper to find edge for edge_rip */
+static float mesh_rip_edgedist(ARegion *ar, float mat[][4], float *co1, float *co2, const int mval[2])
+{
+ float vec1[3], vec2[3], mvalf[2];
+
+ ED_view3d_project_float(ar, co1, vec1, mat);
+ ED_view3d_project_float(ar, co2, vec2, mat);
+ mvalf[0]= (float)mval[0];
+ mvalf[1]= (float)mval[1];
+
+ return dist_to_line_segment_v2(mvalf, vec1, vec2);
+}
+
+/* based on mouse cursor position, it defines how is being ripped */
+static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ARegion *ar= CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+ BMBVHTree *bvhtree;
+ BMOIter siter;
+ BMIter iter, eiter, liter;
+ BMLoop *l;
+ BMEdge *e, *e2, *closest = NULL;
+ BMVert *v, *ripvert = NULL;
+ int side = 0, i, singlesel = 0;
+ float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
+ float dist = FLT_MAX, d;
+
+ ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat);
+
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(e, BM_SELECT))
+ BM_SetIndex(e, 1);
+ else BM_SetIndex(e, 0);
+ }
+
+ /*handle case of one vert selected. identify
+ closest edge around that vert to mouse cursor,
+ then rip two adjacent edges in the vert fan.*/
+ if (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0) {
+ singlesel = 1;
+
+ /*find selected vert*/
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(v, BM_SELECT))
+ break;
+ }
+
+ /*this should be impossible, but sanity checks are a good thing*/
+ if (!v)
+ return OPERATOR_CANCELLED;
+
+ if (!v->e || !v->e->l) {
+ BKE_report(op->reports, RPT_ERROR, "Selected vertex has no faces");
+ return OPERATOR_CANCELLED;
+ }
+
+ /*find closest edge to mouse cursor*/
+ e2 = NULL;
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_VERT, v) {
+ d = mesh_rip_edgedist(ar, projectMat, e->v1->co, e->v2->co, event->mval);
+ if (d < dist) {
+ dist = d;
+ e2 = e;
+ }
+ }
+
+ if (!e2)
+ return OPERATOR_CANCELLED;
+
+ /*rip two adjacent edges*/
+ if (BM_Edge_FaceCount(e2) == 1 || BM_Vert_FaceCount(v) == 2) {
+ l = e2->l;
+ ripvert = BM_Rip_Vertex(bm, l->f, v);
+
+ BLI_assert(ripvert);
+ if (!ripvert) {
+ return OPERATOR_CANCELLED;
+ }
+ } else if (BM_Edge_FaceCount(e2) == 2) {
+ l = e2->l;
+ e = BM_OtherFaceLoop(e2, l->f, v)->e;
+ BM_SetIndex(e, 1);
+ BM_Select(bm, e, 1);
+
+ l = e2->l->radial_next;
+ e = BM_OtherFaceLoop(e2, l->f, v)->e;
+ BM_SetIndex(e, 1);
+ BM_Select(bm, e, 1);
+ }
+
+ dist = FLT_MAX;
+ } else {
+ /*expand edge selection*/
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ e2 = NULL;
+ i = 0;
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ if (BM_GetIndex(e)) {
+ e2 = e;
+ i++;
+ }
+ }
+
+ if (i == 1 && e2->l) {
+ l = BM_OtherFaceLoop(e2, e2->l->f, v);
+ l = l->radial_next;
+ l = BM_OtherFaceLoop(l->e, l->f, v);
+
+ if (l)
+ BM_Select(bm, l->e, 1);
+ }
+ }
+ }
+
+ if (!EDBM_InitOpf(em, &bmop, op, "edgesplit edges=%he", BM_SELECT)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BMO_Exec_Op(bm, &bmop);
+
+ /*build bvh tree for edge visibility tests*/
+ bvhtree = BMBVH_NewBVH(em, 0, NULL, NULL);
+
+ for (i=0; i<2; i++) {
+ BMO_ITER(e, &siter, bm, &bmop, i ? "edgeout2":"edgeout1", BM_EDGE) {
+ float cent[3] = {0, 0, 0}, mid[3], vec[3];
+
+ if (!BMBVH_EdgeVisible(bvhtree, e, ar, v3d, obedit) || !e->l)
+ continue;
+
+ /* method for calculating distance:
+ *
+ * for each edge: calculate face center, then made a vector
+ * from edge midpoint to face center. offset edge midpoint
+ * by a small amount along this vector. */
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, e->l->f) {
+ add_v3_v3(cent, l->v->co);
+ }
+ mul_v3_fl(cent, 1.0f/(float)e->l->f->len);
+
+ mid_v3_v3v3(mid, e->v1->co, e->v2->co);
+ sub_v3_v3v3(vec, cent, mid);
+ normalize_v3(vec);
+ mul_v3_fl(vec, 0.01f);
+ add_v3_v3v3(mid, mid, vec);
+
+ /* yay we have our comparison point, now project it */
+ ED_view3d_project_float(ar, mid, mid, projectMat);
+
+ d = len_squared_v2v2(fmval, mid);
+
+ if (d < dist) {
+ side = i;
+ closest = e;
+ dist = d;
+ }
+ }
+ }
+
+ BMBVH_FreeBVH(bvhtree);
+
+ EDBM_clear_flag_all(em, BM_SELECT);
+ BMO_HeaderFlag_Buffer(bm, &bmop, side?"edgeout2":"edgeout1", BM_SELECT, BM_EDGE);
+
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(e, BM_SELECT))
+ BM_SetIndex(e, 1);
+ else BM_SetIndex(e, 0);
+ }
+
+ /*constrict edge selection again*/
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ e2 = NULL;
+ i = 0;
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+ if (BM_GetIndex(e)) {
+ e2 = e;
+ i++;
+ }
+ }
+
+ if (i == 1) {
+ if (singlesel)
+ BM_Select(bm, v, 0);
+ else
+ BM_Select(bm, e2, 0);
+ }
+ }
+
+ if (ripvert) {
+ BM_Select(bm, ripvert, 1);
+ }
+
+ EDBM_selectmode_flush(em);
+
+ BLI_assert(singlesel ? (bm->totvertsel > 0) : (bm->totedgesel > 0));
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (bm->totvertsel == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_rip(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Rip";
+ ot->idname= "MESH_OT_rip";
+
+ /* api callbacks */
+ ot->invoke= mesh_rip_invoke;
+ ot->poll= EM_view3d_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* to give to transform */
+ Transform_Properties(ot, P_PROPORTIONAL);
+ RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+}
+
+/************************ Shape Operators *************************/
+
+/*BMESH_TODO this should be properly encapsulated in a bmop. but later.*/
+static void shape_propagate(Object *obedit, BMEditMesh *em, wmOperator *op)
+{
+ BMIter iter;
+ BMVert *eve = NULL;
+ float *co;
+ int i, totshape = CustomData_number_of_layers(&em->bm->vdata, CD_SHAPEKEY);
+
+ if (!CustomData_has_layer(&em->bm->vdata, CD_SHAPEKEY)) {
+ BKE_report(op->reports, RPT_ERROR, "Mesh does not have shape keys");
+ return;
+ }
+
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (!BM_TestHFlag(eve, BM_SELECT) || BM_TestHFlag(eve, BM_HIDDEN))
+ continue;
+
+ for (i=0; i<totshape; i++) {
+ co = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, i);
+ copy_v3_v3(co, eve->co);
+ }
+ }
+
+#if 0
+ //TAG Mesh Objects that share this data
+ for(base = scene->base.first; base; base = base->next){
+ if(base->object && base->object->data == me){
+ base->object->recalc = OB_RECALC_DATA;
+ }
+ }
+#endif
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+}
+
+
+static int shape_propagate_to_all_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Mesh *me= obedit->data;
+ BMEditMesh *em= me->edit_btmesh;
+
+ shape_propagate(obedit, em, op);
+
+ DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void MESH_OT_shape_propagate_to_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Shape Propagate";
+ ot->description= "Apply selected vertex locations to all other shape keys";
+ ot->idname= "MESH_OT_shape_propagate_to_all";
+
+ /* api callbacks */
+ ot->exec= shape_propagate_to_all_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/*BMESH_TODO this should be properly encapsulated in a bmop. but later.*/
+static int blend_from_shape_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Mesh *me= obedit->data;
+ BMEditMesh *em= me->edit_btmesh;
+ BMVert *eve;
+ BMIter iter;
+ float co[3], *sco;
+ float blend= RNA_float_get(op->ptr, "blend");
+ int shape= RNA_enum_get(op->ptr, "shape");
+ int add= RNA_boolean_get(op->ptr, "add");
+ int totshape;
+
+ /*sanity check*/
+ totshape = CustomData_number_of_layers(&em->bm->vdata, CD_SHAPEKEY);
+ if (totshape == 0 || shape < 0 || shape >= totshape)
+ return OPERATOR_CANCELLED;
+
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (!BM_TestHFlag(eve, BM_SELECT) || BM_TestHFlag(eve, BM_HIDDEN))
+ continue;
+
+ sco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, shape);
+ copy_v3_v3(co, sco);
+
+
+ if(add) {
+ mul_v3_fl(co, blend);
+ add_v3_v3v3(eve->co, eve->co, co);
+ }
+ else
+ interp_v3_v3v3(eve->co, eve->co, co, blend);
+
+ copy_v3_v3(sco, co);
+ }
+
+ DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
+
+ return OPERATOR_FINISHED;
+}
+
+static EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Mesh *me= (obedit) ? obedit->data : NULL;
+ BMEditMesh *em = me->edit_btmesh;
+ EnumPropertyItem *item= NULL;
+ int totitem= 0;
+
+ if(obedit && obedit->type == OB_MESH && CustomData_has_layer(&em->bm->vdata, CD_SHAPEKEY)) {
+ EnumPropertyItem tmp= {0, "", 0, "", ""};
+ int a;
+
+ for (a=0; a<em->bm->vdata.totlayer; a++) {
+ if (em->bm->vdata.layers[a].type != CD_SHAPEKEY)
+ continue;
+
+ tmp.value= totitem;
+ tmp.identifier= em->bm->vdata.layers[a].name;
+ tmp.name= em->bm->vdata.layers[a].name;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ totitem++;
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *free= 1;
+
+ return item;
+}
+
+void MESH_OT_blend_from_shape(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+ static EnumPropertyItem shape_items[]= {{0, NULL, 0, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Blend From Shape";
+ ot->description= "Blend in shape from a shape key";
+ ot->idname= "MESH_OT_blend_from_shape";
+
+ /* api callbacks */
+ ot->exec= blend_from_shape_exec;
+ ot->invoke= WM_operator_props_popup;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ prop= RNA_def_enum(ot->srna, "shape", shape_items, 0, "Shape", "Shape key to use for blending");
+ RNA_def_enum_funcs(prop, shape_itemf);
+ RNA_def_float(ot->srna, "blend", 1.0f, -FLT_MAX, FLT_MAX, "Blend", "Blending factor", -2.0f, 2.0f);
+ RNA_def_boolean(ot->srna, "add", 1, "Add", "Add rather then blend between shapes");
+}
+
+/* BMESH_TODO - some way to select on an arbitrary axis */
+static int select_axis_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMEditSelection *ese = em->bm->selected.last;
+ int axis= RNA_enum_get(op->ptr, "axis");
+ int mode= RNA_enum_get(op->ptr, "mode"); /* -1==aligned, 0==neg, 1==pos*/
+
+ if(ese==NULL)
+ return OPERATOR_CANCELLED;
+
+ if(ese->type==BM_VERT) {
+ BMVert *ev, *act_vert= (BMVert*)ese->data;
+ BMIter iter;
+ float value= act_vert->co[axis];
+ float limit= CTX_data_tool_settings(C)->doublimit; // XXX
+
+ if(mode==0)
+ value -= limit;
+ else if (mode==1)
+ value += limit;
+
+ BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if(!BM_TestHFlag(ev, BM_HIDDEN)) {
+ switch(mode) {
+ case -1: /* aligned */
+ if(fabs(ev->co[axis] - value) < limit)
+ BM_Select(em->bm, ev, 1);
+ break;
+ case 0: /* neg */
+ if(ev->co[axis] > value)
+ BM_Select(em->bm, ev, 1);
+ break;
+ case 1: /* pos */
+ if(ev->co[axis] < value)
+ BM_Select(em->bm, ev, 1);
+ break;
+ }
+ }
+ }
+ }
+
+ EDBM_selectmode_flush(em);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_axis(wmOperatorType *ot)
+{
+ static EnumPropertyItem axis_mode_items[] = {
+ {0, "POSITIVE", 0, "Positive Axis", ""},
+ {1, "NEGATIVE", 0, "Negative Axis", ""},
+ {-1, "ALIGNED", 0, "Aligned Axis", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+ static EnumPropertyItem axis_items_xyz[] = {
+ {0, "X_AXIS", 0, "X Axis", ""},
+ {1, "Y_AXIS", 0, "Y Axis", ""},
+ {2, "Z_AXIS", 0, "Z Axis", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Select Axis";
+ ot->description= "Select all data in the mesh on a single axis";
+ ot->idname= "MESH_OT_select_axis";
+
+ /* api callbacks */
+ ot->exec= select_axis_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "mode", axis_mode_items, 0, "Axis Mode", "Axis side to use when selecting");
+ RNA_def_enum(ot->srna, "axis", axis_items_xyz, 0, "Axis", "Select the axis to compare each vertex on");
+}
+
+static int solidify_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ Mesh *me = obedit->data;
+ BMEditMesh *em = me->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+
+ float thickness= RNA_float_get(op->ptr, "thickness");
+
+ if (!EDBM_InitOpf(em, &bmop, op, "solidify geom=%hf thickness=%f", BM_SELECT, thickness)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* deselect only the faces in the region to be solidified (leave wire
+ edges and loose verts selected, as there will be no corresponding
+ geometry selected below) */
+ BMO_UnHeaderFlag_Buffer(bm, &bmop, "geom", BM_SELECT, BM_FACE);
+
+ /* run the solidify operator */
+ BMO_Exec_Op(bm, &bmop);
+
+ /* select the newly generated faces */
+ BMO_HeaderFlag_Buffer(bm, &bmop, "geomout", BM_SELECT, BM_FACE);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void MESH_OT_solidify(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+ /* identifiers */
+ ot->name= "Solidify";
+ ot->description= "Create a solid skin by extruding, compensating for sharp angles";
+ ot->idname= "MESH_OT_solidify";
+
+ /* api callbacks */
+ ot->exec= solidify_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ prop= RNA_def_float(ot->srna, "thickness", 0.01f, -FLT_MAX, FLT_MAX, "thickness", "", -10.0f, 10.0f);
+ RNA_def_property_ui_range(prop, -10, 10, 0.1, 4);
+}
+
+#define TRAIL_POLYLINE 1 /* For future use, They don't do anything yet */
+#define TRAIL_FREEHAND 2
+#define TRAIL_MIXED 3 /* (1|2) */
+#define TRAIL_AUTO 4
+#define TRAIL_MIDPOINTS 8
+
+typedef struct CutCurve {
+ float x;
+ float y;
+} CutCurve;
+
+/* ******************************************************************** */
+/* Knife Subdivide Tool. Subdivides edges intersected by a mouse trail
+ drawn by user.
+
+ Currently mapped to KKey when in MeshEdit mode.
+ Usage:
+ Hit Shift K, Select Centers or Exact
+ Hold LMB down to draw path, hit RETKEY.
+ ESC cancels as expected.
+
+ Contributed by Robert Wenzlaff (Det. Thorn).
+
+ 2.5 revamp:
+ - non modal (no menu before cutting)
+ - exit on mouse release
+ - polygon/segment drawing can become handled by WM cb later
+
+ bmesh port version
+*/
+
+#define KNIFE_EXACT 1
+#define KNIFE_MIDPOINT 2
+#define KNIFE_MULTICUT 3
+
+static EnumPropertyItem knife_items[]= {
+ {KNIFE_EXACT, "EXACT", 0, "Exact", ""},
+ {KNIFE_MIDPOINT, "MIDPOINTS", 0, "Midpoints", ""},
+ {KNIFE_MULTICUT, "MULTICUT", 0, "Multicut", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+/* seg_intersect() Determines if and where a mouse trail intersects an EditEdge */
+
+static float bm_seg_intersect(BMEdge *e, CutCurve *c, int len, char mode,
+ struct GHash *gh, int *isected)
+{
+#define MAXSLOPE 100000
+ float x11, y11, x12=0, y12=0, x2max, x2min, y2max;
+ float y2min, dist, lastdist=0, xdiff2, xdiff1;
+ float m1, b1, m2, b2, x21, x22, y21, y22, xi;
+ float yi, x1min, x1max, y1max, y1min, perc=0;
+ float *scr;
+ float threshold = 0.0;
+ int i;
+
+ //threshold = 0.000001; /*tolerance for vertex intersection*/
+ // XXX threshold = scene->toolsettings->select_thresh / 100;
+
+ /* Get screen coords of verts */
+ scr = BLI_ghash_lookup(gh, e->v1);
+ x21=scr[0];
+ y21=scr[1];
+
+ scr = BLI_ghash_lookup(gh, e->v2);
+ x22=scr[0];
+ y22=scr[1];
+
+ xdiff2=(x22-x21);
+ if (xdiff2) {
+ m2=(y22-y21)/xdiff2;
+ b2= ((x22*y21)-(x21*y22))/xdiff2;
+ }
+ else {
+ m2=MAXSLOPE; /* Verticle slope */
+ b2=x22;
+ }
+
+ *isected = 0;
+
+ /*check for *exact* vertex intersection first*/
+ if(mode!=KNIFE_MULTICUT){
+ for (i=0; i<len; i++){
+ if (i>0){
+ x11=x12;
+ y11=y12;
+ }
+ else {
+ x11=c[i].x;
+ y11=c[i].y;
+ }
+ x12=c[i].x;
+ y12=c[i].y;
+
+ /*test e->v1*/
+ if((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)){
+ perc = 0;
+ *isected = 1;
+ return(perc);
+ }
+ /*test e->v2*/
+ else if((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)){
+ perc = 0;
+ *isected = 2;
+ return(perc);
+ }
+ }
+ }
+
+ /*now check for edge interesect (may produce vertex intersection as well)*/
+ for (i=0; i<len; i++){
+ if (i>0){
+ x11=x12;
+ y11=y12;
+ }
+ else {
+ x11=c[i].x;
+ y11=c[i].y;
+ }
+ x12=c[i].x;
+ y12=c[i].y;
+
+ /* Perp. Distance from point to line */
+ if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */
+ /* change in sign. Skip extra math */
+ else dist=x22-x12;
+
+ if (i==0) lastdist=dist;
+
+ /* if dist changes sign, and intersect point in edge's Bound Box*/
+ if ((lastdist*dist)<=0){
+ xdiff1=(x12-x11); /* Equation of line between last 2 points */
+ if (xdiff1){
+ m1=(y12-y11)/xdiff1;
+ b1= ((x12*y11)-(x11*y12))/xdiff1;
+ }
+ else{
+ m1=MAXSLOPE;
+ b1=x12;
+ }
+ x2max=MAX2(x21,x22)+0.001; /* prevent missed edges */
+ x2min=MIN2(x21,x22)-0.001; /* due to round off error */
+ y2max=MAX2(y21,y22)+0.001;
+ y2min=MIN2(y21,y22)-0.001;
+
+ /* Found an intersect, calc intersect point */
+ if (m1==m2){ /* co-incident lines */
+ /* cut at 50% of overlap area*/
+ x1max=MAX2(x11, x12);
+ x1min=MIN2(x11, x12);
+ xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0;
+
+ y1max=MAX2(y11, y12);
+ y1min=MIN2(y11, y12);
+ yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0;
+ }
+ else if (m2==MAXSLOPE){
+ xi=x22;
+ yi=m1*x22+b1;
+ }
+ else if (m1==MAXSLOPE){
+ xi=x12;
+ yi=m2*x12+b2;
+ }
+ else {
+ xi=(b1-b2)/(m2-m1);
+ yi=(b1*m2-m1*b2)/(m2-m1);
+ }
+
+ /* Intersect inside bounding box of edge?*/
+ if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){
+ /*test for vertex intersect that may be 'close enough'*/
+ if(mode!=KNIFE_MULTICUT){
+ if(xi <= (x21 + threshold) && xi >= (x21 - threshold)){
+ if(yi <= (y21 + threshold) && yi >= (y21 - threshold)){
+ *isected = 1;
+ perc = 0;
+ break;
+ }
+ }
+ if(xi <= (x22 + threshold) && xi >= (x22 - threshold)){
+ if(yi <= (y22 + threshold) && yi >= (y22 - threshold)){
+ *isected = 2;
+ perc = 0;
+ break;
+ }
+ }
+ }
+ if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21);
+ else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/
+ //isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */
+
+ break;
+ }
+ }
+ lastdist=dist;
+ }
+ return(perc);
+}
+
+#define MAX_CUTS 2048
+
+static int knife_cut_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
+ BMesh *bm = em->bm;
+ ARegion *ar= CTX_wm_region(C);
+ BMVert *bv;
+ BMIter iter;
+ BMEdge *be;
+ BMOperator bmop;
+ CutCurve curve[MAX_CUTS];
+ struct GHash *gh;
+ float isect=0.0;
+ float *scr, co[4];
+ int len=0, isected, i;
+ short numcuts=1, mode= RNA_int_get(op->ptr, "type");
+
+ /* edit-object needed for matrix, and ar->regiondata for projections to work */
+ if (ELEM3(NULL, obedit, ar, ar->regiondata))
+ return OPERATOR_CANCELLED;
+
+ if (bm->totvertsel < 2) {
+ //error("No edges are selected to operate on");
+ return OPERATOR_CANCELLED;;
+ }
+
+ /* get the cut curve */
+ RNA_BEGIN(op->ptr, itemptr, "path") {
+
+ RNA_float_get_array(&itemptr, "loc", (float *)&curve[len]);
+ len++;
+ if(len>= MAX_CUTS) break;
+ }
+ RNA_END;
+
+ if(len<2) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /*the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer*/
+ gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "knife cut exec");
+ for(bv=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);bv;bv=BMIter_Step(&iter)){
+ scr = MEM_mallocN(sizeof(float)*2, "Vertex Screen Coordinates");
+ copy_v3_v3(co, bv->co);
+ co[3]= 1.0;
+ mul_m4_v4(obedit->obmat, co);
+ project_float(ar, co, scr);
+ BLI_ghash_insert(gh, bv, scr);
+ }
+
+ if (!EDBM_InitOpf(em, &bmop, op, "esubd")) {
+ return OPERATOR_CANCELLED;
+ }
+
+ i = 0;
+ /*store percentage of edge cut for KNIFE_EXACT here.*/
+ for (be=BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); be; be=BMIter_Step(&iter)) {
+ if( BM_Selected(bm, be) ) {
+ isect= bm_seg_intersect(be, curve, len, mode, gh, &isected);
+
+ if (isect != 0.0f) {
+ if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) {
+ BMO_Insert_MapFloat(bm, &bmop,
+ "edgepercents",
+ be, isect);
+
+ }
+ BMO_SetFlag(bm, be, 1);
+ } else BMO_ClearFlag(bm, be, 1);
+ } else BMO_ClearFlag(bm, be, 1);
+ }
+
+ BMO_Flag_To_Slot(bm, &bmop, "edges", 1, BM_EDGE);
+
+ if (mode == KNIFE_MIDPOINT) numcuts = 1;
+ BMO_Set_Int(&bmop, "numcuts", numcuts);
+
+ BMO_Set_Int(&bmop, "flag", B_KNIFE);
+ BMO_Set_Int(&bmop, "quadcornertype", SUBD_STRAIGHT_CUT);
+ BMO_Set_Int(&bmop, "singleedge", 0);
+ BMO_Set_Int(&bmop, "gridfill", 0);
+
+ BMO_Set_Float(&bmop, "radius", 0);
+
+ BMO_Exec_Op(bm, &bmop);
+ if (!EDBM_FinishOp(em, &bmop, op, 1)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_knife_cut(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ ot->name= "Knife Cut";
+ ot->description= "Cut selected edges and faces into parts";
+ ot->idname= "MESH_OT_knife_cut";
+
+ ot->invoke= WM_gesture_lines_invoke;
+ ot->modal= WM_gesture_lines_modal;
+ ot->exec= knife_cut_exec;
+
+ ot->poll= EM_view3d_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", knife_items, KNIFE_EXACT, "Type", "");
+ prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
+
+ /* internal */
+ RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
+}
+
+static int mesh_separate_selected(Main *bmain, Scene *scene, Base *editbase, wmOperator *wmop)
+{
+ Base *basenew;
+ BMIter iter;
+ BMVert *v;
+ BMEdge *e;
+ Object *obedit = editbase->object;
+ Mesh *me = obedit->data;
+ BMEditMesh *em = me->edit_btmesh;
+ BMesh *bmnew;
+ int allocsize[] = {512, 512, 2048, 512};
+
+ if (!em)
+ return OPERATOR_CANCELLED;
+
+ bmnew = BM_Make_Mesh(obedit, allocsize);
+ CustomData_copy(&em->bm->vdata, &bmnew->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&em->bm->edata, &bmnew->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&em->bm->ldata, &bmnew->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&em->bm->pdata, &bmnew->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+
+ CustomData_bmesh_init_pool(&bmnew->vdata, allocsize[0]);
+ CustomData_bmesh_init_pool(&bmnew->edata, allocsize[1]);
+ CustomData_bmesh_init_pool(&bmnew->ldata, allocsize[2]);
+ CustomData_bmesh_init_pool(&bmnew->pdata, allocsize[3]);
+
+ basenew= ED_object_add_duplicate(bmain, scene, editbase, USER_DUP_MESH); /* 0 = fully linked */
+ assign_matarar(basenew->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */
+
+ ED_base_object_select(basenew, BA_DESELECT);
+
+ EDBM_CallOpf(em, wmop, "dupe geom=%hvef dest=%p", BM_SELECT, bmnew);
+ EDBM_CallOpf(em, wmop, "del geom=%hvef context=%i", BM_SELECT, DEL_FACES);
+
+ /*clean up any loose edges*/
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(e, BM_HIDDEN))
+ continue;
+
+ if (BM_Edge_FaceCount(e) != 0)
+ BM_Select(em->bm, e, 0); /*deselect*/
+ }
+ EDBM_CallOpf(em, wmop, "del geom=%hvef context=%i", BM_SELECT, DEL_EDGES);
+
+ /*clean up any loose verts*/
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(v, BM_HIDDEN))
+ continue;
+
+ if (BM_Vert_EdgeCount(v) != 0)
+ BM_Select(em->bm, v, 0); /*deselect*/
+ }
+
+ EDBM_CallOpf(em, wmop, "del geom=%hvef context=%i", BM_SELECT, DEL_VERTS);
+
+ BM_Compute_Normals(bmnew);
+ BMO_CallOpf(bmnew, "bmesh_to_mesh mesh=%p object=%p", basenew->object->data, basenew->object);
+
+ BM_Free_Mesh(bmnew);
+ ((Mesh*)basenew->object->data)->edit_btmesh = NULL;
+
+ return 1;
+}
+
+//BMESH_TODO
+static int mesh_separate_material(Main *UNUSED(bmain), Scene *UNUSED(scene), Base *UNUSED(editbase), wmOperator *UNUSED(wmop))
+{
+ return 0;
+}
+
+static int mesh_separate_loose(Main *bmain, Scene *scene, Base *editbase, wmOperator *wmop)
+{
+ int i;
+ BMVert *v;
+ BMEdge *e;
+ BMVert *v_seed;
+ BMWalker walker;
+ BMIter iter;
+ int result = 0;
+ Object *obedit = editbase->object;
+ Mesh *me = obedit->data;
+ BMEditMesh *em = me->edit_btmesh;
+ BMesh *bm = em->bm;
+ int max_iter = bm->totvert;
+
+ /*Clear all selected vertices*/
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ BM_Select(bm, v, 0);
+ }
+
+ /*Flush the selection to clear edge/face selections to match
+ selected vertices*/
+ EDBM_select_flush(em, SCE_SELECT_VERTEX);
+
+ /*A "while(true)" loop should work here as each iteration should
+ select and remove at least one vertex and when all vertices
+ are selected the loop will break out. But guard against bad
+ behavior by limiting iterations to the number of vertices in the
+ original mesh.*/
+ for(i=0; i<max_iter; i++)
+ {
+ /* Get a seed vertex to start the walk */
+ v_seed = NULL;
+ BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ v_seed = v;
+ break;
+ }
+
+ /* No vertices available, can't do anything */
+ if (v_seed == NULL)
+ {
+ break;
+ }
+
+ /*Select the seed explicitly, in case it has no edges*/
+ BM_Select(bm, v_seed, 1);
+
+ /*Walk from the single vertex, selecting everything connected
+ to it*/
+ BMW_Init(&walker, bm, BMW_SHELL, 0, 0);
+ e = BMW_Begin(&walker, v_seed);
+ for (; e; e=BMW_Step(&walker)) {
+ BM_Select(bm, e->v1, 1);
+ BM_Select(bm, e->v2, 1);
+ }
+ BMW_End(&walker);
+
+ /*Flush the selection to get edge/face selections matching
+ the vertex selection*/
+ EDBM_select_flush(em, SCE_SELECT_VERTEX);
+
+ if (bm->totvert == bm->totvertsel)
+ {
+ /*Every vertex selected, nothing to separate, work is done*/
+ break;
+ }
+
+ /*Move selection into a separate object*/
+ result |= mesh_separate_selected(bmain, scene, editbase, wmop);
+ }
+
+ return result;
+}
+
+static int mesh_separate_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene= CTX_data_scene(C);
+ Base *base= CTX_data_active_base(C);
+ int retval= 0, type= RNA_enum_get(op->ptr, "type");
+
+ if(type == 0)
+ retval= mesh_separate_selected(bmain, scene, base, op);
+ else if(type == 1)
+ retval= mesh_separate_material (bmain, scene, base, op);
+ else if(type == 2)
+ retval= mesh_separate_loose(bmain, scene, base, op);
+
+ if(retval) {
+ DAG_id_tag_update(base->object->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+/* *************** Operator: separate parts *************/
+
+static EnumPropertyItem prop_separate_types[] = {
+ {0, "SELECTED", 0, "Selection", ""},
+ {1, "MATERIAL", 0, "By Material", ""},
+ {2, "LOOSE", 0, "By loose parts", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+void MESH_OT_separate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Separate";
+ ot->description= "Separate selected geometry into a new mesh";
+ ot->idname= "MESH_OT_separate";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= mesh_separate_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_separate_types, 0, "Type", "");
+}
+
+
+static int fill_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMOperator bmop;
+
+ if (!EDBM_InitOpf(em, &bmop, op, "triangle_fill edges=%he", BM_SELECT))
+ return OPERATOR_CANCELLED;
+
+ BMO_Exec_Op(em->bm, &bmop);
+
+ /*select new geometry*/
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_FACE|BM_EDGE);
+
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+
+}
+
+void MESH_OT_fill(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Fill";
+ ot->idname= "MESH_OT_fill";
+
+ /* api callbacks */
+ ot->exec= fill_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int beautify_fill_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ if (!EDBM_CallOpf(em, op, "beautify_fill faces=%hf", BM_SELECT))
+ return OPERATOR_CANCELLED;
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_beautify_fill(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Beautify Fill";
+ ot->idname= "MESH_OT_beautify_fill";
+
+ /* api callbacks */
+ ot->exec= beautify_fill_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************** Quad/Tri Operators *************************/
+
+static int quads_convert_to_tris_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ if (!EDBM_CallOpf(em, op, "triangulate faces=%hf", BM_SELECT))
+ return OPERATOR_CANCELLED;
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_quads_convert_to_tris(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Quads to Tris";
+ ot->idname= "MESH_OT_quads_convert_to_tris";
+
+ /* api callbacks */
+ ot->exec= quads_convert_to_tris_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int tris_convert_to_quads_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ int dosharp, douvs, dovcols, domaterials;
+ float limit = RNA_float_get(op->ptr, "limit");
+
+ dosharp = RNA_boolean_get(op->ptr, "sharp");
+ douvs = RNA_boolean_get(op->ptr, "uvs");
+ dovcols = RNA_boolean_get(op->ptr, "vcols");
+ domaterials = RNA_boolean_get(op->ptr, "materials");
+
+ if (!EDBM_CallOpf(em, op,
+ "join_triangles faces=%hf limit=%f compare_sharp=%i compare_uvs=%i compare_vcols=%i compare_materials=%i",
+ BM_SELECT, limit, dosharp, douvs, dovcols, domaterials))
+ {
+ return OPERATOR_CANCELLED;
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_tris_convert_to_quads(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Tris to Quads";
+ ot->idname= "MESH_OT_tris_convert_to_quads";
+
+ /* api callbacks */
+ ot->exec= tris_convert_to_quads_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_float(ot->srna, "limit", 40.0f, -180.0f, 180.0f, "Max Angle", "Angle Limit in Degrees", -180, 180.0f);
+
+ RNA_def_boolean(ot->srna, "uvs", 0, "Compare UVs", "");
+ RNA_def_boolean(ot->srna, "vcols", 0, "Compare VCols", "");
+ RNA_def_boolean(ot->srna, "sharp", 0, "Compare Sharp", "");
+ RNA_def_boolean(ot->srna, "materials", 0, "Compare Materials", "");
+
+}
+
+static int edge_flip_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
+{
+#if 0
+ Object *obedit= CTX_data_edit_object(C);
+ EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+
+ edge_flip(em);
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ BKE_mesh_end_editmesh(obedit->data, em);
+#endif
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_edge_flip(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Edge Flip";
+ ot->idname= "MESH_OT_edge_flip";
+
+ /* api callbacks */
+ ot->exec= edge_flip_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int split_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)ob->data)->edit_btmesh;
+ BMOperator bmop;
+
+ EDBM_InitOpf(em, &bmop, op, "split geom=%hvef", BM_SELECT);
+ BMO_Exec_Op(em->bm, &bmop);
+ BM_clear_flag_all(em->bm, BM_SELECT);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
+ if (!EDBM_FinishOp(em, &bmop, op, 1)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /*Geometry has changed, need to recalc normals and looptris*/
+ BMEdit_RecalcTesselation(em);
+ EDBM_RecalcNormals(em);
+
+ DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_split(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Split";
+ ot->idname= "MESH_OT_split";
+
+ /* api callbacks */
+ ot->exec= split_mesh_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+static int spin_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ ToolSettings *ts= CTX_data_tool_settings(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMesh *bm= em->bm;
+ BMOperator spinop;
+ float cent[3], axis[3], imat[3][3];
+ float d[3] = {0.0f, 0.0f, 0.0f};
+ int steps, dupli;
+ float degr;
+
+ RNA_float_get_array(op->ptr, "center", cent);
+ RNA_float_get_array(op->ptr, "axis", axis);
+ steps = RNA_int_get(op->ptr, "steps");
+ degr = RNA_float_get(op->ptr, "degrees");
+ if(ts->editbutflag & B_CLOCKWISE) degr= -degr;
+ dupli = RNA_boolean_get(op->ptr, "dupli");
+
+ /* undo object transformation */
+ copy_m3_m4(imat, obedit->imat);
+ sub_v3_v3(cent, obedit->obmat[3]);
+ mul_m3_v3(imat, cent);
+ mul_m3_v3(imat, axis);
+
+ if (!EDBM_InitOpf(em, &spinop, op,
+ "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%d ang=%f dupli=%d",
+ BM_SELECT, cent, axis, d, steps, degr, dupli)) {
+ return OPERATOR_CANCELLED;
+ }
+ BMO_Exec_Op(bm, &spinop);
+ EDBM_clear_flag_all(em, BM_SELECT);
+ BMO_HeaderFlag_Buffer(bm, &spinop, "lastout", BM_SELECT, BM_ALL);
+ if (!EDBM_FinishOp(em, &spinop, op, 1)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+/* get center and axis, in global coords */
+static int spin_mesh_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+{
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= ED_view3d_context_rv3d(C);
+
+ RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d));
+ RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[2]);
+
+ return spin_mesh_exec(C, op);
+}
+
+void MESH_OT_spin(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Spin";
+ ot->idname= "MESH_OT_spin";
+
+ /* api callbacks */
+ ot->invoke= spin_mesh_invoke;
+ ot->exec= spin_mesh_exec;
+ ot->poll= EM_view3d_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, INT_MAX);
+ RNA_def_boolean(ot->srna, "dupli", 0, "Dupli", "Make Duplicates");
+ RNA_def_float(ot->srna, "degrees", 90.0f, -FLT_MAX, FLT_MAX, "Degrees", "Degrees", -360.0f, 360.0f);
+
+ RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX);
+ RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX);
+
+}
+
+static int screw_mesh_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMesh *bm= em->bm;
+ BMEdge *eed;
+ BMVert *eve, *v1, *v2;
+ BMIter iter, eiter;
+ BMOperator spinop;
+ float dvec[3], nor[3], cent[3], axis[3];
+ float imat[3][3];
+ int steps, turns;
+ int valence;
+
+
+ turns= RNA_int_get(op->ptr, "turns");
+ steps= RNA_int_get(op->ptr, "steps");
+ RNA_float_get_array(op->ptr, "center", cent);
+ RNA_float_get_array(op->ptr, "axis", axis);
+
+ /* undo object transformation */
+ copy_m3_m4(imat, obedit->imat);
+ sub_v3_v3(cent, obedit->obmat[3]);
+ mul_m3_v3(imat, cent);
+ mul_m3_v3(imat, axis);
+
+
+ /* find two vertices with valence count==1, more or less is wrong */
+ v1 = NULL;
+ v2 = NULL;
+ for(eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ eve; eve = BMIter_Step(&iter)){
+
+ valence = 0;
+
+ for(eed = BMIter_New(&eiter, em->bm, BM_EDGES_OF_VERT, eve);
+ eed; eed = BMIter_Step(&eiter)){
+
+ if(BM_TestHFlag(eed, BM_SELECT)){
+ valence++;
+ }
+
+ }
+
+ if(valence == 1){
+ if(v1==NULL) v1 = eve;
+ else if(v2==NULL) v2= eve;
+ else {
+ v1= NULL;
+ break;
+ }
+ }
+ }
+
+ if(v1==NULL || v2==NULL) {
+ BKE_report(op->reports, RPT_ERROR, "You have to select a string of connected vertices too");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* calculate dvec */
+ sub_v3_v3v3(dvec, v1->co, v2->co);
+ mul_v3_fl(dvec, 1.0f/steps);
+
+ if(dot_v3v3(nor, dvec)>0.000)
+ negate_v3(dvec);
+
+ if (!EDBM_InitOpf(em, &spinop, op,
+ "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%d ang=%f dupli=0",
+ BM_SELECT, cent, axis, dvec, turns*steps, 360.0f*turns)) {
+ return OPERATOR_CANCELLED;
+ }
+ BMO_Exec_Op(bm, &spinop);
+ EDBM_clear_flag_all(em, BM_SELECT);
+ BMO_HeaderFlag_Buffer(bm, &spinop, "lastout", BM_SELECT, BM_ALL);
+ if (!EDBM_FinishOp(em, &spinop, op, 1)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+/* get center and axis, in global coords */
+static int screw_mesh_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+{
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d= ED_view3d_context_rv3d(C);
+
+ RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d));
+ RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[1]);
+
+ return screw_mesh_exec(C, op);
+}
+
+void MESH_OT_screw(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Screw";
+ ot->idname= "MESH_OT_screw";
+
+ /* api callbacks */
+ ot->invoke= screw_mesh_invoke;
+ ot->exec= screw_mesh_exec;
+ ot->poll= EM_view3d_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /*props */
+ RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, 256);
+ RNA_def_int(ot->srna, "turns", 1, 0, INT_MAX, "Turns", "Turns", 0, 256);
+
+ RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX);
+ RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX);
+}
+
+static int select_by_number_vertices_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMIter iter;
+ int numverts= RNA_int_get(op->ptr, "number");
+ int type = RNA_enum_get(op->ptr, "type");
+
+ for(efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ efa; efa = BMIter_Step(&iter)){
+
+ int select = 0;
+
+ if(type == 0 && efa->len < numverts){
+ select = 1;
+ }else if(type == 1 && efa->len == numverts){
+ select = 1;
+ }else if(type == 2 && efa->len > numverts){
+ select = 1;
+ }
+
+ if(select){
+ BM_Select(em->bm, efa, 1);
+ }
+ }
+
+ EDBM_selectmode_flush(em);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_by_number_vertices(wmOperatorType *ot)
+{
+ static const EnumPropertyItem type_items[] = {
+ {0, "LESS", 0, "Less Than", ""},
+ {1, "EQUAL", 0, "Equal To", ""},
+ {2, "GREATER", 0, "Greater Than", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name= "Select by Number of Vertices";
+ ot->description= "Select vertices or faces by vertex count";
+ ot->idname= "MESH_OT_select_by_number_vertices";
+
+ /* api callbacks */
+ ot->exec= select_by_number_vertices_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "number", 4, 3, INT_MAX, "Number of Vertices", "", 3, INT_MAX);
+ RNA_def_enum(ot->srna, "type", type_items, 1, "Type", "Type of comparison to make");
+}
+
+static int select_loose_verts_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
+ BMVert *eve;
+ BMEdge *eed;
+ BMIter iter;
+
+ for(eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ eve; eve = BMIter_Step(&iter)){
+
+ if(!eve->e){
+ BM_Select(em->bm, eve, 1);
+ }
+ }
+
+ for(eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ eed; eed = BMIter_Step(&iter)){
+
+ if(!eed->l){
+ BM_Select(em->bm, eed, 1);
+ }
+ }
+
+ EDBM_selectmode_flush(em);
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_loose_verts(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Loose Vertices/Edges";
+ ot->description = "Select vertices with edges or faces and edges with no faces";
+ ot->idname = "MESH_OT_select_loose_verts";
+
+ /* api callbacks */
+ ot->exec = select_loose_verts_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+#define MIRROR_THRESH 1.0f
+
+static int select_mirror_exec(bContext *C, wmOperator *op)
+{
+
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+ BMBVHTree *tree = BMBVH_NewBVH(em, 0, NULL, NULL);
+ BMVert *v1, *v2;
+ BMIter iter;
+ int extend= RNA_boolean_get(op->ptr, "extend");
+ float mirror_co[3];
+
+ BM_ITER(v1, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (!BM_TestHFlag(v1, BM_SELECT) || BM_TestHFlag(v1, BM_HIDDEN))
+ BM_SetIndex(v1, 0);
+ else BM_SetIndex(v1, 1);
+ }
+
+ if (!extend)
+ EDBM_clear_flag_all(em, BM_SELECT);
+
+ BM_ITER(v1, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (!BM_GetIndex(v1) || BM_TestHFlag(v1, BM_HIDDEN))
+ continue;
+
+ copy_v3_v3(mirror_co, v1->co);
+ mirror_co[0] *= -1.0f;
+
+ v2 = BMBVH_FindClosestVertTopo(tree, mirror_co, MIRROR_THRESH, v1);
+ if (v2 && !BM_TestHFlag(v2, BM_HIDDEN))
+ BM_Select(em->bm, v2, 1);
+ }
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_mirror(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select Mirror";
+ ot->description= "Select mesh items at mirrored locations";
+ ot->idname= "MESH_OT_select_mirror";
+
+ /* api callbacks */
+ ot->exec= select_mirror_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
+}
+
+#if 0 /* UNUSED */
+/********* qsort routines. not sure how to make these
+ work, since we aren't using linked lists for
+ geometry anymore. might need a sortof "swap"
+ function for bmesh elements. *********/
+
+typedef struct xvertsort {
+ float x;
+ BMVert *v1;
+} xvertsort;
+
+
+static int vergxco(const void *v1, const void *v2)
+{
+ const xvertsort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+
+struct facesort {
+ uintptr_t x;
+ struct EditFace *efa;
+};
+
+static int vergface(const void *v1, const void *v2)
+{
+ const struct facesort *x1=v1, *x2=v2;
+
+ if( x1->x > x2->x ) return 1;
+ else if( x1->x < x2->x) return -1;
+ return 0;
+}
+#endif
+
+// XXX is this needed?
+/* called from buttons */
+#if 0 /* UNUSED */
+static void xsortvert_flag__doSetX(void *userData, EditVert *UNUSED(eve), int x, int UNUSED(y), int index)
+{
+ xvertsort *sortblock = userData;
+
+ sortblock[index].x = x;
+}
+#endif
+
+/* all verts with (flag & 'flag') are sorted */
+static void xsortvert_flag(bContext *UNUSED(C), int UNUSED(flag))
+{
+ /*BMESH_TODO*/
+#if 0 //hrm, geometry isn't in linked lists anymore. . .
+ ViewContext vc;
+ BMEditMesh *em;
+ BMVert *eve;
+ BMIter iter;
+ xvertsort *sortblock;
+ ListBase tbase;
+ int i, amount;
+
+ em_setup_viewcontext(C, &vc);
+ em = vc.em;
+
+ amount = em->bm->totvert;
+ sortblock = MEM_callocN(sizeof(xvertsort)*amount,"xsort");
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if(BM_TestHFlag(eve, BM_SELECT))
+ sortblock[i].v1 = eve;
+ }
+
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+ mesh_foreachScreenVert(&vc, xsortvert_flag__doSetX, sortblock, 0);
+
+ qsort(sortblock, amount, sizeof(xvertsort), vergxco);
+
+ /* make temporal listbase */
+ tbase.first= tbase.last= 0;
+ for (i=0; i<amount; i++) {
+ eve = sortblock[i].v1;
+
+ if (eve) {
+ BLI_remlink(&vc.em->verts, eve);
+ BLI_addtail(&tbase, eve);
+ }
+ }
+
+ BLI_movelisttolist(&vc.em->verts, &tbase);
+
+ MEM_freeN(sortblock);
+#endif
+
+}
+
+static int mesh_vertices_sort_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ xsortvert_flag(C, SELECT);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_vertices_sort(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Vertex Sort";
+ ot->description= "Sort vertex order";
+ ot->idname= "MESH_OT_vertices_sort";
+
+ /* api callbacks */
+ ot->exec= mesh_vertices_sort_exec;
+
+ ot->poll= EM_view3d_poll; /* uses view relative X axis to sort verts */
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ********************** SORT FACES ******************* */
+
+static void permutate(void *list, int num, int size, int *index)
+{
+ void *buf;
+ int len;
+ int i;
+
+ len = num * size;
+
+ buf = MEM_mallocN(len, "permutate");
+ memcpy(buf, list, len);
+
+ for (i = 0; i < num; i++) {
+ memcpy((char *)list + (i * size), (char *)buf + (index[i] * size), size);
+ }
+ MEM_freeN(buf);
+}
+
+/* sort faces on view axis */
+static float *face_sort_floats;
+static int float_sort(const void *v1, const void *v2)
+{
+ float x1, x2;
+
+ x1 = face_sort_floats[((int *) v1)[0]];
+ x2 = face_sort_floats[((int *) v2)[0]];
+
+ if( x1 > x2 ) return 1;
+ else if( x1 < x2 ) return -1;
+ return 0;
+}
+
+static int sort_faces_exec(bContext *C, wmOperator *op)
+{
+ RegionView3D *rv3d= ED_view3d_context_rv3d(C);
+ View3D *v3d= CTX_wm_view3d(C);
+ Object *ob= CTX_data_edit_object(C);
+ Scene *scene= CTX_data_scene(C);
+ Mesh *me;
+ CustomDataLayer *layer;
+ int i, j, *index;
+ int event;
+ float reverse = 1;
+ // XXX int ctrl= 0;
+
+ if (!v3d) return OPERATOR_CANCELLED;
+
+ /* This operator work in Object Mode, not in edit mode.
+ * After talk with Campbell we agree that there is no point to port this to EditMesh right now.
+ * so for now, we just exit_editmode and enter_editmode at the end of this function.
+ */
+ ED_object_exit_editmode(C, EM_FREEDATA);
+
+ me= ob->data;
+ if(me->totpoly==0) {
+ ED_object_enter_editmode(C, 0);
+ return OPERATOR_FINISHED;
+ }
+
+ event= RNA_enum_get(op->ptr, "type");
+
+ // XXX
+ //if(ctrl)
+ // reverse = -1;
+
+ /* create index list */
+ index= (int *)MEM_mallocN(sizeof(int) * me->totpoly, "sort faces");
+ for (i = 0; i < me->totpoly; i++) {
+ index[i] = i;
+ }
+
+ face_sort_floats = (float *) MEM_mallocN(sizeof(float) * me->totpoly, "sort faces float");
+
+ /* sort index list instead of faces itself
+ * and apply this permutation to all face layers
+ */
+ if (event == 5) {
+ /* Random */
+ for(i=0; i<me->totpoly; i++) {
+ face_sort_floats[i] = BLI_frand();
+ }
+ qsort(index, me->totpoly, sizeof(int), float_sort);
+ } else {
+ MPoly *mp;
+ MLoop *ml;
+ MVert *mv;
+ float vec[3];
+ float mat[4][4];
+ float cur[3];
+
+ if (event == 1)
+ mul_m4_m4m4(mat, OBACT->obmat, rv3d->viewmat); /* apply the view matrix to the object matrix */
+ else if (event == 2) { /* sort from cursor */
+ if( v3d && v3d->localvd ) {
+ VECCOPY(cur, v3d->cursor);
+ } else {
+ VECCOPY(cur, scene->cursor);
+ }
+ invert_m4_m4(mat, OBACT->obmat);
+ mul_m4_v3(mat, cur);
+ }
+
+ mp= me->mpoly;
+
+ for(i=0; i<me->totpoly; i++, mp++) {
+ if (event==3) {
+ face_sort_floats[i] = ((float)mp->mat_nr)*reverse;
+ } else if (event==4) {
+ /*selected first*/
+ if (mp->flag & ME_FACE_SEL)
+ face_sort_floats[i] = 0.0;
+ else
+ face_sort_floats[i] = reverse;
+ } else {
+ /* find the face's center */
+ ml = me->mloop+mp->loopstart;
+ zero_v3(vec);
+ for (j = 0; j < mp->totloop; j++, ml++) {
+ mv = me->mvert+ml->v;
+ add_v3_v3(vec, mv->co);
+ }
+ mul_v3_fl(vec, 1.0f / (float)mp->totloop);
+
+ if (event == 1) { /* sort on view axis */
+ mul_m4_v3(mat, vec);
+ face_sort_floats[i] = vec[2] * reverse;
+ } else if(event == 2) { /* distance from cursor*/
+ face_sort_floats[i] = len_v3v3(cur, vec) * reverse; /* back to front */
+ }
+ }
+ }
+ qsort(index, me->totpoly, sizeof(int), float_sort);
+ }
+
+ MEM_freeN(face_sort_floats);
+ for(i = 0; i < me->pdata.totlayer; i++) {
+ layer = &me->pdata.layers[i];
+ permutate(layer->data, me->totpoly, CustomData_sizeof(layer->type), index);
+ }
+
+ MEM_freeN(index);
+ DAG_id_tag_update(ob->data, 0);
+
+ /* Return to editmode. */
+ ED_object_enter_editmode(C, 0);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_sort_faces(wmOperatorType *ot)
+{
+ static EnumPropertyItem type_items[]= {
+ { 1, "VIEW_AXIS", 0, "View Axis", "" },
+ { 2, "CURSOR_DISTANCE", 0, "Cursor Distance", "" },
+ { 3, "MATERIAL", 0, "Material", "" },
+ { 4, "SELECTED", 0, "Selected", "" },
+ { 5, "RANDOMIZE", 0, "Randomize", "" },
+ { 0, NULL, 0, NULL, NULL }};
+
+ /* identifiers */
+ ot->name= "Sort Faces"; // XXX (Ctrl to reverse)%t|
+ ot->description= "The faces of the active Mesh Object are sorted, based on the current view";
+ ot->idname= "MESH_OT_sort_faces";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= sort_faces_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop= RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
+}
+
+#if 0
+/* called from buttons */
+static void hashvert_flag(EditMesh *em, int flag)
+{
+ /* switch vertex order using hash table */
+ EditVert *eve;
+ struct xvertsort *sortblock, *sb, onth, *newsort;
+ ListBase tbase;
+ int amount, a, b;
+
+ /* count */
+ eve= em->verts.first;
+ amount= 0;
+ while(eve) {
+ if(eve->f & flag) amount++;
+ eve= eve->next;
+ }
+ if(amount==0) return;
+
+ /* allocate memory */
+ sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*amount,"sortremovedoub");
+ eve= em->verts.first;
+ while(eve) {
+ if(eve->f & flag) {
+ sb->v1= eve;
+ sb++;
+ }
+ eve= eve->next;
+ }
+
+ BLI_srand(1);
+
+ sb= sortblock;
+ for(a=0; a<amount; a++, sb++) {
+ b= (int)(amount*BLI_drand());
+ if(b>=0 && b<amount) {
+ newsort= sortblock+b;
+ onth= *sb;
+ *sb= *newsort;
+ *newsort= onth;
+ }
+ }
+
+ /* make temporal listbase */
+ tbase.first= tbase.last= 0;
+ sb= sortblock;
+ while(amount--) {
+ eve= sb->v1;
+ BLI_remlink(&em->verts, eve);
+ BLI_addtail(&tbase, eve);
+ sb++;
+ }
+
+ BLI_movelisttolist(&em->verts, &tbase);
+
+ MEM_freeN(sortblock);
+
+}
+#endif
+
+static int mesh_vertices_randomize_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+#if 1 /*BMESH TODO*/
+ (void)em;
+#else
+ hashvert_flag(em, SELECT);
+#endif
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_vertices_randomize(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Vertex Randomize";
+ ot->description= "Randomize vertex order";
+ ot->idname= "MESH_OT_vertices_randomize";
+
+ /* api callbacks */
+ ot->exec= mesh_vertices_randomize_exec;
+
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/******end of qsort stuff ****/
+
+
+static int mesh_noise_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
+ Material *ma;
+ Tex *tex;
+ BMVert *eve;
+ BMIter iter;
+ float fac= RNA_float_get(op->ptr, "factor");
+
+ if(em==NULL) return OPERATOR_FINISHED;
+
+ ma= give_current_material(obedit, obedit->actcol);
+ if(ma==0 || ma->mtex[0]==0 || ma->mtex[0]->tex==0) {
+ BKE_report(op->reports, RPT_WARNING, "Mesh has no material or texture assigned");
+ return OPERATOR_FINISHED;
+ }
+ tex= give_current_material_texture(ma);
+
+ if(tex->type==TEX_STUCCI) {
+ float b2, vec[3];
+ float ofs= tex->turbul/200.0;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_SELECT) && !BM_TestHFlag(eve, BM_HIDDEN)) {
+ b2= BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]);
+ if(tex->stype) ofs*=(b2*b2);
+ vec[0]= fac*(b2-BLI_hnoise(tex->noisesize, eve->co[0]+ofs, eve->co[1], eve->co[2]));
+ vec[1]= fac*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1]+ofs, eve->co[2]));
+ vec[2]= fac*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]+ofs));
+
+ add_v3_v3(eve->co, vec);
+ }
+ }
+ }
+ else {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_SELECT) && !BM_TestHFlag(eve, BM_HIDDEN)) {
+ float tin, dum;
+ externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum, 0);
+ eve->co[2]+= fac*tin;
+ }
+ }
+ }
+
+ EDBM_RecalcNormals(em);
+
+ DAG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_noise(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Noise";
+ ot->description= "Use vertex coordinate as texture coordinate";
+ ot->idname= "MESH_OT_noise";
+
+ /* api callbacks */
+ ot->exec= mesh_noise_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_float(ot->srna, "factor", 0.1f, -FLT_MAX, FLT_MAX, "Factor", "", 0.0f, 1.0f);
+}
+
+/*bevel! yay!!*/
+static int mesh_bevel_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
+ BMIter iter;
+ BMEdge *eed;
+ BMOperator bmop;
+ float factor= RNA_float_get(op->ptr, "percent"), fac=factor /*, dfac */ /* UNUSED */, df, s;
+ /*float p2 = RNA_float_get(op->ptr, "param2");
+ float p3 = RNA_float_get(op->ptr, "param3");
+ float p4 = RNA_float_get(op->ptr, "param4");
+ float p5 = RNA_float_get(op->ptr, "param5");*/
+ int i, recursion = RNA_int_get(op->ptr, "recursion");
+ float *w = NULL, ftot;
+ int li;
+ BLI_array_declare(w);
+
+ BM_add_data_layer(em->bm, &em->bm->edata, CD_PROP_FLT);
+ li = CustomData_number_of_layers(&em->bm->edata, CD_PROP_FLT)-1;
+
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ float d = len_v3v3(eed->v1->co, eed->v2->co);
+ float *dv = CustomData_bmesh_get_n(&em->bm->edata, eed->head.data, CD_PROP_FLT, li);
+
+ *dv = d;
+ }
+
+ if(em==NULL) return OPERATOR_CANCELLED;
+
+ /*ugh, stupid math depends somewhat on angles!*/
+ /* dfac = 1.0/(float)(recursion+1); */ /* UNUSED */
+ df = 1.0;
+ for (i=0, ftot=0.0f; i<recursion; i++) {
+ s = pow(df, 1.25);
+
+ BLI_array_append(w, s);
+ ftot += s;
+
+ df *= 2.0;
+ }
+
+ for (i=0; i<BLI_array_count(w); i++) {
+ w[i] /= ftot;
+ }
+
+ fac = factor;
+ for (i=0; i<BLI_array_count(w); i++) {
+ fac = w[BLI_array_count(w)-i-1]*factor;
+
+ if (!EDBM_InitOpf(em, &bmop, op, "bevel geom=%hev percent=%f lengthlayer=%i uselengths=%i", BM_SELECT, fac, li, 1))
+ return OPERATOR_CANCELLED;
+
+ BMO_Exec_Op(em->bm, &bmop);
+ if (!EDBM_FinishOp(em, &bmop, op, 1))
+ return OPERATOR_CANCELLED;
+ }
+
+ BM_free_data_layer_n(em->bm, &em->bm->edata, CD_MASK_PROP_FLT, li);
+
+ BLI_array_free(w);
+ EDBM_RecalcNormals(em);
+
+ DAG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_bevel(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Bevel";
+ ot->description= "Edge/Vertex Bevel";
+ ot->idname= "MESH_OT_bevel";
+
+ /* api callbacks */
+ ot->exec= mesh_bevel_exec;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_float(ot->srna, "percent", 0.5f, -FLT_MAX, FLT_MAX, "Percentage", "", 0.0f, 1.0f);
+ RNA_def_int(ot->srna, "recursion", 1, 1, 50, "Recursion Level", "Recursion Level", 1, 8);
+ //RNA_def_float(ot->srna, "param2", 1.0f, -FLT_MAX, FLT_MAX, "Parameter 2", "", -1000.0f, 1000.0f);
+ //RNA_def_float(ot->srna, "param3", 0.5f, -FLT_MAX, FLT_MAX, "Parameter 3", "", -1000.0f, 1000.0f);
+ //RNA_def_float(ot->srna, "param4", 0.5f, -FLT_MAX, FLT_MAX, "Parameter 4", "", -1000.0f, 1000.0f);
+ //RNA_def_float(ot->srna, "param5", 0.5f, -FLT_MAX, FLT_MAX, "Parameter 5", "", -1000.0f, 1000.0f);
+}
+
+static int mesh_export_obj_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ DerivedMesh *dm;
+ Scene *scene = CTX_data_scene(C);
+ Mesh *me;
+ Main *bmain = CTX_data_main(C);
+ MVert *mvert, *mv;
+ MLoop *mloop, *ml;
+ MPoly *mpoly, *mp;
+ MTexPoly *mtexpoly;
+ MLoopUV *luv, *mloopuv;
+ /*MLoopCol *mloopcol;*/
+ FILE *file, *matfile;
+ int *face_mat_group;
+ struct {Material *mat; MTexPoly poly; int end;} **matlists;
+ char str[FILE_MAX], str2[FILE_MAX];
+ int i, j, c, free;
+
+ if (ob->type != OB_MESH) {
+ BKE_report(op->reports, RPT_OPERATOR, "Only meshes can be exported");
+ return OPERATOR_CANCELLED;
+ }
+
+ RNA_string_get(op->ptr, "filepath", str);
+
+ sprintf(str2, "%s_materials.mtl", str);
+ file = fopen(str, "wb");
+ matfile = fopen(str2, "wb");
+
+ if (!file) {
+ BKE_report(op->reports, RPT_OPERATOR, "Could not open file");
+
+ if (matfile)
+ fclose(matfile);
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!matfile) {
+ BKE_report(op->reports, RPT_OPERATOR, "Could not open material file");
+
+ if (file)
+ fclose(file);
+ return OPERATOR_CANCELLED;
+ }
+
+ me = ob->data;
+ if (me->edit_btmesh) {
+ EDBM_LoadEditBMesh(scene, ob);
+ }
+
+ if (!RNA_boolean_get(op->ptr, "apply_modifiers")) {
+ dm = CDDM_from_mesh(me, ob);
+ free = 1;
+ } else {
+ dm = mesh_get_derived_final(scene, ob, CD_MASK_DERIVEDMESH);
+ if (!CDDM_Check(dm)) {
+ dm = CDDM_copy(dm, 0);
+ free = 1;
+ } else {
+ free = 0;
+ }
+ }
+
+ face_mat_group = MEM_callocN(sizeof(int)*dm->numPolyData, "face_mat_group");
+
+ if (MAX2(ob->totcol, me->totcol))
+ matlists = MEM_callocN(sizeof(*matlists)*MAX2(me->totcol, ob->totcol), "matlists");
+ else matlists = NULL;
+
+ for (i=0; i<MAX2(ob->totcol, me->totcol); i++) {
+ matlists[i] = MEM_callocN(sizeof(**matlists), "matlists[i]");
+ matlists[i][0].end = 1;
+ }
+
+
+ mvert = CDDM_get_verts(dm);
+ mloop = CDDM_get_loops(dm);
+ mpoly = CDDM_get_polys(dm);
+ mtexpoly = CustomData_get_layer(&dm->polyData, CD_MTEXPOLY);
+ mloopuv = CustomData_get_layer(&dm->loopData, CD_MLOOPUV);
+ /* mloopcol = CustomData_get_layer(&dm->loopData, CD_MLOOPCOL); */ /* UNUSED */
+
+ if (matlists) {
+ /*build material list*/
+ mp = mpoly;
+ for (i=0; i<dm->numPolyData; i++, (mtexpoly ? mtexpoly++ : NULL), mp++) {
+ int found = 0;
+
+ j = 0;
+ while (!matlists[mp->mat_nr][j].end) {
+ Material *mat = ob->matbits[mp->mat_nr] ? ob->mat[mp->mat_nr] : me->mat[mp->mat_nr];
+
+ if (matlists[mp->mat_nr][j].mat == mat) {
+ if (mtexpoly) {
+ if (matlists[mp->mat_nr][j].poly.tpage == mtexpoly->tpage) {
+ found = 1;
+ break;
+ }
+ } else {
+ found = 1;
+ break;
+ }
+ }
+ j++;
+ }
+
+ if (!found) {
+ matlists[mp->mat_nr] = MEM_reallocN(matlists[mp->mat_nr], sizeof(**matlists)*(j+2));
+
+ /*add sentinal*/
+ matlists[mp->mat_nr][j+1].end = 1;
+ matlists[mp->mat_nr][j].end = 0;
+
+ if (ob->matbits && ob->matbits[mp->mat_nr]) {
+ matlists[mp->mat_nr][j].mat = ob->mat[mp->mat_nr];
+ } else {
+ matlists[mp->mat_nr][j].mat = me->mat[mp->mat_nr];
+ }
+
+ if (mtexpoly)
+ matlists[mp->mat_nr][j].poly = *mtexpoly;
+ }
+
+ face_mat_group[i] = j;
+ }
+ }
+
+ /*write material references*/
+ fprintf(file, "mtllib %s_materials.mtl\n", str);
+ fprintf(file, "o %s\n", (ob->id.name+2));
+
+ for (mv=mvert, i=0; i<dm->numVertData; i++, mv++) {
+ fprintf(file, "v %.8f\t%.8f\t%.8f\n", mv->co[0], mv->co[1], mv->co[2]);
+ fprintf(file, "vn %.5f\t%.5f\t%.5f\n", (float)mv->no[0]/65535.0f, (float)mv->no[1]/65535.0f, (float)mv->no[2]/65535.0f);
+ }
+
+ /*write texture coordinates*/
+ if (mloopuv) {
+ fprintf(file, "\n");
+ for (mp=mpoly, i=0; i<dm->numPolyData; i++, mp++) {
+ luv = mloopuv + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, luv++) {
+ fprintf(file, "vt %.8f\t%.8f\n", luv->uv[0], luv->uv[1]);
+ }
+ }
+ }
+
+ fprintf(file, "\n");
+ c = 0;
+ for (mp=mpoly, i=0; i<dm->numPolyData; i++, mp++) {
+ char matname[256];
+
+ if (mp->flag & ME_SMOOTH) {
+ fprintf(file, "s 1\n");
+ } else {
+ fprintf(file, "s off\n");
+ }
+
+ if (matlists) {
+ if (matlists[mp->mat_nr][face_mat_group[i]].mat && matlists[mp->mat_nr][face_mat_group[i]].poly.tpage) {
+ sprintf(matname, "%s__%s", matlists[mp->mat_nr][face_mat_group[i]].mat->id.name+2,
+ matlists[mp->mat_nr][face_mat_group[i]].poly.tpage->id.name+2);
+ } else if (matlists[mp->mat_nr][face_mat_group[i]].mat) {
+ sprintf(matname, "%s", matlists[mp->mat_nr][face_mat_group[i]].mat->id.name+2);
+ } else if (matlists[mp->mat_nr][face_mat_group[i]].poly.tpage != NULL) {
+ sprintf(matname, "texture_%s", matlists[mp->mat_nr][face_mat_group[i]].poly.tpage->id.name+2);
+ } else {
+ sprintf(matname, "__null_material_%d_%d", mp->mat_nr, face_mat_group[mp->mat_nr]);
+ }
+
+ fprintf(file, "usemtl %s\n", matname);
+ }
+
+ fprintf(file, "f ");
+
+ ml = mloop + mp->loopstart;
+ luv = mloopuv ? mloopuv + mp->loopstart : NULL;
+ for (j=0; j<mp->totloop; j++, ml++, (luv ? luv++ : NULL), c++) {
+ if (luv) {
+ fprintf(file, "%d/%d ", ml->v+1, c+1);
+ } else {
+ fprintf(file, "%d ", ml->v+1);
+ }
+ }
+ fprintf(file, "\n");
+ }
+
+ fclose(file);
+
+ /*write material library*/
+ fprintf(matfile, "#Blender MTL File\n\n");
+ for (i=0; i<MAX2(ob->totcol, me->totcol); i++) {
+ Material *mat;
+ char basedir[FILE_MAX], filename[FILE_MAX], str3[FILE_MAX];
+
+ j = 0;
+ while (!matlists[i][j].end) {
+ mat = matlists[i][j].mat;
+
+ if (mat && matlists[i][j].poly.tpage) {
+ fprintf(matfile, "newmtl %s__%s\n", mat->id.name+2,
+ matlists[i][j].poly.tpage->id.name+2);
+ } else if (mat) {
+ fprintf(matfile, "newmtl %s\n", mat->id.name+2);
+ } else if (matlists[i][j].poly.tpage != NULL) {
+ fprintf(matfile, "newmtl texture_%s\n", matlists[i][j].poly.tpage->id.name+2);
+ } else {
+ fprintf(matfile, "newmtl __null_material_%d_%d\n", i, j);
+ }
+
+ if (mat) {
+ fprintf(matfile, "Kd %.6f %.6f %.6f\n", mat->r, mat->g, mat->b);
+ fprintf(matfile, "Ks %.6f %.6f %.6f\n", mat->specr, mat->specg, mat->specb);
+ fprintf(matfile, "Ns %.6f\n", mat->spec*1000.0f);
+ } else {
+ fprintf(matfile, "Kd %.6f %.6f %.6f\n", 0.45f, 0.45f, 0.45f);
+ fprintf(matfile, "Ks %.6f %.6f %.6f\n", 1.0f, 0.4f, 0.1f);
+ fprintf(matfile, "Ns %.6f\n", 300.0f);
+ }
+
+ fprintf(matfile, "illum 2\n");
+
+ if (matlists[i][j].poly.tpage) {
+ BLI_strncpy(str2, matlists[i][j].poly.tpage->name, FILE_MAX);
+ BLI_strncpy(basedir, bmain->name, FILE_MAX);
+
+ BLI_splitdirstring(basedir, filename);
+ BLI_cleanup_file(basedir, str2); /* fix any /foo/../foo/ */
+
+ if (BLI_exists(str2)) {
+ char rel[3] = {0};
+
+ BLI_strncpy(str3, str2, FILE_MAX);
+ if (RNA_boolean_get(op->ptr, "relpaths")) {
+ BLI_path_rel(str3, str);
+
+ if (str3[2] != '.' && str3[2] != '/' && str3[2] != '\\') {
+ rel[0] = '.';
+ rel[1] = '/';
+ }
+ }
+
+ fprintf(matfile, "map_Ka %s%s\n", rel, (str3+2*RNA_boolean_get(op->ptr, "relpaths")));
+ fprintf(matfile, "map_Kd %s%s\n", rel, (str3+2*RNA_boolean_get(op->ptr, "relpaths")));
+ }
+ }
+
+ fprintf(matfile, "\n");
+ j++;
+ }
+ }
+
+ fclose(matfile);
+
+ for (i=0; i<MAX2(ob->totcol, me->totcol); i++) {
+ MEM_freeN(matlists[i]);
+ }
+
+ if (matlists)
+ MEM_freeN(matlists);
+
+ if (face_mat_group)
+ MEM_freeN(face_mat_group);
+
+ if (free) {
+ dm->needsFree = 1;
+ dm->release(dm);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void export_obj_filesel(bContext *C, wmOperator *op, const char *path)
+{
+ RNA_string_set(op->ptr, "filepath", path);
+ WM_event_add_fileselect(C, op);
+}
+
+
+static int export_obj_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+{
+ char filename[FILE_MAX];
+
+ BLI_strncpy(filename, "//untitled.obj", FILE_MAX);
+
+ if(RNA_property_is_set(op->ptr, "filepath"))
+ return mesh_export_obj_exec(C, op);
+
+ export_obj_filesel(C, op, filename);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+
+void EXPORT_MESH_OT_wavefront(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Export Wavefront OBJ";
+ ot->description= "Export Wavefront (obj)";
+ ot->idname= "EXPORT_MESH_OT_wavefront";
+
+ /* api callbacks */
+ ot->exec= mesh_export_obj_exec;
+ ot->invoke= export_obj_invoke;
+ ot->poll= ED_operator_object_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_filesel(ot, FOLDERFILE|TEXTFILE, FILE_SPECIAL, FILE_SAVE, WM_FILESEL_FILEPATH);
+
+ RNA_def_boolean(ot->srna, "apply_modifiers", 0, "Apply Modifiers", "Apply Modifiers");
+ RNA_def_boolean(ot->srna, "relpaths", 0, "Relative Paths", "Use relative paths for textures");
+}
+
+static int bridge_edge_loops(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+
+ if (!EDBM_CallOpf(em, op, "bridge_loops edges=%he", BM_SELECT))
+ return OPERATOR_CANCELLED;
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_bridge_edge_loops(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Bridge edge loops";
+ ot->description= "Make faces between two edge loops";
+ ot->idname= "MESH_OT_bridge_edge_loops";
+
+ /* api callbacks */
+ ot->exec= bridge_edge_loops;
+ ot->poll= ED_operator_editmesh;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "inside", 0, "Inside", "");
+}
diff --git a/source/blender/editors/mesh/bmeshutils.c b/source/blender/editors/mesh/bmeshutils.c
new file mode 100644
index 00000000000..51a2f2e279c
--- /dev/null
+++ b/source/blender/editors/mesh/bmeshutils.c
@@ -0,0 +1,875 @@
+ /* $Id: bmeshutils.c
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_key_types.h"
+
+#include "RNA_types.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_heap.h"
+#include "BLI_array.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_key.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_bmesh.h"
+#include "BKE_report.h"
+#include "BKE_tessmesh.h"
+
+#include "bmesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_view3d.h"
+#include "ED_util.h"
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "editbmesh_bvh.h"
+#include "mesh_intern.h"
+
+void EDBM_RecalcNormals(BMEditMesh *em)
+{
+ BM_Compute_Normals(em->bm);
+}
+
+void EDBM_stats_update(BMEditMesh *em)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+ int *tots[3];
+ int i;
+
+ tots[0] = &em->bm->totvertsel;
+ tots[1] = &em->bm->totedgesel;
+ tots[2] = &em->bm->totfacesel;
+
+ em->bm->totvertsel = em->bm->totedgesel = em->bm->totfacesel = 0;
+
+ for (i=0; i<3; i++) {
+ ele = BMIter_New(&iter, em->bm, types[i], NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(ele, BM_SELECT)) {
+ *tots[i]++;
+ }
+ }
+ }
+}
+
+int EDBM_InitOpf(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *fmt, ...)
+{
+ BMesh *bm = em->bm;
+ va_list list;
+
+ va_start(list, fmt);
+
+ if (!BMO_VInitOpf(bm, bmop, fmt, list)) {
+ BKE_report(op->reports, RPT_ERROR,
+ "Parse error in EDBM_CallOpf");
+ va_end(list);
+ return 0;
+ }
+
+ if (!em->emcopy)
+ em->emcopy = BMEdit_Copy(em);
+ em->emcopyusers++;
+
+ va_end(list);
+
+ return 1;
+}
+
+
+/*returns 0 on error, 1 on success. executes and finishes a bmesh operator*/
+int EDBM_FinishOp(BMEditMesh *em, BMOperator *bmop, wmOperator *op, int report) {
+ const char *errmsg;
+
+ BMO_Finish_Op(em->bm, bmop);
+
+ if (BMO_GetError(em->bm, &errmsg, NULL)) {
+ BMEditMesh *emcopy = em->emcopy;
+
+ if (report) BKE_report(op->reports, RPT_ERROR, errmsg);
+
+ BMEdit_Free(em);
+ *em = *emcopy;
+ BMEdit_RecalcTesselation(em);
+
+ MEM_freeN(emcopy);
+ em->emcopyusers = 0;
+ em->emcopy = NULL;
+ return 0;
+ } else {
+ em->emcopyusers--;
+ if (em->emcopyusers < 0) {
+ printf("warning: em->emcopyusers was less then zero.\n");
+ }
+
+ if (em->emcopyusers <= 0) {
+ BMEdit_Free(em->emcopy);
+ MEM_freeN(em->emcopy);
+ em->emcopy = NULL;
+ }
+ }
+
+ return 1;
+}
+
+int EDBM_CallOpf(BMEditMesh *em, wmOperator *op, const char *fmt, ...)
+{
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+ va_list list;
+
+ va_start(list, fmt);
+
+ if (!BMO_VInitOpf(bm, &bmop, fmt, list)) {
+ BKE_report(op->reports, RPT_ERROR,
+ "Parse error in EDBM_CallOpf");
+ va_end(list);
+ return 0;
+ }
+
+ if (!em->emcopy)
+ em->emcopy = BMEdit_Copy(em);
+ em->emcopyusers++;
+
+ BMO_Exec_Op(bm, &bmop);
+
+ va_end(list);
+ return EDBM_FinishOp(em, &bmop, op, 1);
+}
+
+int EDBM_CallAndSelectOpf(BMEditMesh *em, wmOperator *op, const char *selectslot, const char *fmt, ...)
+{
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+ va_list list;
+
+ va_start(list, fmt);
+
+ if (!BMO_VInitOpf(bm, &bmop, fmt, list)) {
+ BKE_report(op->reports, RPT_ERROR,
+ "Parse error in EDBM_CallOpf");
+ va_end(list);
+ return 0;
+ }
+
+ if (!em->emcopy)
+ em->emcopy = BMEdit_Copy(em);
+ em->emcopyusers++;
+
+ BMO_Exec_Op(bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, selectslot, BM_SELECT, BM_ALL);
+
+ va_end(list);
+ return EDBM_FinishOp(em, &bmop, op, 1);
+}
+
+int EDBM_CallOpfSilent(BMEditMesh *em, const char *fmt, ...)
+{
+ BMesh *bm = em->bm;
+ BMOperator bmop;
+ va_list list;
+
+ va_start(list, fmt);
+
+ if (!BMO_VInitOpf(bm, &bmop, fmt, list)) {
+ va_end(list);
+ return 0;
+ }
+
+ if (!em->emcopy)
+ em->emcopy = BMEdit_Copy(em);
+ em->emcopyusers++;
+
+ BMO_Exec_Op(bm, &bmop);
+
+ va_end(list);
+ return EDBM_FinishOp(em, &bmop, NULL, 0);
+}
+
+void EDBM_selectmode_to_scene(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
+
+ if (!em)
+ return;
+
+ scene->toolsettings->selectmode = em->selectmode;
+
+ /* Request redraw of header buttons (to show new select mode) */
+ WM_event_add_notifier(C, NC_SCENE|ND_TOOLSETTINGS, scene);
+}
+
+void EDBM_MakeEditBMesh(ToolSettings *ts, Scene *UNUSED(scene), Object *ob)
+{
+ Mesh *me = ob->data;
+ BMesh *bm;
+
+ if (!me->mpoly && me->totface) {
+ fprintf(stderr, "%s: bmesh conversion issue! may lose lots of geometry! (bmesh internal error)\n", __func__);
+
+ /*BMESH_TODO need to write smarter code here*/
+ bm = BKE_mesh_to_bmesh(me, ob);
+ } else {
+ bm = BKE_mesh_to_bmesh(me, ob);
+ }
+
+ me->edit_btmesh = BMEdit_Create(bm);
+ me->edit_btmesh->selectmode = ts->selectmode;
+ me->edit_btmesh->me = me;
+ me->edit_btmesh->ob = ob;
+}
+
+void EDBM_LoadEditBMesh(Scene *scene, Object *ob)
+{
+ Mesh *me = ob->data;
+ BMesh *bm = me->edit_btmesh->bm;
+
+ BMO_CallOpf(bm, "object_load_bmesh scene=%p object=%p", scene, ob);
+}
+
+void EDBM_FreeEditBMesh(BMEditMesh *tm)
+{
+ BMEdit_Free(tm);
+}
+
+void EDBM_init_index_arrays(BMEditMesh *tm, int forvert, int foredge, int forface)
+{
+ EDBM_free_index_arrays(tm);
+
+ if (forvert) {
+ BMIter iter;
+ BMVert *ele;
+ int i=0;
+
+ tm->vert_index = MEM_mallocN(sizeof(void**)*tm->bm->totvert, "tm->vert_index");
+
+ ele = BMIter_New(&iter, tm->bm, BM_VERTS_OF_MESH, NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ tm->vert_index[i++] = ele;
+ }
+ }
+
+ if (foredge) {
+ BMIter iter;
+ BMEdge *ele;
+ int i=0;
+
+ tm->edge_index = MEM_mallocN(sizeof(void**)*tm->bm->totedge, "tm->edge_index");
+
+ ele = BMIter_New(&iter, tm->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ tm->edge_index[i++] = ele;
+ }
+ }
+
+ if (forface) {
+ BMIter iter;
+ BMFace *ele;
+ int i=0;
+
+ tm->face_index = MEM_mallocN(sizeof(void**)*tm->bm->totface, "tm->face_index");
+
+ ele = BMIter_New(&iter, tm->bm, BM_FACES_OF_MESH, NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ tm->face_index[i++] = ele;
+ }
+ }
+}
+
+void EDBM_free_index_arrays(BMEditMesh *tm)
+{
+ if (tm->vert_index) {
+ MEM_freeN(tm->vert_index);
+ tm->vert_index = NULL;
+ }
+
+ if (tm->edge_index) {
+ MEM_freeN(tm->edge_index);
+ tm->edge_index = NULL;
+ }
+
+ if (tm->face_index) {
+ MEM_freeN(tm->face_index);
+ tm->face_index = NULL;
+ }
+}
+
+BMVert *EDBM_get_vert_for_index(BMEditMesh *tm, int index)
+{
+ return tm->vert_index && index < tm->bm->totvert ?tm->vert_index[index]:NULL;
+}
+
+BMEdge *EDBM_get_edge_for_index(BMEditMesh *tm, int index)
+{
+ return tm->edge_index && index < tm->bm->totedge ?tm->edge_index[index]:NULL;
+}
+
+BMFace *EDBM_get_face_for_index(BMEditMesh *tm, int index)
+{
+ return (tm->face_index && index<tm->bm->totface && index>=0) ? tm->face_index[index] : NULL;
+}
+
+void EDBM_select_flush(BMEditMesh *em, int selectmode)
+{
+ em->bm->selectmode = selectmode;
+ BM_SelectMode_Flush(em->bm);
+ em->bm->selectmode = em->selectmode;
+}
+
+/*BMESH_TODO*/
+void EDBM_deselect_flush(BMEditMesh *UNUSED(em))
+{
+}
+
+
+void EDBM_selectmode_flush(BMEditMesh *em)
+{
+ em->bm->selectmode = em->selectmode;
+ BM_SelectMode_Flush(em->bm);
+}
+
+/*EDBM_select_[more/less] are api functions, I think the uv editor
+ uses them? though the select more/less ops themselves do not.*/
+static void EDBM_select_more(BMEditMesh *em)
+{
+ BMOperator bmop;
+ int usefaces = em->selectmode > SCE_SELECT_EDGE;
+
+ BMO_InitOpf(em->bm, &bmop,
+ "regionextend geom=%hvef constrict=%d usefaces=%d",
+ BM_SELECT, 0, usefaces);
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
+ BMO_Finish_Op(em->bm, &bmop);
+
+ EDBM_selectmode_flush(em);
+}
+
+static void EDBM_select_less(BMEditMesh *em)
+{
+ BMOperator bmop;
+ int usefaces = em->selectmode > SCE_SELECT_EDGE;
+
+ BMO_InitOpf(em->bm, &bmop,
+ "regionextend geom=%hvef constrict=%d usefaces=%d",
+ BM_SELECT, 0, usefaces);
+ BMO_Exec_Op(em->bm, &bmop);
+ BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
+ BMO_Finish_Op(em->bm, &bmop);
+
+ EDBM_selectmode_flush(em);
+}
+
+int EDBM_get_actSelection(BMEditMesh *em, BMEditSelection *ese)
+{
+ BMEditSelection *ese_last = em->bm->selected.last;
+ BMFace *efa = BM_get_actFace(em->bm, 0);
+
+ ese->next = ese->prev = NULL;
+
+ if (ese_last) {
+ if (ese_last->type == BM_FACE) { /* if there is an active face, use it over the last selected face */
+ if (efa) {
+ ese->data = (void *)efa;
+ } else {
+ ese->data = ese_last->data;
+ }
+ ese->type = BM_FACE;
+ } else {
+ ese->data = ese_last->data;
+ ese->type = ese_last->type;
+ }
+ } else if (efa) { /* no */
+ ese->data = (void *)efa;
+ ese->type = BM_FACE;
+ } else {
+ ese->data = NULL;
+ return 0;
+ }
+ return 1;
+}
+
+void EDBM_clear_flag_all(BMEditMesh *em, int flag)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int i, type;
+
+ if (flag & BM_SELECT)
+ BM_clear_selection_history(em->bm);
+
+ for (i=0; i<3; i++) {
+ switch (i) {
+ case 0:
+ type = BM_VERTS_OF_MESH;
+ break;
+ case 1:
+ type = BM_EDGES_OF_MESH;
+ break;
+ case 2:
+ type = BM_FACES_OF_MESH;
+ break;
+ }
+
+ BM_ITER(ele, &iter, em->bm, type, NULL) {
+ if (flag & BM_SELECT) BM_Select(em->bm, ele, 0);
+ BM_ClearHFlag(ele, flag);
+ }
+ }
+}
+
+void EDBM_set_flag_all(BMEditMesh *em, int flag)
+{
+ BMIter iter;
+ BMHeader *ele;
+ int i, type;
+
+ for (i=0; i<3; i++) {
+ switch (i) {
+ case 0:
+ type = BM_VERTS_OF_MESH;
+ break;
+ case 1:
+ type = BM_EDGES_OF_MESH;
+ break;
+ case 2:
+ type = BM_FACES_OF_MESH;
+ break;
+ }
+
+ ele = BMIter_New(&iter, em->bm, type, NULL);
+ for ( ; ele; ele=BMIter_Step(&iter)) {
+ if (flag & BM_SELECT) {
+ BM_Select(em->bm, ele, 1);
+ }
+
+ BM_SetHFlag(ele, flag & ~BM_SELECT);
+ }
+ }
+}
+
+/**************-------------- Undo ------------*****************/
+
+/* for callbacks */
+
+static void *getEditMesh(bContext *C)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ if(obedit && obedit->type==OB_MESH) {
+ Mesh *me= obedit->data;
+ return me->edit_btmesh;
+ }
+ return NULL;
+}
+
+typedef struct undomesh {
+ Mesh me;
+ int selectmode;
+ char obname[64];
+} undomesh;
+
+/*undo simply makes copies of a bmesh*/
+static void *editbtMesh_to_undoMesh(void *emv, void *obdata)
+{
+ BMEditMesh *em = emv;
+ Mesh *obme = obdata;
+
+ undomesh *me = MEM_callocN(sizeof(undomesh), "undo Mesh");
+ strcpy(me->obname, em->bm->ob->id.name+2);
+
+ /*make sure shape keys work*/
+ me->me.key = obme->key ? copy_key_nolib(obme->key) : NULL;
+
+ /*we recalc the tesselation here, to avoid seeding calls to
+ BMEdit_RecalcTesselation throughout the code.*/
+ BMEdit_RecalcTesselation(em);
+
+ BMO_CallOpf(em->bm, "bmesh_to_mesh mesh=%p notesselation=%i", me, 1);
+ me->selectmode = em->selectmode;
+
+ return me;
+}
+
+static void undoMesh_to_editbtMesh(void *umv, void *emv, void *UNUSED(obdata))
+{
+ BMEditMesh *em = emv, *em2;
+ Object *ob;
+ undomesh *me = umv;
+ BMesh *bm;
+ int allocsize[4] = {512, 512, 2048, 512};
+
+ ob = (Object*)find_id("OB", me->obname);
+ ob->shapenr = em->bm->shapenr;
+
+ BMEdit_Free(em);
+
+ bm = BM_Make_Mesh(ob, allocsize);
+ BMO_CallOpf(bm, "mesh_to_bmesh mesh=%p object=%p set_shapekey=%i", me, ob, 0);
+
+ em2 = BMEdit_Create(bm);
+ *em = *em2;
+
+ em->selectmode = me->selectmode;
+
+ MEM_freeN(em2);
+}
+
+
+static void free_undo(void *umv)
+{
+ if (((Mesh*)umv)->key)
+ {
+ free_key(((Mesh*)umv)->key);
+ MEM_freeN(((Mesh*)umv)->key);
+ }
+
+ free_mesh(umv, 0);
+ MEM_freeN(umv);
+}
+
+/* and this is all the undo system needs to know */
+void undo_push_mesh(bContext *C, const char *name)
+{
+ undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL);
+}
+
+/*write comment here*/
+UvVertMap *EDBM_make_uv_vert_map(BMEditMesh *em, int selected, int do_face_idx_array, float *limit)
+{
+ BMVert *ev;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ /* vars from original func */
+ UvVertMap *vmap;
+ UvMapVert *buf;
+ /* MTexPoly *tf; */ /* UNUSED */
+ MLoopUV *luv;
+ unsigned int a;
+ int totverts, i, totuv;
+
+ if (do_face_idx_array)
+ EDBM_init_index_arrays(em, 0, 0, 1);
+
+ /* we need the vert */
+ totverts=0;
+ BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(ev, totverts);
+ totverts++;
+ }
+
+ totuv = 0;
+
+ /* generate UvMapVert array */
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(!selected || ((!BM_TestHFlag(efa, BM_HIDDEN)) && BM_TestHFlag(efa, BM_SELECT)))
+ totuv += efa->len;
+ }
+
+ if(totuv==0) {
+ if (do_face_idx_array)
+ EDBM_free_index_arrays(em);
+ return NULL;
+ }
+ vmap= (UvVertMap*)MEM_callocN(sizeof(*vmap), "UvVertMap");
+ if (!vmap) {
+ if (do_face_idx_array)
+ EDBM_free_index_arrays(em);
+ return NULL;
+ }
+
+ vmap->vert= (UvMapVert**)MEM_callocN(sizeof(*vmap->vert)*totverts, "UvMapVert*");
+ buf= vmap->buf= (UvMapVert*)MEM_callocN(sizeof(*vmap->buf)*totuv, "UvMapVert");
+
+ if (!vmap->vert || !vmap->buf) {
+ free_uv_vert_map(vmap);
+ if (do_face_idx_array)
+ EDBM_free_index_arrays(em);
+ return NULL;
+ }
+
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(!selected || ((!BM_TestHFlag(efa, BM_HIDDEN)) && BM_TestHFlag(efa, BM_SELECT))) {
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ buf->tfindex= i;
+ buf->f= a;
+ buf->separate = 0;
+
+ buf->next= vmap->vert[BM_GetIndex(l->v)];
+ vmap->vert[BM_GetIndex(l->v)]= buf;
+
+ buf++;
+ i++;
+ }
+ }
+
+ a++;
+ }
+
+ /* sort individual uvs for each vert */
+ a = 0;
+ BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ UvMapVert *newvlist= NULL, *vlist=vmap->vert[a];
+ UvMapVert *iterv, *v, *lastv, *next;
+ float *uv, *uv2, uvdiff[2];
+
+ while(vlist) {
+ v= vlist;
+ vlist= vlist->next;
+ v->next= newvlist;
+ newvlist= v;
+
+ efa = EDBM_get_face_for_index(em, v->f);
+ /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
+
+ l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, v->tfindex);
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ uv = luv->uv;
+
+ lastv= NULL;
+ iterv= vlist;
+
+ while(iterv) {
+ next= iterv->next;
+ efa = EDBM_get_face_for_index(em, iterv->f);
+ /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
+
+ l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ uv2 = luv->uv;
+
+ sub_v2_v2v2(uvdiff, uv2, uv);
+
+ if(fabs(uv[0]-uv2[0]) < limit[0] && fabs(uv[1]-uv2[1]) < limit[1]) {
+ if(lastv) lastv->next= next;
+ else vlist= next;
+ iterv->next= newvlist;
+ newvlist= iterv;
+ }
+ else
+ lastv=iterv;
+
+ iterv= next;
+ }
+
+ newvlist->separate = 1;
+ }
+
+ vmap->vert[a]= newvlist;
+ a++;
+ }
+
+ if (do_face_idx_array)
+ EDBM_free_index_arrays(em);
+
+ return vmap;
+}
+
+
+UvMapVert *EDBM_get_uv_map_vert(UvVertMap *vmap, unsigned int v)
+{
+ return vmap->vert[v];
+}
+
+void EDBM_free_uv_vert_map(UvVertMap *vmap)
+{
+ if (vmap) {
+ if (vmap->vert) MEM_freeN(vmap->vert);
+ if (vmap->buf) MEM_freeN(vmap->buf);
+ MEM_freeN(vmap);
+ }
+}
+
+
+/* last_sel, use em->act_face otherwise get the last selected face in the editselections
+ * at the moment, last_sel is mainly useful for gaking sure the space image dosnt flicker */
+MTexPoly *EDBM_get_active_mtexpoly(BMEditMesh *em, BMFace **act_efa, int sloppy)
+{
+ BMFace *efa = NULL;
+
+ if(!EDBM_texFaceCheck(em))
+ return NULL;
+
+ efa = BM_get_actFace(em->bm, sloppy);
+
+ if (efa) {
+ if (act_efa) *act_efa = efa;
+ return CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ }
+
+ if (act_efa) *act_efa= NULL;
+ return NULL;
+}
+
+/* can we edit UV's for this mesh?*/
+int EDBM_texFaceCheck(BMEditMesh *em)
+{
+ /* some of these checks could be a touch overkill */
+ return em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY) &&
+ CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV);
+}
+
+int EDBM_vertColorCheck(BMEditMesh *em)
+{
+ /* some of these checks could be a touch overkill */
+ return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL);
+}
+
+
+void EDBM_CacheMirrorVerts(BMEditMesh *em)
+{
+ BMBVHTree *tree = BMBVH_NewBVH(em, 0, NULL, NULL);
+ BMIter iter;
+ BMVert *v;
+ float invmat[4][4];
+ int li, i;
+
+ if (!em->vert_index) {
+ EDBM_init_index_arrays(em, 1, 0, 0);
+ em->mirr_free_arrays = 1;
+ }
+
+ if (!CustomData_get_layer_named(&em->bm->vdata, CD_PROP_INT, (char*)"__mirror_index")) {
+ BM_add_data_layer_named(em->bm, &em->bm->vdata, CD_PROP_INT, (char*)"__mirror_index");
+ }
+
+ li = CustomData_get_named_layer_index(&em->bm->vdata, CD_PROP_INT, "__mirror_index");
+ em->bm->vdata.layers[li].flag |= CD_FLAG_TEMPORARY;
+
+ /*multiply verts by object matrix, temporarily*/
+
+ i = 0;
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(v, i);
+ i++;
+
+ if (em->ob)
+ mul_m4_v3(em->ob->obmat, v->co);
+ }
+
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BMVert *mirr;
+ int *idx = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, li);
+ float co[3] = {-v->co[0], v->co[1], v->co[2]};
+
+ //temporary for testing, check for selection
+ if (!BM_TestHFlag(v, BM_SELECT))
+ continue;
+
+ mirr = BMBVH_FindClosestVertTopo(tree, co, BM_SEARCH_MAXDIST, v);
+ if (mirr && mirr != v) {
+ *idx = BM_GetIndex(mirr);
+ idx = CustomData_bmesh_get_layer_n(&em->bm->vdata,mirr->head.data, li);
+ *idx = BM_GetIndex(v);
+ } else *idx = -1;
+ }
+
+ /*unmultiply by object matrix*/
+ if (em->ob) {
+ i = 0;
+ invert_m4_m4(invmat, em->ob->obmat);
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(v, i);
+ i++;
+
+ mul_m4_v3(invmat, v->co);
+ }
+
+ BMBVH_FreeBVH(tree);
+ }
+}
+
+BMVert *EDBM_GetMirrorVert(BMEditMesh *em, BMVert *v)
+{
+ int *mirr = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, em->mirror_cdlayer);
+
+ if (mirr && *mirr >=0 && *mirr < em->bm->totvert) {
+ if (!em->vert_index) {
+ printf("err: should only be called between "
+ "EDBM_CacheMirrorVerts and EDBM_EndMirrorCache");
+ return NULL;
+ }
+
+ return em->vert_index[*mirr];
+ }
+
+ return NULL;
+}
+
+void EDBM_EndMirrorCache(BMEditMesh *em)
+{
+ if (em->mirr_free_arrays) {
+ MEM_freeN(em->vert_index);
+ em->vert_index = NULL;
+ }
+}
diff --git a/source/blender/editors/mesh/editbmesh_add.c b/source/blender/editors/mesh/editbmesh_add.c
new file mode 100644
index 00000000000..9668019b7ed
--- /dev/null
+++ b/source/blender/editors/mesh/editbmesh_add.c
@@ -0,0 +1,647 @@
+ /* $Id: bmesh_tools.c
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_key_types.h"
+
+#include "RNA_types.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_heap.h"
+#include "BLI_array.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_bmesh.h"
+#include "BKE_report.h"
+#include "BKE_tessmesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_view3d.h"
+#include "ED_util.h"
+#include "ED_screen.h"
+#include "ED_transform.h"
+#include "ED_object.h"
+
+#include "UI_interface.h"
+
+#include "mesh_intern.h"
+#include "bmesh.h"
+
+#include "editbmesh_bvh.h"
+
+
+/* uses context to figure out transform for primitive */
+/* returns standard diameter */
+static float new_primitive_matrix(bContext *C, float *loc, float *rot, float primmat[][4])
+{
+ Object *obedit= CTX_data_edit_object(C);
+ View3D *v3d =CTX_wm_view3d(C);
+ float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3];
+
+ unit_m4(primmat);
+
+ eul_to_mat3(rmat, rot);
+ invert_m3(rmat);
+
+ /* inverse transform for initial rotation and object */
+ copy_m3_m4(mat, obedit->obmat);
+ mul_m3_m3m3(cmat, rmat, mat);
+ invert_m3_m3(imat, cmat);
+ copy_m4_m3(primmat, imat);
+
+ /* center */
+ VECCOPY(primmat[3], loc);
+ VECSUB(primmat[3], primmat[3], obedit->obmat[3]);
+ invert_m3_m3(imat, mat);
+ mul_m3_v3(imat, primmat[3]);
+
+ if(v3d) return v3d->grid;
+ return 1.0f;
+}
+
+/* ********* add primitive operators ************* */
+
+static void make_prim_init(bContext *C, float *dia, float mat[][4],
+ int *state, float *loc, float *rot, unsigned int layer)
+{
+ Object *obedit= CTX_data_edit_object(C);
+
+ *state = 0;
+ if(obedit==NULL || obedit->type!=OB_MESH) {
+ obedit= ED_object_add_type(C, OB_MESH, loc, rot, FALSE, layer);
+
+ /* create editmode */
+ ED_object_enter_editmode(C, EM_DO_UNDO|EM_IGNORE_LAYER); /* rare cases the active layer is messed up */
+ *state = 1;
+ }
+ else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+
+ *dia *= new_primitive_matrix(C, loc, rot, mat);
+}
+
+static void make_prim_finish(bContext *C, int *state, int enter_editmode)
+{
+ Object *obedit;
+ Mesh *me;
+ BMEditMesh *em;
+
+ obedit = CTX_data_edit_object(C);
+ me = obedit->data;
+ em = me->edit_btmesh;
+
+ /* Primitive has all verts selected, use vert select flush
+ to push this up to edges & faces. */
+ EDBM_select_flush(em, SCE_SELECT_VERTEX);
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ /* userdef */
+ if (*state && !enter_editmode) {
+ ED_object_exit_editmode(C, EM_FREEDATA); /* adding EM_DO_UNDO messes up operator redo */
+ }
+ WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
+
+}
+static int add_primitive_plane_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit;
+ Mesh *me;
+ BMEditMesh *em;
+ float loc[3], rot[3], mat[4][4], dia;
+ int enter_editmode;
+ int state;
+ unsigned int layer;
+
+ ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
+ make_prim_init(C, &dia, mat, &state, loc, rot, layer);
+
+ obedit = CTX_data_edit_object(C);
+ me = obedit->data;
+ em = me->edit_btmesh;
+
+ if (!EDBM_CallAndSelectOpf(em, op, "vertout",
+ "create_grid xsegments=%i ysegments=%i size=%f mat=%m4", 1, 1, sqrt(2.0), mat))
+ return OPERATOR_CANCELLED;
+
+ /* BMESH_TODO make plane side this: sqrt(2.0f) - plane (diameter of 1.41 makes it unit size) */
+ make_prim_finish(C, &state, enter_editmode);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_plane_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Plane";
+ ot->description= "Construct a filled planar mesh with 4 vertices";
+ ot->idname= "MESH_OT_primitive_plane_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_plane_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_cube_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit;
+ Mesh *me;
+ BMEditMesh *em;
+ float loc[3], rot[3], mat[4][4], dia;
+ int enter_editmode;
+ int state;
+ unsigned int layer;
+
+ ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
+ make_prim_init(C, &dia, mat, &state, loc, rot, layer);
+
+ obedit= CTX_data_edit_object(C);
+ me = obedit->data;
+ em = me->edit_btmesh;
+
+ if (!EDBM_CallAndSelectOpf(em, op, "vertout", "create_cube mat=%m4 size=%f", mat, 2.0f))
+ return OPERATOR_CANCELLED;
+
+ /* BMESH_TODO make plane side this: sqrt(2.0f) - plane (diameter of 1.41 makes it unit size) */
+ make_prim_finish(C, &state, enter_editmode);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_cube_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Cube";
+ ot->description= "Construct a cube mesh";
+ ot->idname= "MESH_OT_primitive_cube_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_cube_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static const EnumPropertyItem fill_type_items[]= {
+ {0, "NOTHING", 0, "Nothing", "Don't fill at all"},
+ {1, "NGON", 0, "Ngon", "Use ngons"},
+ {2, "TRIFAN", 0, "Triangle Fan", "Use triangle fans"},
+ {0, NULL, 0, NULL, NULL}};
+
+static int add_primitive_circle_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit;
+ Mesh *me;
+ BMEditMesh *em;
+ float loc[3], rot[3], mat[4][4], dia;
+ int enter_editmode;
+ int state, cap_end, cap_tri;
+ unsigned int layer;
+
+ cap_end = RNA_enum_get(op->ptr, "fill_type");
+ cap_tri = cap_end==2;
+
+ ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
+ make_prim_init(C, &dia, mat, &state, loc, rot, layer);
+
+ obedit = CTX_data_edit_object(C);
+ me = obedit->data;
+ em = me->edit_btmesh;
+
+ if (!EDBM_CallAndSelectOpf(em, op, "vertout",
+ "create_circle segments=%i diameter=%f cap_ends=%i cap_tris=%i mat=%m4",
+ RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius"),
+ cap_end, cap_tri, mat))
+ return OPERATOR_CANCELLED;
+
+ make_prim_finish(C, &state, enter_editmode);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_circle_add(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Add Circle";
+ ot->description= "Construct a circle mesh";
+ ot->idname= "MESH_OT_primitive_circle_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_circle_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 3, 500);
+ prop = RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_enum(ot->srna, "fill_type", fill_type_items, 0, "Fill Type", "");
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit;
+ Mesh *me;
+ BMEditMesh *em;
+ float loc[3], rot[3], mat[4][4], dia;
+ int enter_editmode;
+ int state, cap_end, cap_tri;
+ unsigned int layer;
+
+ cap_end = RNA_enum_get(op->ptr, "end_fill_type");
+ cap_tri = cap_end==2;
+
+ ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
+ make_prim_init(C, &dia, mat, &state, loc, rot, layer);
+
+ obedit = CTX_data_edit_object(C);
+ me = obedit->data;
+ em = me->edit_btmesh;
+
+ if (!EDBM_CallAndSelectOpf(em, op, "vertout",
+ "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%i cap_tris=%i depth=%f mat=%m4",
+ 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))
+ return OPERATOR_CANCELLED;
+
+ make_prim_finish(C, &state, enter_editmode);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Add Tube";
+ ot->description= "Construct a tube mesh";
+ ot->idname= "MESH_OT_primitive_cylinder_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_cylinder_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
+ prop = RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ prop = RNA_def_float(ot->srna, "depth", 1.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Cap Fill Type", "");
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_cone_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit;
+ Mesh *me;
+ BMEditMesh *em;
+ float loc[3], rot[3], mat[4][4], dia;
+ int enter_editmode;
+ int state, cap_end, cap_tri;
+ unsigned int layer;
+
+ cap_end = RNA_enum_get(op->ptr, "end_fill_type");
+ cap_tri = cap_end==2;
+
+ ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
+ make_prim_init(C, &dia, mat, &state, loc, rot, layer);
+
+ obedit = CTX_data_edit_object(C);
+ me = obedit->data;
+ em = me->edit_btmesh;
+
+ if (!EDBM_CallAndSelectOpf(em, op, "vertout",
+ "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%i cap_tris=%i depth=%f mat=%m4",
+ 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))
+ return OPERATOR_CANCELLED;
+
+ make_prim_finish(C, &state, enter_editmode);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_cone_add(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Add Cone";
+ ot->description= "Construct a conic mesh (ends filled)";
+ ot->idname= "MESH_OT_primitive_cone_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_cone_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
+ RNA_def_float(ot->srna, "radius1", 1.0f, 0.0, FLT_MAX, "Radius 1", "", 0.001, 100.00);
+ RNA_def_float(ot->srna, "radius2", 0.0f, 0.0, FLT_MAX, "Radius 2", "", 0.001, 100.00);
+ prop = RNA_def_float(ot->srna, "depth", 1.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Base Fill Type", "");
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_grid_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit;
+ Mesh *me;
+ BMEditMesh *em;
+ float loc[3], rot[3], mat[4][4], dia;
+ int enter_editmode;
+ int state;
+ unsigned int layer;
+
+ ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
+ make_prim_init(C, &dia, mat, &state, loc, rot, layer);
+
+ obedit = CTX_data_edit_object(C);
+ me = obedit->data;
+ em = me->edit_btmesh;
+
+ if (!EDBM_CallAndSelectOpf(em, op, "vertout",
+ "create_grid xsegments=%i ysegments=%i size=%f mat=%m4",
+ RNA_int_get(op->ptr, "x_subdivisions"),
+ RNA_int_get(op->ptr, "y_subdivisions"),
+ RNA_float_get(op->ptr, "size"), mat))
+ {
+ return OPERATOR_CANCELLED;
+ }
+
+ make_prim_finish(C, &state, enter_editmode);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_grid_add(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Add Grid";
+ ot->description= "Construct a grid mesh";
+ ot->idname= "MESH_OT_primitive_grid_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_grid_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "x_subdivisions", 10, INT_MIN, INT_MAX, "X Subdivisions", "", 3, 1000);
+ RNA_def_int(ot->srna, "y_subdivisions", 10, INT_MIN, INT_MAX, "Y Subdivisions", "", 3, 1000);
+ prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, FLT_MAX);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit;
+ Mesh *me;
+ BMEditMesh *em;
+ float loc[3], rot[3], mat[4][4], dia;
+ int enter_editmode;
+ int state, view_aligned;
+ unsigned int layer;
+
+ ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, &view_aligned);
+ if (!view_aligned)
+ rot[0] += M_PI/2.0f;
+
+ make_prim_init(C, &dia, mat, &state, loc, rot, layer);
+
+ obedit = CTX_data_edit_object(C);
+ me = obedit->data;
+ em = me->edit_btmesh;
+
+ if (!EDBM_CallAndSelectOpf(em, op, "vertout", "create_monkey mat=%m4", mat)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ make_prim_finish(C, &state, enter_editmode);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_monkey_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Monkey";
+ ot->description= "Construct a Suzanne mesh";
+ ot->idname= "MESH_OT_primitive_monkey_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_monkey_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+
+static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit;
+ Mesh *me;
+ BMEditMesh *em;
+ float loc[3], rot[3], mat[4][4], dia;
+ int enter_editmode;
+ int state;
+ unsigned int layer;
+
+ ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
+ make_prim_init(C, &dia, mat, &state, loc, rot, layer);
+
+ obedit = CTX_data_edit_object(C);
+ me = obedit->data;
+ em = me->edit_btmesh;
+
+ if (!EDBM_CallAndSelectOpf(em, op, "vertout",
+ "create_uvsphere segments=%i revolutions=%i diameter=%f mat=%m4",
+ RNA_int_get(op->ptr, "rings"), RNA_int_get(op->ptr, "segments"),
+ RNA_float_get(op->ptr,"size"), mat))
+ return OPERATOR_CANCELLED;
+
+ make_prim_finish(C, &state, enter_editmode);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Add UV Sphere";
+ ot->description= "Construct a UV sphere mesh";
+ ot->idname= "MESH_OT_primitive_uv_sphere_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_uvsphere_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "segments", 32, INT_MIN, INT_MAX, "Segments", "", 3, 500);
+ RNA_def_int(ot->srna, "rings", 24, INT_MIN, INT_MAX, "Rings", "", 3, 500);
+ prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, FLT_MAX);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit;
+ Mesh *me;
+ BMEditMesh *em;
+ float loc[3], rot[3], mat[4][4], dia;
+ int enter_editmode;
+ int state;
+ unsigned int layer;
+
+ ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
+ make_prim_init(C, &dia, mat, &state, loc, rot, layer);
+
+ obedit = CTX_data_edit_object(C);
+ me = obedit->data;
+ em = me->edit_btmesh;
+
+ if (!EDBM_CallAndSelectOpf(em, op, "vertout",
+ "create_icosphere subdivisions=%i diameter=%f mat=%m4",
+ RNA_int_get(op->ptr, "subdivisions"),
+ RNA_float_get(op->ptr, "size"), mat)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ make_prim_finish(C, &state, enter_editmode);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Add Ico Sphere";
+ ot->description= "Construct an Icosphere mesh";
+ ot->idname= "MESH_OT_primitive_ico_sphere_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_icosphere_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "subdivisions", 2, 0, 6, "Subdivisions", "", 0, 8);
+ prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, FLT_MAX);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+
+ ED_object_add_generic_props(ot, TRUE);
+}
diff --git a/source/blender/editors/mesh/editbmesh_bvh.c b/source/blender/editors/mesh/editbmesh_bvh.c
new file mode 100644
index 00000000000..d73f63c0df2
--- /dev/null
+++ b/source/blender/editors/mesh/editbmesh_bvh.c
@@ -0,0 +1,781 @@
+ /* $Id:
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2010 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#define IN_EDITMESHBVH
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include "BLO_sys_types.h" // for intptr_t support
+
+#include "DNA_mesh_types.h"
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_key_types.h"
+
+#include "RNA_types.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_editVert.h"
+#include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_heap.h"
+#include "BLI_array.h"
+#include "BLI_kdopbvh.h"
+#include "BLI_smallhash.h"
+
+#include "BKE_DerivedMesh.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_bmesh.h"
+#include "BKE_report.h"
+#include "BKE_tessmesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_view3d.h"
+#include "ED_util.h"
+#include "ED_screen.h"
+#include "ED_transform.h"
+
+#include "UI_interface.h"
+
+#include "mesh_intern.h"
+#include "bmesh.h"
+
+#include "editbmesh_bvh.h"
+
+typedef struct BMBVHTree {
+ BMEditMesh *em;
+ BMesh *bm;
+ BVHTree *tree;
+ float epsilon;
+ float maxdist; //for nearest point search
+ float uv[2];
+
+ /*stuff for topological vert search*/
+ BMVert *v, *curv;
+ GHash *gh;
+ float curw, curd;
+ float co[3], (*cagecos)[3], (*cos)[3];
+ int curtag, flag;
+
+ Object *ob;
+ Scene *scene;
+} BMBVHTree;
+
+static void cage_mapped_verts_callback(void *userData, int index, float *co,
+ float *UNUSED(no_f), short *UNUSED(no_s))
+{
+ void **data = userData;
+ BMEditMesh *em = data[0];
+ float (*cagecos)[3] = data[1];
+ SmallHash *hash = data[2];
+
+ if (index >= 0 && index < em->bm->totvert && !BLI_smallhash_haskey(hash, index)) {
+ BLI_smallhash_insert(hash, index, NULL);
+ copy_v3_v3(cagecos[index], co);
+ }
+}
+
+BMBVHTree *BMBVH_NewBVH(BMEditMesh *em, int flag, Scene *scene, Object *obedit)
+{
+ BMBVHTree *tree = MEM_callocN(sizeof(*tree), "BMBVHTree");
+ DerivedMesh *cage, *final;
+ SmallHash shash;
+ float cos[3][3], (*cagecos)[3] = NULL;
+ int i;
+
+ /*when initializing cage verts, we only want the first cage coordinate for each vertex,
+ so that e.g. mirror or array use original vertex coordiantes and not mirrored or duplicate*/
+ BLI_smallhash_init(&shash);
+
+ BMEdit_RecalcTesselation(em);
+
+ tree->ob = obedit;
+ tree->scene = scene;
+ tree->em = em;
+ tree->bm = em->bm;
+ tree->epsilon = FLT_EPSILON*2.0f;
+ tree->flag = flag;
+
+ tree->tree = BLI_bvhtree_new(em->tottri, tree->epsilon, 8, 8);
+
+ if (flag & BMBVH_USE_CAGE) {
+ BMIter iter;
+ BMVert *v;
+ void *data[3];
+
+ tree->cos = MEM_callocN(sizeof(float)*3*em->bm->totvert, "bmbvh cos");
+ BM_ITER_INDEX(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL, i) {
+ BM_SetIndex(v, i);
+ copy_v3_v3(tree->cos[i], v->co);
+ }
+
+ cage = editbmesh_get_derived_cage_and_final(scene, obedit, em, &final, CD_MASK_DERIVEDMESH);
+ cagecos = MEM_callocN(sizeof(float)*3*em->bm->totvert, "bmbvh cagecos");
+
+ data[0] = em;
+ data[1] = cagecos;
+ data[2] = &shash;
+
+ cage->foreachMappedVert(cage, cage_mapped_verts_callback, data);
+ }
+
+ tree->cagecos = cagecos;
+
+ for (i=0; i<em->tottri; i++) {
+ if (flag & BMBVH_USE_CAGE) {
+ copy_v3_v3(cos[0], cagecos[BM_GetIndex(em->looptris[i][0]->v)]);
+ copy_v3_v3(cos[1], cagecos[BM_GetIndex(em->looptris[i][1]->v)]);
+ copy_v3_v3(cos[2], cagecos[BM_GetIndex(em->looptris[i][2]->v)]);
+ } else {
+ copy_v3_v3(cos[0], em->looptris[i][0]->v->co);
+ copy_v3_v3(cos[1], em->looptris[i][1]->v->co);
+ copy_v3_v3(cos[2], em->looptris[i][2]->v->co);
+ }
+
+ BLI_bvhtree_insert(tree->tree, i, (float*)cos, 3);
+ }
+
+ BLI_bvhtree_balance(tree->tree);
+ BLI_smallhash_release(&shash);
+
+ return tree;
+}
+
+void BMBVH_FreeBVH(BMBVHTree *tree)
+{
+ BLI_bvhtree_free(tree->tree);
+
+ if (tree->cagecos)
+ MEM_freeN(tree->cagecos);
+ if (tree->cos)
+ MEM_freeN(tree->cos);
+
+ MEM_freeN(tree);
+}
+
+/*taken from bvhutils.c*/
+static float ray_tri_intersection(const BVHTreeRay *ray, const float UNUSED(m_dist), float *v0,
+ float *v1, float *v2, float *uv, float UNUSED(e))
+{
+ float dist;
+
+ if(isect_ray_tri_v3((float*)ray->origin, (float*)ray->direction, v0, v1, v2, &dist, uv))
+ return dist;
+
+ return FLT_MAX;
+}
+
+static void raycallback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ BMBVHTree *tree = userdata;
+ BMLoop **ls = tree->em->looptris[index];
+ float dist, uv[2];
+
+ if (!ls[0] || !ls[1] || !ls[2])
+ return;
+
+ dist = ray_tri_intersection(ray, hit->dist, ls[0]->v->co, ls[1]->v->co,
+ ls[2]->v->co, uv, tree->epsilon);
+ if (dist < hit->dist) {
+ hit->dist = dist;
+ hit->index = index;
+
+ VECCOPY(hit->no, ls[0]->v->no);
+
+ copy_v3_v3(hit->co, ray->direction);
+ normalize_v3(hit->co);
+ mul_v3_fl(hit->co, dist);
+ add_v3_v3(hit->co, ray->origin);
+
+ copy_v2_v2(tree->uv, uv);
+ }
+}
+
+BMFace *BMBVH_RayCast(BMBVHTree *tree, float *co, float *dir, float *hitout, float *cagehit)
+{
+ BVHTreeRayHit hit;
+
+ hit.dist = FLT_MAX;
+ hit.index = -1;
+
+ tree->uv[0] = tree->uv[1] = 0.0f;
+
+ BLI_bvhtree_ray_cast(tree->tree, co, dir, 0.0f, &hit, raycallback, tree);
+ if (hit.dist != FLT_MAX && hit.index != -1) {
+ if (hitout) {
+ if (tree->flag & BMBVH_RETURN_ORIG) {
+ BMVert *v1, *v2, *v3;
+ float co[3];
+ int i;
+
+ v1 = tree->em->looptris[hit.index][0]->v;
+ v2 = tree->em->looptris[hit.index][1]->v;
+ v3 = tree->em->looptris[hit.index][2]->v;
+
+ for (i=0; i<3; i++) {
+ co[i] = v1->co[i] + (v2->co[i] - v1->co[i])*tree->uv[0] + (v3->co[i]-v1->co[i])*tree->uv[1];
+ }
+ copy_v3_v3(hitout, co);
+ } else {
+ copy_v3_v3(hitout, hit.co);
+ }
+
+ if (cagehit)
+ copy_v3_v3(cagehit, hit.co);
+ }
+
+ return tree->em->looptris[hit.index][0]->f;
+ }
+
+ return NULL;
+}
+
+BVHTree *BMBVH_BVHTree(BMBVHTree *tree)
+{
+ return tree->tree;
+}
+
+static void vertsearchcallback(void *userdata, int index, const float *UNUSED(co), BVHTreeNearest *hit)
+{
+ BMBVHTree *tree = userdata;
+ BMLoop **ls = tree->em->looptris[index];
+ float dist, maxdist, v[3];
+ int i;
+
+ maxdist = tree->maxdist;
+
+ for (i=0; i<3; i++) {
+ sub_v3_v3v3(v, hit->co, ls[i]->v->co);
+
+ dist = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+ if (dist < hit->dist && dist < maxdist) {
+ VECCOPY(hit->co, ls[i]->v->co);
+ VECCOPY(hit->no, ls[i]->v->no);
+ hit->dist = dist;
+ }
+ }
+}
+
+BMVert *BMBVH_FindClosestVert(BMBVHTree *tree, float *co, float maxdist)
+{
+ BVHTreeNearest hit;
+
+ VECCOPY(hit.co, co);
+ hit.dist = maxdist*5;
+ hit.index = -1;
+
+ tree->maxdist = maxdist;
+
+ BLI_bvhtree_find_nearest(tree->tree, co, &hit, vertsearchcallback, tree);
+ if (hit.dist != FLT_MAX && hit.index != -1) {
+ BMLoop **ls = tree->em->looptris[hit.index];
+ float dist, curdist = tree->maxdist, v[3];
+ int cur=0, i;
+
+ maxdist = tree->maxdist;
+
+ for (i=0; i<3; i++) {
+ sub_v3_v3v3(v, hit.co, ls[i]->v->co);
+
+ dist = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+ if (dist < curdist) {
+ cur = i;
+ curdist = dist;
+ }
+ }
+
+ return ls[i]->v;
+ }
+
+ return NULL;
+}
+
+typedef struct walklist {
+ BMVert *v;
+ int valence;
+ int depth;
+ float w, r;
+ int totwalked;
+
+ /*state data*/
+ BMVert *lastv;
+ BMLoop *curl, *firstl;
+ BMEdge *cure;
+} walklist;
+
+
+static short winding(float *v1, float *v2, float *v3)
+/* is v3 to the right of v1-v2 ? With exception: v3==v1 || v3==v2 */
+{
+ double inp;
+
+ //inp= (v2[cox]-v1[cox])*(v1[coy]-v3[coy]) +(v1[coy]-v2[coy])*(v1[cox]-v3[cox]);
+ inp= (v2[0]-v1[0])*(v1[1]-v3[1]) +(v1[1]-v2[1])*(v1[0]-v3[0]);
+
+ if(inp<0.0) return 0;
+ else if(inp==0) {
+ if(v1[0]==v3[0] && v1[1]==v3[1]) return 0;
+ if(v2[0]==v3[0] && v2[1]==v3[1]) return 0;
+ }
+ return 1;
+}
+
+static float topo_compare(BMesh *bm, BMVert *v1, BMVert *v2)
+{
+ BMIter iter1, iter2;
+ BMEdge *e1, *e2, *cure1 = NULL, *cure2 = NULL;
+ BMLoop *l1, *l2;
+ BMVert *lastv1, *lastv2;
+ GHash *gh;
+ walklist *stack1=NULL, *stack2=NULL;
+ BLI_array_declare(stack1);
+ BLI_array_declare(stack2);
+ float vec1[3], vec2[3], minangle=FLT_MAX, w;
+ int lvl=1;
+ static int maxlevel = 3;
+
+ /*ok. see how similar v is to v2, based on topological similaritys in the local
+ topological neighborhood*/
+
+ /*step 1: find two edges, one that contains v and one that contains v2, with the
+ smallest angle between the two edges*/
+
+ BM_ITER(e1, &iter1, bm, BM_EDGES_OF_VERT, v1) {
+ BM_ITER(e2, &iter2, bm, BM_EDGES_OF_VERT, v2) {
+ float angle;
+
+ if (e1->v1 == e2->v1 || e1->v2 == e2->v2 || e1->v1 == e2->v2 || e1->v2 == e2->v1)
+ continue;
+
+ sub_v3_v3v3(vec1, BM_OtherEdgeVert(e1, v1)->co, v1->co);
+ sub_v3_v3v3(vec2, BM_OtherEdgeVert(e2, v2)->co, v2->co);
+
+ angle = fabs(angle_v3v3(vec1, vec2));
+
+ if (angle < minangle) {
+ minangle = angle;
+ cure1 = e1;
+ cure2 = e2;
+ }
+ }
+ }
+
+ if (!cure1 || !cure1->l || !cure2->l) {
+ /*just return 1.0 in this case*/
+ return 1.0f;
+ }
+
+ /*assumtions
+
+ we assume a 2-manifold mesh here. if at any time this isn't the case,
+ e.g. a hole or an edge with more then 2 faces around it, we um ignore
+ that edge I guess, and try to make the algorithm go around as necassary.*/
+
+ l1 = cure1->l;
+ l2 = cure2->l;
+
+ lastv1 = l1->v == v1 ? l1->next->v : l1->prev->v;
+ lastv2 = l2->v == v2 ? l2->next->v : l2->prev->v;
+
+ /*we can only provide meaningful comparisons if v1 and v2 have the same valence*/
+ if (BM_Vert_EdgeCount(v1) != BM_Vert_EdgeCount(v2))
+ return 1.0f; /*full mismatch*/
+
+ gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh bvh");
+
+#define SPUSH(s, d, vt, lv, e)\
+ if (BLI_array_count(s) <= lvl) BLI_array_growone(s);\
+ memset((s+lvl), 0, sizeof(*s));\
+ s[lvl].depth = d;\
+ s[lvl].v = vt;\
+ s[lvl].cure = e;\
+ s[lvl].lastv = lv;\
+ s[lvl].valence = BM_Vert_EdgeCount(vt);\
+
+ lvl = 0;
+
+ SPUSH(stack1, 0, v1, lastv1, cure1);
+ SPUSH(stack2, 0, v2, lastv2, cure2);
+
+ BLI_srand( BLI_rand() ); /* random seed */
+
+ lvl = 1;
+ while (lvl) {
+ int term = 0;
+ walklist *s1 = stack1 + lvl - 1, *s2 = stack2 + lvl - 1;
+
+ /*pop from the stack*/
+ lvl--;
+
+ if (s1->curl && s1->curl->e == s1->cure)
+ term = 1;
+ if (s2->curl && s2->curl->e == s2->cure)
+ term = 1;
+
+ /*find next case to do*/
+ if (!s1->curl)
+ s1->curl = s1->cure->l;
+ if (!s2->curl) {
+ float no1[3], no2[3], angle;
+ int wind1, wind2;
+
+ s2->curl = s2->cure->l;
+
+ /*find which of two possible faces to use*/
+ l1 = BM_OtherFaceLoop(s1->curl->e, s1->curl->f, s1->lastv);
+ l2 = BM_OtherFaceLoop(s2->curl->e, s2->curl->f, s2->lastv);
+
+ if (l1->v == s2->lastv) {
+ l1 = l1->next;
+ if (l1->v == s2->v)
+ l1 = l1->prev->prev;
+ } else if (l1->v == s2->v) {
+ l1 = l1->next;
+ if (l1->v == s2->lastv)
+ l1 = l1->prev->prev;
+ }
+
+ if (l2->v == s2->lastv) {
+ l2 = l2->next;
+ if (l2->v == s2->v)
+ l2 = l2->prev->prev;
+ } else if (l2->v == s2->v) {
+ l2 = l2->next;
+ if (l2->v == s2->lastv)
+ l2 = l2->prev->prev;
+ }
+
+ wind1 = winding(s1->v->co, s1->lastv->co, l1->v->co);
+
+ wind2 = winding(s2->v->co, s2->lastv->co, l2->v->co);
+
+ /*if angle between the two adjacent faces is greater then 90 degrees,
+ we need to flip wind2*/
+ l1 = l2;
+ l2 = s2->curl->radial_next;
+ l2 = BM_OtherFaceLoop(l2->e, l2->f, s2->lastv);
+
+ if (l2->v == s2->lastv) {
+ l2 = l2->next;
+ if (l2->v == s2->v)
+ l2 = l2->prev->prev;
+ } else if (l2->v == s2->v) {
+ l2 = l2->next;
+ if (l2->v == s2->lastv)
+ l2 = l2->prev->prev;
+ }
+
+ normal_tri_v3(no1, s2->v->co, s2->lastv->co, l1->v->co);
+ normal_tri_v3(no2, s2->v->co, s2->lastv->co, l2->v->co);
+
+ /*enforce identical winding as no1*/
+ mul_v3_fl(no2, -1.0);
+
+ angle = angle_v3v3(no1, no2);
+ if (angle > M_PI/2 - FLT_EPSILON*2)
+ wind2 = !wind2;
+
+ if (wind1 == wind2)
+ s2->curl = s2->curl->radial_next;
+ }
+
+ /*handle termination cases of having already looped through all child
+ nodes, or the valence mismatching between v1 and v2, or we hit max
+ recursion depth*/
+ term |= s1->valence != s2->valence || lvl+1 > maxlevel;
+ term |= s1->curl->radial_next == l1;
+ term |= s2->curl->radial_next == l2;
+
+ if (!term) {
+ lastv1 = s1->v;
+ lastv2 = s2->v;
+ v1 = BM_OtherEdgeVert(s1->curl->e, lastv1);
+ v2 = BM_OtherEdgeVert(s2->curl->e, lastv2);
+
+ e1 = s1->curl->e;
+ e2 = s2->curl->e;
+
+ if (!BLI_ghash_haskey(gh, v1) && !BLI_ghash_haskey(gh, v2)) {
+ /*repush the current stack item*/
+ lvl++;
+
+ //if (maxlevel % 2 == 0) {
+ BLI_ghash_insert(gh, v1, NULL);
+ BLI_ghash_insert(gh, v2, NULL);
+ //}
+
+ /*now push the child node*/
+ SPUSH(stack1, lvl, v1, lastv1, e1);
+ SPUSH(stack2, lvl, v2, lastv2, e2);
+
+ lvl++;
+
+ s1 = stack1 + lvl - 2;
+ s2 = stack2 + lvl - 2;
+ }
+
+ s1->curl = s1->curl->v == s1->v ? s1->curl->prev : s1->curl->next;
+ s2->curl = s2->curl->v == s2->v ? s2->curl->prev : s2->curl->next;
+
+ s1->curl = s1->curl->radial_next;
+ s2->curl = s2->curl->radial_next;
+ }
+
+#define WADD(stack, s)\
+ if (lvl) {/*silly attempt to make this non-commutative: randomize\
+ how much this particular weight adds to the total*/\
+ stack[lvl-1].r += r;\
+ s->w *= r;\
+ stack[lvl-1].totwalked++;\
+ stack[lvl-1].w += s->w;\
+ }
+
+ /*if no next case to do, update parent weight*/
+ if (term) {
+ float r = 0.8f + BLI_frand()*0.2f - FLT_EPSILON;
+
+ if (s1->totwalked) {
+ s1->w /= s1->r;
+ } else
+ s1->w = s1->valence == s2->valence ? 1.0f : 0.0f;
+
+ WADD(stack1, s1);
+
+ if (s2->totwalked) {
+ s2->w /= s2->r;
+ } else
+ s2->w = s1->valence == s2->valence ? 1.0f : 0.0f;
+
+ WADD(stack2, s2);
+
+ /*apply additional penalty to weight mismatch*/
+ if (s2->w != s1->w)
+ s2->w *= 0.8f;
+ }
+ }
+
+ w = (stack1[0].w + stack2[0].w)*0.5f;
+
+ BLI_array_free(stack1);
+ BLI_array_free(stack2);
+
+ BLI_ghash_free(gh, NULL, NULL);
+
+ return 1.0f - w;
+}
+
+static void vertsearchcallback_topo(void *userdata, int index, const float *UNUSED(co), BVHTreeNearest *UNUSED(hit))
+{
+ BMBVHTree *tree = userdata;
+ BMLoop **ls = tree->em->looptris[index];
+ int i;
+ float vec[3], w;
+
+ for (i=0; i<3; i++) {
+ float dis;
+
+ if (BLI_ghash_haskey(tree->gh, ls[i]->v))
+ continue;
+
+ sub_v3_v3v3(vec, tree->co, ls[i]->v->co);
+ dis = dot_v3v3(vec, vec);
+
+ w = topo_compare(tree->em->bm, tree->v, ls[i]->v);
+ tree->curtag++;
+
+ if (w < tree->curw-FLT_EPSILON*4) {
+ tree->curw = w;
+ tree->curv = ls[i]->v;
+
+ sub_v3_v3v3(vec, tree->co, ls[i]->v->co);
+ tree->curd = dot_v3v3(vec, vec);
+
+ /*we deliberately check for equality using (smallest possible float)*4
+ comparison factor, to always prefer distance in cases of verts really
+ close to each other*/
+ } else if (fabs(tree->curw - w) < FLT_EPSILON*4) {
+ /*if w is equal to hitex->curw, sort by distance*/
+ sub_v3_v3v3(vec, tree->co, ls[i]->v->co);
+ dis = dot_v3v3(vec, vec);
+
+ if (dis < tree->curd) {
+ tree->curd = dis;
+ tree->curv = ls[i]->v;
+ }
+ }
+
+ BLI_ghash_insert(tree->gh, ls[i]->v, NULL);
+ }
+}
+
+BMVert *BMBVH_FindClosestVertTopo(BMBVHTree *tree, float *co, float maxdist, BMVert *sourcev)
+{
+ BVHTreeNearest hit;
+
+ memset(&hit, 0, sizeof(hit));
+
+ VECCOPY(hit.co, co);
+ VECCOPY(tree->co, co);
+ hit.index = -1;
+ hit.dist = maxdist;
+
+ tree->curw = FLT_MAX;
+ tree->curd = FLT_MAX;
+ tree->curv = NULL;
+ tree->curtag = 1;
+
+ tree->gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh bvh");
+
+ tree->maxdist = maxdist;
+ tree->v = sourcev;
+
+ BLI_bvhtree_find_nearest(tree->tree, co, &hit, vertsearchcallback_topo, tree);
+
+ BLI_ghash_free(tree->gh, NULL, NULL);
+ tree->gh = NULL;
+
+ return tree->curv;
+}
+
+
+#if 0 //BMESH_TODO: not implemented yet
+int BMBVH_VertVisible(BMBVHTree *tree, BMEdge *e, RegionView3D *r3d)
+{
+
+}
+#endif
+
+static BMFace *edge_ray_cast(BMBVHTree *tree, float *co, float *dir, float *hitout, BMEdge *e)
+{
+ BMFace *f = BMBVH_RayCast(tree, co, dir, hitout, NULL);
+
+ if (f && BM_Edge_In_Face(f, e))
+ return NULL;
+
+ return f;
+}
+
+static void scale_point(float *c1, float *p, float s)
+{
+ sub_v3_v3(c1, p);
+ mul_v3_fl(c1, s);
+ add_v3_v3(c1, p);
+}
+
+
+int BMBVH_EdgeVisible(BMBVHTree *tree, BMEdge *e, ARegion *ar, View3D *v3d, Object *obedit)
+{
+ BMFace *f;
+ float co1[3], co2[3], co3[3], dir1[4], dir2[4], dir3[4];
+ float origin[3], invmat[4][4];
+ float epsilon = 0.01f;
+ float mval_f[2], end[3];
+
+ if (!ar) {
+ printf("error in BMBVH_EdgeVisible!\n");
+ return 0;
+ }
+
+ mval_f[0] = ar->winx/2.0;
+ mval_f[1] = ar->winy/2.0;
+ ED_view3d_win_to_segment_clip(ar, v3d, mval_f, origin, end);
+
+ invert_m4_m4(invmat, obedit->obmat);
+ mul_m4_v3(invmat, origin);
+
+ VECCOPY(co1, e->v1->co);
+ add_v3_v3v3(co2, e->v1->co, e->v2->co);
+ mul_v3_fl(co2, 0.5f);
+ VECCOPY(co3, e->v2->co);
+
+ scale_point(co1, co2, 0.99);
+ scale_point(co3, co2, 0.99);
+
+ /*ok, idea is to generate rays going from the camera origin to the
+ three points on the edge (v1, mid, v2)*/
+ sub_v3_v3v3(dir1, origin, co1);
+ sub_v3_v3v3(dir2, origin, co2);
+ sub_v3_v3v3(dir3, origin, co3);
+
+ normalize_v3(dir1);
+ normalize_v3(dir2);
+ normalize_v3(dir3);
+
+ mul_v3_fl(dir1, epsilon);
+ mul_v3_fl(dir2, epsilon);
+ mul_v3_fl(dir3, epsilon);
+
+ /*offset coordinates slightly along view vectors, to avoid
+ hitting the faces that own the edge.*/
+ add_v3_v3v3(co1, co1, dir1);
+ add_v3_v3v3(co2, co2, dir2);
+ add_v3_v3v3(co3, co3, dir3);
+
+ normalize_v3(dir1);
+ normalize_v3(dir2);
+ normalize_v3(dir3);
+
+ /*do three samplings: left, middle, right*/
+ f = edge_ray_cast(tree, co1, dir1, NULL, e);
+ if (f && !edge_ray_cast(tree, co2, dir2, NULL, e))
+ return 1;
+ else if (f && !edge_ray_cast(tree, co3, dir3, NULL, e))
+ return 1;
+ else if (!f)
+ return 1;
+
+ return 0;
+}
diff --git a/source/blender/editors/mesh/editbmesh_bvh.h b/source/blender/editors/mesh/editbmesh_bvh.h
new file mode 100644
index 00000000000..a3ad9c7dcca
--- /dev/null
+++ b/source/blender/editors/mesh/editbmesh_bvh.h
@@ -0,0 +1,38 @@
+#ifndef _EDITBMESH_BVH
+#define _EDITBMESH_BVH
+
+struct BMEditMesh;
+struct BMFace;
+struct BMEdge;
+struct BMVert;
+struct RegionView3D;
+struct BMBVHTree;
+struct BVHTree;
+struct Scene;
+struct Object;
+
+#ifndef IN_EDITMESHBVH
+typedef struct BMBVHTree BMBVHTree;
+#endif
+
+struct BMBVHTree *BMBVH_NewBVH(struct BMEditMesh *em, int flag, struct Scene *scene, struct Object *obedit);
+void BMBVH_FreeBVH(struct BMBVHTree *tree);
+struct BVHTree *BMBVH_BVHTree(struct BMBVHTree *tree);
+
+struct BMFace *BMBVH_RayCast(struct BMBVHTree *tree, float *co, float *dir, float *hitout, float *cagehit);
+
+int BMBVH_EdgeVisible(struct BMBVHTree *tree, struct BMEdge *e,
+ struct ARegion *ar, struct View3D *v3d, struct Object *obedit);
+
+#define BM_SEARCH_MAXDIST 0.4f
+
+/*find a vert closest to co in a sphere of radius maxdist*/
+struct BMVert *BMBVH_FindClosestVert(struct BMBVHTree *tree, float *co, float maxdist);
+struct BMVert *BMBVH_FindClosestVertTopo(struct BMBVHTree *tree, float *co,
+ float maxdist, struct BMVert *sourcev);
+
+/*BMBVH_NewBVH flag parameter*/
+#define BMBVH_USE_CAGE 1 /*project geometry onto modifier cage */
+#define BMBVH_RETURN_ORIG 2 /*use with BMBVH_USE_CAGE, returns hits in relation to original geometry*/
+
+#endif /* _EDITBMESH_H */
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 279657e71c2..7eb9c15ed0a 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -13,7 +13,7 @@
*
* 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.
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
@@ -34,12 +34,11 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_heap.h"
#include "BLI_edgehash.h"
#include "BLI_editVert.h"
-#include "BLI_utildefines.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -52,6 +51,7 @@
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_context.h"
+#include "BKE_tessmesh.h"
#include "BIF_gl.h"
@@ -67,44 +67,73 @@
/* 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)
{
- Mesh *me= get_mesh(ob);
- DerivedMesh *dm= ob->derivedFinal;
- MFace *faces, *mf, *mf_orig;
+ Mesh *me = get_mesh(ob);
+ DerivedMesh *dm = ob->derivedFinal;
+ MPoly *polys, *mp_orig;
+ MFace *faces, *mf;
int *index_array = NULL;
- int totface;
+ int totface, totpoly;
int i;
- if(me==NULL || dm==NULL)
+ if (me==NULL || dm==NULL) {
return;
+ }
- index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ /*
+ * Try to push updated mesh poly flags to two other data sets:
+ * - Mesh polys => Mesh tess faces
+ * - Mesh polys => Final derived mesh polys
+ */
- if(!index_array)
- return;
-
- faces = dm->getFaceArray(dm);
- totface = dm->getNumFaces(dm);
-
- mf= faces;
-
- for (i= 0; i<totface; i++, mf++) { /* loop over derived mesh faces */
- mf_orig= me->mface + index_array[i];
- mf->flag= mf_orig->flag;
+ if ((index_array = CustomData_get_layer(&me->fdata, CD_ORIGINDEX))) {
+ faces = me->mface;
+ totface = me->totface;
+
+ /* loop over tessfaces */
+ for (i= 0; i<totface; i++) {
+ /* Copy flags onto the tessface from its poly */
+ mp_orig = me->mpoly + index_array[i];
+ faces[i].flag = mp_orig->flag;
+ }
+ }
+
+ if ((index_array = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX))) {
+ polys = dm->getPolyArray(dm);
+ totpoly = dm->getNumFaces(dm);
+
+ /* loop over final derived polys */
+ for (i= 0; i<totpoly; i++) {
+ /* Copy flags onto the mesh poly from its final derived poly */
+ mp_orig = me->mpoly + index_array[i];
+ polys[i].flag = mp_orig->flag;
+ }
}
}
/* returns 0 if not found, otherwise 1 */
-static int facesel_face_pick(struct bContext *C, Mesh *me, const int mval[2], unsigned int *index, short rect)
+static int facesel_face_pick(struct bContext *C, Mesh *me, Object *ob, const int mval[2], unsigned int *index, short rect)
{
+ Scene *scene = CTX_data_scene(C);
ViewContext vc;
view3d_set_viewcontext(C, &vc);
- if (!me || me->totface==0)
+ if (!me || me->totpoly==0)
return 0;
-// XXX if (v3d->flag & V3D_INVALID_BACKBUF) {
+ /*we can't assume mfaces have a correct origindex layer that indices to mpolys.
+ so instead we have to regenerate the tesselation faces altogether.
+
+ the final 0, 0 paramters causes it to use the index of each mpoly, instead
+ of reading from the origindex layer.*/
+ me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata,
+ me->mvert, me->totface, me->totloop, me->totpoly, 0, 0);
+ mesh_update_customdata_pointers(me);
+ makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH, 0);
+
+ // XXX if (v3d->flag & V3D_INVALID_BACKBUF) {
// XXX drawview.c! check_backbuf();
// XXX persp(PERSP_VIEW);
// XXX }
@@ -121,7 +150,7 @@ static int facesel_face_pick(struct bContext *C, Mesh *me, const int mval[2], un
*index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
}
- if ((*index)<=0 || (*index)>(unsigned int)me->totface)
+ if ((*index)<=0 || (*index)>(unsigned int)me->totpoly)
return 0;
(*index)--;
@@ -131,41 +160,35 @@ static int facesel_face_pick(struct bContext *C, Mesh *me, const int mval[2], un
/* last_sel, use em->act_face otherwise get the last selected face in the editselections
* at the moment, last_sel is mainly useful for gaking sure the space image dosnt flicker */
-MTFace *EM_get_active_mtface(EditMesh *em, EditFace **act_efa, MCol **mcol, int sloppy)
+static MTexPoly *EDBM_get_active_mtface(BMEditMesh *em, BMFace **act_efa, int sloppy)
{
- EditFace *efa = NULL;
+ BMFace *efa = NULL;
- if(!EM_texFaceCheck(em))
+ if(!EDBM_texFaceCheck(em))
return NULL;
- efa = EM_get_actFace(em, sloppy);
+ efa = BM_get_actFace(em->bm, sloppy);
if (efa) {
- if (mcol) {
- if (CustomData_has_layer(&em->fdata, CD_MCOL))
- *mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
- else
- *mcol = NULL;
- }
if (act_efa) *act_efa = efa;
- return CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ return CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
}
+
if (act_efa) *act_efa= NULL;
- if(mcol) *mcol = NULL;
return NULL;
}
void paintface_hide(Object *ob, const int unselected)
{
Mesh *me;
- MFace *mface;
+ MPoly *mface;
int a;
me= get_mesh(ob);
- if(me==NULL || me->totface==0) return;
+ if(me==NULL || me->totpoly==0) return;
- mface= me->mface;
- a= me->totface;
+ mface= me->mpoly;
+ a= me->totpoly;
while(a--) {
if((mface->flag & ME_HIDE) == 0) {
if(unselected) {
@@ -187,14 +210,14 @@ void paintface_hide(Object *ob, const int unselected)
void paintface_reveal(Object *ob)
{
Mesh *me;
- MFace *mface;
+ MPoly *mface;
int a;
me= get_mesh(ob);
- if(me==NULL || me->totface==0) return;
+ if(me==NULL || me->totpoly==0) return;
- mface= me->mface;
- a= me->totface;
+ mface= me->mpoly;
+ a= me->totpoly;
while(a--) {
if(mface->flag & ME_HIDE) {
mface->flag |= ME_FACE_SEL;
@@ -208,30 +231,30 @@ void paintface_reveal(Object *ob)
/* Set tface seams based on edge data, uses hash table to find seam edges. */
-static void hash_add_face(EdgeHash *ehash, MFace *mf)
+static void hash_add_face(EdgeHash *ehash, MPoly *mf, MLoop *mloop)
{
- BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL);
- BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL);
- if(mf->v4) {
- BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL);
- BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL);
+ MLoop *ml, *ml2;
+ int i;
+
+ for (i=0, ml=mloop; i<mf->totloop; i++, ml++) {
+ ml2 = mloop + (i+1) % mf->totloop;
+ BLI_edgehash_insert(ehash, ml->v, ml2->v, NULL);
}
- else
- BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL);
}
static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index)
{
- MFace *mf;
- int a, doit=1, mark=0;
- char *linkflag;
EdgeHash *ehash, *seamhash;
+ MPoly *mf;
+ MLoop *ml;
MEdge *med;
+ char *linkflag;
+ int a, b, doit=1, mark=0;
ehash= BLI_edgehash_new();
seamhash = BLI_edgehash_new();
- linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv");
+ linkflag= MEM_callocN(sizeof(char)*me->totpoly, "linkflaguv");
for(med=me->medge, a=0; a < me->totedge; a++, med++)
if(med->flag & ME_SEAM)
@@ -239,17 +262,17 @@ static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int ind
if (mode==0 || mode==1) {
/* only put face under cursor in array */
- mf= ((MFace*)me->mface) + index;
- hash_add_face(ehash, mf);
+ mf= ((MPoly*)me->mpoly) + index;
+ hash_add_face(ehash, mf, me->mloop + mf->loopstart);
linkflag[index]= 1;
}
else {
/* fill array by selection */
- mf= me->mface;
- for(a=0; a<me->totface; a++, mf++) {
+ mf= me->mpoly;
+ for(a=0; a<me->totpoly; a++, mf++) {
if(mf->flag & ME_HIDE);
else if(mf->flag & ME_FACE_SEL) {
- hash_add_face(ehash, mf);
+ hash_add_face(ehash, mf, me->mloop + mf->loopstart);
linkflag[a]= 1;
}
}
@@ -259,35 +282,26 @@ static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int ind
doit= 0;
/* expand selection */
- mf= me->mface;
- for(a=0; a<me->totface; a++, mf++) {
+ mf= me->mpoly;
+ for(a=0; a<me->totpoly; a++, mf++) {
if(mf->flag & ME_HIDE)
continue;
if(!linkflag[a]) {
+ MLoop *mnextl;
mark= 0;
- if(!BLI_edgehash_haskey(seamhash, mf->v1, mf->v2))
- if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2))
- mark= 1;
- if(!BLI_edgehash_haskey(seamhash, mf->v2, mf->v3))
- if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3))
- mark= 1;
- if(mf->v4) {
- if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v4))
- if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4))
- mark= 1;
- if(!BLI_edgehash_haskey(seamhash, mf->v4, mf->v1))
- if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1))
- mark= 1;
+ ml = me->mloop + mf->loopstart;
+ for (b=0; b<mf->totloop; b++, ml++) {
+ mnextl = b < mf->totloop-1 ? ml - 1 : me->mloop + mf->loopstart;
+ if (!BLI_edgehash_haskey(seamhash, ml->v, mnextl->v))
+ if (!BLI_edgehash_haskey(ehash, ml->v, mnextl->v))
+ mark = 1;
}
- else if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v1))
- if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1))
- mark = 1;
if(mark) {
linkflag[a]= 1;
- hash_add_face(ehash, mf);
+ hash_add_face(ehash, mf, me->mloop + mf->loopstart);
doit= 1;
}
}
@@ -299,24 +313,24 @@ static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int ind
BLI_edgehash_free(seamhash, NULL);
if(mode==0 || mode==2) {
- for(a=0, mf=me->mface; a<me->totface; a++, mf++)
+ for(a=0, mf=me->mpoly; a<me->totpoly; a++, mf++)
if(linkflag[a])
mf->flag |= ME_FACE_SEL;
else
mf->flag &= ~ME_FACE_SEL;
}
else if(mode==1) {
- for(a=0, mf=me->mface; a<me->totface; a++, mf++)
+ for(a=0, mf=me->mpoly; a<me->totpoly; a++, mf++)
if(linkflag[a] && (mf->flag & ME_FACE_SEL))
break;
- if (a<me->totface) {
- for(a=0, mf=me->mface; a<me->totface; a++, mf++)
+ if (a<me->totpoly) {
+ for(a=0, mf=me->mpoly; a<me->totpoly; a++, mf++)
if(linkflag[a])
mf->flag &= ~ME_FACE_SEL;
}
else {
- for(a=0, mf=me->mface; a<me->totface; a++, mf++)
+ for(a=0, mf=me->mpoly; a<me->totpoly; a++, mf++)
if(linkflag[a])
mf->flag |= ME_FACE_SEL;
}
@@ -331,7 +345,7 @@ void paintface_select_linked(bContext *UNUSED(C), Object *ob, int UNUSED(mval[2]
unsigned int index=0;
me = get_mesh(ob);
- if(me==NULL || me->totface==0) return;
+ if(me==NULL || me->totpoly==0) return;
if (mode==0 || mode==1) {
// XXX - Causes glitches, not sure why
@@ -347,31 +361,30 @@ void paintface_select_linked(bContext *UNUSED(C), Object *ob, int UNUSED(mval[2]
}
/* note: caller needs to run paintface_flush_flags(ob) after this */
-void paintface_deselect_all_visible(Object *ob, int action, short flush_flags)
+void paintface_deselect_all_visible(Object *ob, int action, short UNUSED(flush_flags))
{
Mesh *me;
- MFace *mface;
+ MPoly *mface;
int a;
me= get_mesh(ob);
if(me==NULL) return;
if(action == SEL_INVERT) {
- mface= me->mface;
- a= me->totface;
+ mface= me->mpoly;
+ a= me->totpoly;
while(a--) {
if((mface->flag & ME_HIDE) == 0) {
mface->flag ^= ME_FACE_SEL;
}
mface++;
}
- }
- else {
+ } else {
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
- mface= me->mface;
- a= me->totface;
+ mface= me->mpoly;
+ a= me->totpoly;
while(a--) {
if((mface->flag & ME_HIDE) == 0 && mface->flag & ME_FACE_SEL) {
action = SEL_DESELECT;
@@ -380,292 +393,93 @@ void paintface_deselect_all_visible(Object *ob, int action, short flush_flags)
mface++;
}
}
-
- mface= me->mface;
- a= me->totface;
- while(a--) {
- if((mface->flag & ME_HIDE) == 0) {
- switch (action) {
- case SEL_SELECT:
- mface->flag |= ME_FACE_SEL;
- break;
- case SEL_DESELECT:
- mface->flag &= ~ME_FACE_SEL;
- break;
- case SEL_INVERT:
- mface->flag ^= ME_FACE_SEL;
- break;
- }
- }
- mface++;
- }
}
- if(flush_flags) {
- paintface_flush_flags(ob);
- }
+ //BMESH_TODO object_facesel_flush_dm(ob);
+// XXX notifier! object_tface_flags_changed(OBACT, 0);
}
-int paintface_minmax(Object *ob, float *min, float *max)
-{
- Mesh *me= get_mesh(ob);
- MFace *mf;
- MVert *mv;
- int a, ok=0;
- float vec[3];
-
- if(me==NULL)
- return ok;
-
- mv= me->mvert;
- mf= me->mface;
- for (a=me->totface; a>0; a--, mf++) {
- if ((mf->flag & ME_HIDE || !(mf->flag & ME_FACE_SEL)) == 0) {
- int i= mf->v4 ? 3:2;
- do {
- mul_v3_m4v3(vec, ob->obmat, (mv + (*(&mf->v1 + i)))->co);
- DO_MINMAX(vec, min, max);
- } while (i--);
- ok= 1;
- }
- }
- return ok;
-}
-
-/* ******************** edge loop shortest path ********************* */
-
-#define ME_SEAM_DONE 2 /* reuse this flag */
-
-static float edgetag_cut_cost(int e1, int e2, int vert)
-{
- EditVert *v = EM_get_vert_for_index(vert);
- EditEdge *eed1 = EM_get_edge_for_index(e1), *eed2 = EM_get_edge_for_index(e2);
- EditVert *v1 = EM_get_vert_for_index( (eed1->v1->tmp.l == vert)? eed1->v2->tmp.l: eed1->v1->tmp.l );
- EditVert *v2 = EM_get_vert_for_index( (eed2->v1->tmp.l == vert)? eed2->v2->tmp.l: eed2->v1->tmp.l );
- float cost, d1[3], d2[3];
-
- cost = len_v3v3(v1->co, v->co);
- cost += len_v3v3(v->co, v2->co);
-
- sub_v3_v3v3(d1, v->co, v1->co);
- sub_v3_v3v3(d2, v2->co, v->co);
-
- cost = cost + 0.5f*cost*(2.0f - fabsf(d1[0]*d2[0] + d1[1]*d2[1] + d1[2]*d2[2]));
-
- return cost;
-}
-
-static void edgetag_add_adjacent(Heap *heap, int mednum, int vertnum, int *nedges, int *edges, int *prevedge, float *cost)
-{
- int startadj, endadj = nedges[vertnum+1];
-
- for (startadj = nedges[vertnum]; startadj < endadj; startadj++) {
- int adjnum = edges[startadj];
- EditEdge *eedadj = EM_get_edge_for_index(adjnum);
- float newcost;
-
- if (eedadj->f2 & ME_SEAM_DONE)
- continue;
-
- newcost = cost[mednum] + edgetag_cut_cost(mednum, adjnum, vertnum);
-
- if (cost[adjnum] > newcost) {
- cost[adjnum] = newcost;
- prevedge[adjnum] = mednum;
- BLI_heap_insert(heap, newcost, SET_INT_IN_POINTER(adjnum));
- }
- }
-}
-
-void edgetag_context_set(Scene *scene, EditEdge *eed, int val)
+static void selectswap_tface(Scene *scene)
{
+ Mesh *me;
+ MPoly *mface;
+ int a;
+
+ me= get_mesh(OBACT);
+ if(me==0) return;
- switch (scene->toolsettings->edge_mode) {
- case EDGE_MODE_SELECT:
- EM_select_edge(eed, val);
- break;
- case EDGE_MODE_TAG_SEAM:
- if (val) {eed->seam = 255;}
- else {eed->seam = 0;}
- break;
- case EDGE_MODE_TAG_SHARP:
- if (val) {eed->sharp = 1;}
- else {eed->sharp = 0;}
- break;
- case EDGE_MODE_TAG_CREASE:
- if (val) {eed->crease = 1.0f;}
- else {eed->crease = 0.0f;}
- break;
- case EDGE_MODE_TAG_BEVEL:
- if (val) {eed->bweight = 1.0f;}
- else {eed->bweight = 0.0f;}
- break;
+ mface= me->mpoly;
+ a= me->totpoly;
+ while(a--) {
+ if(mface->flag & ME_HIDE);
+ else {
+ if(mface->flag & ME_FACE_SEL) mface->flag &= ~ME_FACE_SEL;
+ else mface->flag |= ME_FACE_SEL;
+ }
}
}
-int edgetag_context_check(Scene *scene, EditEdge *eed)
+int paintface_minmax(Object *ob, float *min, float *max)
{
- switch (scene->toolsettings->edge_mode) {
- case EDGE_MODE_SELECT:
- return (eed->f & SELECT) ? 1 : 0;
- case EDGE_MODE_TAG_SEAM:
- return eed->seam ? 1 : 0;
- case EDGE_MODE_TAG_SHARP:
- return eed->sharp ? 1 : 0;
- case EDGE_MODE_TAG_CREASE:
- return eed->crease ? 1 : 0;
- case EDGE_MODE_TAG_BEVEL:
- return eed->bweight ? 1 : 0;
- }
- return 0;
-}
-
+ Mesh *me;
+ MPoly *mf;
+ MTexPoly *tf;
+ MLoop *ml;
+ MVert *mv;
+ int a, b, ok=0;
+ float vec[3], bmat[3][3];
-int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge *target)
-{
- EditEdge *eed;
- EditVert *ev;
+ me= get_mesh(ob);
+ if(!me || !me->mtpoly) return ok;
- Heap *heap;
- float *cost;
- int a, totvert=0, totedge=0, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0;
-
-
- /* we need the vert */
- for (ev= em->verts.first, totvert=0; ev; ev= ev->next) {
- ev->tmp.l = totvert;
- totvert++;
- }
-
- for (eed= em->edges.first; eed; eed = eed->next) {
- eed->f2 = 0;
- if (eed->h) {
- eed->f2 |= ME_SEAM_DONE;
- }
- eed->tmp.l = totedge;
- totedge++;
- }
-
- /* alloc */
- nedges = MEM_callocN(sizeof(*nedges)*totvert+1, "SeamPathNEdges");
- edges = MEM_mallocN(sizeof(*edges)*totedge*2, "SeamPathEdges");
- prevedge = MEM_mallocN(sizeof(*prevedge)*totedge, "SeamPathPrevious");
- cost = MEM_mallocN(sizeof(*cost)*totedge, "SeamPathCost");
-
- /* count edges, compute adjacent edges offsets and fill adjacent edges */
- for (eed= em->edges.first; eed; eed = eed->next) {
- nedges[eed->v1->tmp.l+1]++;
- nedges[eed->v2->tmp.l+1]++;
- }
-
- for (a=1; a<totvert; a++) {
- int newswap = nedges[a+1];
- nedges[a+1] = nedgeswap + nedges[a];
- nedgeswap = newswap;
- }
- nedges[0] = nedges[1] = 0;
+ copy_m3_m4(bmat, ob->obmat);
- for (a=0, eed= em->edges.first; eed; a++, eed = eed->next) {
- edges[nedges[eed->v1->tmp.l+1]++] = a;
- edges[nedges[eed->v2->tmp.l+1]++] = a;
-
- cost[a] = 1e20f;
- prevedge[a] = -1;
- }
-
- /* regular dijkstra shortest path, but over edges instead of vertices */
- heap = BLI_heap_new();
- BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(source->tmp.l));
- cost[source->tmp.l] = 0.0f;
-
- EM_init_index_arrays(em, 1, 1, 0);
-
-
- while (!BLI_heap_empty(heap)) {
- mednum = GET_INT_FROM_POINTER(BLI_heap_popmin(heap));
- eed = EM_get_edge_for_index( mednum );
-
- if (mednum == target->tmp.l)
- break;
-
- if (eed->f2 & ME_SEAM_DONE)
+ mv= me->mvert;
+ mf= me->mpoly;
+ tf= me->mtpoly;
+ for (a=me->totpoly; a>0; a--, mf++, tf++) {
+ if (mf->flag & ME_HIDE || !(mf->flag & ME_FACE_SEL))
continue;
- eed->f2 |= ME_SEAM_DONE;
-
- edgetag_add_adjacent(heap, mednum, eed->v1->tmp.l, nedges, edges, prevedge, cost);
- edgetag_add_adjacent(heap, mednum, eed->v2->tmp.l, nedges, edges, prevedge, cost);
- }
-
-
- MEM_freeN(nedges);
- MEM_freeN(edges);
- MEM_freeN(cost);
- BLI_heap_free(heap, NULL);
-
- for (eed= em->edges.first; eed; eed = eed->next) {
- eed->f2 &= ~ME_SEAM_DONE;
- }
-
- if (mednum != target->tmp.l) {
- MEM_freeN(prevedge);
- EM_free_index_arrays();
- return 0;
- }
-
- /* follow path back to source and mark as seam */
- if (mednum == target->tmp.l) {
- short allseams = 1;
+ ml = me->mloop + mf->totloop;
+ for (b=0; b<mf->totloop; b++, ml++) {
+ VECCOPY(vec, (mv+ml->v)->co);
+ mul_m3_v3(bmat, vec);
+ add_v3_v3v3(vec, vec, ob->obmat[3]);
+ DO_MINMAX(vec, min, max);
+ }
- mednum = target->tmp.l;
- do {
- eed = EM_get_edge_for_index( mednum );
- if (!edgetag_context_check(scene, eed)) {
- allseams = 0;
- break;
- }
- mednum = prevedge[mednum];
- } while (mednum != source->tmp.l);
-
- mednum = target->tmp.l;
- do {
- eed = EM_get_edge_for_index( mednum );
- if (allseams)
- edgetag_context_set(scene, eed, 0);
- else
- edgetag_context_set(scene, eed, 1);
- mednum = prevedge[mednum];
- } while (mednum != -1);
+ ok= 1;
}
- MEM_freeN(prevedge);
- EM_free_index_arrays();
- return 1;
+ return ok;
}
/* *************************************** */
#if 0
-static void seam_edgehash_insert_face(EdgeHash *ehash, MFace *mf)
+static void seam_edgehash_insert_face(EdgeHash *ehash, MPoly *mf, MLoop *loopstart)
{
- BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL);
- BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL);
- if (mf->v4) {
- BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL);
- BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL);
+ MLoop *ml1, *ml2;
+ int a;
+
+ for (a=0; a<mf->totloop; a++) {
+ ml1 = loopstart + a;
+ ml2 = loopstart + (a+1) % mf->totloop;
+
+ BLI_edgehash_insert(ehash, ml1->v, ml2->v, NULL);
}
- else
- BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL);
}
void seam_mark_clear_tface(Scene *scene, short mode)
{
Mesh *me;
- MFace *mf;
+ MPoly *mf;
+ MLoop *ml1, *ml2;
MEdge *med;
- int a;
+ int a, b;
me= get_mesh(OBACT);
- if(me==0 || me->totface==0) return;
+ if(me==0 || me->totpoly==0) return;
if (mode == 0)
mode = pupmenu("Seams%t|Mark Border Seam %x1|Clear Seam %x2");
@@ -676,9 +490,9 @@ void seam_mark_clear_tface(Scene *scene, short mode)
if (mode == 2) {
EdgeHash *ehash = BLI_edgehash_new();
- for (a=0, mf=me->mface; a<me->totface; a++, mf++)
+ for (a=0, mf=me->mpoly; a<me->totpoly; a++, mf++)
if (!(mf->flag & ME_HIDE) && (mf->flag & ME_FACE_SEL))
- seam_edgehash_insert_face(ehash, mf);
+ seam_edgehash_insert_face(ehash, mf, me->mloop + mf->loopstart);
for (a=0, med=me->medge; a<me->totedge; a++, med++)
if (BLI_edgehash_haskey(ehash, med->v1, med->v2))
@@ -691,11 +505,11 @@ void seam_mark_clear_tface(Scene *scene, short mode)
EdgeHash *ehash1 = BLI_edgehash_new();
EdgeHash *ehash2 = BLI_edgehash_new();
- for (a=0, mf=me->mface; a<me->totface; a++, mf++) {
+ for (a=0, mf=me->mpoly; a<me->totpoly; a++, mf++) {
if ((mf->flag & ME_HIDE) || !(mf->flag & ME_FACE_SEL))
- seam_edgehash_insert_face(ehash1, mf);
+ seam_edgehash_insert_face(ehash1, mf, me->mloop + mf->loopstart);
else
- seam_edgehash_insert_face(ehash2, mf);
+ seam_edgehash_insert_face(ehash2, mf, me->mloop + mf->loopstart);
}
for (a=0, med=me->medge; a<me->totedge; a++, med++)
@@ -717,21 +531,24 @@ void seam_mark_clear_tface(Scene *scene, short mode)
int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], int extend)
{
Mesh *me;
- MFace *mface, *msel;
+ MPoly *mface, *msel;
unsigned int a, index;
/* Get the face under the cursor */
me = get_mesh(ob);
- if (!facesel_face_pick(C, me, mval, &index, 1))
+ if (!facesel_face_pick(C, me, ob, mval, &index, 1))
return 0;
- msel= (((MFace*)me->mface)+index);
+ if (index >= me->totpoly || index < 0)
+ return 0;
+
+ msel= me->mpoly + index;
if (msel->flag & ME_HIDE) return 0;
/* clear flags */
- mface = me->mface;
- a = me->totface;
+ mface = me->mpoly;
+ a = me->totpoly;
if (!extend) {
while (a--) {
mface->flag &= ~ME_FACE_SEL;
@@ -759,25 +576,36 @@ int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], in
int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend)
{
+ Object *ob = vc->obact;
Mesh *me;
- MFace *mface;
+ MPoly *mface;
struct ImBuf *ibuf;
unsigned int *rt;
- int a, index;
char *selar;
+ int a, index;
int sx= rect->xmax-rect->xmin+1;
int sy= rect->ymax-rect->ymin+1;
-
- me= get_mesh(vc->obact);
+
+ me= get_mesh(ob);
+ if(me==0) return 0;
+ if(me->totpoly==0) return 0;
if(me==NULL || me->totface==0 || sx*sy <= 0)
return OPERATOR_CANCELLED;
- selar= MEM_callocN(me->totface+1, "selar");
+ selar= MEM_callocN(me->totpoly+1, "selar");
if (extend == 0 && select)
paintface_deselect_all_visible(vc->obact, SEL_DESELECT, FALSE);
+ if (extend == 0 && select) {
+ mface= me->mpoly;
+ for(a=1; a<=me->totpoly; a++, mface++) {
+ if((mface->flag & ME_HIDE) == 0)
+ mface->flag &= ~ME_FACE_SEL;
+ }
+ }
+
view3d_validate_backbuf(vc);
ibuf = IMB_allocImBuf(sx,sy,32,IB_rect);
@@ -794,8 +622,8 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend)
rt++;
}
- mface= me->mface;
- for(a=1; a<=me->totface; a++, mface++) {
+ mface= me->mpoly;
+ for(a=1; a<=me->totpoly; a++, mface++) {
if(selar[a]) {
if(mface->flag & ME_HIDE);
else {
@@ -816,3 +644,101 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend)
return OPERATOR_FINISHED;
}
+
+
+/* (similar to void paintface_flush_flags(Object *ob))
+ * copy the vertex flags, most importantly selection from the mesh to the final derived mesh,
+ * use in object mode when selecting vertices (while painting) */
+void paintvert_flush_flags(Object *ob)
+{
+ Mesh *me= get_mesh(ob);
+ DerivedMesh *dm= ob->derivedFinal;
+ MVert *dm_mvert, *dm_mv;
+ int *index_array = NULL;
+ int totvert;
+ int i;
+
+ if(me==NULL || dm==NULL)
+ return;
+
+ index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
+
+ dm_mvert = dm->getVertArray(dm);
+ totvert = dm->getNumVerts(dm);
+
+ dm_mv= dm_mvert;
+
+ if(index_array) {
+ int orig_index;
+ for (i= 0; i<totvert; i++, dm_mv++) {
+ orig_index= index_array[i];
+ if(orig_index != ORIGINDEX_NONE) {
+ dm_mv->flag= me->mvert[index_array[i]].flag;
+ }
+ }
+ }
+ else {
+ for (i= 0; i<totvert; i++, dm_mv++) {
+ dm_mv->flag= me->mvert[i].flag;
+ }
+ }
+}
+/* note: if the caller passes FALSE to flush_flags, then they will need to run paintvert_flush_flags(ob) themselves */
+void paintvert_deselect_all_visible(Object *ob, int action, short flush_flags)
+{
+ Mesh *me;
+ MVert *mvert;
+ int a;
+
+ me= get_mesh(ob);
+ if(me==NULL) return;
+
+ if(action == SEL_INVERT) {
+ mvert= me->mvert;
+ a= me->totvert;
+ while(a--) {
+ if((mvert->flag & ME_HIDE) == 0) {
+ mvert->flag ^= SELECT;
+ }
+ mvert++;
+ }
+ }
+ else {
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+
+ mvert= me->mvert;
+ a= me->totvert;
+ while(a--) {
+ if((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) {
+ action = SEL_DESELECT;
+ break;
+ }
+ mvert++;
+ }
+ }
+
+ mvert= me->mvert;
+ a= me->totvert;
+ while(a--) {
+ if((mvert->flag & ME_HIDE) == 0) {
+ switch (action) {
+ case SEL_SELECT:
+ mvert->flag |= SELECT;
+ break;
+ case SEL_DESELECT:
+ mvert->flag &= ~SELECT;
+ break;
+ case SEL_INVERT:
+ mvert->flag ^= SELECT;
+ break;
+ }
+ }
+ mvert++;
+ }
+ }
+
+ if(flush_flags) {
+ paintvert_flush_flags(ob);
+ }
+}
diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c
deleted file mode 100644
index 85ac87d8bcb..00000000000
--- a/source/blender/editors/mesh/editmesh.c
+++ /dev/null
@@ -1,2056 +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.
- *
- * Contributor(s): Blender Foundation, full recode 2002-2008
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/mesh/editmesh.c
- * \ingroup edmesh
- */
-
-
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
-#include "DNA_key_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_editVert.h"
-#include "BLI_dynstr.h"
-#include "BLI_rand.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_DerivedMesh.h"
-#include "BKE_context.h"
-#include "BKE_depsgraph.h"
-#include "BKE_global.h"
-#include "BKE_key.h"
-#include "BKE_main.h"
-#include "BKE_material.h"
-#include "BKE_mesh.h"
-#include "BKE_paint.h"
-#include "BKE_report.h"
-#include "BKE_multires.h"
-
-#include "ED_mesh.h"
-#include "ED_object.h"
-#include "ED_screen.h"
-#include "ED_util.h"
-#include "ED_view3d.h"
-
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-/* own include */
-#include "mesh_intern.h"
-
-/*
-editmesh.c:
- - add/alloc/free data
- - hashtables
- - enter/exit editmode
-*/
-
-/* XXX */
-static void BIF_undo_push(const char *UNUSED(arg)) {}
-static void error(const char *UNUSED(arg)) {}
-
-
-/* ***************** HASH ********************* */
-
-
-#define EDHASHSIZE (512*512)
-#define EDHASH(a, b) (a % EDHASHSIZE)
-
-
-/* ************ ADD / REMOVE / FIND ****************** */
-
-static void *calloc_em(EditMesh *UNUSED(em), size_t size, size_t nr)
-{
- return calloc(size, nr);
-}
-
-/* used to bypass normal calloc with fast one */
-static void *(*callocvert)(EditMesh *, size_t, size_t) = calloc_em;
-static void *(*callocedge)(EditMesh *, size_t, size_t) = calloc_em;
-static void *(*callocface)(EditMesh *, size_t, size_t) = calloc_em;
-
-EditVert *addvertlist(EditMesh *em, float *vec, EditVert *example)
-{
- EditVert *eve;
- static int hashnr= 0;
-
- eve= callocvert(em, sizeof(EditVert), 1);
- BLI_addtail(&em->verts, eve);
- em->totvert++;
-
- if(vec) VECCOPY(eve->co, vec);
-
- eve->hash= hashnr++;
- if( hashnr>=EDHASHSIZE) hashnr= 0;
-
- /* new verts get keyindex of -1 since they did not
- * have a pre-editmode vertex order
- */
- eve->keyindex = -1;
-
- if(example) {
- CustomData_em_copy_data(&em->vdata, &em->vdata, example->data, &eve->data);
- eve->bweight = example->bweight;
- }
- else {
- CustomData_em_set_default(&em->vdata, &eve->data);
- }
-
- return eve;
-}
-
-void free_editvert (EditMesh *em, EditVert *eve)
-{
-
- EM_remove_selection(em, eve, EDITVERT);
- CustomData_em_free_block(&em->vdata, &eve->data);
- if(eve->fast==0)
- free(eve);
-
- em->totvert--;
-}
-
-
-EditEdge *findedgelist(EditMesh *em, EditVert *v1, EditVert *v2)
-{
- EditVert *v3;
- struct HashEdge *he;
-
- /* swap ? */
- if( v1 > v2) {
- v3= v2;
- v2= v1;
- v1= v3;
- }
-
- if(em->hashedgetab==NULL)
- em->hashedgetab= MEM_callocN(EDHASHSIZE*sizeof(struct HashEdge), "hashedgetab");
-
- he= em->hashedgetab + EDHASH(v1->hash, v2->hash);
-
- while(he) {
-
- if(he->eed && he->eed->v1==v1 && he->eed->v2==v2) return he->eed;
-
- he= he->next;
- }
- return 0;
-}
-
-static void insert_hashedge(EditMesh *em, EditEdge *eed)
-{
- /* assuming that eed is not in the list yet, and that a find has been done before */
-
- struct HashEdge *first, *he;
-
- first= em->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
-
- if( first->eed==0 ) {
- first->eed= eed;
- }
- else {
- he= &eed->hash;
- he->eed= eed;
- he->next= first->next;
- first->next= he;
- }
-}
-
-static void remove_hashedge(EditMesh *em, EditEdge *eed)
-{
- /* assuming eed is in the list */
-
- struct HashEdge *first, *he, *prev=NULL;
-
- he=first= em->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
-
- while(he) {
- if(he->eed == eed) {
- /* remove from list */
- if(he==first) {
- if(first->next) {
- he= first->next;
- first->eed= he->eed;
- first->next= he->next;
- }
- else he->eed= 0;
- }
- else {
- prev->next= he->next;
- }
- return;
- }
- prev= he;
- he= he->next;
- }
-}
-
-EditEdge *addedgelist(EditMesh *em, EditVert *v1, EditVert *v2, EditEdge *example)
-{
- EditVert *v3;
- EditEdge *eed;
- int swap= 0;
-
- if(v1==v2) return NULL;
- if(v1==NULL || v2==NULL) return NULL;
-
- /* swap ? */
- if(v1>v2) {
- v3= v2;
- v2= v1;
- v1= v3;
- swap= 1;
- }
-
- /* find in hashlist */
- eed= findedgelist(em, v1, v2);
-
- if(eed==NULL) {
-
- eed= (EditEdge *)callocedge(em, sizeof(EditEdge), 1);
- eed->v1= v1;
- eed->v2= v2;
- BLI_addtail(&em->edges, eed);
- eed->dir= swap;
- insert_hashedge(em, eed);
- em->totedge++;
-
- /* copy edge data:
- rule is to do this with addedgelist call, before addfacelist */
- if(example) {
- eed->crease= example->crease;
- eed->bweight= example->bweight;
- eed->sharp = example->sharp;
- eed->seam = example->seam;
- eed->h |= (example->h & EM_FGON);
- }
- }
-
- return eed;
-}
-
-void remedge(EditMesh *em, EditEdge *eed)
-{
- BLI_remlink(&em->edges, eed);
- remove_hashedge(em, eed);
-
- em->totedge--;
-}
-
-void free_editedge(EditMesh *em, EditEdge *eed)
-{
- EM_remove_selection(em, eed, EDITEDGE);
- if(eed->fast==0){
- free(eed);
- }
-}
-
-void free_editface(EditMesh *em, EditFace *efa)
-{
- EM_remove_selection(em, efa, EDITFACE);
-
- if (em->act_face==efa) {
- EM_set_actFace(em, em->faces.first == efa ? NULL : em->faces.first);
- }
-
- CustomData_em_free_block(&em->fdata, &efa->data);
- if(efa->fast==0)
- free(efa);
-
- em->totface--;
-}
-
-void free_vertlist(EditMesh *em, ListBase *edve)
-{
- EditVert *eve, *next;
-
- if (!edve) return;
-
- eve= edve->first;
- while(eve) {
- next= eve->next;
- free_editvert(em, eve);
- eve= next;
- }
- edve->first= edve->last= NULL;
- em->totvert= em->totvertsel= 0;
-}
-
-void free_edgelist(EditMesh *em, ListBase *lb)
-{
- EditEdge *eed, *next;
-
- eed= lb->first;
- while(eed) {
- next= eed->next;
- free_editedge(em, eed);
- eed= next;
- }
- lb->first= lb->last= NULL;
- em->totedge= em->totedgesel= 0;
-}
-
-void free_facelist(EditMesh *em, ListBase *lb)
-{
- EditFace *efa, *next;
-
- efa= lb->first;
- while(efa) {
- next= efa->next;
- free_editface(em, efa);
- efa= next;
- }
- lb->first= lb->last= NULL;
- em->totface= em->totfacesel= 0;
-}
-
-EditFace *addfacelist(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, EditFace *example, EditFace *exampleEdges)
-{
- EditFace *efa;
- EditEdge *e1, *e2=0, *e3=0, *e4=0;
-
- /* added sanity check... seems to happen for some tools, or for enter editmode for corrupted meshes */
- if(v1==v4 || v2==v4 || v3==v4) v4= NULL;
-
- /* add face to list and do the edges */
- if(exampleEdges) {
- e1= addedgelist(em, v1, v2, exampleEdges->e1);
- e2= addedgelist(em, v2, v3, exampleEdges->e2);
- if(v4) e3= addedgelist(em, v3, v4, exampleEdges->e3);
- else e3= addedgelist(em, v3, v1, exampleEdges->e3);
- if(v4) e4= addedgelist(em, v4, v1, exampleEdges->e4);
- }
- else {
- e1= addedgelist(em, v1, v2, NULL);
- e2= addedgelist(em, v2, v3, NULL);
- if(v4) e3= addedgelist(em, v3, v4, NULL);
- else e3= addedgelist(em, v3, v1, NULL);
- if(v4) e4= addedgelist(em, v4, v1, NULL);
- }
-
- if(v1==v2 || v2==v3 || v1==v3) return NULL;
- if(e2==0) return NULL;
-
- efa= (EditFace *)callocface(em, sizeof(EditFace), 1);
- efa->v1= v1;
- efa->v2= v2;
- efa->v3= v3;
- efa->v4= v4;
-
- efa->e1= e1;
- efa->e2= e2;
- efa->e3= e3;
- efa->e4= e4;
-
- if(example) {
- efa->mat_nr= example->mat_nr;
- efa->flag= example->flag;
- CustomData_em_copy_data(&em->fdata, &em->fdata, example->data, &efa->data);
- CustomData_em_validate_data(&em->fdata, efa->data, efa->v4 ? 4 : 3);
- }
- else {
- efa->mat_nr= em->mat_nr;
-
- CustomData_em_set_default(&em->fdata, &efa->data);
- }
-
- BLI_addtail(&em->faces, efa);
- em->totface++;
-
- if(efa->v4) {
- normal_quad_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
- cent_quad_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
- }
- else {
- normal_tri_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co);
- cent_tri_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co);
- }
-
- return efa;
-}
-
-/* ************************ end add/new/find ************ */
-
-/* ************************ Edit{Vert,Edge,Face} utilss ***************************** */
-
-/* some nice utility functions */
-
-EditVert *editedge_getOtherVert(EditEdge *eed, EditVert *eve)
-{
- if (eve==eed->v1) {
- return eed->v2;
- } else if (eve==eed->v2) {
- return eed->v1;
- } else {
- return NULL;
- }
-}
-
-EditVert *editedge_getSharedVert(EditEdge *eed, EditEdge *eed2)
-{
- if (eed->v1==eed2->v1 || eed->v1==eed2->v2) {
- return eed->v1;
- } else if (eed->v2==eed2->v1 || eed->v2==eed2->v2) {
- return eed->v2;
- } else {
- return NULL;
- }
-}
-
-int editedge_containsVert(EditEdge *eed, EditVert *eve)
-{
- return (eed->v1==eve || eed->v2==eve);
-}
-
-int editface_containsVert(EditFace *efa, EditVert *eve)
-{
- return (efa->v1==eve || efa->v2==eve || efa->v3==eve || (efa->v4 && efa->v4==eve));
-}
-
-int editface_containsEdge(EditFace *efa, EditEdge *eed)
-{
- return (efa->e1==eed || efa->e2==eed || efa->e3==eed || (efa->e4 && efa->e4==eed));
-}
-
-
-/* ************************ stuct EditMesh manipulation ***************************** */
-
-/* fake callocs for fastmalloc below */
-static void *calloc_fastvert(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr))
-{
- EditVert *eve= em->curvert++;
- eve->fast= 1;
- return eve;
-}
-static void *calloc_fastedge(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr))
-{
- EditEdge *eed= em->curedge++;
- eed->fast= 1;
- return eed;
-}
-static void *calloc_fastface(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr))
-{
- EditFace *efa= em->curface++;
- efa->fast= 1;
- return efa;
-}
-
-/* allocate 1 chunk for all vertices, edges, faces. These get tagged to
- prevent it from being freed
-*/
-static void init_editmesh_fastmalloc(EditMesh *em, int totvert, int totedge, int totface)
-{
- if(totvert) em->allverts= MEM_callocN(totvert*sizeof(EditVert), "allverts");
- else em->allverts= NULL;
- em->curvert= em->allverts;
-
- if(totedge==0) totedge= 4*totface; // max possible
-
- if(totedge) em->alledges= MEM_callocN(totedge*sizeof(EditEdge), "alledges");
- else em->alledges= NULL;
- em->curedge= em->alledges;
-
- if(totface) em->allfaces= MEM_callocN(totface*sizeof(EditFace), "allfaces");
- else em->allfaces= NULL;
- em->curface= em->allfaces;
-
- callocvert= calloc_fastvert;
- callocedge= calloc_fastedge;
- callocface= calloc_fastface;
-}
-
-static void end_editmesh_fastmalloc(void)
-{
- callocvert= calloc_em;
- callocedge= calloc_em;
- callocface= calloc_em;
-}
-
-/* do not free editmesh itself here */
-void free_editMesh(EditMesh *em)
-{
- if(em==NULL) return;
-
- if(em->verts.first) free_vertlist(em, &em->verts);
- if(em->edges.first) free_edgelist(em, &em->edges);
- if(em->faces.first) free_facelist(em, &em->faces);
- if(em->selected.first) BLI_freelistN(&(em->selected));
-
- CustomData_free(&em->vdata, 0);
- CustomData_free(&em->fdata, 0);
-
- if(em->derivedFinal) {
- if (em->derivedFinal!=em->derivedCage) {
- em->derivedFinal->needsFree= 1;
- em->derivedFinal->release(em->derivedFinal);
- }
- em->derivedFinal= NULL;
- }
- if(em->derivedCage) {
- em->derivedCage->needsFree= 1;
- em->derivedCage->release(em->derivedCage);
- em->derivedCage= NULL;
- }
-
- /* DEBUG: hashtabs are slowest part of enter/exit editmode. here a testprint */
-#if 0
- if(em->hashedgetab) {
- HashEdge *he, *hen;
- int a, used=0, max=0, nr;
- he= em->hashedgetab;
- for(a=0; a<EDHASHSIZE; a++, he++) {
- if(he->eed) used++;
- hen= he->next;
- nr= 0;
- while(hen) {
- nr++;
- hen= hen->next;
- }
- if(max<nr) max= nr;
- }
- printf("hastab used %d max %d\n", used, max);
- }
-#endif
- if(em->hashedgetab) MEM_freeN(em->hashedgetab);
- em->hashedgetab= NULL;
-
- if(em->allverts) MEM_freeN(em->allverts);
- if(em->alledges) MEM_freeN(em->alledges);
- if(em->allfaces) MEM_freeN(em->allfaces);
-
- em->allverts= em->curvert= NULL;
- em->alledges= em->curedge= NULL;
- em->allfaces= em->curface= NULL;
-
- mesh_octree_table(NULL, NULL, NULL, 'e');
- mesh_mirrtopo_table(NULL, 'e');
-
- em->totvert= em->totedge= em->totface= 0;
-
-// XXX if(em->retopo_paint_data) retopo_free_paint_data(em->retopo_paint_data);
- em->retopo_paint_data= NULL;
- em->act_face = NULL;
-}
-
-static void editMesh_set_hash(EditMesh *em)
-{
- EditEdge *eed;
-
- if(em->hashedgetab) MEM_freeN(em->hashedgetab);
- em->hashedgetab= NULL;
-
- for(eed=em->edges.first; eed; eed= eed->next) {
- if( findedgelist(em, eed->v1, eed->v2)==NULL )
- insert_hashedge(em, eed);
- }
-
-}
-
-
-/* ************************ IN & OUT EDITMODE ***************************** */
-
-
-static void edge_normal_compare(EditEdge *eed, EditFace *efa1)
-{
- EditFace *efa2;
- float cent1[3], cent2[3];
- float inp;
-
- efa2 = eed->tmp.f;
- if(efa1==efa2) return;
-
- inp= efa1->n[0]*efa2->n[0] + efa1->n[1]*efa2->n[1] + efa1->n[2]*efa2->n[2];
- if(inp<0.999f && inp >-0.999f) eed->f2= 1;
-
- if(efa1->v4) cent_quad_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co, efa1->v4->co);
- else cent_tri_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co);
- if(efa2->v4) cent_quad_v3(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co, efa2->v4->co);
- else cent_tri_v3(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co);
-
- sub_v3_v3v3(cent1, cent2, cent1);
- normalize_v3(cent1);
- inp= cent1[0]*efa1->n[0] + cent1[1]*efa1->n[1] + cent1[2]*efa1->n[2];
-
- if(inp < -0.001f) eed->f1= 1;
-}
-
-#if 0
-typedef struct {
- EditEdge *eed;
- float noLen,no[3];
- int adjCount;
-} EdgeDrawFlagInfo;
-
-static int edgeDrawFlagInfo_cmp(const void *av, const void *bv)
-{
- const EdgeDrawFlagInfo *a = av;
- const EdgeDrawFlagInfo *b = bv;
-
- if (a->noLen<b->noLen) return -1;
- else if (a->noLen>b->noLen) return 1;
- else return 0;
-}
-#endif
-
-static void edge_drawflags(Mesh *me, EditMesh *em)
-{
- EditVert *eve;
- EditEdge *eed, *e1, *e2, *e3, *e4;
- EditFace *efa;
-
- /* - count number of times edges are used in faces: 0 en 1 time means draw edge
- * - edges more than 1 time used: in *tmp.f is pointer to first face
- * - check all faces, when normal differs to much: draw (flag becomes 1)
- */
-
- /* later on: added flags for 'cylinder' and 'sphere' intersection tests in old
- game engine (2.04)
- */
-
- recalc_editnormals(em);
-
- /* init */
- eve= em->verts.first;
- while(eve) {
- eve->f1= 1; /* during test it's set at zero */
- eve= eve->next;
- }
- eed= em->edges.first;
- while(eed) {
- eed->f2= eed->f1= 0;
- eed->tmp.f = 0;
- eed= eed->next;
- }
-
- efa= em->faces.first;
- while(efa) {
- e1= efa->e1;
- e2= efa->e2;
- e3= efa->e3;
- e4= efa->e4;
- if(e1->f2<4) e1->f2+= 1;
- if(e2->f2<4) e2->f2+= 1;
- if(e3->f2<4) e3->f2+= 1;
- if(e4 && e4->f2<4) e4->f2+= 1;
-
- if(e1->tmp.f == 0) e1->tmp.f = (void *) efa;
- if(e2->tmp.f == 0) e2->tmp.f = (void *) efa;
- if(e3->tmp.f ==0) e3->tmp.f = (void *) efa;
- if(e4 && (e4->tmp.f == 0)) e4->tmp.f = (void *) efa;
-
- efa= efa->next;
- }
-
- if(me->drawflag & ME_ALLEDGES) {
- efa= em->faces.first;
- while(efa) {
- if(efa->e1->f2>=2) efa->e1->f2= 1;
- if(efa->e2->f2>=2) efa->e2->f2= 1;
- if(efa->e3->f2>=2) efa->e3->f2= 1;
- if(efa->e4 && efa->e4->f2>=2) efa->e4->f2= 1;
-
- efa= efa->next;
- }
- }
- else {
-
- /* handle single-edges for 'test cylinder flag' (old engine) */
-
- eed= em->edges.first;
- while(eed) {
- if(eed->f2==1) eed->f1= 1;
- eed= eed->next;
- }
-
- /* all faces, all edges with flag==2: compare normal */
- efa= em->faces.first;
- while(efa) {
- if(efa->e1->f2==2) edge_normal_compare(efa->e1, efa);
- else efa->e1->f2= 1;
- if(efa->e2->f2==2) edge_normal_compare(efa->e2, efa);
- else efa->e2->f2= 1;
- if(efa->e3->f2==2) edge_normal_compare(efa->e3, efa);
- else efa->e3->f2= 1;
- if(efa->e4) {
- if(efa->e4->f2==2) edge_normal_compare(efa->e4, efa);
- else efa->e4->f2= 1;
- }
- efa= efa->next;
- }
-
- /* sphere collision flag */
-
- eed= em->edges.first;
- while(eed) {
- if(eed->f1!=1) {
- eed->v1->f1= eed->v2->f1= 0;
- }
- eed= eed->next;
- }
-
- }
-}
-
-/* turns Mesh into editmesh */
-void make_editMesh(Scene *scene, Object *ob)
-{
- Mesh *me= ob->data;
- MFace *mface;
- MVert *mvert;
- MSelect *mselect;
- KeyBlock *actkey;
- EditMesh *em;
- EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4;
- EditFace *efa, *efa_last_sel= NULL;
- EditEdge *eed;
- EditSelection *ese;
- float *co, (*keyco)[3]= NULL;
- int tot, a, eekadoodle= 0;
- const short is_paint_sel= paint_facesel_test(ob);
-
- if(me->edit_mesh==NULL)
- me->edit_mesh= MEM_callocN(sizeof(EditMesh), "editmesh");
- else
- /* because of reload */
- free_editMesh(me->edit_mesh);
-
- em= me->edit_mesh;
-
- em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced
- em->act_face = NULL;
- em->totvert= tot= me->totvert;
- em->totedge= me->totedge;
- em->totface= me->totface;
-
- if(tot==0) {
- return;
- }
-
- if(ob->actcol > 0)
- em->mat_nr= ob->actcol-1;
-
- /* initialize fastmalloc for editmesh */
- init_editmesh_fastmalloc(em, me->totvert, me->totedge, me->totface);
-
- actkey = ob_get_keyblock(ob);
- if(actkey) {
- /* undo-ing in past for previous editmode sessions gives corrupt 'keyindex' values */
- undo_editmode_clear();
- keyco= actkey->data;
- em->shapenr= ob->shapenr;
- }
-
- /* make editverts */
- CustomData_copy(&me->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
- mvert= me->mvert;
-
- evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist");
- for(a=0; a<tot; a++, mvert++) {
-
- co= mvert->co;
-
- /* edit the shape key coordinate if available */
- if(keyco && a < actkey->totelem)
- co= keyco[a];
-
- eve= addvertlist(em, co, NULL);
- evlist[a]= eve;
-
- /* face select sets selection in next loop */
- if(!is_paint_sel)
- eve->f |= (mvert->flag & 1);
-
- if (mvert->flag & ME_HIDE) eve->h= 1;
- normal_short_to_float_v3(eve->no, mvert->no);
-
- eve->bweight= ((float)mvert->bweight)/255.0f;
-
- /* lets overwrite the keyindex of the editvert
- * with the order it used to be in before
- * editmode
- */
- eve->keyindex = a;
-
- CustomData_to_em_block(&me->vdata, &em->vdata, a, &eve->data);
- }
-
- if(actkey && actkey->totelem!=me->totvert);
- else {
- MEdge *medge= me->medge;
-
- CustomData_copy(&me->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
- /* make edges */
- for(a=0; a<me->totedge; a++, medge++) {
- eed= addedgelist(em, evlist[medge->v1], evlist[medge->v2], NULL);
- /* eed can be zero when v1 and v2 are identical, dxf import does this... */
- if(eed) {
- eed->crease= ((float)medge->crease)/255.0f;
- eed->bweight= ((float)medge->bweight)/255.0f;
-
- if(medge->flag & ME_SEAM) eed->seam= 1;
- if(medge->flag & ME_SHARP) eed->sharp = 1;
- if(medge->flag & SELECT) eed->f |= SELECT;
- if(medge->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines!
- if(medge->flag & ME_HIDE) eed->h |= 1;
- if(em->selectmode==SCE_SELECT_EDGE)
- EM_select_edge(eed, eed->f & SELECT); // force edge selection to vertices, seems to be needed ...
- CustomData_to_em_block(&me->edata,&em->edata, a, &eed->data);
- }
- }
-
- CustomData_copy(&me->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
-
- /* make faces */
- mface= me->mface;
-
- for(a=0; a<me->totface; a++, mface++) {
- eve1= evlist[mface->v1];
- eve2= evlist[mface->v2];
- if(!mface->v3) eekadoodle= 1;
- eve3= evlist[mface->v3];
- if(mface->v4) eve4= evlist[mface->v4]; else eve4= NULL;
-
- efa= addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL);
-
- if(efa) {
- CustomData_to_em_block(&me->fdata, &em->fdata, a, &efa->data);
-
- efa->mat_nr= mface->mat_nr;
- efa->flag= mface->flag & ~ME_HIDE;
-
- /* select and hide face flag */
- if(mface->flag & ME_HIDE) {
- efa->h= 1;
- } else {
- if (a==me->act_face) {
- EM_set_actFace(em, efa);
- }
-
- /* dont allow hidden and selected */
- if(mface->flag & ME_FACE_SEL) {
- efa->f |= SELECT;
-
- if(is_paint_sel) {
- EM_select_face(efa, 1); /* flush down */
- }
-
- efa_last_sel= efa;
- }
- }
- }
- }
- }
-
- if(EM_get_actFace(em, 0)==NULL && efa_last_sel) {
- EM_set_actFace(em, efa_last_sel);
- }
-
- if(eekadoodle)
- error("This Mesh has old style edgecodes, please put it in the bugtracker!");
-
- MEM_freeN(evlist);
-
- end_editmesh_fastmalloc(); // resets global function pointers
-
- if(me->mselect){
- //restore editselections
- EM_init_index_arrays(em, 1,1,1);
- mselect = me->mselect;
-
- for(a=0; a<me->totselect; a++, mselect++){
- /*check if recorded selection is still valid, if so copy into editmesh*/
- if( (mselect->type == EDITVERT && me->mvert[mselect->index].flag & SELECT) || (mselect->type == EDITEDGE && me->medge[mselect->index].flag & SELECT) || (mselect->type == EDITFACE && me->mface[mselect->index].flag & ME_FACE_SEL) ){
- ese = MEM_callocN(sizeof(EditSelection), "Edit Selection");
- ese->type = mselect->type;
- if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(mselect->index); else
- if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(mselect->index); else
- if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(mselect->index);
- BLI_addtail(&(em->selected),ese);
- }
- }
- EM_free_index_arrays();
- }
- /* this creates coherent selections. also needed for older files */
- EM_selectmode_set(em);
- /* paranoia check to enforce hide rules */
- EM_hide_reset(em);
- /* sets helper flags which arent saved */
- EM_fgon_flags(em);
-
- if (EM_get_actFace(em, 0)==NULL) {
- EM_set_actFace(em, em->faces.first ); /* will use the first face, this is so we alwats have an active face */
- }
-}
-
-/* makes Mesh out of editmesh */
-void load_editMesh(Scene *scene, Object *obedit)
-{
- Mesh *me= obedit->data;
- MVert *mvert, *oldverts;
- MEdge *medge;
- MFace *mface;
- MSelect *mselect;
- EditMesh *em= me->edit_mesh;
- EditVert *eve;
- EditFace *efa, *efa_act;
- EditEdge *eed;
- EditSelection *ese;
- float *fp, *newkey, *oldkey;
- int i, a, ototvert;
-
- /* this one also tests of edges are not in faces: */
- /* eed->f2==0: not in face, f2==1: draw it */
- /* eed->f1 : flag for dynaface (cylindertest, old engine) */
- /* eve->f1 : flag for dynaface (sphere test, old engine) */
- /* eve->f2 : being used in vertexnormals */
- edge_drawflags(me, em);
-
- EM_stats_update(em);
-
- /* new Vertex block */
- if(em->totvert==0) mvert= NULL;
- else mvert= MEM_callocN(em->totvert*sizeof(MVert), "loadeditMesh vert");
-
- /* new Edge block */
- if(em->totedge==0) medge= NULL;
- else medge= MEM_callocN(em->totedge*sizeof(MEdge), "loadeditMesh edge");
-
- /* new Face block */
- if(em->totface==0) mface= NULL;
- else mface= MEM_callocN(em->totface*sizeof(MFace), "loadeditMesh face");
-
- /* lets save the old verts just in case we are actually working on
- * a key ... we now do processing of the keys at the end */
- oldverts= me->mvert;
- ototvert= me->totvert;
-
- /* don't free this yet */
- CustomData_set_layer(&me->vdata, CD_MVERT, NULL);
-
- /* free custom data */
- CustomData_free(&me->vdata, me->totvert);
- CustomData_free(&me->edata, me->totedge);
- CustomData_free(&me->fdata, me->totface);
-
- /* add new custom data */
- me->totvert= em->totvert;
- me->totedge= em->totedge;
- me->totface= em->totface;
-
- CustomData_copy(&em->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert);
- CustomData_copy(&em->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge);
- CustomData_copy(&em->fdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface);
-
- CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
- CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
- CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface);
- mesh_update_customdata_pointers(me);
-
- /* the vertices, use ->tmp.l as counter */
- eve= em->verts.first;
- a= 0;
-
- while(eve) {
- VECCOPY(mvert->co, eve->co);
-
- /* vertex normal */
- normal_float_to_short_v3(mvert->no, eve->no);
-
- /* note: it used to remove me->dvert when it was not in use, cancelled
- that... annoying when you have a fresh vgroup */
- CustomData_from_em_block(&em->vdata, &me->vdata, eve->data, a);
-
- eve->tmp.l = a++; /* counter */
-
- mvert->flag= 0;
- mvert->flag |= (eve->f & SELECT);
- if (eve->h) mvert->flag |= ME_HIDE;
-
- mvert->bweight= (char)(255.0f*eve->bweight);
-
- eve= eve->next;
- mvert++;
- }
-
- /* the edges */
- a= 0;
- eed= em->edges.first;
- while(eed) {
- medge->v1= (unsigned int) eed->v1->tmp.l;
- medge->v2= (unsigned int) eed->v2->tmp.l;
-
- medge->flag= (eed->f & SELECT) | ME_EDGERENDER;
- if(eed->f2<2) medge->flag |= ME_EDGEDRAW;
- if(eed->f2==0) medge->flag |= ME_LOOSEEDGE;
- if(eed->sharp) medge->flag |= ME_SHARP;
- if(eed->seam) medge->flag |= ME_SEAM;
- if(eed->h & EM_FGON) medge->flag |= ME_FGON; // different defines yes
- if(eed->h & 1) medge->flag |= ME_HIDE;
-
- medge->crease= (char)(255.0f*eed->crease);
- medge->bweight= (char)(255.0f*eed->bweight);
- CustomData_from_em_block(&em->edata, &me->edata, eed->data, a);
-
- eed->tmp.l = a++;
-
- medge++;
- eed= eed->next;
- }
-
- /* the faces */
- a = 0;
- efa= em->faces.first;
- efa_act= EM_get_actFace(em, 0);
- i = 0;
- me->act_face = -1;
- while(efa) {
- mface= &((MFace *) me->mface)[i];
-
- mface->v1= (unsigned int) efa->v1->tmp.l;
- mface->v2= (unsigned int) efa->v2->tmp.l;
- mface->v3= (unsigned int) efa->v3->tmp.l;
- if (efa->v4) mface->v4 = (unsigned int) efa->v4->tmp.l;
-
- mface->mat_nr= efa->mat_nr;
-
- mface->flag= efa->flag;
- /* bit 0 of flag is already taken for smooth... */
-
- if(efa->h) {
- mface->flag |= ME_HIDE;
- mface->flag &= ~ME_FACE_SEL;
- } else {
- if(efa->f & 1) mface->flag |= ME_FACE_SEL;
- else mface->flag &= ~ME_FACE_SEL;
- }
-
- /* watch: efa->e1->f2==0 means loose edge */
-
- if(efa->e1->f2==1) {
- efa->e1->f2= 2;
- }
- if(efa->e2->f2==1) {
- efa->e2->f2= 2;
- }
- if(efa->e3->f2==1) {
- efa->e3->f2= 2;
- }
- if(efa->e4 && efa->e4->f2==1) {
- efa->e4->f2= 2;
- }
-
- CustomData_from_em_block(&em->fdata, &me->fdata, efa->data, i);
-
- /* no index '0' at location 3 or 4 */
- test_index_face(mface, &me->fdata, i, efa->v4?4:3);
-
- if (efa_act == efa)
- me->act_face = a;
-
- efa->tmp.l = a++;
- i++;
- efa= efa->next;
- }
-
- /* patch hook indices and vertex parents */
- {
- Object *ob;
- ModifierData *md;
- EditVert **vertMap = NULL;
- int j;
-
- for (ob=G.main->object.first; ob; ob=ob->id.next) {
- if (ob->parent==obedit && ELEM(ob->partype, PARVERT1,PARVERT3)) {
-
- /* duplicate code from below, make it function later...? */
- if (!vertMap) {
- vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
-
- for (eve=em->verts.first; eve; eve=eve->next) {
- if (eve->keyindex!=-1)
- vertMap[eve->keyindex] = eve;
- }
- }
- if(ob->par1 < ototvert) {
- eve = vertMap[ob->par1];
- if(eve) ob->par1= eve->tmp.l;
- }
- if(ob->par2 < ototvert) {
- eve = vertMap[ob->par2];
- if(eve) ob->par2= eve->tmp.l;
- }
- if(ob->par3 < ototvert) {
- eve = vertMap[ob->par3];
- if(eve) ob->par3= eve->tmp.l;
- }
-
- }
- if (ob->data==me) {
- for (md=ob->modifiers.first; md; md=md->next) {
- if (md->type==eModifierType_Hook) {
- HookModifierData *hmd = (HookModifierData*) md;
-
- if (!vertMap) {
- vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
-
- for (eve=em->verts.first; eve; eve=eve->next) {
- if (eve->keyindex!=-1)
- vertMap[eve->keyindex] = eve;
- }
- }
-
- for (i=j=0; i<hmd->totindex; i++) {
- if(hmd->indexar[i] < ototvert) {
- eve = vertMap[hmd->indexar[i]];
-
- if (eve) {
- hmd->indexar[j++] = eve->tmp.l;
- }
- }
- else j++;
- }
-
- hmd->totindex = j;
- }
- }
- }
- }
-
- if (vertMap) MEM_freeN(vertMap);
- }
-
- /* are there keys? */
- if(me->key) {
- KeyBlock *currkey;
- KeyBlock *actkey= BLI_findlink(&me->key->block, em->shapenr-1);
-
- float (*ofs)[3] = NULL;
-
- /* editing the base key should update others */
- if(me->key->type==KEY_RELATIVE && oldverts) {
- int act_is_basis = 0;
- /* find if this key is a basis for any others */
- for(currkey = me->key->block.first; currkey; currkey= currkey->next) {
- if(em->shapenr-1 == currkey->relative) {
- act_is_basis = 1;
- break;
- }
- }
-
- if(act_is_basis) { /* active key is a base */
- float (*fp)[3]= actkey->data;
- i=0;
- ofs= MEM_callocN(sizeof(float) * 3 * em->totvert, "currkey->data");
- eve= em->verts.first;
- mvert = me->mvert;
- while(eve) {
- if(eve->keyindex>=0)
- VECSUB(ofs[i], mvert->co, fp[eve->keyindex]);
-
- eve= eve->next;
- i++;
- mvert++;
- }
- }
- }
-
-
- /* Lets reorder the key data so that things line up roughly
- * with the way things were before editmode */
- currkey = me->key->block.first;
- while(currkey) {
- int apply_offset = (ofs && (currkey != actkey) && (em->shapenr-1 == currkey->relative));
-
- fp= newkey= MEM_callocN(me->key->elemsize*em->totvert, "currkey->data");
- oldkey = currkey->data;
-
- eve= em->verts.first;
-
- i = 0;
- mvert = me->mvert;
- while(eve) {
- if (eve->keyindex >= 0 && eve->keyindex < currkey->totelem) { // valid old vertex
- if(currkey == actkey) {
- if(actkey == me->key->refkey) {
- VECCOPY(fp, mvert->co);
- }
- else {
- VECCOPY(fp, mvert->co);
- if(oldverts) {
- VECCOPY(mvert->co, oldverts[eve->keyindex].co);
- }
- }
- }
- else {
- if(oldkey) {
- VECCOPY(fp, oldkey + 3 * eve->keyindex);
- }
- }
- }
- else {
- VECCOPY(fp, mvert->co);
- }
-
- /* propagate edited basis offsets to other shapes */
- if(apply_offset) {
- VECADD(fp, fp, ofs[i]);
- }
-
- fp+= 3;
- ++i;
- ++mvert;
- eve= eve->next;
- }
- currkey->totelem= em->totvert;
- if(currkey->data) MEM_freeN(currkey->data);
- currkey->data = newkey;
-
- currkey= currkey->next;
- }
-
- if(ofs) MEM_freeN(ofs);
- }
-
- if(oldverts) MEM_freeN(oldverts);
-
- i = 0;
- for(ese=em->selected.first; ese; ese=ese->next) i++;
- me->totselect = i;
- if(i==0) mselect= NULL;
- else mselect= MEM_callocN(i*sizeof(MSelect), "loadeditMesh selections");
-
- if(me->mselect) MEM_freeN(me->mselect);
- me->mselect= mselect;
-
- for(ese=em->selected.first; ese; ese=ese->next){
- mselect->type = ese->type;
- if(ese->type == EDITVERT) mselect->index = ((EditVert*)ese->data)->tmp.l;
- else if(ese->type == EDITEDGE) mselect->index = ((EditEdge*)ese->data)->tmp.l;
- else if(ese->type == EDITFACE) mselect->index = ((EditFace*)ese->data)->tmp.l;
- mselect++;
- }
-
- /* to be sure: clear ->tmp.l pointers */
- eve= em->verts.first;
- while(eve) {
- eve->tmp.l = 0;
- eve= eve->next;
- }
-
- eed= em->edges.first;
- while(eed) {
- eed->tmp.l = 0;
- eed= eed->next;
- }
-
- efa= em->faces.first;
- while(efa) {
- efa->tmp.l = 0;
- efa= efa->next;
- }
-
- /* remake softbody of all users */
- if(me->id.us>1) {
- Base *base;
- for(base= scene->base.first; base; base= base->next)
- if(base->object->data==me)
- base->object->recalc |= OB_RECALC_DATA;
- }
-
- mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
-
- /* topology could be changed, ensure mdisps are ok */
- multires_topology_changed(scene, obedit);
-}
-
-void remake_editMesh(Scene *scene, Object *ob)
-{
- make_editMesh(scene, ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- BIF_undo_push("Undo all changes");
-}
-
-/* *************** Operator: separate parts *************/
-
-static EnumPropertyItem prop_separate_types[] = {
- {0, "SELECTED", 0, "Selection", ""},
- {1, "MATERIAL", 0, "By Material", ""},
- {2, "LOOSE", 0, "By loose parts", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-/* return 1: success */
-static int mesh_separate_selected(wmOperator *op, Main *bmain, Scene *scene, Base *editbase)
-{
- EditMesh *em, *emnew;
- EditVert *eve, *v1;
- EditEdge *eed, *e1;
- EditFace *efa, *f1;
- Object *obedit;
- Mesh *me, *menew;
- Base *basenew;
-
- if(editbase==NULL) return 0;
-
- obedit= editbase->object;
- me= obedit->data;
- em= BKE_mesh_get_editmesh(me);
- if(me->key) {
- BKE_report(op->reports, RPT_WARNING, "Can't separate mesh with shape keys");
- BKE_mesh_end_editmesh(me, em);
- return 0;
- }
-
- if(em->selected.first)
- BLI_freelistN(&(em->selected)); /* clear the selection order */
-
- EM_selectmode_set(em); // enforce full consistent selection flags
-
- EM_stats_update(em);
-
- if(em->totvertsel==0) {
- BKE_mesh_end_editmesh(me, em);
- return 0;
- }
-
- /* we are going to work as follows:
- * 1. add a linked duplicate object: this will be the new one, we remember old pointer
- * 2. give new object empty mesh and put in editmode
- * 3: do a split if needed on current editmesh.
- * 4. copy over: all NOT selected verts, edges, faces
- * 5. call load_editMesh() on the new object
- */
-
- /* 1 */
- basenew= ED_object_add_duplicate(bmain, scene, editbase, 0); /* 0 = fully linked */
- ED_base_object_select(basenew, BA_DESELECT);
-
- /* 2 */
- basenew->object->data= menew= add_mesh(me->id.name+2); /* empty */
- assign_matarar(basenew->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */
- me->id.us--;
- make_editMesh(scene, basenew->object);
- emnew= menew->edit_mesh;
- CustomData_copy(&em->vdata, &emnew->vdata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
- CustomData_copy(&em->edata, &emnew->edata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
- CustomData_copy(&em->fdata, &emnew->fdata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
-
- /* 3 */
- /* SPLIT: first make duplicate */
- adduplicateflag(em, SELECT);
- /* SPLIT: old faces have 3x flag 128 set, delete these ones */
- delfaceflag(em, 128);
- /* since we do tricky things with verts/edges/faces, this makes sure all is selected coherent */
- EM_selectmode_set(em);
-
- /* 4 */
- /* move over: everything that is selected */
- for(eve= em->verts.first; eve; eve= v1) {
- v1= eve->next;
- if(eve->f & SELECT) {
- BLI_remlink(&em->verts, eve);
- BLI_addtail(&emnew->verts, eve);
- }
- }
-
- for(eed= em->edges.first; eed; eed= e1) {
- e1= eed->next;
- if(eed->f & SELECT) {
- BLI_remlink(&em->edges, eed);
- BLI_addtail(&emnew->edges, eed);
- }
- }
-
- for(efa= em->faces.first; efa; efa= f1) {
- f1= efa->next;
- if (efa == em->act_face && (efa->f & SELECT)) {
- EM_set_actFace(em, NULL);
- }
-
- if(efa->f & SELECT) {
- BLI_remlink(&em->faces, efa);
- BLI_addtail(&emnew->faces, efa);
- }
- }
-
- /* 5 */
- load_editMesh(scene, basenew->object);
- free_editMesh(emnew);
- MEM_freeN(menew->edit_mesh);
- menew->edit_mesh= NULL;
-
- /* copy settings */
- menew->texflag= me->texflag;
- menew->drawflag= me->drawflag;
- menew->flag= me->flag;
- menew->editflag= me->editflag;
- menew->smoothresh= me->smoothresh;
-
- /* hashedges are invalid now, make new! */
- editMesh_set_hash(em);
-
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
- DAG_id_tag_update(&basenew->object->id, OB_RECALC_DATA);
-
- BKE_mesh_end_editmesh(me, em);
-
- return 1;
-}
-
-/* return 1: success */
-static int mesh_separate_material(wmOperator *op, Main *bmain, Scene *scene, Base *editbase)
-{
- Mesh *me= editbase->object->data;
- EditMesh *em= BKE_mesh_get_editmesh(me);
- unsigned char curr_mat;
-
- for (curr_mat = 1; curr_mat < editbase->object->totcol; ++curr_mat) {
- /* clear selection, we're going to use that to select material group */
- EM_clear_flag_all(em, SELECT);
- /* select the material */
- EM_select_by_material(em, curr_mat);
- /* and now separate */
- if(em->totfacesel > 0) {
- mesh_separate_selected(op, bmain, scene, editbase);
- }
- }
-
- BKE_mesh_end_editmesh(me, em);
- return 1;
-}
-
-/* return 1: success */
-static int mesh_separate_loose(wmOperator *op, Main *bmain, Scene *scene, Base *editbase)
-{
- Mesh *me;
- EditMesh *em;
- int doit= 1;
-
- me= editbase->object->data;
- em= BKE_mesh_get_editmesh(me);
-
- if(me->key) {
- error("Can't separate with vertex keys");
- BKE_mesh_end_editmesh(me, em);
- return 0;
- }
-
- EM_clear_flag_all(em, SELECT);
-
- while(doit) {
- /* Select a random vert to start with */
- EditVert *eve;
- int tot;
-
- /* check if all verts that are visible have been done */
- for(eve=em->verts.first; eve; eve= eve->next)
- if(!eve->h) break;
- if(eve==NULL) break; /* only hidden verts left, quit early */
-
- /* first non hidden vert */
- eve->f |= SELECT;
-
- selectconnected_mesh_all(em);
-
- /* don't separate the very last part */
- for(eve=em->verts.first; eve; eve= eve->next)
- if((eve->f & SELECT)==0) break;
- if(eve==NULL) break;
-
- tot= BLI_countlist(&em->verts);
-
- /* and now separate */
- doit= mesh_separate_selected(op, bmain, scene, editbase);
-
- /* with hidden verts this can happen */
- if(tot == BLI_countlist(&em->verts))
- break;
- }
-
- BKE_mesh_end_editmesh(me, em);
- return 1;
-}
-
-
-static int mesh_separate_exec(bContext *C, wmOperator *op)
-{
- Main *bmain= CTX_data_main(C);
- Scene *scene= CTX_data_scene(C);
- Base *base= CTX_data_active_base(C);
- int retval= 0, type= RNA_enum_get(op->ptr, "type");
-
- if(type == 0)
- retval= mesh_separate_selected(op, bmain, scene, base);
- else if(type == 1)
- retval= mesh_separate_material(op, bmain, scene, base);
- else if(type == 2)
- retval= mesh_separate_loose(op, bmain, scene, base);
-
- if(retval) {
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
-
- // XXX: new object was created, but selection wasn't actually changed
- // need this for outliner update without adding new ND. nazgul.
- WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
- }
- return OPERATOR_CANCELLED;
-}
-
-void MESH_OT_separate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Separate";
- ot->description= "Separate selected geometry into a new mesh";
- ot->idname= "MESH_OT_separate";
-
- /* api callbacks */
- ot->invoke= WM_menu_invoke;
- ot->exec= mesh_separate_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- ot->prop= RNA_def_enum(ot->srna, "type", prop_separate_types, 0, "Type", "");
-}
-
-
-/* ******************************************** */
-
-/* *************** UNDO ***************************** */
-/* new mesh undo, based on pushing editmesh data itself */
-/* reuses same code as for global and curve undo... unify that (ton) */
-
-/* only one 'hack', to save memory it doesn't store the first push, but does a remake editmesh */
-
-/* a compressed version of editmesh data */
-
-typedef struct EditVertC
-{
- float no[3];
- float co[3];
- unsigned char f, h;
- short bweight;
- int keyindex;
-} EditVertC;
-
-typedef struct EditEdgeC
-{
- int v1, v2;
- unsigned char f, h, seam, sharp, pad;
- short crease, bweight, fgoni;
-} EditEdgeC;
-
-typedef struct EditFaceC
-{
- int v1, v2, v3, v4;
- unsigned char flag, f, h, fgonf, pad1;
- short mat_nr;
-} EditFaceC;
-
-typedef struct EditSelectionC{
- short type;
- int index;
-}EditSelectionC;
-
-typedef struct UndoMesh {
- EditVertC *verts;
- EditEdgeC *edges;
- EditFaceC *faces;
- EditSelectionC *selected;
- int totvert, totedge, totface, totsel;
- int selectmode, shapenr;
- char retopo_mode;
- CustomData vdata, edata, fdata;
-} UndoMesh;
-
-/* for callbacks */
-
-static void free_undoMesh(void *umv)
-{
- UndoMesh *um= umv;
-
- if(um->verts) MEM_freeN(um->verts);
- if(um->edges) MEM_freeN(um->edges);
- if(um->faces) MEM_freeN(um->faces);
- if(um->selected) MEM_freeN(um->selected);
-// XXX if(um->retopo_paint_data) retopo_free_paint_data(um->retopo_paint_data);
- CustomData_free(&um->vdata, um->totvert);
- CustomData_free(&um->edata, um->totedge);
- CustomData_free(&um->fdata, um->totface);
- MEM_freeN(um);
-}
-
-static void *editMesh_to_undoMesh(void *emv)
-{
- EditMesh *em= (EditMesh *)emv;
- UndoMesh *um;
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
- EditSelection *ese;
- EditVertC *evec=NULL;
- EditEdgeC *eedc=NULL;
- EditFaceC *efac=NULL;
- EditSelectionC *esec=NULL;
- int a;
-
- um= MEM_callocN(sizeof(UndoMesh), "undomesh");
-
- um->selectmode = em->selectmode;
- um->shapenr = em->shapenr;
-
- for(eve=em->verts.first; eve; eve= eve->next) um->totvert++;
- for(eed=em->edges.first; eed; eed= eed->next) um->totedge++;
- for(efa=em->faces.first; efa; efa= efa->next) um->totface++;
- for(ese=em->selected.first; ese; ese=ese->next) um->totsel++;
- /* malloc blocks */
-
- if(um->totvert) evec= um->verts= MEM_callocN(um->totvert*sizeof(EditVertC), "allvertsC");
- if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC");
- if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC");
- if(um->totsel) esec= um->selected= MEM_callocN(um->totsel*sizeof(EditSelectionC), "allselections");
-
- if(um->totvert) CustomData_copy(&em->vdata, &um->vdata, CD_MASK_EDITMESH, CD_CALLOC, um->totvert);
- if(um->totedge) CustomData_copy(&em->edata, &um->edata, CD_MASK_EDITMESH, CD_CALLOC, um->totedge);
- if(um->totface) CustomData_copy(&em->fdata, &um->fdata, CD_MASK_EDITMESH, CD_CALLOC, um->totface);
-
- /* now copy vertices */
- a = 0;
- for(eve=em->verts.first; eve; eve= eve->next, evec++, a++) {
- copy_v3_v3(evec->co, eve->co);
- copy_v3_v3(evec->no, eve->no);
-
- evec->f= eve->f;
- evec->h= eve->h;
- evec->keyindex= eve->keyindex;
- eve->tmp.l = a; /*store index*/
- evec->bweight= (short)(eve->bweight*255.0f);
-
- CustomData_from_em_block(&em->vdata, &um->vdata, eve->data, a);
- }
-
- /* copy edges */
- a = 0;
- for(eed=em->edges.first; eed; eed= eed->next, eedc++, a++) {
- eedc->v1= (int)eed->v1->tmp.l;
- eedc->v2= (int)eed->v2->tmp.l;
- eedc->f= eed->f;
- eedc->h= eed->h;
- eedc->seam= eed->seam;
- eedc->sharp= eed->sharp;
- eedc->crease= (short)(eed->crease*255.0f);
- eedc->bweight= (short)(eed->bweight*255.0f);
- eedc->fgoni= eed->fgoni;
- eed->tmp.l = a; /*store index*/
- CustomData_from_em_block(&em->edata, &um->edata, eed->data, a);
-
- }
-
- /* copy faces */
- a = 0;
- for(efa=em->faces.first; efa; efa= efa->next, efac++, a++) {
- efac->v1= (int)efa->v1->tmp.l;
- efac->v2= (int)efa->v2->tmp.l;
- efac->v3= (int)efa->v3->tmp.l;
- if(efa->v4) efac->v4= (int)efa->v4->tmp.l;
- else efac->v4= -1;
-
- efac->mat_nr= efa->mat_nr;
- efac->flag= efa->flag;
- efac->f= efa->f;
- efac->h= efa->h;
- efac->fgonf= efa->fgonf;
-
- efa->tmp.l = a; /*store index*/
-
- CustomData_from_em_block(&em->fdata, &um->fdata, efa->data, a);
- }
-
- a = 0;
- for(ese=em->selected.first; ese; ese=ese->next, esec++){
- esec->type = ese->type;
- if(ese->type == EDITVERT) a = esec->index = ((EditVert*)ese->data)->tmp.l;
- else if(ese->type == EDITEDGE) a = esec->index = ((EditEdge*)ese->data)->tmp.l;
- else if(ese->type == EDITFACE) a = esec->index = ((EditFace*)ese->data)->tmp.l;
- }
-
-// XXX um->retopo_paint_data= retopo_paint_data_copy(em->retopo_paint_data);
-// um->retopo_mode= scene->toolsettings->retopo_mode;
-
- return um;
-}
-
-static void undoMesh_to_editMesh(void *umv, void *emv)
-{
- EditMesh *em= (EditMesh *)emv;
- UndoMesh *um= (UndoMesh *)umv;
- EditVert *eve, **evar=NULL;
- EditEdge *eed;
- EditFace *efa;
- EditSelection *ese;
- EditVertC *evec;
- EditEdgeC *eedc;
- EditFaceC *efac;
- EditSelectionC *esec;
- int a=0;
-
- free_editMesh(em);
-
- /* malloc blocks */
- memset(em, 0, sizeof(EditMesh));
-
- em->selectmode = um->selectmode;
- em->shapenr = um->shapenr;
-
- init_editmesh_fastmalloc(em, um->totvert, um->totedge, um->totface);
-
- CustomData_free(&em->vdata, 0);
- CustomData_free(&em->edata, 0);
- CustomData_free(&em->fdata, 0);
-
- CustomData_copy(&um->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
- CustomData_copy(&um->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
- CustomData_copy(&um->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
-
- /* now copy vertices */
-
- if(um->totvert) evar= MEM_mallocN(um->totvert*sizeof(EditVert *), "vertex ar");
- for(a=0, evec= um->verts; a<um->totvert; a++, evec++) {
- eve= addvertlist(em, evec->co, NULL);
- evar[a]= eve;
-
- copy_v3_v3(eve->no, evec->no);
- eve->f= evec->f;
- eve->h= evec->h;
- eve->keyindex= evec->keyindex;
- eve->bweight= ((float)evec->bweight)/255.0f;
-
- CustomData_to_em_block(&um->vdata, &em->vdata, a, &eve->data);
- }
-
- /* copy edges */
- for(a=0, eedc= um->edges; a<um->totedge; a++, eedc++) {
- eed= addedgelist(em, evar[eedc->v1], evar[eedc->v2], NULL);
-
- eed->f= eedc->f;
- eed->h= eedc->h;
- eed->seam= eedc->seam;
- eed->sharp= eedc->sharp;
- eed->fgoni= eedc->fgoni;
- eed->crease= ((float)eedc->crease)/255.0f;
- eed->bweight= ((float)eedc->bweight)/255.0f;
- CustomData_to_em_block(&um->edata, &em->edata, a, &eed->data);
- }
-
- /* copy faces */
- for(a=0, efac= um->faces; a<um->totface; a++, efac++) {
- if(efac->v4 != -1)
- efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], evar[efac->v4], NULL, NULL);
- else
- efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], NULL, NULL ,NULL);
-
- efa->mat_nr= efac->mat_nr;
- efa->flag= efac->flag;
- efa->f= efac->f;
- efa->h= efac->h;
- efa->fgonf= efac->fgonf;
-
- CustomData_to_em_block(&um->fdata, &em->fdata, a, &efa->data);
- }
-
- end_editmesh_fastmalloc();
- if(evar) MEM_freeN(evar);
-
- em->totvert = um->totvert;
- em->totedge = um->totedge;
- em->totface = um->totface;
- /*restore stored editselections*/
- if(um->totsel){
- EM_init_index_arrays(em, 1,1,1);
- for(a=0, esec= um->selected; a<um->totsel; a++, esec++){
- ese = MEM_callocN(sizeof(EditSelection), "Edit Selection");
- ese->type = esec->type;
- if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(esec->index); else
- if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(esec->index); else
- if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(esec->index);
- BLI_addtail(&(em->selected),ese);
- }
- EM_free_index_arrays();
- }
-
- /* restore total selections */
- EM_nvertices_selected(em);
- EM_nedges_selected(em);
- EM_nfaces_selected(em);
-
-// XXX retopo_free_paint();
-// em->retopo_paint_data= retopo_paint_data_copy(um->retopo_paint_data);
-// scene->toolsettings->retopo_mode= um->retopo_mode;
-// if(scene->toolsettings->retopo_mode) {
-// XXX if(G.vd->depths) G.vd->depths->damaged= 1;
-// retopo_queue_updates(G.vd);
-// retopo_paint_view_update(G.vd);
-// }
-
-}
-
-static void *getEditMesh(bContext *C)
-{
- Object *obedit= CTX_data_edit_object(C);
- if(obedit && obedit->type==OB_MESH) {
- Mesh *me= obedit->data;
- return me->edit_mesh;
- }
- return NULL;
-}
-
-/* and this is all the undo system needs to know */
-void undo_push_mesh(bContext *C, const char *name)
-{
- undo_editmode_push(C, name, getEditMesh, free_undoMesh, undoMesh_to_editMesh, editMesh_to_undoMesh, NULL);
-}
-
-
-
-/* *************** END UNDO *************/
-
-static EditVert **g_em_vert_array = NULL;
-static EditEdge **g_em_edge_array = NULL;
-static EditFace **g_em_face_array = NULL;
-
-void EM_init_index_arrays(EditMesh *em, int forVert, int forEdge, int forFace)
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
- int i;
-
- if (forVert) {
- em->totvert= BLI_countlist(&em->verts);
-
- if(em->totvert) {
- g_em_vert_array = MEM_mallocN(sizeof(*g_em_vert_array)*em->totvert, "em_v_arr");
-
- for (i=0,eve=em->verts.first; eve; i++,eve=eve->next)
- g_em_vert_array[i] = eve;
- }
- }
-
- if (forEdge) {
- em->totedge= BLI_countlist(&em->edges);
-
- if(em->totedge) {
- g_em_edge_array = MEM_mallocN(sizeof(*g_em_edge_array)*em->totedge, "em_e_arr");
-
- for (i=0,eed=em->edges.first; eed; i++,eed=eed->next)
- g_em_edge_array[i] = eed;
- }
- }
-
- if (forFace) {
- em->totface= BLI_countlist(&em->faces);
-
- if(em->totface) {
- g_em_face_array = MEM_mallocN(sizeof(*g_em_face_array)*em->totface, "em_f_arr");
-
- for (i=0,efa=em->faces.first; efa; i++,efa=efa->next)
- g_em_face_array[i] = efa;
- }
- }
-}
-
-void EM_free_index_arrays(void)
-{
- if (g_em_vert_array) MEM_freeN(g_em_vert_array);
- if (g_em_edge_array) MEM_freeN(g_em_edge_array);
- if (g_em_face_array) MEM_freeN(g_em_face_array);
- g_em_vert_array = NULL;
- g_em_edge_array = NULL;
- g_em_face_array = NULL;
-}
-
-EditVert *EM_get_vert_for_index(int index)
-{
- return g_em_vert_array?g_em_vert_array[index]:NULL;
-}
-
-EditEdge *EM_get_edge_for_index(int index)
-{
- return g_em_edge_array?g_em_edge_array[index]:NULL;
-}
-
-EditFace *EM_get_face_for_index(int index)
-{
- return g_em_face_array?g_em_face_array[index]:NULL;
-}
-
-/* can we edit UV's for this mesh?*/
-int EM_texFaceCheck(EditMesh *em)
-{
- /* some of these checks could be a touch overkill */
- if ( (em) &&
- (em->faces.first) &&
- (CustomData_has_layer(&em->fdata, CD_MTFACE)))
- return 1;
- return 0;
-}
-
-/* can we edit colors for this mesh?*/
-int EM_vertColorCheck(EditMesh *em)
-{
- /* some of these checks could be a touch overkill */
- if ( (em) &&
- (em->faces.first) &&
- (CustomData_has_layer(&em->fdata, CD_MCOL)))
- return 1;
- return 0;
-}
-
-
-void em_setup_viewcontext(bContext *C, ViewContext *vc)
-{
- view3d_set_viewcontext(C, vc);
-
- if(vc->obedit) {
- Mesh *me= vc->obedit->data;
- vc->em= me->edit_mesh;
- }
-}
-
-
-/* (similar to void paintface_flush_flags(Object *ob))
- * copy the vertex flags, most importantly selection from the mesh to the final derived mesh,
- * use in object mode when selecting vertices (while painting) */
-void paintvert_flush_flags(Object *ob)
-{
- Mesh *me= get_mesh(ob);
- DerivedMesh *dm= ob->derivedFinal;
- MVert *dm_mvert, *dm_mv;
- int *index_array = NULL;
- int totvert;
- int i;
-
- if(me==NULL || dm==NULL)
- return;
-
- index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
-
- dm_mvert = dm->getVertArray(dm);
- totvert = dm->getNumVerts(dm);
-
- dm_mv= dm_mvert;
-
- if(index_array) {
- int orig_index;
- for (i= 0; i<totvert; i++, dm_mv++) {
- orig_index= index_array[i];
- if(orig_index != ORIGINDEX_NONE) {
- dm_mv->flag= me->mvert[index_array[i]].flag;
- }
- }
- }
- else {
- for (i= 0; i<totvert; i++, dm_mv++) {
- dm_mv->flag= me->mvert[i].flag;
- }
- }
-}
-/* note: if the caller passes FALSE to flush_flags, then they will need to run paintvert_flush_flags(ob) themselves */
-void paintvert_deselect_all_visible(Object *ob, int action, short flush_flags)
-{
- Mesh *me;
- MVert *mvert;
- int a;
-
- me= get_mesh(ob);
- if(me==NULL) return;
-
- if(action == SEL_INVERT) {
- mvert= me->mvert;
- a= me->totvert;
- while(a--) {
- if((mvert->flag & ME_HIDE) == 0) {
- mvert->flag ^= SELECT;
- }
- mvert++;
- }
- }
- else {
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
-
- mvert= me->mvert;
- a= me->totvert;
- while(a--) {
- if((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) {
- action = SEL_DESELECT;
- break;
- }
- mvert++;
- }
- }
-
- mvert= me->mvert;
- a= me->totvert;
- while(a--) {
- if((mvert->flag & ME_HIDE) == 0) {
- switch (action) {
- case SEL_SELECT:
- mvert->flag |= SELECT;
- break;
- case SEL_DESELECT:
- mvert->flag &= ~SELECT;
- break;
- case SEL_INVERT:
- mvert->flag ^= SELECT;
- break;
- }
- }
- mvert++;
- }
- }
-
- if(flush_flags) {
- paintvert_flush_flags(ob);
- }
-}
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
deleted file mode 100644
index 64fa322f2a5..00000000000
--- a/source/blender/editors/mesh/editmesh_add.c
+++ /dev/null
@@ -1,1790 +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) 2004 by Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/mesh/editmesh_add.c
- * \ingroup edmesh
- */
-
-
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-
-#include "RNA_define.h"
-#include "RNA_access.h"
-#include "RNA_enum_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_editVert.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_context.h"
-#include "BKE_depsgraph.h"
-#include "BKE_library.h"
-#include "BKE_mesh.h"
-#include "BKE_report.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "ED_mesh.h"
-#include "ED_screen.h"
-#include "ED_transform.h"
-#include "ED_view3d.h"
-#include "ED_object.h"
-
-#include "mesh_intern.h"
-
-/* bpymenu removed XXX */
-
-/* XXX */
-#define add_numbut(a, b, c, d, e, f, g) {}
-/* XXX */
-
-static float icovert[12][3] = {
- {0.0f,0.0f,-200.0f},
- {144.72f, -105.144f,-89.443f},
- {-55.277f, -170.128,-89.443f},
- {-178.885f,0.0f,-89.443f},
- {-55.277f,170.128f,-89.443f},
- {144.72f,105.144f,-89.443f},
- {55.277f,-170.128f,89.443f},
- {-144.72f,-105.144f,89.443f},
- {-144.72f,105.144f,89.443f},
- {55.277f,170.128f,89.443f},
- {178.885f,0.0f,89.443f},
- {0.0f,0.0f,200.0f}
-};
-static short icoface[20][3] = {
- {2,0,1},
- {1,0,5},
- {3,0,2},
- {4,0,3},
- {5,0,4},
- {1,5,10},
- {2,1,6},
- {3,2,7},
- {4,3,8},
- {5,4,9},
- {6,1,10},
- {7,2,6},
- {8,3,7},
- {9,4,8},
- {10,5,9},
- {6,10,11},
- {7,6,11},
- {8,7,11},
- {9,8,11},
- {10,9,11}
-};
-
-/* *************** add-click-mesh (extrude) operator ************** */
-
-static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
-{
- ViewContext vc;
- EditVert *eve;
- float min[3], max[3];
- int done= 0;
- short use_proj;
-
- em_setup_viewcontext(C, &vc);
-
- use_proj= (vc.scene->toolsettings->snap_flag & SCE_SNAP) && (vc.scene->toolsettings->snap_mode==SCE_SNAP_MODE_FACE);
-
- invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
-
- INIT_MINMAX(min, max);
-
- for(eve= vc.em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) {
- DO_MINMAX(eve->co, min, max);
- done= 1;
- }
- }
-
- /* call extrude? */
- if(done) {
- const short rot_src= RNA_boolean_get(op->ptr, "rotate_source");
- EditEdge *eed;
- float vec[3], cent[3], mat[3][3];
- float nor[3]= {0.0, 0.0, 0.0};
-
- /* 2D normal calc */
- float mval_f[2];
-
- mval_f[0]= (float)event->mval[0];
- mval_f[1]= (float)event->mval[1];
-
- done= 0;
-
- /* calculate the normal for selected edges */
- for(eed= vc.em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
- float co1[3], co2[3];
- mul_v3_m4v3(co1, vc.obedit->obmat, eed->v1->co);
- mul_v3_m4v3(co2, vc.obedit->obmat, eed->v2->co);
- project_float_noclip(vc.ar, co1, co1);
- project_float_noclip(vc.ar, co2, co2);
-
- /* 2D rotate by 90d while adding.
- * (x, y) = (y, -x)
- *
- * accumulate the screenspace normal in 2D,
- * with screenspace edge length weighting the result. */
- if(line_point_side_v2(co1, co2, mval_f) >= 0.0f) {
- nor[0] += (co1[1] - co2[1]);
- nor[1] += -(co1[0] - co2[0]);
- }
- else {
- nor[0] += (co2[1] - co1[1]);
- nor[1] += -(co2[0] - co1[0]);
- }
- done= 1;
- }
- }
-
- if(done) {
- float view_vec[3], cross[3];
-
- /* convert the 2D nomal into 3D */
- mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* worldspace */
- mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */
-
- /* correct the normal to be aligned on the view plane */
- copy_v3_v3(view_vec, vc.rv3d->viewinv[2]);
- mul_mat3_m4_v3(vc.obedit->imat, view_vec);
- cross_v3_v3v3(cross, nor, view_vec);
- cross_v3_v3v3(nor, view_vec, cross);
- normalize_v3(nor);
- }
-
- /* center */
- mid_v3_v3v3(cent, min, max);
- copy_v3_v3(min, cent);
-
- mul_m4_v3(vc.obedit->obmat, min); // view space
- view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE);
- mul_m4_v3(vc.obedit->imat, min); // back in object space
-
- sub_v3_v3(min, cent);
-
- /* calculate rotation */
- unit_m3(mat);
- if(done) {
- float dot;
-
- copy_v3_v3(vec, min);
- normalize_v3(vec);
- dot= dot_v3v3(vec, nor);
-
- if( fabs(dot)<0.999) {
- float cross[3], si, q1[4];
-
- cross_v3_v3v3(cross, nor, vec);
- normalize_v3(cross);
- dot= 0.5f*saacos(dot);
-
- /* halve the rotation if its applied twice */
- if(rot_src) dot *= 0.5f;
-
- si= (float)sin(dot);
- q1[0]= (float)cos(dot);
- q1[1]= cross[0]*si;
- q1[2]= cross[1]*si;
- q1[3]= cross[2]*si;
- quat_to_mat3( mat,q1);
- }
- }
-
- if(rot_src) {
- rotateflag(vc.em, SELECT, cent, mat);
- /* also project the source, for retopo workflow */
- if(use_proj)
- EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);
- }
-
- extrudeflag(vc.obedit, vc.em, SELECT, nor, 0);
- rotateflag(vc.em, SELECT, cent, mat);
- translateflag(vc.em, SELECT, min);
-
- recalc_editnormals(vc.em);
- }
- else if(vc.em->selectmode & SCE_SELECT_VERTEX) {
-
- float imat[4][4];
- const float *curs= give_cursor(vc.scene, vc.v3d);
-
- copy_v3_v3(min, curs);
- view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE);
-
- eve= addvertlist(vc.em, 0, NULL);
-
- invert_m4_m4(imat, vc.obedit->obmat);
- mul_v3_m4v3(eve->co, imat, min);
-
- eve->f= SELECT;
- }
-
- if(use_proj)
- EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);
-
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, vc.obedit->data);
- DAG_id_tag_update(vc.obedit->data, 0);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Duplicate or Extrude at 3D Cursor";
- ot->description= "Duplicate and extrude selected vertices, edges or faces towards 3D Cursor";
- ot->idname= "MESH_OT_dupli_extrude_cursor";
-
- /* api callbacks */
- ot->invoke= dupli_extrude_cursor;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "rotate_source", 1, "Rotate Source", "Rotate initial selection giving better shape");
-}
-
-
-/* ********************** */
-
-/* selected faces get hidden edges */
-static int make_fgon(EditMesh *em, wmOperator *op, int make)
-{
- EditFace *efa;
- EditEdge *eed;
- EditVert *eve;
- float *nor=NULL; // reference
- int done=0;
-
- if(make==0) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- efa->fgonf= 0;
- efa->e1->h &= ~EM_FGON;
- efa->e2->h &= ~EM_FGON;
- efa->e3->h &= ~EM_FGON;
- if(efa->e4) efa->e4->h &= ~EM_FGON;
- done= 1;
- }
- }
- EM_fgon_flags(em); // redo flags and indices for fgons
-
- return done;
- }
-
- /* tagging edges. rule is:
- - edge used by exactly 2 selected faces
- - no vertices allowed with only tagged edges (return)
- - face normals are allowed to difffer
-
- */
- for(eed= em->edges.first; eed; eed= eed->next) {
- eed->f1= 0; // amount of selected
- eed->f2= 0; // amount of unselected
- }
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- if(nor==NULL) nor= efa->n;
- if(efa->e1->f1 < 3) efa->e1->f1++;
- if(efa->e2->f1 < 3) efa->e2->f1++;
- if(efa->e3->f1 < 3) efa->e3->f1++;
- if(efa->e4 && efa->e4->f1 < 3) efa->e4->f1++;
- }
- else {
- if(efa->e1->f2 < 3) efa->e1->f2++;
- if(efa->e2->f2 < 3) efa->e2->f2++;
- if(efa->e3->f2 < 3) efa->e3->f2++;
- if(efa->e4 && efa->e4->f2 < 3) efa->e4->f2++;
- }
- }
- // now eed->f1 becomes tagged edge
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f1==2 && eed->f2==0) eed->f1= 1;
- else eed->f1= 0;
- }
-
- // no vertices allowed with only tagged edges
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f1) {
- eed->v1->f1 |= 1;
- eed->v2->f1 |= 1;
- }
- else {
- eed->v1->f1 |= 2;
- eed->v2->f1 |= 2;
- }
- }
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f1==1) break;
- }
- if(eve) {
- BKE_report(op->reports, RPT_WARNING, "Cannot make a polygon with interior vertices");
- return 0;
- }
-
- // check for faces
- if(nor==NULL) {
- BKE_report(op->reports, RPT_WARNING, "No faces were selected to make FGon");
- return 0;
- }
-
- // and there we go
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f1) {
- eed->h |= EM_FGON;
- done= 1;
- }
- }
-
- if(done)
- EM_fgon_flags(em); // redo flags and indices for fgons
- return done;
-}
-
-static int make_fgon_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- if( make_fgon(em, op, 1) ) {
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
- }
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
-}
-
-void MESH_OT_fgon_make(struct wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Make F-gon";
- ot->description= "Make fgon from selected faces";
- ot->idname= "MESH_OT_fgon_make";
-
- /* api callbacks */
- ot->exec= make_fgon_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int clear_fgon_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- if( make_fgon(em, op, 0) ) {
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
- }
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
-}
-
-void MESH_OT_fgon_clear(struct wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Clear F-gon";
- ot->description= "Clear fgon from selected face";
- ot->idname= "MESH_OT_fgon_clear";
-
- /* api callbacks */
- ot->exec= clear_fgon_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/* precondition; 4 vertices selected, check for 4 edges and create face */
-static EditFace *addface_from_edges(EditMesh *em)
-{
- EditEdge *eed, *eedar[4]={NULL, NULL, NULL, NULL};
- EditVert *v1=NULL, *v2=NULL, *v3=NULL, *v4=NULL;
- int a;
-
- /* find the 4 edges */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if( (eed->f & SELECT) || (eed->v1->f & eed->v2->f & SELECT) ) {
- if(eedar[0]==NULL) eedar[0]= eed;
- else if(eedar[1]==NULL) eedar[1]= eed;
- else if(eedar[2]==NULL) eedar[2]= eed;
- else eedar[3]= eed;
-
- }
- }
-
-
- if(eedar[3]) {
- /* first 2 points */
- v1= eedar[0]->v1;
- v2= eedar[0]->v2;
-
- /* find the 2 edges connected to first edge */
- for(a=1; a<4; a++) {
- if( eedar[a]->v1 == v2) v3= eedar[a]->v2;
- else if(eedar[a]->v2 == v2) v3= eedar[a]->v1;
- else if( eedar[a]->v1 == v1) v4= eedar[a]->v2;
- else if(eedar[a]->v2 == v1) v4= eedar[a]->v1;
- }
-
- /* verify if last edge exists */
- if(v3 && v4) {
- for(a=1; a<4; a++) {
- if( eedar[a]->v1==v3 && eedar[a]->v2==v4) break;
- if( eedar[a]->v2==v3 && eedar[a]->v1==v4) break;
- }
- if(a!=4) {
- return addfacelist(em, v1, v2, v3, v4, NULL, NULL);
- }
- }
- }
- return NULL;
-}
-
-/* ******************************* */
-
-/* this also allows to prevent triangles being made in quads */
-static int compareface_overlaps(EditFace *vl1, EditFace *vl2)
-{
- EditVert *v1, *v2, *v3, *v4;
- int equal= 0;
-
- v1= vl2->v1;
- v2= vl2->v2;
- v3= vl2->v3;
- v4= vl2->v4;
-
- if(vl1==vl2) return 0;
-
- if(v4==NULL && vl1->v4==NULL) {
- if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) equal++;
- if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) equal++;
- if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) equal++;
- }
- else {
- if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) equal++;
- if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) equal++;
- if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) equal++;
- if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) equal++;
- }
-
- if(v4 && vl1->v4) {
- if(equal==4) return 1;
- }
- else
- if(equal>=3) return 1;
-
- return 0;
-}
-
-/* checks for existence, and for tria overlapping inside quad */
-static EditFace *exist_face_overlaps(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4)
-{
- EditFace *efa, efatest;
-
- efatest.v1= v1;
- efatest.v2= v2;
- efatest.v3= v3;
- efatest.v4= v4;
-
- efa= em->faces.first;
- while(efa) {
- if(compareface_overlaps(&efatest, efa)) return efa;
- efa= efa->next;
- }
- return NULL;
-}
-
-/* will be new face smooth or solid? depends on smoothness of face neighbours
- * of new face, if function return 1, then new face will be smooth, when functio
- * will return zero, then new face will be solid */
-static void fix_new_face(EditMesh *em, EditFace *eface)
-{
- struct EditFace *efa;
- struct EditEdge *eed=NULL;
- struct EditVert *v1 = eface->v1, *v2 = eface->v2, *v3 = eface->v3, *v4 = eface->v4;
- struct EditVert *ev1=NULL, *ev2=NULL;
- short smooth=0; /* "total smoothnes" of faces in neighbourhood */
- short coef; /* "weight" of smoothness */
- short count=0; /* number of edges with same direction as eface */
- short vi00=0, vi01=0, vi10=0, vi11=0; /* vertex indexes */
-
- efa = em->faces.first;
-
- while(efa) {
-
- if(efa==eface) {
- efa = efa->next;
- continue;
- }
-
- coef = 0;
- ev1 = ev2 = NULL;
- eed = NULL;
-
- if(efa->v1==v1 || efa->v2==v1 || efa->v3==v1 || efa->v4==v1) {
- ev1 = v1;
- coef++;
- }
- if(efa->v1==v2 || efa->v2==v2 || efa->v3==v2 || efa->v4==v2) {
- if(ev1) ev2 = v2;
- else ev1 = v2;
- coef++;
- }
- if(efa->v1==v3 || efa->v2==v3 || efa->v3==v3 || efa->v4==v3) {
- if(coef<2) {
- if(ev1) ev2 = v3;
- else ev1 = v3;
- }
- coef++;
- }
- if((v4) && (efa->v1==v4 || efa->v2==v4 || efa->v3==v4 || efa->v4==v4)) {
- if(ev1 && coef<2) ev2 = v4;
- coef++;
- }
-
- /* "democracy" of smoothness */
- if(efa->flag & ME_SMOOTH)
- smooth += coef;
- else
- smooth -= coef;
-
- /* try to find edge using vertexes ev1 and ev2 */
- if((ev1) && (ev2) && (ev1!=ev2)) eed = findedgelist(em, ev1, ev2);
-
- /* has bordering edge of efa same direction as edge of eface ? */
- if(eed) {
- if(eed->v1==v1) vi00 = 1;
- else if(eed->v1==v2) vi00 = 2;
- else if(eed->v1==v3) vi00 = 3;
- else if(v4 && eed->v1==v4) vi00 = 4;
-
- if(eed->v2==v1) vi01 = 1;
- else if(eed->v2==v2) vi01 = 2;
- else if(eed->v2==v3) vi01 = 3;
- else if(v4 && eed->v2==v4) vi01 = 4;
-
- if(v4) {
- if(vi01==1 && vi00==4) vi00 = 0;
- if(vi01==4 && vi00==1) vi01 = 0;
- }
- else {
- if(vi01==1 && vi00==3) vi00 = 0;
- if(vi01==3 && vi00==1) vi01 = 0;
- }
-
- if(eed->v1==efa->v1) vi10 = 1;
- else if(eed->v1==efa->v2) vi10 = 2;
- else if(eed->v1==efa->v3) vi10 = 3;
- else if(efa->v4 && eed->v1==efa->v4) vi10 = 4;
-
- if(eed->v2==efa->v1) vi11 = 1;
- else if(eed->v2==efa->v2) vi11 = 2;
- else if(eed->v2==efa->v3) vi11 = 3;
- else if(efa->v4 && eed->v2==efa->v4) vi11 = 4;
-
- if(efa->v4) {
- if(vi11==1 && vi10==4) vi10 = 0;
- if(vi11==4 && vi10==1) vi11 = 0;
- }
- else {
- if(vi11==1 && vi10==3) vi10 = 0;
- if(vi11==3 && vi10==1) vi11 = 0;
- }
-
- if(((vi00>vi01) && (vi10>vi11)) ||
- ((vi00<vi01) && (vi10<vi11)))
- count++;
- else
- count--;
- }
-
- efa = efa->next;
- }
-
- /* set up smoothness according voting of face in neighbourhood */
- if(smooth >= 0)
- eface->flag |= ME_SMOOTH;
- else
- eface->flag &= ~ME_SMOOTH;
-
- /* flip face, when too much "face normals" in neighbourhood is different */
- if(count > 0) {
- flipface(em, eface);
- }
-}
-
-/* only adds quads or trias when there's edges already */
-static void addfaces_from_edgenet(EditMesh *em)
-{
- EditVert *eve1, *eve2, *eve3, *eve4;
-
- for(eve1= em->verts.first; eve1; eve1= eve1->next) {
- for(eve2= em->verts.first; (eve1->f & 1) && eve2; eve2= eve2->next) {
- if(findedgelist(em, eve1,eve2)) {
- for(eve3= em->verts.first; (eve2->f & 1) && eve3; eve3= eve3->next) {
- if((eve2!=eve3 && (eve3->f & 1) && findedgelist(em, eve1,eve3))) {
- EditEdge *sh_edge= NULL;
- EditVert *sh_vert= NULL;
-
- sh_edge= findedgelist(em, eve2,eve3);
-
- if(sh_edge) { /* Add a triangle */
- if(!exist_face_overlaps(em, eve1,eve2,eve3,NULL))
- fix_new_face(em, addfacelist(em, eve1,eve2,eve3,NULL,NULL,NULL));
- }
- else { /* Check for a shared vertex */
- for(eve4= em->verts.first; eve4; eve4= eve4->next) {
- if(eve4!=eve1 && eve4!=eve2 && eve4!=eve3 && (eve4->f & 1) &&
- !findedgelist(em, eve1,eve4) && findedgelist(em, eve2,eve4) &&
- findedgelist(em, eve3,eve4)) {
- sh_vert= eve4;
- break;
- }
- }
-
- if(sh_vert) {
- if(sh_vert) {
- if(!exist_face_overlaps(em, eve1,eve2,eve4,eve3))
- fix_new_face(em, addfacelist(em, eve1,eve2,eve4,eve3,NULL,NULL));
- }
- }
- }
- }
- }
- }
- }
- }
-
- EM_select_flush(em);
-
-// XXX DAG_id_tag_update(obedit->data, 0);
-}
-
-static void addedgeface_mesh(EditMesh *em, wmOperator *op)
-{
- EditVert *eve, *neweve[4];
- EditEdge *eed;
- EditFace *efa;
- short amount=0;
-
- /* how many selected ? */
- if(em->selectmode & SCE_SELECT_EDGE) {
- /* in edge mode finding selected vertices means flushing down edge codes... */
- /* can't make face with only edge selection info... */
- EM_selectmode_set(em);
- }
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) {
- amount++;
- if(amount>4) break;
- neweve[amount-1]= eve;
- }
- }
-
- if(amount==2) {
- eed= addedgelist(em, neweve[0], neweve[1], NULL);
- EM_select_edge(eed, 1);
-
- // XXX DAG_id_tag_update(obedit->data, 0);
- return;
- }
- else if(amount > 4) {
- addfaces_from_edgenet(em);
- return;
- }
- else if(amount<2) {
- BKE_report(op->reports, RPT_WARNING, "More vertices are needed to make an edge/face");
- return;
- }
-
- efa= NULL; // check later
-
- if(amount==3) {
-
- if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2], NULL)==0) {
- efa= addfacelist(em, neweve[0], neweve[1], neweve[2], 0, NULL, NULL);
- EM_select_face(efa, 1);
- }
- else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face");
- }
- else if(amount==4) {
- /* this test survives when theres 2 triangles */
- if(exist_face(em, neweve[0], neweve[1], neweve[2], neweve[3])==0) {
- int tria= 0;
-
- /* remove trias if they exist, 4 cases.... */
- if(exist_face(em, neweve[0], neweve[1], neweve[2], NULL)) tria++;
- if(exist_face(em, neweve[0], neweve[1], neweve[3], NULL)) tria++;
- if(exist_face(em, neweve[0], neweve[2], neweve[3], NULL)) tria++;
- if(exist_face(em, neweve[1], neweve[2], neweve[3], NULL)) tria++;
-
- if(tria==2) join_triangles(em);
- else if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2], neweve[3])==0) {
- /* If there are 4 Verts, But more selected edges, we need to call addfaces_from_edgenet */
- EditEdge *eedcheck;
- int count;
- count = 0;
- for(eedcheck= em->edges.first; eedcheck; eedcheck= eedcheck->next) {
- if(eedcheck->f & SELECT) {
- count++;
- }
- }
-
- if(count++ > 4){
- addfaces_from_edgenet(em);
- return;
- } else {
- /* if 4 edges exist, we just create the face, convex or not */
- efa= addface_from_edges(em);
- if(efa==NULL) {
-
- /* the order of vertices can be anything, 6 cases to check */
- if( convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co) ) {
- efa= addfacelist(em, neweve[0], neweve[1], neweve[2], neweve[3], NULL, NULL);
- }
- else if( convex(neweve[0]->co, neweve[2]->co, neweve[3]->co, neweve[1]->co) ) {
- efa= addfacelist(em, neweve[0], neweve[2], neweve[3], neweve[1], NULL, NULL);
- }
- else if( convex(neweve[0]->co, neweve[2]->co, neweve[1]->co, neweve[3]->co) ) {
- efa= addfacelist(em, neweve[0], neweve[2], neweve[1], neweve[3], NULL, NULL);
- }
- else if( convex(neweve[0]->co, neweve[1]->co, neweve[3]->co, neweve[2]->co) ) {
- efa= addfacelist(em, neweve[0], neweve[1], neweve[3], neweve[2], NULL, NULL);
- }
- else if( convex(neweve[0]->co, neweve[3]->co, neweve[2]->co, neweve[1]->co) ) {
- efa= addfacelist(em, neweve[0], neweve[3], neweve[2], neweve[1], NULL, NULL);
- }
- else if( convex(neweve[0]->co, neweve[3]->co, neweve[1]->co, neweve[2]->co) ) {
- efa= addfacelist(em, neweve[0], neweve[3], neweve[1], neweve[2], NULL, NULL);
- }
- else BKE_report(op->reports, RPT_WARNING, "cannot find nice quad from concave set of vertices");
-
- }
- }
- }
- else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face");
- }
- else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face");
- }
-
- if(efa) {
- EM_select_face(efa, 1);
-
- fix_new_face(em, efa);
-
- recalc_editnormals(em);
- }
- }
-
-static int addedgeface_mesh_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- addedgeface_mesh(em, op);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_edge_face_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Make Edge/Face";
- ot->description= "Add an edge or face to selected";
- ot->idname= "MESH_OT_edge_face_add";
-
- /* api callbacks */
- ot->exec= addedgeface_mesh_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
-}
-
-
-
-/* ************************ primitives ******************* */
-
-// HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker
-// this hack is only used so that scons+mingw + split-sources hack works
- // ------------------------------- start copied code
-/* these are not the monkeys you are looking for */
-static int monkeyo= 4;
-static int monkeynv= 271;
-static int monkeynf= 250;
-static signed char monkeyv[271][3]= {
-{-71,21,98},{-63,12,88},{-57,7,74},{-82,-3,79},{-82,4,92},
-{-82,17,100},{-92,21,102},{-101,12,95},{-107,7,83},
-{-117,31,84},{-109,31,95},{-96,31,102},{-92,42,102},
-{-101,50,95},{-107,56,83},{-82,66,79},{-82,58,92},
-{-82,46,100},{-71,42,98},{-63,50,88},{-57,56,74},
-{-47,31,72},{-55,31,86},{-67,31,97},{-66,31,99},
-{-70,43,100},{-82,48,103},{-93,43,105},{-98,31,105},
-{-93,20,105},{-82,31,106},{-82,15,103},{-70,20,100},
-{-127,55,95},{-127,45,105},{-127,-87,94},{-127,-41,100},
-{-127,-24,102},{-127,-99,92},{-127,52,77},{-127,73,73},
-{-127,115,-70},{-127,72,-109},{-127,9,-106},{-127,-49,-45},
-{-101,-24,72},{-87,-56,73},{-82,-89,73},{-80,-114,68},
-{-85,-121,67},{-104,-124,71},{-127,-126,74},{-71,-18,68},
-{-46,-5,69},{-21,19,57},{-17,55,76},{-36,62,80},
-{-64,77,88},{-86,97,94},{-107,92,97},{-119,63,96},
-{-106,53,99},{-111,39,98},{-101,12,95},{-79,2,90},
-{-64,8,86},{-47,24,83},{-45,38,83},{-50,48,85},
-{-72,56,92},{-95,60,97},{-127,-98,94},{-113,-92,94},
-{-112,-107,91},{-119,-113,89},{-127,-114,88},{-127,-25,96},
-{-127,-18,95},{-114,-19,95},{-111,-29,96},{-116,-37,95},
-{-76,-6,86},{-48,7,80},{-34,26,77},{-32,48,84},
-{-39,53,93},{-71,70,102},{-87,82,107},{-101,79,109},
-{-114,55,108},{-111,-13,104},{-100,-57,91},{-95,-90,88},
-{-93,-105,85},{-97,-117,81},{-106,-119,81},{-127,-121,82},
-{-127,6,93},{-127,27,98},{-85,61,95},{-106,18,96},
-{-110,27,97},{-112,-88,94},{-117,-57,96},{-127,-57,96},
-{-127,-42,95},{-115,-35,100},{-110,-29,102},{-113,-17,100},
-{-122,-16,100},{-127,-26,106},{-121,-19,104},{-115,-20,104},
-{-113,-29,106},{-117,-32,103},{-127,-37,103},{-94,-40,71},
-{-106,-31,91},{-104,-40,91},{-97,-32,71},{-127,-112,88},
-{-121,-111,88},{-115,-105,91},{-115,-95,93},{-127,-100,84},
-{-115,-96,85},{-115,-104,82},{-121,-109,81},{-127,-110,81},
-{-105,28,100},{-103,20,99},{-84,55,97},{-92,54,99},
-{-73,51,99},{-55,45,89},{-52,37,88},{-53,25,87},
-{-66,13,92},{-79,8,95},{-98,14,100},{-104,38,100},
-{-100,48,100},{-97,46,97},{-102,38,97},{-96,16,97},
-{-79,11,93},{-68,15,90},{-57,27,86},{-56,36,86},
-{-59,43,87},{-74,50,96},{-91,51,98},{-84,52,96},
-{-101,22,96},{-102,29,96},{-113,59,78},{-102,85,79},
-{-84,88,76},{-65,71,71},{-40,58,63},{-25,52,59},
-{-28,21,48},{-50,0,53},{-71,-12,60},{-127,115,37},
-{-127,126,-10},{-127,-25,-86},{-127,-59,24},{-127,-125,59},
-{-127,-103,44},{-127,-73,41},{-127,-62,36},{-18,30,7},
-{-17,41,-6},{-28,34,-56},{-68,56,-90},{-33,-6,9},
-{-51,-16,-21},{-45,-1,-55},{-84,7,-85},{-97,-45,52},
-{-104,-53,33},{-90,-91,49},{-95,-64,50},{-85,-117,51},
-{-109,-97,47},{-111,-69,46},{-106,-121,56},{-99,-36,55},
-{-100,-29,60},{-101,-22,64},{-100,-50,21},{-89,-40,-34},
-{-83,-19,-69},{-69,111,-49},{-69,119,-9},{-69,109,30},
-{-68,67,55},{-34,52,43},{-46,58,36},{-45,90,7},
-{-25,72,16},{-25,79,-15},{-45,96,-25},{-45,87,-57},
-{-25,69,-46},{-48,42,-75},{-65,3,-70},{-22,42,-26},
-{-75,-22,19},{-72,-25,-27},{-13,52,-30},{-28,-18,-16},
-{6,-13,-42},{37,7,-55},{46,41,-54},{31,65,-54},
-{4,61,-40},{3,53,-37},{25,56,-50},{35,37,-52},
-{28,10,-52},{5,-5,-39},{-21,-9,-17},{-9,46,-28},
-{-6,39,-37},{-14,-3,-27},{6,0,-47},{25,12,-57},
-{31,32,-57},{23,46,-56},{4,44,-46},{-19,37,-27},
-{-20,22,-35},{-30,12,-35},{-22,11,-35},{-19,2,-35},
-{-23,-2,-35},{-34,0,-9},{-35,-3,-22},{-35,5,-24},
-{-25,26,-27},{-13,31,-34},{-13,30,-41},{-23,-2,-41},
-{-18,2,-41},{-21,10,-41},{-29,12,-41},{-19,22,-41},
-{6,42,-53},{25,44,-62},{34,31,-63},{28,11,-62},
-{7,0,-54},{-14,-2,-34},{-5,37,-44},{-13,14,-42},
-{-7,8,-43},{1,16,-47},{-4,22,-45},{3,30,-48},
-{8,24,-49},{15,27,-50},{12,35,-50},{4,56,-62},
-{33,60,-70},{48,38,-64},{41,7,-68},{6,-11,-63},
-{-26,-16,-42},{-17,49,-49},
-};
-
-static signed char monkeyf[250][4]= {
-{27,4,5,26}, {25,4,5,24}, {3,6,5,4}, {1,6,5,2}, {5,6,7,4},
-{3,6,7,2}, {5,8,7,6}, {3,8,7,4}, {7,8,9,6},
-{5,8,9,4}, {7,10,9,8}, {5,10,9,6}, {9,10,11,8},
-{7,10,11,6}, {9,12,11,10}, {7,12,11,8}, {11,6,13,12},
-{5,4,13,12}, {3,-2,13,12}, {-3,-4,13,12}, {-5,-10,13,12},
-{-11,-12,14,12}, {-13,-18,14,13}, {-19,4,5,13}, {10,12,4,4},
-{10,11,9,9}, {8,7,9,9}, {7,5,6,6}, {6,3,4,4},
-{5,1,2,2}, {4,-1,0,0}, {3,-3,-2,-2}, {22,67,68,23},
-{20,65,66,21}, {18,63,64,19}, {16,61,62,17}, {14,59,60,15},
-{12,19,48,57}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47},
-{18,19,48,47}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47},
-{18,19,48,47}, {18,-9,-8,47}, {18,27,45,46}, {26,55,43,44},
-{24,41,42,54}, {22,39,40,23}, {20,37,38,21}, {18,35,36,19},
-{16,33,34,17}, {14,31,32,15}, {12,39,30,13}, {11,48,45,38},
-{8,36,-19,9}, {8,-20,44,47}, {42,45,46,43}, {18,19,40,39},
-{16,17,38,37}, {14,15,36,35}, {32,44,43,33}, {12,33,32,42},
-{19,44,43,42}, {40,41,42,-27}, {8,9,39,-28}, {15,43,42,16},
-{13,43,42,14}, {11,43,42,12}, {9,-30,42,10}, {37,12,38,-32},
-{-33,37,45,46}, {-33,40,41,39}, {38,40,41,37}, {36,40,41,35},
-{34,40,41,33}, {36,39,38,37}, {35,40,39,38}, {1,2,14,21},
-{1,2,40,13}, {1,2,40,39}, {1,24,12,39}, {-34,36,38,11},
-{35,38,36,37}, {-37,8,35,37}, {-11,-12,-45,40}, {-11,-12,39,38},
-{-11,-12,37,36}, {-11,-12,35,34}, {33,34,40,41}, {33,34,38,39},
-{33,34,36,37}, {33,-52,34,35}, {33,37,36,34}, {33,35,34,34},
-{8,7,37,36}, {-32,7,35,46}, {-34,-33,45,46}, {4,-33,43,34},
-{-34,-33,41,42}, {-34,-33,39,40}, {-34,-33,37,38}, {-34,-33,35,36},
-{-34,-33,33,34}, {-34,-33,31,32}, {-34,-4,28,30}, {-5,-34,28,27},
-{-35,-44,36,27}, {26,35,36,45}, {24,25,44,45}, {25,23,44,42},
-{25,24,41,40}, {25,24,39,38}, {25,24,37,36}, {25,24,35,34},
-{25,24,33,32}, {25,24,31,30}, {15,24,29,38}, {25,24,27,26},
-{23,12,37,26}, {11,12,35,36}, {-86,-59,36,-80}, {-60,-61,36,35},
-{-62,-63,36,35}, {-64,-65,36,35}, {-66,-67,36,35}, {-68,-69,36,35},
-{-70,-71,36,35}, {-72,-73,36,35}, {-74,-75,36,35}, {42,43,53,58},
-{40,41,57,56}, {38,39,55,57}, {-81,-80,37,56}, {-83,-82,55,52},
-{-85,-84,51,49}, {-87,-86,48,49}, {47,50,51,48}, {46,48,51,49},
-{43,46,49,44}, {-92,-91,45,42}, {-23,49,50,-20}, {-94,40,48,-24},
-{-96,-22,48,49}, {-97,48,21,-90}, {-100,36,50,23}, {22,49,48,-100},
-{-101,47,46,22}, {21,45,35,25}, {33,34,44,41}, {13,14,28,24},
-{-107,26,30,-106}, {14,46,45,15}, {14,44,43,-110}, {-111,42,23,-110},
-{6,7,45,46}, {45,44,47,46}, {45,46,47,48}, {47,46,49,48},
-{17,49,47,48}, {17,36,46,48}, {35,36,44,45}, {35,36,40,43},
-{35,36,38,39}, {-4,-3,37,35}, {-123,34,33,1}, {-9,-8,-7,-6},
-{-10,-7,32,-125}, {-127,-11,-126,-126}, {-7,-6,5,31}, {4,5,33,30},
-{4,39,33,32}, {4,35,32,38}, {20,21,39,38}, {4,37,38,5},
-{-11,-10,36,3}, {-11,15,14,35}, {13,16,34,34}, {-13,14,13,13},
-{-3,1,30,29}, {-3,28,29,1}, {-2,31,28,-1}, {12,13,27,30},
-{-2,26,12,12}, {35,29,42,36}, {34,35,36,33}, {32,35,36,31},
-{30,35,36,29}, {28,35,36,27}, {26,35,36,25}, {34,39,38,35},
-{32,39,38,33}, {30,39,38,31}, {28,39,38,29}, {26,39,38,27},
-{25,31,32,38}, {-18,-17,45,44}, {-18,17,28,44}, {-24,-20,42,-23},
-{11,35,27,14}, {25,28,39,41}, {37,41,40,38}, {34,40,36,35},
-{32,40,39,33}, {30,39,31,40}, {21,29,39,22}, {-31,37,28,4},
-{-32,33,35,36}, {32,33,34,34}, {18,35,36,48}, {34,25,40,35},
-{24,25,38,39}, {24,25,36,37}, {24,25,34,35}, {24,25,32,33},
-{24,13,41,31}, {17,11,41,35}, {15,16,34,35}, {13,14,34,35},
-{11,12,34,35}, {9,10,34,35}, {7,8,34,35}, {26,25,37,36},
-{35,36,37,38}, {37,36,39,38}, {37,38,39,40}, {25,31,36,39},
-{18,34,35,30}, {17,22,30,33}, {19,29,21,20}, {16,26,29,17},
-{24,29,28,25}, {22,31,28,23}, {20,31,30,21}, {18,31,30,19},
-{16,30,17,17}, {-21,-22,35,34}, {-21,-22,33,32}, {-21,-22,31,30},
-{-21,-22,29,28}, {-21,-22,27,26}, {-28,-22,25,31}, {24,28,29,30},
-{23,24,26,27}, {23,24,25,25}, {-69,-35,-32,27}, {-70,26,25,-66},
-{-68,-67,24,-33},
-};
- // ------------------------------- end copied code
-
-
-#define PRIM_PLANE 0
-#define PRIM_CUBE 1
-#define PRIM_CIRCLE 4
-#define PRIM_CYLINDER 5
-#define PRIM_CONE 7
-#define PRIM_GRID 10
-#define PRIM_UVSPHERE 11
-#define PRIM_ICOSPHERE 12
-#define PRIM_MONKEY 13
-
-static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int seg,
- int subdiv, float dia, float depth, int ext, int fill)
-{
- /*
- * type - for the type of shape
- * dia - the radius for cone,sphere cylinder etc.
- * depth -
- * ext - extrude
- * fill - end capping, and option to fill in circle
- * cent[3] - center of the data.
- * */
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- EditVert *eve, *v1=NULL, *v2, *v3, *v4=NULL, *vtop, *vdown;
- float phi, phid, vec[3];
- float q[4], cmat[3][3], nor[3]= {0.0, 0.0, 0.0};
- short a, b;
-
- EM_clear_flag_all(em, SELECT);
-
- phid= 2.0f*(float)M_PI/tot;
- phi= .25f*(float)M_PI;
-
- switch(type) {
- case PRIM_GRID: /* grid */
- /* clear flags */
- eve= em->verts.first;
- while(eve) {
- eve->f= 0;
- eve= eve->next;
- }
-
- /* one segment first: the X axis */
- phi = (2*dia)/(float)(tot-1);
- phid = (2*dia)/(float)(seg-1);
- for(a=tot-1;a>=0;a--) {
- vec[0] = (phi*a) - dia;
- vec[1]= - dia;
- vec[2]= 0.0f;
- eve= addvertlist(em, vec, NULL);
- eve->f= 1+2+4;
- if(a < tot -1) addedgelist(em, eve->prev, eve, NULL);
- }
- /* extrude and translate */
- vec[0]= vec[2]= 0.0;
- vec[1]= phid;
-
- for(a=0;a<seg-1;a++) {
- extrudeflag_vert(obedit, em, 2, nor, 0); // nor unused
- translateflag(em, 2, vec);
- }
-
- /* and now do imat */
- eve= em->verts.first;
- while(eve) {
- if(eve->f & SELECT) {
- mul_m4_v3(mat,eve->co);
- }
- eve= eve->next;
- }
- recalc_editnormals(em);
- break;
-
- case PRIM_UVSPHERE: /* UVsphere */
-
- /* clear all flags */
- eve= em->verts.first;
- while(eve) {
- eve->f= 0;
- eve= eve->next;
- }
-
- /* one segment first */
- phi= 0;
- phid/=2;
- for(a=0; a<=tot; a++) {
- vec[0]= dia*sinf(phi);
- vec[1]= 0.0;
- vec[2]= dia*cosf(phi);
- eve= addvertlist(em, vec, NULL);
- eve->f= 1+2+4;
- if(a==0) v1= eve;
- else addedgelist(em, eve, eve->prev, NULL);
- phi+= phid;
- }
-
- /* extrude and rotate */
- phi= M_PI/seg;
- q[0]= cos(phi);
- q[3]= sin(phi);
- q[1]=q[2]= 0;
- quat_to_mat3( cmat,q);
-
- for(a=0; a<seg; a++) {
- extrudeflag_vert(obedit, em, 2, nor, 0); // nor unused
- rotateflag(em, 2, v1->co, cmat);
- }
-
- removedoublesflag(em, 4, 0, 0.0001);
-
- /* and now do imat */
- eve= em->verts.first;
- while(eve) {
- if(eve->f & SELECT) {
- mul_m4_v3(mat,eve->co);
- }
- eve= eve->next;
- }
- recalc_editnormals(em);
- break;
- case PRIM_ICOSPHERE: /* Icosphere */
- {
- EditVert *eva[12];
- EditEdge *eed;
-
- /* clear all flags */
- eve= em->verts.first;
- while(eve) {
- eve->f= 0;
- eve= eve->next;
- }
- dia/=200;
- for(a=0;a<12;a++) {
- vec[0]= dia*icovert[a][0];
- vec[1]= dia*icovert[a][1];
- vec[2]= dia*icovert[a][2];
- eva[a]= addvertlist(em, vec, NULL);
- eva[a]->f= 1+2;
- }
- for(a=0;a<20;a++) {
- EditFace *evtemp;
- v1= eva[ icoface[a][0] ];
- v2= eva[ icoface[a][1] ];
- v3= eva[ icoface[a][2] ];
- evtemp = addfacelist(em, v1, v2, v3, 0, NULL, NULL);
- evtemp->e1->f = 1+2;
- evtemp->e2->f = 1+2;
- evtemp->e3->f = 1+2;
- }
-
- dia*=200;
- for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0, B_SPHERE,1, SUBDIV_CORNER_PATH, 0);
- /* and now do imat */
- eve= em->verts.first;
- while(eve) {
- if(eve->f & 2) {
- mul_m4_v3(mat,eve->co);
- }
- eve= eve->next;
- }
-
- // Clear the flag 2 from the edges
- for(eed=em->edges.first;eed;eed=eed->next){
- if(eed->f & 2){
- eed->f &= !2;
- }
- }
- }
- break;
- case PRIM_MONKEY: /* Monkey */
- {
- //extern int monkeyo, monkeynv, monkeynf;
- //extern signed char monkeyf[][4];
- //extern signed char monkeyv[][3];
- EditVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv");
- int i;
-
- for (i=0; i<monkeynv; i++) {
- float v[3];
- v[0]= (monkeyv[i][0]+127)/128.0, v[1]= monkeyv[i][1]/128.0, v[2]= monkeyv[i][2]/128.0;
- tv[i]= addvertlist(em, v, NULL);
- tv[i]->f |= SELECT;
- tv[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]:addvertlist(em, v, NULL);
- tv[monkeynv+i]->f |= SELECT;
- }
- for (i=0; i<monkeynf; i++) {
- addfacelist(em, tv[monkeyf[i][0]+i-monkeyo], tv[monkeyf[i][1]+i-monkeyo], tv[monkeyf[i][2]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL);
- addfacelist(em, tv[monkeynv+monkeyf[i][2]+i-monkeyo], tv[monkeynv+monkeyf[i][1]+i-monkeyo], tv[monkeynv+monkeyf[i][0]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeynv+monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL);
- }
-
- MEM_freeN(tv);
-
- /* and now do imat */
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) {
- mul_m4_v3(mat,eve->co);
- }
- }
- recalc_editnormals(em);
- }
- break;
- default: /* all types except grid, sphere... */
- if(type==PRIM_CONE);
- else if(ext==0)
- depth= 0.0f;
-
- /* first vertex at 0° for circular objects */
- if( ELEM3(type, PRIM_CIRCLE,PRIM_CYLINDER,PRIM_CONE) )
- phi = 0.0f;
-
- vtop= vdown= v1= v2= 0;
- for(b=0; b<=ext; b++) {
- for(a=0; a<tot; a++) {
-
- vec[0]= dia*sinf(phi);
- vec[1]= dia*cosf(phi);
- vec[2]= b?depth:-depth;
-
- mul_m4_v3(mat, vec);
- eve= addvertlist(em, vec, NULL);
- eve->f= SELECT;
- if(a==0) {
- if(b==0) v1= eve;
- else v2= eve;
- }
- phi+=phid;
- }
- }
-
- /* center vertices */
- /* type PRIM_CONE can only have 1 one side filled
- * if the cone has no capping, dont add vtop */
- if(type == PRIM_CONE || (fill && !ELEM(type, PRIM_PLANE, PRIM_CUBE))) {
- vec[0]= vec[1]= 0.0f;
- vec[2]= type==PRIM_CONE ? depth : -depth;
- mul_m4_v3(mat, vec);
- vdown= addvertlist(em, vec, NULL);
- if((ext || type==PRIM_CONE) && fill) {
- vec[0]= vec[1]= 0.0f;
- vec[2]= type==PRIM_CONE ? -depth : depth;
- mul_m4_v3(mat,vec);
- vtop= addvertlist(em, vec, NULL);
- }
- } else {
- vdown= v1;
- vtop= v2;
- }
- if(vtop) vtop->f= SELECT;
- if(vdown) vdown->f= SELECT;
-
- /* top and bottom face */
- if(fill || type==PRIM_CONE) {
- if(tot==4 && ELEM(type, PRIM_PLANE, PRIM_CUBE)) {
- v3= v1->next->next;
- if(ext) v4= v2->next->next;
-
- addfacelist(em, v3, v1->next, v1, v3->next, NULL, NULL);
- if(ext) addfacelist(em, v2, v2->next, v4, v4->next, NULL, NULL);
-
- }
- else {
- v3= v1;
- v4= v2;
- for(a=1; a<tot; a++) {
- addfacelist(em, vdown, v3, v3->next, 0, NULL, NULL);
- v3= v3->next;
- if(ext && fill) {
- addfacelist(em, vtop, v4, v4->next, 0, NULL, NULL);
- v4= v4->next;
- }
- }
- if(!ELEM(type, PRIM_PLANE, PRIM_CUBE)) {
- addfacelist(em, vdown, v3, v1, 0, NULL, NULL);
- if(ext) addfacelist(em, vtop, v4, v2, 0, NULL, NULL);
- }
- }
- }
- else if(type==PRIM_CIRCLE) { /* we need edges for a circle */
- v3= v1;
- for(a=1;a<tot;a++) {
- addedgelist(em, v3, v3->next, NULL);
- v3= v3->next;
- }
- addedgelist(em, v3, v1, NULL);
- }
- /* side faces */
- if(ext) {
- v3= v1;
- v4= v2;
- for(a=1; a<tot; a++) {
- addfacelist(em, v3, v3->next, v4->next, v4, NULL, NULL);
- v3= v3->next;
- v4= v4->next;
- }
- addfacelist(em, v3, v1, v2, v4, NULL, NULL);
- }
- else if(fill && type==PRIM_CONE) {
- /* add the bottom flat area of the cone
- * if capping is disabled dont bother */
- v3= v1;
- for(a=1; a<tot; a++) {
- addfacelist(em, vtop, v3->next, v3, 0, NULL, NULL);
- v3= v3->next;
- }
- addfacelist(em, vtop, v1, v3, 0, NULL, NULL);
- }
- }
-
- EM_stats_update(em);
- /* simple selection flush OK, based on fact it's a single model */
- EM_select_flush(em); /* flushes vertex -> edge -> face selection */
-
- if(!ELEM5(type, PRIM_GRID, PRIM_PLANE, PRIM_ICOSPHERE, PRIM_UVSPHERE, PRIM_MONKEY))
- EM_recalc_normal_direction(em, FALSE, TRUE); /* otherwise monkey has eyes in wrong direction */
-
- BKE_mesh_end_editmesh(obedit->data, em);
-}
-
-/* ********* add primitive operators ************* */
-
-static const char *get_mesh_defname(int type)
-{
- switch (type) {
- case PRIM_PLANE: return "Plane";
- case PRIM_CUBE: return "Cube";
- case PRIM_CIRCLE: return "Circle";
- case PRIM_CYLINDER: return "Cylinder";
- case PRIM_CONE: return "Cone";
- case PRIM_GRID: return "Grid";
- case PRIM_UVSPHERE: return "Sphere";
- case PRIM_ICOSPHERE: return "Icosphere";
- case PRIM_MONKEY: return "Monkey";
- default:
- return "Mesh";
- }
-}
-
-static void make_prim_ext(bContext *C, float *loc, float *rot, int enter_editmode, unsigned int layer,
- int type, int tot, int seg,
- int subdiv, float dia, float depth, int ext, int fill)
-{
- Object *obedit= CTX_data_edit_object(C);
- int newob = 0;
- float mat[4][4];
- float scale;
-
- if(obedit==NULL || obedit->type!=OB_MESH) {
- obedit= ED_object_add_type(C, OB_MESH, loc, rot, FALSE, layer);
-
- rename_id((ID *)obedit, get_mesh_defname(type));
- rename_id((ID *)obedit->data, get_mesh_defname(type));
-
- /* create editmode */
- ED_object_enter_editmode(C, EM_DO_UNDO|EM_IGNORE_LAYER); /* rare cases the active layer is messed up */
- newob = 1;
- }
- else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
-
- scale= ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
-
- dia *= scale;
- depth *= scale * 0.5f;
-
- make_prim(obedit, type, mat, tot, seg, subdiv, dia, depth, ext, fill);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
-
- /* userdef */
- if (newob && !enter_editmode) {
- ED_object_exit_editmode(C, EM_FREEDATA); /* adding EM_DO_UNDO messes up operator redo */
- }
- WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
-}
-
-static int add_primitive_plane_exec(bContext *C, wmOperator *op)
-{
- int enter_editmode;
- unsigned int layer;
- float loc[3], rot[3];
-
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
- return OPERATOR_CANCELLED;
-
- /* sqrt(2.0f) - plane (diameter of 1.41 makes it unit size) */
- make_prim_ext(C, loc, rot, enter_editmode, layer,
- PRIM_PLANE, 4, 0, 0, sqrt(2.0f), 0.0f, 0, 1);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_primitive_plane_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Add Plane";
- ot->description= "Construct a filled planar mesh with 4 vertices";
- ot->idname= "MESH_OT_primitive_plane_add";
-
- /* api callbacks */
- ot->invoke= ED_object_add_generic_invoke;
- ot->exec= add_primitive_plane_exec;
- ot->poll= ED_operator_scene_editable;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_cube_exec(bContext *C, wmOperator *op)
-{
- int enter_editmode;
- unsigned int layer;
- float loc[3], rot[3];
-
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
- return OPERATOR_CANCELLED;
-
- /* sqrt(2.0f) - plane (diameter of 1.41 makes it unit size) */
- make_prim_ext(C, loc, rot, enter_editmode, layer,
- PRIM_CUBE, 4, 0, 0, sqrt(2.0f), 2.0f, 1, 1);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_primitive_cube_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Add Cube";
- ot->description= "Construct a cube mesh";
- ot->idname= "MESH_OT_primitive_cube_add";
-
- /* api callbacks */
- ot->invoke= ED_object_add_generic_invoke;
- ot->exec= add_primitive_cube_exec;
- ot->poll= ED_operator_scene_editable;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_circle_exec(bContext *C, wmOperator *op)
-{
- int enter_editmode;
- unsigned int layer;
- float loc[3], rot[3];
-
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
- return OPERATOR_CANCELLED;
-
- make_prim_ext(C, loc, rot, enter_editmode, layer,
- PRIM_CIRCLE, RNA_int_get(op->ptr, "vertices"), 0, 0,
- RNA_float_get(op->ptr,"radius"), 0.0f, 0,
- RNA_boolean_get(op->ptr, "fill"));
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_primitive_circle_add(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Add Circle";
- ot->description= "Construct a circle mesh";
- ot->idname= "MESH_OT_primitive_circle_add";
-
- /* api callbacks */
- ot->invoke= ED_object_add_generic_invoke;
- ot->exec= add_primitive_circle_exec;
- ot->poll= ED_operator_scene_editable;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_int(ot->srna, "vertices", 32, 3, INT_MAX, "Vertices", "", 3, 500);
- prop = RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
- RNA_def_boolean(ot->srna, "fill", 0, "Fill", "");
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
-{
- int enter_editmode;
- unsigned int layer;
- float loc[3], rot[3];
-
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
- return OPERATOR_CANCELLED;
-
- make_prim_ext(C, loc, rot, enter_editmode, layer,
- PRIM_CYLINDER, RNA_int_get(op->ptr, "vertices"), 0, 0,
- RNA_float_get(op->ptr,"radius"),
- RNA_float_get(op->ptr, "depth"), 1,
- RNA_boolean_get(op->ptr, "cap_ends"));
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Add Cylinder";
- ot->description= "Construct a cylinder mesh";
- ot->idname= "MESH_OT_primitive_cylinder_add";
-
- /* api callbacks */
- ot->invoke= ED_object_add_generic_invoke;
- ot->exec= add_primitive_cylinder_exec;
- ot->poll= ED_operator_scene_editable;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_int(ot->srna, "vertices", 32, 2, INT_MAX, "Vertices", "", 2, 500);
- prop = RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
- prop = RNA_def_float(ot->srna, "depth", 2.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
- RNA_def_boolean(ot->srna, "cap_ends", 1, "Cap Ends", "");
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_cone_exec(bContext *C, wmOperator *op)
-{
- int enter_editmode;
- unsigned int layer;
- float loc[3], rot[3];
-
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
- return OPERATOR_CANCELLED;
-
- make_prim_ext(C, loc, rot, enter_editmode, layer,
- PRIM_CONE, RNA_int_get(op->ptr, "vertices"), 0, 0,
- RNA_float_get(op->ptr,"radius"), RNA_float_get(op->ptr, "depth"),
- 0, RNA_boolean_get(op->ptr, "cap_end"));
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_primitive_cone_add(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Add Cone";
- ot->description= "Construct a conic mesh (ends filled)";
- ot->idname= "MESH_OT_primitive_cone_add";
-
- /* api callbacks */
- ot->invoke= ED_object_add_generic_invoke;
- ot->exec= add_primitive_cone_exec;
- ot->poll= ED_operator_scene_editable;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_int(ot->srna, "vertices", 32, 2, INT_MAX, "Vertices", "", 2, 500);
- prop = RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
- prop = RNA_def_float(ot->srna, "depth", 2.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
- RNA_def_boolean(ot->srna, "cap_end", 1, "Cap End", "");
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_grid_exec(bContext *C, wmOperator *op)
-{
- int enter_editmode;
- unsigned int layer;
- float loc[3], rot[3];
-
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
- return OPERATOR_CANCELLED;
-
- make_prim_ext(C, loc, rot, enter_editmode, layer,
- PRIM_GRID, RNA_int_get(op->ptr, "x_subdivisions"),
- RNA_int_get(op->ptr, "y_subdivisions"), 0,
- RNA_float_get(op->ptr,"size"), 0.0f, 0, 1);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_primitive_grid_add(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Add Grid";
- ot->description= "Construct a grid mesh";
- ot->idname= "MESH_OT_primitive_grid_add";
-
- /* api callbacks */
- ot->invoke= ED_object_add_generic_invoke;
- ot->exec= add_primitive_grid_exec;
- ot->poll= ED_operator_scene_editable;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_int(ot->srna, "x_subdivisions", 10, 3, INT_MAX, "X Subdivisions", "", 3, 1000);
- RNA_def_int(ot->srna, "y_subdivisions", 10, 3, INT_MAX, "Y Subdivisions", "", 3, 1000);
- prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, FLT_MAX);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
-{
- int enter_editmode;
- unsigned int layer;
- float loc[3], rot[3];
-
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
- return OPERATOR_CANCELLED;
-
- make_prim_ext(C, loc, rot, enter_editmode, layer,
- PRIM_MONKEY, 0, 0, 2, 0.0f, 0.0f, 0, 0);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_primitive_monkey_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Add Monkey";
- ot->description= "Construct a Suzanne mesh";
- ot->idname= "MESH_OT_primitive_monkey_add";
-
- /* api callbacks */
- ot->invoke= ED_object_add_generic_invoke;
- ot->exec= add_primitive_monkey_exec;
- ot->poll= ED_operator_scene_editable;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
-{
- int enter_editmode;
- unsigned int layer;
- float loc[3], rot[3];
-
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
- return OPERATOR_CANCELLED;
-
- make_prim_ext(C, loc, rot, enter_editmode, layer,
- PRIM_UVSPHERE, RNA_int_get(op->ptr, "ring_count"),
- RNA_int_get(op->ptr, "segments"), 0,
- RNA_float_get(op->ptr,"size"), 0.0f, 0, 0);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Add UV Sphere";
- ot->description= "Construct a UV sphere mesh";
- ot->idname= "MESH_OT_primitive_uv_sphere_add";
-
- /* api callbacks */
- ot->invoke= ED_object_add_generic_invoke;
- ot->exec= add_primitive_uvsphere_exec;
- ot->poll= ED_operator_scene_editable;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_int(ot->srna, "segments", 32, 3, INT_MAX, "Segments", "", 3, 500);
- RNA_def_int(ot->srna, "ring_count", 16, 3, INT_MAX, "Rings", "", 3, 500);
- prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
-{
- int enter_editmode;
- unsigned int layer;
- float loc[3], rot[3];
-
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
- return OPERATOR_CANCELLED;
-
- make_prim_ext(C, loc, rot, enter_editmode, layer,
- PRIM_ICOSPHERE, 0, 0, RNA_int_get(op->ptr, "subdivisions"),
- RNA_float_get(op->ptr,"size"), 0.0f, 0, 0);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Add Ico Sphere";
- ot->description= "Construct an Icosphere mesh";
- ot->idname= "MESH_OT_primitive_ico_sphere_add";
-
- /* api callbacks */
- ot->invoke= ED_object_add_generic_invoke;
- ot->exec= add_primitive_icosphere_exec;
- ot->poll= ED_operator_scene_editable;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_int(ot->srna, "subdivisions", 2, 1, INT_MAX, "Subdivisions", "", 1, 8);
- prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0f, FLT_MAX, "Size", "", 0.001f, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-/****************** add duplicate operator ***************/
-
-static int mesh_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(ob->data);
-
- adduplicateflag(em, SELECT);
-
- BKE_mesh_end_editmesh(ob->data, em);
-
- DAG_id_tag_update(ob->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
-
- return OPERATOR_FINISHED;
-}
-
-static int mesh_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
-{
- WM_cursor_wait(1);
- mesh_duplicate_exec(C, op);
- WM_cursor_wait(0);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_duplicate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Duplicate Mesh";
- ot->description= "Duplicate selected vertices, edges or faces";
- ot->idname= "MESH_OT_duplicate";
-
- /* api callbacks */
- ot->invoke= mesh_duplicate_invoke;
- ot->exec= mesh_duplicate_exec;
-
- ot->poll= ED_operator_editmesh;
-
- /* to give to transform */
- RNA_def_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", "");
-}
-
diff --git a/source/blender/editors/mesh/editmesh_lib.c b/source/blender/editors/mesh/editmesh_lib.c
deleted file mode 100644
index 0c0163d0f24..00000000000
--- a/source/blender/editors/mesh/editmesh_lib.c
+++ /dev/null
@@ -1,2855 +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) 2004 by Blender Foundation
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/mesh/editmesh_lib.c
- * \ingroup edmesh
- */
-
-
-/*
-
-editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data
-
-*/
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_editVert.h"
-#include "BLI_edgehash.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_customdata.h"
-#include "BKE_context.h"
-#include "BKE_global.h"
-#include "BKE_mesh.h"
-
-
-#include "ED_mesh.h"
-#include "ED_screen.h"
-#include "ED_view3d.h"
-#include "ED_transform.h"
-
-#include "mesh_intern.h"
-
-/* Helpers for EM_set_flag_all_selectmode */
-#define SET_EVE_FLAG(eve, flag) \
- if (eve->h==0) { \
- if (flag & SELECT && !(eve->f & SELECT)) { \
- ++selvert; \
- } \
- eve->f |= flag; \
- }
-
-#define SET_EED_FLAG(eed, flag) \
- if (eed->h==0) { \
- if (flag & SELECT && !(eed->f & SELECT)) { \
- ++seledge; \
- } \
- eed->f |= flag; \
- SET_EVE_FLAG(eed->v1, flag); \
- SET_EVE_FLAG(eed->v2, flag); \
- }
-
-
-/* ****************** stats *************** */
-
-int EM_nfaces_selected(EditMesh *em)
-{
- EditFace *efa;
- int count= 0;
-
- for (efa= em->faces.first; efa; efa= efa->next)
- if (efa->f & SELECT)
- count++;
-
- em->totfacesel= count;
-
- return count;
-}
-
-int EM_nedges_selected(EditMesh *em)
-{
- EditEdge *eed;
- int count= 0;
-
- for (eed= em->edges.first; eed; eed= eed->next)
- if(eed->f & SELECT)
- count++;
-
- em->totedgesel= count;
-
- return count;
-}
-
-int EM_nvertices_selected(EditMesh *em)
-{
- EditVert *eve;
- int count= 0;
-
- for (eve= em->verts.first; eve; eve= eve->next)
- if (eve->f & SELECT)
- count++;
-
- em->totvertsel= count;
-
- return count;
-}
-
-void EM_stats_update(EditMesh *em)
-{
-
- em->totvert= BLI_countlist(&em->verts);
- em->totedge= BLI_countlist(&em->edges);
- em->totface= BLI_countlist(&em->faces);
-
- EM_nvertices_selected(em);
- EM_nedges_selected(em);
- EM_nfaces_selected(em);
-}
-
-/* ************************************** */
-
-/* this replaces the active flag used in uv/face mode */
-void EM_set_actFace(EditMesh *em, EditFace *efa)
-{
- em->act_face = efa;
-}
-
-EditFace *EM_get_actFace(EditMesh *em, int sloppy)
-{
- if (em->act_face) {
- return em->act_face;
- } else if (sloppy) {
- EditFace *efa= NULL;
- EditSelection *ese;
-
- ese = em->selected.last;
- for (; ese; ese=ese->prev){
- if(ese->type == EDITFACE) {
- efa = (EditFace *)ese->data;
-
- if (efa->h) efa= NULL;
- else break;
- }
- }
- if (efa==NULL) {
- for (efa= em->faces.first; efa; efa= efa->next) {
- if (efa->f & SELECT)
- break;
- }
- }
- return efa; /* can still be null */
- }
- return NULL;
-}
-
-int EM_get_actSelection(EditMesh *em, EditSelection *ese)
-{
- EditSelection *ese_last = em->selected.last;
- EditFace *efa = EM_get_actFace(em, 0);
-
- ese->next = ese->prev = NULL;
-
- if (ese_last) {
- if (ese_last->type == EDITFACE) { /* if there is an active face, use it over the last selected face */
- if (efa) {
- ese->data = (void *)efa;
- } else {
- ese->data = ese_last->data;
- }
- ese->type = EDITFACE;
- } else {
- ese->data = ese_last->data;
- ese->type = ese_last->type;
- }
- } else if (efa) { /* no */
- ese->data = (void *)efa;
- ese->type = EDITFACE;
- } else {
- ese->data = NULL;
- return 0;
- }
- return 1;
-}
-
-/* ********* Selection History ************ */
-static int EM_check_selection(EditMesh *em, void *data)
-{
- EditSelection *ese;
-
- for(ese = em->selected.first; ese; ese = ese->next){
- if(ese->data == data) return 1;
- }
-
- return 0;
-}
-
-void EM_remove_selection(EditMesh *em, void *data, int UNUSED(type))
-{
- EditSelection *ese;
- for(ese=em->selected.first; ese; ese = ese->next){
- if(ese->data == data){
- BLI_freelinkN(&(em->selected),ese);
- break;
- }
- }
-}
-
-void EM_store_selection(EditMesh *em, void *data, int type)
-{
- EditSelection *ese;
- if(!EM_check_selection(em, data)){
- ese = (EditSelection*) MEM_callocN( sizeof(EditSelection), "Edit Selection");
- ese->type = type;
- ese->data = data;
- BLI_addtail(&(em->selected),ese);
- }
-}
-
-void EM_validate_selections(EditMesh *em)
-{
- EditSelection *ese, *nextese;
-
- ese = em->selected.first;
-
- while(ese){
- nextese = ese->next;
- if(ese->type == EDITVERT && !(((EditVert*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese);
- else if(ese->type == EDITEDGE && !(((EditEdge*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese);
- else if(ese->type == EDITFACE && !(((EditFace*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese);
- ese = nextese;
- }
-}
-
-static void EM_strip_selections(EditMesh *em)
-{
- EditSelection *ese, *nextese;
- if(!(em->selectmode & SCE_SELECT_VERTEX)){
- ese = em->selected.first;
- while(ese){
- nextese = ese->next;
- if(ese->type == EDITVERT) BLI_freelinkN(&(em->selected),ese);
- ese = nextese;
- }
- }
- if(!(em->selectmode & SCE_SELECT_EDGE)){
- ese=em->selected.first;
- while(ese){
- nextese = ese->next;
- if(ese->type == EDITEDGE) BLI_freelinkN(&(em->selected), ese);
- ese = nextese;
- }
- }
- if(!(em->selectmode & SCE_SELECT_FACE)){
- ese=em->selected.first;
- while(ese){
- nextese = ese->next;
- if(ese->type == EDITFACE) BLI_freelinkN(&(em->selected), ese);
- ese = nextese;
- }
- }
-}
-
-/* generic way to get data from an EditSelection type
-These functions were written to be used by the Modifier widget when in Rotate about active mode,
-but can be used anywhere.
-EM_editselection_center
-EM_editselection_normal
-EM_editselection_plane
-*/
-void EM_editselection_center(float *center, EditSelection *ese)
-{
- if (ese->type==EDITVERT) {
- EditVert *eve= ese->data;
- copy_v3_v3(center, eve->co);
- } else if (ese->type==EDITEDGE) {
- EditEdge *eed= ese->data;
- add_v3_v3v3(center, eed->v1->co, eed->v2->co);
- mul_v3_fl(center, 0.5);
- } else if (ese->type==EDITFACE) {
- EditFace *efa= ese->data;
- copy_v3_v3(center, efa->cent);
- }
-}
-
-void EM_editselection_normal(float *normal, EditSelection *ese)
-{
- if (ese->type==EDITVERT) {
- EditVert *eve= ese->data;
- copy_v3_v3(normal, eve->no);
- } else if (ese->type==EDITEDGE) {
- EditEdge *eed= ese->data;
- float plane[3]; /* need a plane to correct the normal */
- float vec[3]; /* temp vec storage */
-
- add_v3_v3v3(normal, eed->v1->no, eed->v2->no);
- sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
-
- /* the 2 vertex normals will be close but not at rightangles to the edge
- for rotate about edge we want them to be at right angles, so we need to
- do some extra colculation to correct the vert normals,
- we need the plane for this */
- cross_v3_v3v3(vec, normal, plane);
- cross_v3_v3v3(normal, plane, vec);
- normalize_v3(normal);
-
- } else if (ese->type==EDITFACE) {
- EditFace *efa= ese->data;
- copy_v3_v3(normal, efa->n);
- }
-}
-
-/* Calculate a plane that is rightangles to the edge/vert/faces normal
-also make the plane run along an axis that is related to the geometry,
-because this is used for the manipulators Y axis.*/
-void EM_editselection_plane(float *plane, EditSelection *ese)
-{
- if (ese->type==EDITVERT) {
- EditVert *eve= ese->data;
- float vec[3]={0,0,0};
-
- if (ese->prev) { /*use previously selected data to make a useful vertex plane */
- EM_editselection_center(vec, ese->prev);
- sub_v3_v3v3(plane, vec, eve->co);
- } else {
- /* make a fake plane thats at rightangles to the normal
- we cant make a crossvec from a vec thats the same as the vec
- unlikely but possible, so make sure if the normal is (0,0,1)
- that vec isnt the same or in the same direction even.*/
- if (eve->no[0]<0.5f) vec[0]=1;
- else if (eve->no[1]<0.5f) vec[1]=1;
- else vec[2]=1;
- cross_v3_v3v3(plane, eve->no, vec);
- }
- } else if (ese->type==EDITEDGE) {
- EditEdge *eed= ese->data;
-
- /*the plane is simple, it runs along the edge
- however selecting different edges can swap the direction of the y axis.
- this makes it less likely for the y axis of the manipulator
- (running along the edge).. to flip less often.
- at least its more predictable */
- if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */
- sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
- else
- sub_v3_v3v3(plane, eed->v1->co, eed->v2->co);
-
- } else if (ese->type==EDITFACE) {
- EditFace *efa= ese->data;
- float vec[3];
- if (efa->v4) { /*if its a quad- set the plane along the 2 longest edges.*/
- float vecA[3], vecB[3];
- sub_v3_v3v3(vecA, efa->v4->co, efa->v3->co);
- sub_v3_v3v3(vecB, efa->v1->co, efa->v2->co);
- add_v3_v3v3(plane, vecA, vecB);
-
- sub_v3_v3v3(vecA, efa->v1->co, efa->v4->co);
- sub_v3_v3v3(vecB, efa->v2->co, efa->v3->co);
- add_v3_v3v3(vec, vecA, vecB);
- /*use the biggest edge length*/
- if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
- copy_v3_v3(plane, vec);
- } else {
- /*start with v1-2 */
- sub_v3_v3v3(plane, efa->v1->co, efa->v2->co);
-
- /*test the edge between v2-3, use if longer */
- sub_v3_v3v3(vec, efa->v2->co, efa->v3->co);
- if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
- copy_v3_v3(plane, vec);
-
- /*test the edge between v1-3, use if longer */
- sub_v3_v3v3(vec, efa->v3->co, efa->v1->co);
- if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
- copy_v3_v3(plane, vec);
- }
- }
- normalize_v3(plane);
-}
-
-
-
-void EM_select_face(EditFace *efa, int sel)
-{
- if(sel) {
- efa->f |= SELECT;
- efa->e1->f |= SELECT;
- efa->e2->f |= SELECT;
- efa->e3->f |= SELECT;
- if(efa->e4) efa->e4->f |= SELECT;
- efa->v1->f |= SELECT;
- efa->v2->f |= SELECT;
- efa->v3->f |= SELECT;
- if(efa->v4) efa->v4->f |= SELECT;
- }
- else {
- efa->f &= ~SELECT;
- efa->e1->f &= ~SELECT;
- efa->e2->f &= ~SELECT;
- efa->e3->f &= ~SELECT;
- if(efa->e4) efa->e4->f &= ~SELECT;
- efa->v1->f &= ~SELECT;
- efa->v2->f &= ~SELECT;
- efa->v3->f &= ~SELECT;
- if(efa->v4) efa->v4->f &= ~SELECT;
- }
-}
-
-void EM_select_edge(EditEdge *eed, int sel)
-{
- if(sel) {
- eed->f |= SELECT;
- eed->v1->f |= SELECT;
- eed->v2->f |= SELECT;
- }
- else {
- eed->f &= ~SELECT;
- eed->v1->f &= ~SELECT;
- eed->v2->f &= ~SELECT;
- }
-}
-
-void EM_select_face_fgon(EditMesh *em, EditFace *efa, int val)
-{
- short index=0;
-
- if(efa->fgonf==0) EM_select_face(efa, val);
- else {
- if(efa->e1->fgoni) index= efa->e1->fgoni;
- if(efa->e2->fgoni) index= efa->e2->fgoni;
- if(efa->e3->fgoni) index= efa->e3->fgoni;
- if(efa->v4 && efa->e4->fgoni) index= efa->e4->fgoni;
-
- if((index==0) && (G.f & G_DEBUG))printf("wrong fgon select\n");
-
- // select all ngon faces with index
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->fgonf) {
- if(efa->e1->fgoni==index || efa->e2->fgoni==index ||
- efa->e3->fgoni==index || (efa->e4 && efa->e4->fgoni==index) ) {
- EM_select_face(efa, val);
- }
- }
- }
- }
-}
-
-
-/* only vertices */
-int faceselectedOR(EditFace *efa, int flag)
-{
- if ((efa->v1->f | efa->v2->f | efa->v3->f | (efa->v4?efa->v4->f:0))&flag) {
- return 1;
- } else {
- return 0;
- }
-}
-
-// replace with (efa->f & SELECT)
-int faceselectedAND(EditFace *efa, int flag)
-{
- if ((efa->v1->f & efa->v2->f & efa->v3->f & (efa->v4?efa->v4->f:flag))&flag) {
- return 1;
- } else {
- return 0;
- }
-}
-
-void EM_clear_flag_all(EditMesh *em, int flag)
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- for (eve= em->verts.first; eve; eve= eve->next) eve->f &= ~flag;
- for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~flag;
- for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~flag;
-
- if(flag & SELECT) {
- BLI_freelistN(&(em->selected));
- em->totvertsel= em->totedgesel= em->totfacesel= 0;
- }
-}
-
-void EM_set_flag_all(EditMesh *em, int flag)
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- for (eve= em->verts.first; eve; eve= eve->next) if(eve->h==0) eve->f |= flag;
- for (eed= em->edges.first; eed; eed= eed->next) if(eed->h==0) eed->f |= flag;
- for (efa= em->faces.first; efa; efa= efa->next) if(efa->h==0) efa->f |= flag;
-
- if(flag & SELECT) {
- em->totvertsel= em->totvert;
- em->totedgesel= em->totedge;
- em->totfacesel= em->totface;
- }
-}
-
-void EM_set_flag_all_selectmode(EditMesh *em, int flag)
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- int selvert= 0, seledge= 0, selface= 0;
-
- if (em->selectmode & SCE_SELECT_VERTEX) {
- /* If vertex select mode enabled all the data could be affected */
- for (eve= em->verts.first; eve; eve= eve->next) if(eve->h==0) eve->f |= flag;
- for (eed= em->edges.first; eed; eed= eed->next) if(eed->h==0) eed->f |= flag;
- for (efa= em->faces.first; efa; efa= efa->next) if(efa->h==0) efa->f |= flag;
-
- if (flag & SELECT) {
- selvert= em->totvert;
- seledge= em->totedge;
- selface= em->totface;
- }
- } else if (em->selectmode & SCE_SELECT_EDGE) {
- /* If edge select mode is enabled we should affect on all edges, faces and */
- /* vertices, connected to them */
-
- for (eed= em->edges.first; eed; eed= eed->next) {
- SET_EED_FLAG(eed, flag)
- }
-
- for (efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0) {
- efa->f |= flag;
-
- if (flag & SELECT) {
- ++selface;
- }
- }
- }
- } else if (em->selectmode & SCE_SELECT_FACE) {
- /* No vertex and edge select mode, only face selection */
- /* In face select mode only edges and vertices belongs to faces should be affected */
-
- for (efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0) {
- efa->f |= flag;
- SET_EED_FLAG(efa->e1, flag);
- SET_EED_FLAG(efa->e2, flag);
- SET_EED_FLAG(efa->e3, flag);
-
- if (efa->e4) {
- SET_EED_FLAG(efa->e4, flag);
- }
-
- if (flag & SELECT) {
- ++selface;
- }
- }
- }
- }
-
- if(flag & SELECT) {
- em->totvertsel= selvert;
- em->totedgesel= seledge;
- em->totfacesel= selface;
- }
- }
-/* flush for changes in vertices only */
-void EM_deselect_flush(EditMesh *em)
-{
- EditEdge *eed;
- EditFace *efa;
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->v1->f & eed->v2->f & SELECT);
- else eed->f &= ~SELECT;
- }
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->v4) {
- if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT );
- else efa->f &= ~SELECT;
- }
- else {
- if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT );
- else efa->f &= ~SELECT;
- }
- }
- EM_nedges_selected(em);
- EM_nfaces_selected(em);
-}
-
-
-/* flush selection to edges & faces */
-
-/* this only based on coherent selected vertices, for example when adding new
- objects. call clear_flag_all() before you select vertices to be sure it ends OK!
-
-*/
-
-void EM_select_flush(EditMesh *em)
-{
- EditEdge *eed;
- EditFace *efa;
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT;
- }
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->v4) {
- if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT ) efa->f |= SELECT;
- }
- else {
- if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT ) efa->f |= SELECT;
- }
- }
- EM_nedges_selected(em);
- EM_nfaces_selected(em);
-}
-
-/* when vertices or edges can be selected, also make fgon consistent */
-static void check_fgons_selection(EditMesh *em)
-{
- EditFace *efa, *efan;
- EditEdge *eed;
- ListBase *lbar;
- int sel, desel, index, totfgon= 0;
-
- /* count amount of fgons */
- for(eed= em->edges.first; eed; eed= eed->next)
- if(eed->fgoni>totfgon) totfgon= eed->fgoni;
-
- if(totfgon==0) return;
-
- lbar= MEM_callocN((totfgon+1)*sizeof(ListBase), "listbase array");
-
- /* put all fgons in lbar */
- for(efa= em->faces.first; efa; efa= efan) {
- efan= efa->next;
- index= efa->e1->fgoni;
- if(index==0) index= efa->e2->fgoni;
- if(index==0) index= efa->e3->fgoni;
- if(index==0 && efa->e4) index= efa->e4->fgoni;
- if(index) {
- BLI_remlink(&em->faces, efa);
- BLI_addtail(&lbar[index], efa);
- }
- }
-
- /* now check the fgons */
- for(index=1; index<=totfgon; index++) {
- /* we count on vertices/faces/edges being set OK, so we only have to set ngon itself */
- sel= desel= 0;
- for(efa= lbar[index].first; efa; efa= efa->next) {
- if(efa->e1->fgoni==0) {
- if(efa->e1->f & SELECT) sel++;
- else desel++;
- }
- if(efa->e2->fgoni==0) {
- if(efa->e2->f & SELECT) sel++;
- else desel++;
- }
- if(efa->e3->fgoni==0) {
- if(efa->e3->f & SELECT) sel++;
- else desel++;
- }
- if(efa->e4 && efa->e4->fgoni==0) {
- if(efa->e4->f & SELECT) sel++;
- else desel++;
- }
-
- if(sel && desel) break;
- }
-
- if(sel && desel) sel= 0;
- else if(sel) sel= 1;
- else sel= 0;
-
- /* select/deselect and put back */
- for(efa= lbar[index].first; efa; efa= efa->next) {
- if(sel) efa->f |= SELECT;
- else efa->f &= ~SELECT;
- }
- BLI_movelisttolist(&em->faces, &lbar[index]);
- }
-
- MEM_freeN(lbar);
-}
-
-
-/* flush to edges & faces */
-
-/* based on select mode it selects edges/faces
- assumed is that verts/edges/faces were properly selected themselves
- with the calls above
-*/
-
-void EM_selectmode_flush(EditMesh *em)
-{
- EditEdge *eed;
- EditFace *efa;
-
- // flush to edges & faces
- if(em->selectmode & SCE_SELECT_VERTEX) {
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT;
- else eed->f &= ~SELECT;
- }
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->v4) {
- if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT) efa->f |= SELECT;
- else efa->f &= ~SELECT;
- }
- else {
- if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT) efa->f |= SELECT;
- else efa->f &= ~SELECT;
- }
- }
- }
- // flush to faces
- else if(em->selectmode & SCE_SELECT_EDGE) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->e4) {
- if(efa->e1->f & efa->e2->f & efa->e3->f & efa->e4->f & SELECT) efa->f |= SELECT;
- else efa->f &= ~SELECT;
- }
- else {
- if(efa->e1->f & efa->e2->f & efa->e3->f & SELECT) efa->f |= SELECT;
- else efa->f &= ~SELECT;
- }
- }
- }
- // make sure selected faces have selected edges too, for extrude (hack?)
- else if(em->selectmode & SCE_SELECT_FACE) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) EM_select_face(efa, 1);
- }
- }
-
- if(!(em->selectmode & SCE_SELECT_FACE))
- check_fgons_selection(em);
-
- EM_nvertices_selected(em);
- EM_nedges_selected(em);
- EM_nfaces_selected(em);
-}
-
-void EM_convertsel(EditMesh *em, short oldmode, short selectmode)
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
- /*clear flags*/
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1 = 0;
- for(eed= em->edges.first; eed; eed= eed->next) eed->f1 = 0;
- for(efa= em->faces.first; efa; efa= efa->next) efa->f1 = 0;
-
- /*have to find out what the selectionmode was previously*/
- if(oldmode == SCE_SELECT_VERTEX) {
- if(selectmode == SCE_SELECT_EDGE){
- /*select all edges associated with every selected vertex*/
- for(eed= em->edges.first; eed; eed= eed->next){
- if(eed->v1->f&SELECT) eed->f1 = 1;
- else if(eed->v2->f&SELECT) eed->f1 = 1;
- }
-
- for(eed= em->edges.first; eed; eed= eed->next){
- if(eed->f1 == 1) EM_select_edge(eed,1);
- }
- }
- else if(selectmode == SCE_SELECT_FACE){
- /*select all faces associated with every selected vertex*/
- for(efa= em->faces.first; efa; efa= efa->next){
- if(efa->v1->f&SELECT) efa->f1 = 1;
- else if(efa->v2->f&SELECT) efa->f1 = 1;
- else if(efa->v3->f&SELECT) efa->f1 = 1;
- else{
- if(efa->v4){
- if(efa->v4->f&SELECT) efa->f1 =1;
- }
- }
- }
- for(efa= em->faces.first; efa; efa= efa->next){
- if(efa->f1 == 1) EM_select_face(efa,1);
- }
- }
- }
-
- if(oldmode == SCE_SELECT_EDGE){
- if(selectmode == SCE_SELECT_FACE){
- for(efa= em->faces.first; efa; efa= efa->next){
- if(efa->e1->f&SELECT) efa->f1 = 1;
- else if(efa->e2->f&SELECT) efa->f1 = 1;
- else if(efa->e3->f&SELECT) efa->f1 = 1;
- else if(efa->e4){
- if(efa->e4->f&SELECT) efa->f1 = 1;
- }
- }
- for(efa= em->faces.first; efa; efa= efa->next){
- if(efa->f1 == 1) EM_select_face(efa,1);
- }
- }
- }
-
- check_fgons_selection(em);
-
- EM_nvertices_selected(em);
- EM_nedges_selected(em);
- EM_nfaces_selected(em);
-}
-
-void EM_selectmode_to_scene(struct Scene *scene, struct Object *obedit)
-{
- scene->toolsettings->selectmode= get_mesh(obedit)->edit_mesh->selectmode;
-}
-
-/* when switching select mode, makes sure selection is consistent for editing */
-/* also for paranoia checks to make sure edge or face mode works */
-void EM_selectmode_set(EditMesh *em)
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- EM_strip_selections(em); /*strip EditSelections from em->selected that are not relevant to new mode*/
-
- if(em->selectmode & SCE_SELECT_VERTEX) {
- /* vertices -> edges -> faces */
- for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~SELECT;
- for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~SELECT;
-
- EM_select_flush(em);
- }
- else if(em->selectmode & SCE_SELECT_EDGE) {
- /* deselect vertices, and select again based on edge select */
- for(eve= em->verts.first; eve; eve= eve->next) eve->f &= ~SELECT;
- for(eed= em->edges.first; eed; eed= eed->next)
- if(eed->f & SELECT) EM_select_edge(eed, 1);
- /* selects faces based on edge status */
- EM_selectmode_flush(em);
- }
- else if(em->selectmode & SCE_SELECT_FACE) {
- /* deselect eges, and select again based on face select */
- for(eed= em->edges.first; eed; eed= eed->next) EM_select_edge(eed, 0);
-
- for(efa= em->faces.first; efa; efa= efa->next)
- if(efa->f & SELECT) EM_select_face(efa, 1);
- }
-
- EM_nvertices_selected(em);
- EM_nedges_selected(em);
- EM_nfaces_selected(em);
-}
-
-/* paranoia check, actually only for entering editmode. rule:
-- vertex hidden, always means edge is hidden too
-- edge hidden, always means face is hidden too
-- face hidden, dont change anything
-*/
-void EM_hide_reset(EditMesh *em)
-{
- EditEdge *eed;
- EditFace *efa;
-
- for(eed= em->edges.first; eed; eed= eed->next)
- if(eed->v1->h || eed->v2->h) eed->h |= 1;
-
- for(efa= em->faces.first; efa; efa= efa->next)
- if((efa->e1->h & 1) || (efa->e2->h & 1) || (efa->e3->h & 1) || (efa->e4 && (efa->e4->h & 1)))
- efa->h= 1;
-
-}
-
-void EM_data_interp_from_verts(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *eve, float fac)
-{
- void *src[2];
- float w[2];
-
- if (v1->data && v2->data) {
- src[0]= v1->data;
- src[1]= v2->data;
- w[0] = 1.0f-fac;
- w[1] = fac;
-
- CustomData_em_interp(&em->vdata, src, w, NULL, 2, eve->data);
- }
-}
-
-void EM_data_interp_from_faces(EditMesh *em, EditFace *efa1, EditFace *efa2, EditFace *efan, int i1, int i2, int i3, int i4)
-{
- float w[2][4][4];
- void *src[2];
- int count = (efa2)? 2: 1;
-
- if (efa1->data) {
- /* set weights for copying from corners directly to other corners */
- memset(w, 0, sizeof(w));
-
- w[i1/4][0][i1%4]= 1.0f;
- w[i2/4][1][i2%4]= 1.0f;
- w[i3/4][2][i3%4]= 1.0f;
- if (i4 != -1)
- w[i4/4][3][i4%4]= 1.0f;
-
- src[0]= efa1->data;
- src[1]= (efa2)? efa2->data: NULL;
-
- CustomData_em_interp(&em->fdata, src, NULL, (float*)w, count, efan->data);
- }
-}
-
-EditFace *EM_face_from_faces(EditMesh *em, EditFace *efa1, EditFace *efa2, int i1, int i2, int i3, int i4)
-{
- EditFace *efan;
- EditVert **v[2];
-
- v[0]= &efa1->v1;
- v[1]= (efa2)? &efa2->v1: NULL;
-
- efan= addfacelist(em, v[i1/4][i1%4], v[i2/4][i2%4], v[i3/4][i3%4],
- (i4 == -1)? 0: v[i4/4][i4%4], efa1, NULL);
-
- EM_data_interp_from_faces(em, efa1, efa2, efan, i1, i2, i3, i4);
-
- return efan;
-}
-
-static void update_data_blocks(EditMesh *em, CustomData *olddata, CustomData *data)
-{
- EditFace *efa;
- EditVert *eve;
- void *block;
-
- if (data == &em->vdata) {
- for(eve= em->verts.first; eve; eve= eve->next) {
- block = NULL;
- CustomData_em_set_default(data, &block);
- CustomData_em_copy_data(olddata, data, eve->data, &block);
- CustomData_em_free_block(olddata, &eve->data);
- eve->data= block;
- }
- }
- else if (data == &em->fdata) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- block = NULL;
- CustomData_em_set_default(data, &block);
- CustomData_em_copy_data(olddata, data, efa->data, &block);
- CustomData_em_free_block(olddata, &efa->data);
- efa->data= block;
- }
- }
-}
-
-void EM_add_data_layer(EditMesh *em, CustomData *data, int type, const char *name)
-{
- CustomData olddata;
-
- olddata= *data;
- olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
- CustomData_add_layer_named(data, type, CD_CALLOC, NULL, 0, name);
-
- update_data_blocks(em, &olddata, data);
- if (olddata.layers) MEM_freeN(olddata.layers);
-}
-
-void EM_free_data_layer(EditMesh *em, CustomData *data, int type)
-{
- CustomData olddata;
-
- olddata= *data;
- olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
- CustomData_free_layer_active(data, type, 0);
-
- update_data_blocks(em, &olddata, data);
- if (olddata.layers) MEM_freeN(olddata.layers);
-}
-
-/* ******** EXTRUDE ********* */
-
-static void add_normal_aligned(float *nor, float *add)
-{
- if(dot_v3v3(nor, add) < -0.9999f)
- sub_v3_v3(nor, add);
- else
- add_v3_v3(nor, add);
-}
-
-static void set_edge_directions_f2(EditMesh *em, int val)
-{
- EditFace *efa;
- int do_all= 1;
-
- /* edge directions are used for extrude, to detect direction of edges that make new faces */
- /* we have set 'f2' flags in edges that need to get a direction set (e.g. get new face) */
- /* the val argument differs... so we need it as arg */
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- do_all= 0;
- if(efa->e1->f2<val) {
- if(efa->e1->v1 == efa->v1) efa->e1->dir= 0;
- else efa->e1->dir= 1;
- }
- if(efa->e2->f2<val) {
- if(efa->e2->v1 == efa->v2) efa->e2->dir= 0;
- else efa->e2->dir= 1;
- }
- if(efa->e3->f2<val) {
- if(efa->e3->v1 == efa->v3) efa->e3->dir= 0;
- else efa->e3->dir= 1;
- }
- if(efa->e4 && efa->e4->f2<val) {
- if(efa->e4->v1 == efa->v4) efa->e4->dir= 0;
- else efa->e4->dir= 1;
- }
- }
- }
- /* ok, no faces done... then we at least set it for exterior edges */
- if(do_all) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->e1->v1 == efa->v1) efa->e1->dir= 0;
- else efa->e1->dir= 1;
- if(efa->e2->v1 == efa->v2) efa->e2->dir= 0;
- else efa->e2->dir= 1;
- if(efa->e3->v1 == efa->v3) efa->e3->dir= 0;
- else efa->e3->dir= 1;
- if(efa->e4) {
- if(efa->e4->v1 == efa->v4) efa->e4->dir= 0;
- else efa->e4->dir= 1;
- }
- }
- }
-}
-
-/* individual face extrude */
-/* will use vertex normals for extrusion directions, so *nor is unaffected */
-short extrudeflag_face_indiv(EditMesh *em, short UNUSED(flag), float *UNUSED(nor))
-{
- EditVert *eve, *v1, *v2, *v3, *v4;
- EditEdge *eed;
- EditFace *efa, *nextfa;
-
- if(em==NULL) return 0;
-
- /* selected edges with 1 or more selected face become faces */
- /* selected faces each makes new faces */
- /* always remove old faces, keeps volumes manifold */
- /* select the new extrusion, deselect old */
-
- /* step 1; init, count faces in edges */
- recalc_editnormals(em);
-
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; // new select flag
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- eed->f2= 0; // amount of unselected faces
- }
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT);
- else {
- efa->e1->f2++;
- efa->e2->f2++;
- efa->e3->f2++;
- if(efa->e4) efa->e4->f2++;
- }
- }
-
- /* step 2: make new faces from faces */
- for(efa= em->faces.last; efa; efa= efa->prev) {
- if(efa->f & SELECT) {
- v1= addvertlist(em, efa->v1->co, efa->v1);
- v2= addvertlist(em, efa->v2->co, efa->v2);
- v3= addvertlist(em, efa->v3->co, efa->v3);
-
- v1->f1= v2->f1= v3->f1= 1;
- copy_v3_v3(v1->no, efa->n);
- copy_v3_v3(v2->no, efa->n);
- copy_v3_v3(v3->no, efa->n);
- if(efa->v4) {
- v4= addvertlist(em, efa->v4->co, efa->v4);
- v4->f1= 1;
- copy_v3_v3(v4->no, efa->n);
- }
- else v4= NULL;
-
- /* side faces, clockwise */
- addfacelist(em, efa->v2, v2, v1, efa->v1, efa, NULL);
- addfacelist(em, efa->v3, v3, v2, efa->v2, efa, NULL);
- if(efa->v4) {
- addfacelist(em, efa->v4, v4, v3, efa->v3, efa, NULL);
- addfacelist(em, efa->v1, v1, v4, efa->v4, efa, NULL);
- }
- else {
- addfacelist(em, efa->v1, v1, v3, efa->v3, efa, NULL);
- }
- /* top face */
- addfacelist(em, v1, v2, v3, v4, efa, NULL);
- }
- }
-
- /* step 3: remove old faces */
- efa= em->faces.first;
- while(efa) {
- nextfa= efa->next;
- if(efa->f & SELECT) {
- BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
- }
- efa= nextfa;
- }
-
- /* step 4: redo selection */
- EM_clear_flag_all(em, SELECT);
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f1) eve->f |= SELECT;
- }
-
- EM_select_flush(em);
-
- /* step 5; update normals after extrude */
- recalc_editnormals(em);
-
- return 'n';
-}
-
-
-/* extrudes individual edges */
-/* nor is filled with constraint vector */
-short extrudeflag_edges_indiv(EditMesh *em, short flag, float *nor)
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- for(eve= em->verts.first; eve; eve= eve->next) eve->tmp.v = NULL;
- for(eed= em->edges.first; eed; eed= eed->next) {
- eed->tmp.f = NULL;
- eed->f2= ((eed->f & flag)!=0);
- }
-
- set_edge_directions_f2(em, 2);
-
- /* sample for next loop */
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->e1->tmp.f = efa;
- efa->e2->tmp.f = efa;
- efa->e3->tmp.f = efa;
- if(efa->e4) efa->e4->tmp.f = efa;
- }
- /* make the faces */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & flag) {
- if(eed->v1->tmp.v == NULL)
- eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1);
- if(eed->v2->tmp.v == NULL)
- eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2);
-
- if(eed->dir==1)
- addfacelist(em, eed->v1, eed->v2,
- eed->v2->tmp.v, eed->v1->tmp.v,
- eed->tmp.f, NULL);
- else
- addfacelist(em, eed->v2, eed->v1,
- eed->v1->tmp.v, eed->v2->tmp.v,
- eed->tmp.f, NULL);
-
- /* for transform */
- if(eed->tmp.f) {
- efa = eed->tmp.f;
- if (efa->f & SELECT) add_normal_aligned(nor, efa->n);
- }
- }
- }
- normalize_v3(nor);
-
- /* set correct selection */
- EM_clear_flag_all(em, SELECT);
- for(eve= em->verts.last; eve; eve= eve->prev) {
- if(eve->tmp.v) {
- eve->tmp.v->f |= flag;
- }
- }
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->v1->f & eed->v2->f & flag) eed->f |= flag;
- }
-
- /* update normals after extrude */
- recalc_editnormals(em);
-
- if(is_zero_v3(nor)) return 'g'; // g is grab
- return 'n'; // n is for normal constraint
-}
-
-/* extrudes individual vertices */
-short extrudeflag_verts_indiv(EditMesh *em, short flag, float *UNUSED(nor))
-{
- EditVert *eve;
-
- /* make the edges */
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & flag) {
- eve->tmp.v = addvertlist(em, eve->co, eve);
- addedgelist(em, eve, eve->tmp.v, NULL);
- }
- else eve->tmp.v = NULL;
- }
-
- /* set correct selection */
- EM_clear_flag_all(em, SELECT);
-
- for(eve= em->verts.last; eve; eve= eve->prev)
- if (eve->tmp.v)
- eve->tmp.v->f |= flag;
-
- return 'g'; // g is grab
-}
-
-
-/* this is actually a recode of extrudeflag(), using proper edge/face select */
-/* hurms, doesnt use 'flag' yet, but its not called by primitive making stuff anyway */
-static short extrudeflag_edge(Object *obedit, EditMesh *em, short UNUSED(flag), float *nor, int all)
-{
- /* all select edges/faces: extrude */
- /* old select is cleared, in new ones it is set */
- EditVert *eve, *nextve;
- EditEdge *eed, *nexted;
- EditFace *efa, *nextfa, *efan;
- short del_old= 0;
- ModifierData *md;
-
- if(em==NULL) return 0;
-
- md = obedit->modifiers.first;
-
- /* selected edges with 0 or 1 selected face become faces */
- /* selected faces generate new faces */
-
- /* if *one* selected face has edge with unselected face; remove old selected faces */
-
- /* if selected edge is not used anymore; remove */
- /* if selected vertex is not used anymore: remove */
-
- /* select the new extrusion, deselect old */
-
-
- /* step 1; init, count faces in edges */
- recalc_editnormals(em);
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- eve->tmp.v = NULL;
- eve->f1= 0;
- }
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- eed->f1= 0; // amount of unselected faces
- eed->f2= 0; // amount of selected faces
- if(eed->f & SELECT) {
- eed->v1->f1= 1; // we call this 'selected vertex' now
- eed->v2->f1= 1;
- }
- eed->tmp.f = NULL; // here we tuck face pointer, as sample
- }
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- efa->e1->f2++;
- efa->e2->f2++;
- efa->e3->f2++;
- if(efa->e4) efa->e4->f2++;
-
- // sample for next loop
- efa->e1->tmp.f = efa;
- efa->e2->tmp.f = efa;
- efa->e3->tmp.f = efa;
- if(efa->e4) efa->e4->tmp.f = efa;
- }
- else {
- efa->e1->f1++;
- efa->e2->f1++;
- efa->e3->f1++;
- if(efa->e4) efa->e4->f1++;
- }
- }
-
- /* If a mirror modifier with clipping is on, we need to adjust some
- * of the cases above to handle edges on the line of symmetry.
- */
- for (; md; md=md->next) {
- if ((md->type==eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
- MirrorModifierData *mmd = (MirrorModifierData*) md;
-
- if(mmd->flag & MOD_MIR_CLIPPING) {
- float mtx[4][4];
- if (mmd->mirror_ob) {
- float imtx[4][4];
- invert_m4_m4(imtx, mmd->mirror_ob->obmat);
- mul_m4_m4m4(mtx, obedit->obmat, imtx);
- }
-
- for (eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f2 == 1) {
- float co1[3], co2[3];
-
- copy_v3_v3(co1, eed->v1->co);
- copy_v3_v3(co2, eed->v2->co);
-
- if (mmd->mirror_ob) {
- mul_m4_v3(mtx, co1);
- mul_m4_v3(mtx, co2);
- }
-
- if (mmd->flag & MOD_MIR_AXIS_X)
- if ( (fabsf(co1[0]) < mmd->tolerance) &&
- (fabsf(co2[0]) < mmd->tolerance) )
- ++eed->f2;
-
- if (mmd->flag & MOD_MIR_AXIS_Y)
- if ( (fabsf(co1[1]) < mmd->tolerance) &&
- (fabsf(co2[1]) < mmd->tolerance) )
- ++eed->f2;
-
- if (mmd->flag & MOD_MIR_AXIS_Z)
- if ( (fabsf(co1[2]) < mmd->tolerance) &&
- (fabsf(co2[2]) < mmd->tolerance) )
- ++eed->f2;
- }
- }
- }
- }
- }
-
- set_edge_directions_f2(em, 2);
-
- /* step 1.5: if *one* selected face has edge with unselected face; remove old selected faces */
- if(all == 0) {
- for(efa= em->faces.last; efa; efa= efa->prev) {
- if(efa->f & SELECT) {
- if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1 || (efa->e4 && efa->e4->f1)) {
- del_old= 1;
- break;
- }
- }
- }
- }
-
- /* step 2: make new faces from edges */
- for(eed= em->edges.last; eed; eed= eed->prev) {
- if(eed->f & SELECT) {
- if(eed->f2<2) {
- if(eed->v1->tmp.v == NULL)
- eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1);
- if(eed->v2->tmp.v == NULL)
- eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2);
-
- /* if del_old, the preferred normal direction is exact
- * opposite as for keep old faces
- */
- if(eed->dir!=del_old)
- addfacelist(em, eed->v1, eed->v2,
- eed->v2->tmp.v, eed->v1->tmp.v,
- eed->tmp.f, NULL);
- else
- addfacelist(em, eed->v2, eed->v1,
- eed->v1->tmp.v, eed->v2->tmp.v,
- eed->tmp.f, NULL);
- }
- }
- }
-
- /* step 3: make new faces from faces */
- for(efa= em->faces.last; efa; efa= efa->prev) {
- if(efa->f & SELECT) {
- if (efa->v1->tmp.v == NULL)
- efa->v1->tmp.v = addvertlist(em, efa->v1->co, efa->v1);
- if (efa->v2->tmp.v ==NULL)
- efa->v2->tmp.v = addvertlist(em, efa->v2->co, efa->v2);
- if (efa->v3->tmp.v ==NULL)
- efa->v3->tmp.v = addvertlist(em, efa->v3->co, efa->v3);
- if (efa->v4 && (efa->v4->tmp.v == NULL))
- efa->v4->tmp.v = addvertlist(em, efa->v4->co, efa->v4);
-
- if(efa->v4)
- efan = addfacelist(em, efa->v1->tmp.v, efa->v2->tmp.v,
- efa->v3->tmp.v, efa->v4->tmp.v, efa, efa);
- else
- efan = addfacelist(em, efa->v1->tmp.v, efa->v2->tmp.v,
- efa->v3->tmp.v, NULL, efa, efa);
-
- /* keep old faces means flipping normal, reverse vertex order gives bad UV's & VCols etc - [#25260] */
- if(del_old==0) {
- flipface(em, efan);
- }
-
- if (em->act_face == efa) {
- em->act_face = efan;
- }
-
- /* for transform */
- add_normal_aligned(nor, efa->n);
- }
- }
-
- if(del_old) {
-
- /* step 4: remove old faces, if del_old */
- efa= em->faces.first;
- while(efa) {
- nextfa= efa->next;
- if(efa->f & SELECT) {
- BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
- }
- efa= nextfa;
- }
-
-
- /* step 5: remove selected unused edges */
- /* start tagging again */
- for(eed= em->edges.first; eed; eed= eed->next) eed->f1=0;
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->e1->f1= 1;
- efa->e2->f1= 1;
- efa->e3->f1= 1;
- if(efa->e4) efa->e4->f1= 1;
- }
- /* remove */
- eed= em->edges.first;
- while(eed) {
- nexted= eed->next;
- if(eed->f & SELECT) {
- if(eed->f1==0) {
- remedge(em, eed);
- free_editedge(em, eed);
- }
- }
- eed= nexted;
- }
-
- /* step 6: remove selected unused vertices */
- for(eed= em->edges.first; eed; eed= eed->next)
- eed->v1->f1= eed->v2->f1= 0;
-
- eve= em->verts.first;
- while(eve) {
- nextve= eve->next;
- if(eve->f1) {
- // hack... but we need it for step 7, redoing selection
- if(eve->tmp.v) eve->tmp.v->tmp.v= eve->tmp.v;
-
- BLI_remlink(&em->verts, eve);
- free_editvert(em, eve);
- }
- eve= nextve;
- }
- }
-
- normalize_v3(nor); // translation normal grab
-
- /* step 7: redo selection */
- EM_clear_flag_all(em, SELECT);
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->tmp.v) {
- eve->tmp.v->f |= SELECT;
- }
- }
-
- EM_select_flush(em);
-
- /* step 8; update normals after extrude */
- recalc_editnormals(em);
-
- if(is_zero_v3(nor)) return 'g'; // grab
- return 'n'; // normal constraint
-}
-
-short extrudeflag_vert(Object *obedit, EditMesh *em, short flag, float *nor, int all)
-{
- /* all verts/edges/faces with (f & 'flag'): extrude */
- /* from old verts, 'flag' is cleared, in new ones it is set */
- EditVert *eve, *v1, *v2, *v3, *v4, *nextve;
- EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
- EditFace *efa, *efa2, *nextvl;
- short sel=0, del_old= 0, is_face_sel=0;
- ModifierData *md;
-
- if(em==NULL) return 0;
-
- md = obedit->modifiers.first;
-
- /* clear vert flag f1, we use this to detect a loose selected vertice */
- eve= em->verts.first;
- while(eve) {
- if(eve->f & flag) eve->f1= 1;
- else eve->f1= 0;
- eve= eve->next;
- }
- /* clear edges counter flag, if selected we set it at 1 */
- eed= em->edges.first;
- while(eed) {
- if( (eed->v1->f & flag) && (eed->v2->f & flag) ) {
- eed->f2= 1;
- eed->v1->f1= 0;
- eed->v2->f1= 0;
- }
- else eed->f2= 0;
-
- eed->f1= 1; /* this indicates it is an 'old' edge (in this routine we make new ones) */
- eed->tmp.f = NULL; /* used as sample */
-
- eed= eed->next;
- }
-
- /* we set a flag in all selected faces, and increase the associated edge counters */
-
- efa= em->faces.first;
- while(efa) {
- efa->f1= 0;
-
- if(faceselectedAND(efa, flag)) {
- e1= efa->e1;
- e2= efa->e2;
- e3= efa->e3;
- e4= efa->e4;
-
- if(e1->f2 < 3) e1->f2++;
- if(e2->f2 < 3) e2->f2++;
- if(e3->f2 < 3) e3->f2++;
- if(e4 && e4->f2 < 3) e4->f2++;
-
- efa->f1= 1;
- is_face_sel= 1; // for del_old
- }
- else if(faceselectedOR(efa, flag)) {
- e1= efa->e1;
- e2= efa->e2;
- e3= efa->e3;
- e4= efa->e4;
-
- if( (e1->v1->f & flag) && (e1->v2->f & flag) ) e1->f1= 2;
- if( (e2->v1->f & flag) && (e2->v2->f & flag) ) e2->f1= 2;
- if( (e3->v1->f & flag) && (e3->v2->f & flag) ) e3->f1= 2;
- if( e4 && (e4->v1->f & flag) && (e4->v2->f & flag) ) e4->f1= 2;
- }
-
- // sample for next loop
- efa->e1->tmp.f = efa;
- efa->e2->tmp.f = efa;
- efa->e3->tmp.f = efa;
- if(efa->e4) efa->e4->tmp.f = efa;
-
- efa= efa->next;
- }
-
- set_edge_directions_f2(em, 3);
-
- /* the current state now is:
- eve->f1==1: loose selected vertex
-
- eed->f2==0 : edge is not selected, no extrude
- eed->f2==1 : edge selected, is not part of a face, extrude
- eed->f2==2 : edge selected, is part of 1 face, extrude
- eed->f2==3 : edge selected, is part of more faces, no extrude
-
- eed->f1==0: new edge
- eed->f1==1: edge selected, is part of selected face, when eed->f==3: remove
- eed->f1==2: edge selected, part of a partially selected face
-
- efa->f1==1 : duplicate this face
- */
-
- /* If a mirror modifier with clipping is on, we need to adjust some
- * of the cases above to handle edges on the line of symmetry.
- */
- for (; md; md=md->next) {
- if ((md->type==eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
- MirrorModifierData *mmd = (MirrorModifierData*) md;
-
- if(mmd->flag & MOD_MIR_CLIPPING) {
- float mtx[4][4];
- if (mmd->mirror_ob) {
- float imtx[4][4];
- invert_m4_m4(imtx, mmd->mirror_ob->obmat);
- mul_m4_m4m4(mtx, obedit->obmat, imtx);
- }
-
- for (eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f2 == 2) {
- float co1[3], co2[3];
-
- copy_v3_v3(co1, eed->v1->co);
- copy_v3_v3(co2, eed->v2->co);
-
- if (mmd->mirror_ob) {
- mul_m4_v3(mtx, co1);
- mul_m4_v3(mtx, co2);
- }
-
- if (mmd->flag & MOD_MIR_AXIS_X)
- if ( (fabsf(co1[0]) < mmd->tolerance) &&
- (fabsf(co2[0]) < mmd->tolerance) )
- ++eed->f2;
-
- if (mmd->flag & MOD_MIR_AXIS_Y)
- if ( (fabsf(co1[1]) < mmd->tolerance) &&
- (fabsf(co2[1]) < mmd->tolerance) )
- ++eed->f2;
- if (mmd->flag & MOD_MIR_AXIS_Z)
- if ( (fabsf(co1[2]) < mmd->tolerance) &&
- (fabsf(co2[2]) < mmd->tolerance) )
- ++eed->f2;
- }
- }
- }
- }
- }
-
- /* copy all selected vertices, */
- /* write pointer to new vert in old struct at eve->tmp.v */
- eve= em->verts.last;
- while(eve) {
- eve->f &= ~128; /* clear, for later test for loose verts */
- if(eve->f & flag) {
- sel= 1;
- v1= addvertlist(em, 0, NULL);
-
- copy_v3_v3(v1->co, eve->co);
- copy_v3_v3(v1->no, eve->no);
- v1->f= eve->f;
- eve->f &= ~flag;
- eve->tmp.v = v1;
- }
- else eve->tmp.v = NULL;
- eve= eve->prev;
- }
-
- if(sel==0) return 0;
-
- /* all edges with eed->f2==1 or eed->f2==2 become faces */
-
- /* if del_old==1 then extrude is in partial geometry, to keep it manifold.
- verts with f1==0 and (eve->f & 128)==0) are removed
- edges with eed->f2>2 are removed
- faces with efa->f1 are removed
- if del_old==0 the extrude creates a volume.
- */
-
- /* find if we delete old faces */
- if(is_face_sel && all==0) {
- for(eed= em->edges.first; eed; eed= eed->next) {
- if( (eed->f2==1 || eed->f2==2) ) {
- if(eed->f1==2) {
- del_old= 1;
- break;
- }
- }
- }
- }
-
- eed= em->edges.last;
- while(eed) {
- nexted= eed->prev;
- if( eed->f2<3) {
- eed->v1->f |= 128; /* = no loose vert! */
- eed->v2->f |= 128;
- }
- if( (eed->f2==1 || eed->f2==2) ) {
-
- /* if del_old, the preferred normal direction is exact opposite as for keep old faces */
- if(eed->dir != del_old)
- efa2 = addfacelist(em, eed->v1, eed->v2,
- eed->v2->tmp.v, eed->v1->tmp.v,
- eed->tmp.f, NULL);
- else
- efa2 = addfacelist(em, eed->v2, eed->v1,
- eed->v1->tmp.v, eed->v2->tmp.v,
- eed->tmp.f, NULL);
-
- /* Needs smarter adaption of existing creases.
- * If addedgelist is used, make sure seams are set to 0 on these
- * new edges, since we do not want to add any seams on extrusion.
- */
- efa2->e1->crease= eed->crease;
- efa2->e2->crease= eed->crease;
- efa2->e3->crease= eed->crease;
- if(efa2->e4) efa2->e4->crease= eed->crease;
- }
-
- eed= nexted;
- }
-
- /* duplicate faces, if necessary remove old ones */
- efa= em->faces.first;
- while(efa) {
- nextvl= efa->next;
- if(efa->f1 & 1) {
-
- v1 = efa->v1->tmp.v;
- v2 = efa->v2->tmp.v;
- v3 = efa->v3->tmp.v;
- if(efa->v4)
- v4 = efa->v4->tmp.v;
- else
- v4= NULL;
-
- /* hmm .. not sure about edges here */
- if(del_old==0) // if we keep old, we flip normal
- efa2= addfacelist(em, v3, v2, v1, v4, efa, efa);
- else
- efa2= addfacelist(em, v1, v2, v3, v4, efa, efa);
-
- /* for transform */
- add_normal_aligned(nor, efa->n);
-
- if(del_old) {
- BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
- }
- }
- efa= nextvl;
- }
- /* delete edges after copying edges above! */
- if(del_old) {
- eed= em->edges.first;
- while(eed) {
- nexted= eed->next;
- if(eed->f2==3 && eed->f1==1) {
- remedge(em, eed);
- free_editedge(em, eed);
- }
- eed= nexted;
- }
- }
-
- normalize_v3(nor); // for grab
-
- /* for all vertices with eve->tmp.v!=0
- if eve->f1==1: make edge
- if flag!=128 : if del_old==1: remove
- */
- eve= em->verts.last;
- while(eve) {
- nextve= eve->prev;
- if(eve->tmp.v) {
- if(eve->f1==1) addedgelist(em, eve, eve->tmp.v, NULL);
- else if( (eve->f & 128)==0) {
- if(del_old) {
- BLI_remlink(&em->verts,eve);
- free_editvert(em, eve);
- eve= NULL;
- }
- }
- }
- if(eve) {
- eve->f &= ~128;
- }
- eve= nextve;
- }
- // since its vertex select mode now, it also deselects higher order
- EM_selectmode_flush(em);
-
- if(is_zero_v3(nor)) return 'g'; // g is grab, for correct undo print
- return 'n';
-}
-
-/* generic extrude */
-short extrudeflag(Object *obedit, EditMesh *em, short flag, float *nor, int all)
-{
- if(em->selectmode & SCE_SELECT_VERTEX)
- return extrudeflag_vert(obedit, em, flag, nor, all);
- else
- return extrudeflag_edge(obedit, em, flag, nor, all);
-
-}
-
-void rotateflag(EditMesh *em, short flag, float *cent, float rotmat[][3])
-{
- /* all verts with (flag & 'flag') rotate */
- EditVert *eve;
-
- eve= em->verts.first;
- while(eve) {
- if(eve->f & flag) {
- eve->co[0]-=cent[0];
- eve->co[1]-=cent[1];
- eve->co[2]-=cent[2];
- mul_m3_v3(rotmat,eve->co);
- eve->co[0]+=cent[0];
- eve->co[1]+=cent[1];
- eve->co[2]+=cent[2];
- }
- eve= eve->next;
- }
-}
-
-void translateflag(EditMesh *em, short flag, float *vec)
-{
- /* all verts with (flag & 'flag') translate */
- EditVert *eve;
-
- eve= em->verts.first;
- while(eve) {
- if(eve->f & flag) {
- eve->co[0]+=vec[0];
- eve->co[1]+=vec[1];
- eve->co[2]+=vec[2];
- }
- eve= eve->next;
- }
-}
-
-/* helper call for below */
-static EditVert *adduplicate_vertex(EditMesh *em, EditVert *eve, int flag)
-{
- /* FIXME: copy deformation weight from eve ok here? */
- EditVert *v1= addvertlist(em, eve->co, eve);
-
- v1->f= eve->f;
- eve->f &= ~flag;
- eve->f|= 128;
-
- eve->tmp.v = v1;
-
- return v1;
-}
-
-/* old selection has flag 128 set, and flag 'flag' cleared
-new selection has flag 'flag' set */
-void adduplicateflag(EditMesh *em, int flag)
-{
- EditVert *eve, *v1, *v2, *v3, *v4;
- EditEdge *eed, *newed;
- EditFace *efa, *newfa, *act_efa = EM_get_actFace(em, 0);
-
- EM_clear_flag_all(em, 128);
- EM_selectmode_set(em); // paranoia check, selection now is consistent
-
- /* vertices first */
- for(eve= em->verts.last; eve; eve= eve->prev) {
-
- if(eve->f & flag)
- adduplicate_vertex(em, eve, flag);
- else
- eve->tmp.v = NULL;
- }
-
- /* copy edges, note that vertex selection can be independent of edge */
- for(eed= em->edges.last; eed; eed= eed->prev) {
- if( eed->f & flag ) {
- v1 = eed->v1->tmp.v;
- if(v1==NULL) v1= adduplicate_vertex(em, eed->v1, flag);
- v2 = eed->v2->tmp.v;
- if(v2==NULL) v2= adduplicate_vertex(em, eed->v2, flag);
-
- newed= addedgelist(em, v1, v2, eed);
-
- newed->f= eed->f;
- eed->f &= ~flag;
- eed->f |= 128;
- }
- }
-
- /* then duplicate faces, again create new vertices if needed */
- for(efa= em->faces.last; efa; efa= efa->prev) {
- if(efa->f & flag) {
- v1 = efa->v1->tmp.v;
- if(v1==NULL) v1= adduplicate_vertex(em, efa->v1, flag);
- v2 = efa->v2->tmp.v;
- if(v2==NULL) v2= adduplicate_vertex(em, efa->v2, flag);
- v3 = efa->v3->tmp.v;
- if(v3==NULL) v3= adduplicate_vertex(em, efa->v3, flag);
- if(efa->v4) {
- v4 = efa->v4->tmp.v;
- if(v4==NULL) v4= adduplicate_vertex(em, efa->v4, flag);
- }
- else v4= NULL;
-
- newfa= addfacelist(em, v1, v2, v3, v4, efa, efa);
-
- if (efa==act_efa) {
- EM_set_actFace(em, newfa);
- }
-
- newfa->f= efa->f;
- efa->f &= ~flag;
- efa->f |= 128;
- }
- }
-
- EM_fgon_flags(em); // redo flags and indices for fgons
-}
-
-void delfaceflag(EditMesh *em, int flag)
-{
- /* delete all faces with 'flag', including loose edges and loose vertices */
- /* this is maybe a bit weird, but this function is used for 'split' and 'separate' */
- /* in remaining vertices/edges 'flag' is cleared */
- EditVert *eve,*nextve;
- EditEdge *eed, *nexted;
- EditFace *efa,*nextvl;
-
- /* to detect loose edges, we put f2 flag on 1 */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & flag) eed->f2= 1;
- else eed->f2= 0;
- }
-
- /* delete faces */
- efa= em->faces.first;
- while(efa) {
- nextvl= efa->next;
- if(efa->f & flag) {
-
- efa->e1->f2= 1;
- efa->e2->f2= 1;
- efa->e3->f2= 1;
- if(efa->e4) {
- efa->e4->f2= 1;
- }
-
- BLI_remlink(&em->faces, efa);
- free_editface(em, efa);
- }
- efa= nextvl;
- }
-
- /* all remaining faces: make sure we keep the edges */
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->e1->f2= 0;
- efa->e2->f2= 0;
- efa->e3->f2= 0;
- if(efa->e4) {
- efa->e4->f2= 0;
- }
- }
-
- /* remove tagged edges, and clear remaining ones */
- eed= em->edges.first;
- while(eed) {
- nexted= eed->next;
-
- if(eed->f2==1) {
- remedge(em, eed);
- free_editedge(em, eed);
- }
- else {
- eed->f &= ~flag;
- eed->v1->f &= ~flag;
- eed->v2->f &= ~flag;
- }
- eed= nexted;
- }
-
- /* vertices with 'flag' now are the loose ones, and will be removed */
- eve= em->verts.first;
- while(eve) {
- nextve= eve->next;
- if(eve->f & flag) {
- BLI_remlink(&em->verts, eve);
- free_editvert(em, eve);
- }
- eve= nextve;
- }
-
-}
-
-/* ********************* */
-#if 0
-static int check_vnormal_flip(float *n, float *vnorm)
-{
- float inp;
-
- inp= n[0]*vnorm[0]+n[1]*vnorm[1]+n[2]*vnorm[2];
-
- /* angles 90 degrees: dont flip */
- if(inp> -0.000001) return 0;
-
- return 1;
-}
-#endif
-
-
-
-/* does face centers too */
-void recalc_editnormals(EditMesh *em)
-{
- EditFace *efa;
- EditVert *eve;
-
- for(eve= em->verts.first; eve; eve=eve->next)
- zero_v3(eve->no);
-
- for(efa= em->faces.first; efa; efa=efa->next) {
- float *n4= (efa->v4)? efa->v4->no: NULL;
- float *c4= (efa->v4)? efa->v4->co: NULL;
-
- if(efa->v4) {
- normal_quad_v3(efa->n, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
- cent_quad_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
- }
- else {
- normal_tri_v3(efa->n, efa->v1->co, efa->v2->co, efa->v3->co);
- cent_tri_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co);
- }
-
- accumulate_vertex_normals(efa->v1->no, efa->v2->no, efa->v3->no, n4,
- efa->n, efa->v1->co, efa->v2->co, efa->v3->co, c4);
- }
-
- /* following Mesh convention; we use vertex coordinate itself for normal in this case */
- for(eve= em->verts.first; eve; eve=eve->next) {
- if(normalize_v3(eve->no) == 0.0f) {
- copy_v3_v3(eve->no, eve->co);
- normalize_v3(eve->no);
- }
- }
-}
-
-int compareface(EditFace *vl1, EditFace *vl2)
-{
- EditVert *v1, *v2, *v3, *v4;
-
- if(vl1->v4 && vl2->v4) {
- v1= vl2->v1;
- v2= vl2->v2;
- v3= vl2->v3;
- v4= vl2->v4;
-
- if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) {
- if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) {
- if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) {
- if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) {
- return 1;
- }
- }
- }
- }
- }
- else if(vl1->v4==0 && vl2->v4==0) {
- v1= vl2->v1;
- v2= vl2->v2;
- v3= vl2->v3;
-
- if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) {
- if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) {
- if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) {
- return 1;
- }
- }
- }
- }
-
- return 0;
-}
-
-/* checks for existence, not tria overlapping inside quad */
-EditFace *exist_face(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4)
-{
- EditFace *efa, efatest;
-
- efatest.v1= v1;
- efatest.v2= v2;
- efatest.v3= v3;
- efatest.v4= v4;
-
- efa= em->faces.first;
- while(efa) {
- if(compareface(&efatest, efa)) return efa;
- efa= efa->next;
- }
- return NULL;
-}
-
-/* evaluate if entire quad is a proper convex quad */
-int convex(float *v1, float *v2, float *v3, float *v4)
-{
- float nor[3], nor1[3], nor2[3], vec[4][2];
-
- /* define projection, do both trias apart, quad is undefined! */
- normal_tri_v3( nor1,v1, v2, v3);
- normal_tri_v3( nor2,v1, v3, v4);
- nor[0]= ABS(nor1[0]) + ABS(nor2[0]);
- nor[1]= ABS(nor1[1]) + ABS(nor2[1]);
- nor[2]= ABS(nor1[2]) + ABS(nor2[2]);
-
- if(nor[2] >= nor[0] && nor[2] >= nor[1]) {
- vec[0][0]= v1[0]; vec[0][1]= v1[1];
- vec[1][0]= v2[0]; vec[1][1]= v2[1];
- vec[2][0]= v3[0]; vec[2][1]= v3[1];
- vec[3][0]= v4[0]; vec[3][1]= v4[1];
- }
- else if(nor[1] >= nor[0] && nor[1]>= nor[2]) {
- vec[0][0]= v1[0]; vec[0][1]= v1[2];
- vec[1][0]= v2[0]; vec[1][1]= v2[2];
- vec[2][0]= v3[0]; vec[2][1]= v3[2];
- vec[3][0]= v4[0]; vec[3][1]= v4[2];
- }
- else {
- vec[0][0]= v1[1]; vec[0][1]= v1[2];
- vec[1][0]= v2[1]; vec[1][1]= v2[2];
- vec[2][0]= v3[1]; vec[2][1]= v3[2];
- vec[3][0]= v4[1]; vec[3][1]= v4[2];
- }
-
- /* linetests, the 2 diagonals have to instersect to be convex */
- if( isect_line_line_v2(vec[0], vec[2], vec[1], vec[3]) > 0 ) return 1;
- return 0;
-}
-
-
-/* ********************* Fake Polgon support (FGon) ***************** */
-
-
-/* results in:
- - faces having ->fgonf flag set (also for draw)
- - edges having ->fgoni index set (for select)
-*/
-
-float EM_face_area(EditFace *efa)
-{
- if(efa->v4) return area_quad_v3(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
- else return area_tri_v3(efa->v1->co, efa->v2->co, efa->v3->co);
-}
-
-float EM_face_perimeter(EditFace *efa)
-{
- if(efa->v4) return
- len_v3v3(efa->v1->co, efa->v2->co)+
- len_v3v3(efa->v2->co, efa->v3->co)+
- len_v3v3(efa->v3->co, efa->v4->co)+
- len_v3v3(efa->v4->co, efa->v1->co);
-
- else return
- len_v3v3(efa->v1->co, efa->v2->co)+
- len_v3v3(efa->v2->co, efa->v3->co)+
- len_v3v3(efa->v3->co, efa->v1->co);
-}
-
-void EM_fgon_flags(EditMesh *em)
-{
- EditFace *efa, *efan, *efamax;
- EditEdge *eed;
- ListBase listb={NULL, NULL};
- float size, maxsize;
- short done, curindex= 1;
-
- // for each face with fgon edge AND not fgon flag set
- for(eed= em->edges.first; eed; eed= eed->next) eed->fgoni= 0; // index
- for(efa= em->faces.first; efa; efa= efa->next) efa->fgonf= 0; // flag
-
- // for speed & simplicity, put fgon face candidates in new listbase
- efa= em->faces.first;
- while(efa) {
- efan= efa->next;
- if( (efa->e1->h & EM_FGON) || (efa->e2->h & EM_FGON) ||
- (efa->e3->h & EM_FGON) || (efa->e4 && (efa->e4->h & EM_FGON)) ) {
- BLI_remlink(&em->faces, efa);
- BLI_addtail(&listb, efa);
- }
- efa= efan;
- }
-
- // find an undone face with fgon edge
- for(efa= listb.first; efa; efa= efa->next) {
- if(efa->fgonf==0) {
-
- // init this face
- efa->fgonf= EM_FGON;
- if(efa->e1->h & EM_FGON) efa->e1->fgoni= curindex;
- if(efa->e2->h & EM_FGON) efa->e2->fgoni= curindex;
- if(efa->e3->h & EM_FGON) efa->e3->fgoni= curindex;
- if(efa->e4 && (efa->e4->h & EM_FGON)) efa->e4->fgoni= curindex;
-
- // we search for largest face, to give facedot drawing rights
- maxsize= EM_face_area(efa);
- efamax= efa;
-
- // now flush curendex over edges and set faceflags
- done= 1;
- while(done==1) {
- done= 0;
-
- for(efan= listb.first; efan; efan= efan->next) {
- if(efan->fgonf==0) {
- // if one if its edges has index set, do other too
- if( (efan->e1->fgoni==curindex) || (efan->e2->fgoni==curindex) ||
- (efan->e3->fgoni==curindex) || (efan->e4 && (efan->e4->fgoni==curindex)) ) {
-
- efan->fgonf= EM_FGON;
- if(efan->e1->h & EM_FGON) efan->e1->fgoni= curindex;
- if(efan->e2->h & EM_FGON) efan->e2->fgoni= curindex;
- if(efan->e3->h & EM_FGON) efan->e3->fgoni= curindex;
- if(efan->e4 && (efan->e4->h & EM_FGON)) efan->e4->fgoni= curindex;
-
- size= EM_face_area(efan);
- if(size>maxsize) {
- efamax= efan;
- maxsize= size;
- }
- done= 1;
- }
- }
- }
- }
-
- efamax->fgonf |= EM_FGON_DRAW;
- curindex++;
-
- }
- }
-
- // put fgon face candidates back in listbase
- efa= listb.first;
- while(efa) {
- efan= efa->next;
- BLI_remlink(&listb, efa);
- BLI_addtail(&em->faces, efa);
- efa= efan;
- }
-
- // remove fgon flags when edge not in fgon (anymore)
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->fgoni==0) eed->h &= ~EM_FGON;
- }
-
-}
-
-/* editmesh vertmap, copied from intern.mesh.c
- * if do_face_idx_array is 0 it means we need to run it as well as freeing
- * */
-
-UvVertMap *EM_make_uv_vert_map(EditMesh *em, int selected, int do_face_idx_array, float *limit)
-{
- EditVert *ev;
- EditFace *efa;
- int totverts;
-
- /* vars from original func */
- UvVertMap *vmap;
- UvMapVert *buf;
- MTFace *tf;
- unsigned int a;
- int i, totuv, nverts;
-
- if (do_face_idx_array)
- EM_init_index_arrays(em, 0, 0, 1);
-
- /* we need the vert */
- for (ev= em->verts.first, totverts=0; ev; ev= ev->next, totverts++) {
- ev->tmp.l = totverts;
- }
-
- totuv = 0;
-
- /* generate UvMapVert array */
- for (efa= em->faces.first; efa; efa= efa->next)
- if(!selected || ((!efa->h) && (efa->f & SELECT)))
- totuv += (efa->v4)? 4: 3;
-
- if(totuv==0) {
- if (do_face_idx_array)
- EM_free_index_arrays();
- return NULL;
- }
- vmap= (UvVertMap*)MEM_callocN(sizeof(*vmap), "UvVertMap");
- if (!vmap) {
- if (do_face_idx_array)
- EM_free_index_arrays();
- return NULL;
- }
-
- vmap->vert= (UvMapVert**)MEM_callocN(sizeof(*vmap->vert)*totverts, "UvMapVert*");
- buf= vmap->buf= (UvMapVert*)MEM_callocN(sizeof(*vmap->buf)*totuv, "UvMapVert");
-
- if (!vmap->vert || !vmap->buf) {
- free_uv_vert_map(vmap);
- if (do_face_idx_array)
- EM_free_index_arrays();
- return NULL;
- }
-
- for (a=0, efa= em->faces.first; efa; a++, efa= efa->next) {
- if(!selected || ((!efa->h) && (efa->f & SELECT))) {
- nverts= (efa->v4)? 4: 3;
-
- for(i=0; i<nverts; i++) {
- buf->tfindex= i;
- buf->f= a;
- buf->separate = 0;
-
- buf->next= vmap->vert[(*(&efa->v1 + i))->tmp.l];
- vmap->vert[(*(&efa->v1 + i))->tmp.l]= buf;
-
- buf++;
- }
- }
- }
-
- /* sort individual uvs for each vert */
- for(a=0, ev=em->verts.first; ev; a++, ev= ev->next) {
- UvMapVert *newvlist= NULL, *vlist=vmap->vert[a];
- UvMapVert *iterv, *v, *lastv, *next;
- float *uv, *uv2, uvdiff[2];
-
- while(vlist) {
- v= vlist;
- vlist= vlist->next;
- v->next= newvlist;
- newvlist= v;
-
- efa = EM_get_face_for_index(v->f);
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- uv = tf->uv[v->tfindex];
-
- lastv= NULL;
- iterv= vlist;
-
- while(iterv) {
- next= iterv->next;
- efa = EM_get_face_for_index(iterv->f);
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- uv2 = tf->uv[iterv->tfindex];
-
- sub_v2_v2v2(uvdiff, uv2, uv);
-
- if(fabsf(uv[0]-uv2[0]) < limit[0] && fabsf(uv[1]-uv2[1]) < limit[1]) {
- if(lastv) lastv->next= next;
- else vlist= next;
- iterv->next= newvlist;
- newvlist= iterv;
- }
- else
- lastv=iterv;
-
- iterv= next;
- }
-
- newvlist->separate = 1;
- }
-
- vmap->vert[a]= newvlist;
- }
-
- if (do_face_idx_array)
- EM_free_index_arrays();
-
- return vmap;
-}
-
-UvMapVert *EM_get_uv_map_vert(UvVertMap *vmap, unsigned int v)
-{
- return vmap->vert[v];
-}
-
-void EM_free_uv_vert_map(UvVertMap *vmap)
-{
- if (vmap) {
- if (vmap->vert) MEM_freeN(vmap->vert);
- if (vmap->buf) MEM_freeN(vmap->buf);
- MEM_freeN(vmap);
- }
-}
-
-/* poll call for mesh operators requiring a view3d context */
-int EM_view3d_poll(bContext *C)
-{
- if(ED_operator_editmesh(C) && ED_operator_view3d_active(C))
- return 1;
- return 0;
-}
-
-/* higher quality normals */
-
-/* NormalCalc */
-/* NormalCalc modifier: calculates higher quality normals
-*/
-
-/* each edge uses this to */
-typedef struct EdgeFaceRef {
- int f1; /* init as -1 */
- int f2;
-} EdgeFaceRef;
-
-void EM_make_hq_normals(EditMesh *em)
-{
- EditFace *efa;
- EditVert *eve;
- int i;
-
- EdgeHash *edge_hash = BLI_edgehash_new();
- EdgeHashIterator *edge_iter;
- int edge_ref_count = 0;
- int ed_v1, ed_v2; /* use when getting the key */
- EdgeFaceRef *edge_ref_array = MEM_callocN(em->totedge * sizeof(EdgeFaceRef), "Edge Connectivity");
- EdgeFaceRef *edge_ref;
- float edge_normal[3];
-
- EM_init_index_arrays(em, 1, 1, 1);
-
- for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) {
- zero_v3(eve->no);
- eve->tmp.l= i;
- }
-
- /* This function adds an edge hash if its not there, and adds the face index */
-#define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \
- edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, EDV1, EDV2); \
- if (!edge_ref) { \
- edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \
- edge_ref->f1=i; \
- edge_ref->f2=-1; \
- BLI_edgehash_insert(edge_hash, EDV1, EDV2, edge_ref); \
- } else { \
- edge_ref->f2=i; \
- }
-
-
- efa= em->faces.first;
- for(i = 0; i < em->totface; i++, efa= efa->next) {
- if(efa->v4) {
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v1->tmp.l, efa->v2->tmp.l);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v2->tmp.l, efa->v3->tmp.l);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v3->tmp.l, efa->v4->tmp.l);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v4->tmp.l, efa->v1->tmp.l);
- } else {
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v1->tmp.l, efa->v2->tmp.l);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v2->tmp.l, efa->v3->tmp.l);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v3->tmp.l, efa->v1->tmp.l);
- }
- }
-
-#undef NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE
-
-
- for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) {
- /* Get the edge vert indices, and edge value (the face indices that use it)*/
- BLI_edgehashIterator_getKey(edge_iter, (int*)&ed_v1, (int*)&ed_v2);
- edge_ref = BLI_edgehashIterator_getValue(edge_iter);
-
- if (edge_ref->f2 != -1) {
- EditFace *ef1= EM_get_face_for_index(edge_ref->f1), *ef2= EM_get_face_for_index(edge_ref->f2);
- float angle= angle_normalized_v3v3(ef1->n, ef2->n);
- if(angle > 0.0f) {
- /* We have 2 faces using this edge, calculate the edges normal
- * using the angle between the 2 faces as a weighting */
- add_v3_v3v3(edge_normal, ef1->n, ef2->n);
- normalize_v3(edge_normal);
- mul_v3_fl(edge_normal, angle);
- }
- else {
- /* cant do anything useful here!
- Set the face index for a vert incase it gets a zero normal */
- EM_get_vert_for_index(ed_v1)->tmp.l=
- EM_get_vert_for_index(ed_v2)->tmp.l= -(edge_ref->f1 + 1);
- continue;
- }
- } else {
- /* only one face attached to that edge */
- /* an edge without another attached- the weight on this is
- * undefined, M_PI/2 is 90d in radians and that seems good enough */
- copy_v3_v3(edge_normal, EM_get_face_for_index(edge_ref->f1)->n);
- mul_v3_fl(edge_normal, M_PI/2);
- }
- add_v3_v3(EM_get_vert_for_index(ed_v1)->no, edge_normal );
- add_v3_v3(EM_get_vert_for_index(ed_v2)->no, edge_normal );
-
-
- }
- BLI_edgehashIterator_free(edge_iter);
- BLI_edgehash_free(edge_hash, NULL);
- MEM_freeN(edge_ref_array);
-
- /* normalize vertex normals and assign */
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(normalize_v3(eve->no) == 0.0f && eve->tmp.l < 0) {
- /* exceptional case, totally flat */
- efa= EM_get_face_for_index(-(eve->tmp.l) - 1);
- copy_v3_v3(eve->no, efa->n);
- }
- }
-
- EM_free_index_arrays();
-}
-
-void EM_solidify(EditMesh *em, float dist)
-{
- EditFace *efa;
- EditVert *eve;
- float *vert_angles= MEM_callocN(sizeof(float) * em->totvert * 2, "EM_solidify"); /* 2 in 1 */
- float *vert_accum= vert_angles + em->totvert;
- float face_angles[4];
- int i, j;
-
- for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) {
- eve->tmp.l= i;
- }
-
- efa= em->faces.first;
- for(i = 0; i < em->totface; i++, efa= efa->next) {
-
- if(!(efa->f & SELECT))
- continue;
-
- if(efa->v4) {
- angle_quad_v3(face_angles, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
- j= 3;
- }
- else {
- angle_tri_v3(face_angles, efa->v1->co, efa->v2->co, efa->v3->co);
- j= 2;
- }
-
- for(; j>=0; j--) {
- eve= *(&efa->v1 + j);
- vert_accum[eve->tmp.l] += face_angles[j];
- vert_angles[eve->tmp.l]+= shell_angle_to_dist(angle_normalized_v3v3(eve->no, efa->n)) * face_angles[j];
- }
- }
-
- for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) {
- if(vert_accum[i]) { /* zero if unselected */
- madd_v3_v3fl(eve->co, eve->no, dist * vert_angles[i] / vert_accum[i]);
- }
- }
-
- MEM_freeN(vert_angles);
-}
-
-/* not that optimal!, should be nicer with bmesh */
-static void tag_face_edges(EditFace *efa)
-{
- if(efa->v4)
- efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= efa->e4->tmp.l= 1;
- else
- efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= 1;
-}
-static int tag_face_edges_test(EditFace *efa)
-{
- if(efa->v4)
- return (efa->e1->tmp.l || efa->e2->tmp.l || efa->e3->tmp.l || efa->e4->tmp.l) ? 1:0;
- else
- return (efa->e1->tmp.l || efa->e2->tmp.l || efa->e3->tmp.l) ? 1:0;
-}
-
-static void em_deselect_nth_face(EditMesh *em, int nth, EditFace *efa_act)
-{
- EditFace *efa;
- EditEdge *eed;
- int ok= 1;
-
- if(efa_act==NULL) {
- return;
- }
-
- /* to detect loose edges, we put f2 flag on 1 */
- for(eed= em->edges.first; eed; eed= eed->next) {
- eed->tmp.l= 0;
- }
-
- for (efa= em->faces.first; efa; efa= efa->next) {
- efa->tmp.l = 0;
- }
-
- efa_act->tmp.l = 1;
-
- while(ok) {
- ok = 0;
-
- for (efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- if(efa->tmp.l==1) { /* initialize */
- tag_face_edges(efa);
- }
-
- if(efa->tmp.l) {
- efa->tmp.l++;
- }
- }
- }
-
- for (efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- if(efa->tmp.l==0 && tag_face_edges_test(efa)) {
- efa->tmp.l= 1;
- ok = 1; /* keep looping */
- }
- }
- }
- }
-
- for (efa= em->faces.first; efa; efa= efa->next) {
- if(efa->tmp.l > 0 && efa->tmp.l % nth) {
- EM_select_face(efa, 0);
- }
- }
- for (efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- EM_select_face(efa, 1);
- }
- }
-
- EM_nvertices_selected(em);
- EM_nedges_selected(em);
- EM_nfaces_selected(em);
-}
-
-/* not that optimal!, should be nicer with bmesh */
-static void tag_edge_verts(EditEdge *eed)
-{
- eed->v1->tmp.l= eed->v2->tmp.l= 1;
-}
-static int tag_edge_verts_test(EditEdge *eed)
-{
- return (eed->v1->tmp.l || eed->v2->tmp.l) ? 1:0;
-}
-
-static void em_deselect_nth_edge(EditMesh *em, int nth, EditEdge *eed_act)
-{
- EditEdge *eed;
- EditVert *eve;
- int ok= 1;
-
- if(eed_act==NULL) {
- return;
- }
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- eve->tmp.l= 0;
- }
-
- for (eed= em->edges.first; eed; eed= eed->next) {
- eed->tmp.l = 0;
- }
-
- eed_act->tmp.l = 1;
-
- while(ok) {
- ok = 0;
-
- for (eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
- if(eed->tmp.l==1) { /* initialize */
- tag_edge_verts(eed);
- }
-
- if(eed->tmp.l) {
- eed->tmp.l++;
- }
- }
- }
-
- for (eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
- if(eed->tmp.l==0 && tag_edge_verts_test(eed)) {
- eed->tmp.l= 1;
- ok = 1; /* keep looping */
- }
- }
- }
- }
-
- for (eed= em->edges.first; eed; eed= eed->next) {
- if(eed->tmp.l > 0 && eed->tmp.l % nth) {
- EM_select_edge(eed, 0);
- }
- }
- for (eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
- EM_select_edge(eed, 1);
- }
- }
-
- {
- /* grr, should be a function */
- EditFace *efa;
- for (efa= em->faces.first; efa; efa= efa->next) {
- if(efa->v4) {
- if(efa->e1->f & efa->e2->f & efa->e3->f & efa->e4->f & SELECT );
- else efa->f &= ~SELECT;
- }
- else {
- if(efa->e1->f & efa->e2->f & efa->e3->f & SELECT );
- else efa->f &= ~SELECT;
- }
- }
- }
-
- EM_nvertices_selected(em);
- EM_nedges_selected(em);
- EM_nfaces_selected(em);
-}
-
-static void em_deselect_nth_vert(EditMesh *em, int nth, EditVert *eve_act)
-{
- EditVert *eve;
- EditEdge *eed;
- int ok= 1;
-
- if(eve_act==NULL) {
- return;
- }
-
- for (eve= em->verts.first; eve; eve= eve->next) {
- eve->tmp.l = 0;
- }
-
- eve_act->tmp.l = 1;
-
- while(ok) {
- ok = 0;
-
- for (eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) {
- if(eve->tmp.l)
- eve->tmp.l++;
- }
- }
-
- for (eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
- if(eed->v1->tmp.l==2 && eed->v2->tmp.l==0) { /* initialize */
- eed->v2->tmp.l= 1;
- ok = 1; /* keep looping */
- }
- else if(eed->v2->tmp.l==2 && eed->v1->tmp.l==0) { /* initialize */
- eed->v1->tmp.l= 1;
- ok = 1; /* keep looping */
- }
- }
- }
- }
-
- for (eve= em->verts.first; eve; eve= eve->next) {
- if(eve->tmp.l > 0 && eve->tmp.l % nth) {
- eve->f &= ~SELECT;
- }
- }
-
- EM_deselect_flush(em);
-
- EM_nvertices_selected(em);
- // EM_nedges_selected(em); // flush does these
- // EM_nfaces_selected(em); // flush does these
-}
-
-static void deselect_nth_active(EditMesh *em, EditVert **eve_p, EditEdge **eed_p, EditFace **efa_p)
-{
- EditSelection *ese;
-
- *eve_p= NULL;
- *eed_p= NULL;
- *efa_p= NULL;
-
- ese= (EditSelection*)em->selected.last;
-
- if(ese) {
- switch(ese->type) {
- case EDITVERT:
- *eve_p= (EditVert *)ese->data;
- return;
- case EDITEDGE:
- *eed_p= (EditEdge *)ese->data;
- return;
- case EDITFACE:
- *efa_p= (EditFace *)ese->data;
- return;
- }
- }
-
- if(em->selectmode & SCE_SELECT_VERTEX) {
- EditVert *eve;
- for (eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) {
- *eve_p= eve;
- return;
- }
- }
- }
-
- if(em->selectmode & SCE_SELECT_EDGE) {
- EditEdge *eed;
- for (eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
- *eed_p= eed;
- return;
- }
- }
- }
-
- if(em->selectmode & SCE_SELECT_FACE) {
- EditFace *efa= EM_get_actFace(em, 1);
- if(efa) {
- *efa_p= efa;
- return;
- }
- }
-}
-
-int EM_deselect_nth(EditMesh *em, int nth)
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- deselect_nth_active(em, &eve, &eed, &efa);
-
- if(eve)
- em_deselect_nth_vert(em, nth, eve);
- else if (eed)
- em_deselect_nth_edge(em, nth, eed);
- else if (efa)
- em_deselect_nth_face(em, nth, efa);
- else
- return 0;
-
- return 1;
-}
-
-void EM_project_snap_verts(bContext *C, ARegion *ar, Object *obedit, EditMesh *em)
-{
- EditVert *eve;
- for(eve= em->verts.first;eve; eve=eve->next) {
- if(eve->f & SELECT) {
- float mval[2], vec[3], no_dummy[3];
- int dist_dummy;
- mul_v3_m4v3(vec, obedit->obmat, eve->co);
- project_float_noclip(ar, vec, mval);
- if(snapObjectsContext(C, mval, &dist_dummy, vec, no_dummy, SNAP_NOT_OBEDIT)) {
- mul_v3_m4v3(eve->co, obedit->imat, vec);
- }
- }
- }
-}
diff --git a/source/blender/editors/mesh/editmesh_loop.c b/source/blender/editors/mesh/editmesh_loop.c
deleted file mode 100644
index a671de71636..00000000000
--- a/source/blender/editors/mesh/editmesh_loop.c
+++ /dev/null
@@ -1,738 +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) 2004 by Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/mesh/editmesh_loop.c
- * \ingroup edmesh
- */
-
-
-/*
-
-editmesh_loop: tools with own drawing subloops, select, knife, subdiv
-
-*/
-
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_utildefines.h"
-#include "BLI_editVert.h"
-#include "BLI_ghash.h"
-
-#include "BKE_context.h"
-#include "BKE_depsgraph.h"
-#include "BKE_mesh.h"
-#include "BKE_array_mallocn.h"
-
-#include "PIL_time.h"
-
-#include "BIF_gl.h"
-
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "ED_mesh.h"
-#include "ED_view3d.h"
-
-#include "mesh_intern.h"
-
-/* **** XXX ******** */
-static void error(const char *UNUSED(arg)) {}
-/* **** XXX ******** */
-
-#if 0 /* UNUSED 2.5 */
-static void edgering_sel(EditMesh *em, EditEdge *startedge, int select, int previewlines)
-{
- EditEdge *eed;
- EditFace *efa;
- EditVert *v[2][2];
- float co[2][3];
- int looking= 1,i;
-
- /* in eed->f1 we put the valence (amount of faces in edge) */
- /* in eed->f2 we put tagged flag as correct loop */
- /* in efa->f1 we put tagged flag as correct to select */
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- eed->f1= 0;
- eed->f2= 0;
- }
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->f1= 0;
- if(efa->h==0) {
- efa->e1->f1++;
- efa->e2->f1++;
- efa->e3->f1++;
- if(efa->e4) efa->e4->f1++;
- }
- }
-
- // tag startedge OK
- startedge->f2= 1;
-
- while(looking) {
- looking= 0;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->e4 && efa->f1==0 && efa->h == 0) { // not done quad
- if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
-
- // if edge tagged, select opposing edge and mark face ok
- if(efa->e1->f2) {
- efa->e3->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- else if(efa->e2->f2) {
- efa->e4->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- if(efa->e3->f2) {
- efa->e1->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- if(efa->e4->f2) {
- efa->e2->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- }
- }
- }
- }
-
- if(previewlines > 0 && select == 0){
-// XXX persp(PERSP_VIEW);
-// XXX glPushMatrix();
-// XXX mymultmatrix(obedit->obmat);
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->v4 == NULL) { continue; }
- if(efa->h == 0){
- if(efa->e1->f2 == 1){
- if(efa->e1->h == 1 || efa->e3->h == 1 )
- continue;
-
- v[0][0] = efa->v1;
- v[0][1] = efa->v2;
- v[1][0] = efa->v4;
- v[1][1] = efa->v3;
- } else if(efa->e2->f2 == 1){
- if(efa->e2->h == 1 || efa->e4->h == 1)
- continue;
- v[0][0] = efa->v2;
- v[0][1] = efa->v3;
- v[1][0] = efa->v1;
- v[1][1] = efa->v4;
- } else { continue; }
-
- for(i=1;i<=previewlines;i++){
- co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
- co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
- co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
-
- co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
- co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
- co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];
- glColor3ub(255, 0, 255);
- glBegin(GL_LINES);
- glVertex3f(co[0][0],co[0][1],co[0][2]);
- glVertex3f(co[1][0],co[1][1],co[1][2]);
- glEnd();
- }
- }
- }
- glPopMatrix();
- } else {
-
- /* (de)select the edges */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f2) EM_select_edge(eed, select);
- }
- }
-}
-
-static void CutEdgeloop(Object *obedit, wmOperator *op, EditMesh *em, int numcuts)
-{
- ViewContext vc; // XXX
- EditEdge *nearest=NULL, *eed;
- float fac;
- int keys = 0, holdnum=0, selectmode, dist;
- int mvalo[2] = {0, 0}, mval[2] = {0, 0};
- short event=0, val, choosing=1, cancel=0, cuthalf = 0, smooth=0;
- short hasHidden = 0;
- char msg[128];
-
- selectmode = em->selectmode;
-
- if(em->selectmode & SCE_SELECT_FACE){
- em->selectmode = SCE_SELECT_EDGE;
- EM_selectmode_set(em);
- }
-
-
- BIF_undo_push("Loopcut Begin");
- while(choosing && !cancel){
-// XXX getmouseco_areawin(mval);
- if (mval[0] != mvalo[0] || mval[1] != mvalo[1]) {
- mvalo[0] = mval[0];
- mvalo[1] = mval[1];
- dist= 50;
- nearest = findnearestedge(&vc, &dist); // returns actual distance in dist
-// scrarea_do_windraw(curarea); // after findnearestedge, backbuf!
-
- BLI_snprintf(msg, sizeof(msg),"Number of Cuts: %d (S)mooth: %s", numcuts, smooth ? "on":"off");
-
-// headerprint(msg);
- /* Need to figure preview */
- if(nearest){
- edgering_sel(em, nearest, 0, numcuts);
- }
-// XXX screen_swapbuffers();
-
- /* backbuffer refresh for non-apples (no aux) */
-#ifndef __APPLE__
-// XXX if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
-// backdrawview3d(0);
-// }
-#endif
- }
- else PIL_sleep_ms(10); // idle
-
-
- while(qtest())
- {
- val=0;
-// XXX event= extern_qread(&val);
- if(val && (event == MOUSEX || event == MOUSEY)){ ; }
- else if(val && ((event==LEFTMOUSE || event==RETKEY) || (event == MIDDLEMOUSE || event==PADENTER)))
- {
- if(event == MIDDLEMOUSE){
- cuthalf = 1;
- }
- if (nearest==NULL)
- cancel = 1;
- choosing=0;
- mvalo[0] = -1;
- }
- else if(val && (event==ESCKEY || event==RIGHTMOUSE ))
- {
- choosing=0;
- cancel = 1;
- mvalo[0] = -1;
- }
- else if(val && (event==PADPLUSKEY || event==WHEELUPMOUSE))
- {
- numcuts++;
- mvalo[0] = -1;
- }
- else if(val && (event==PADMINUS || event==WHEELDOWNMOUSE))
- {
- if(numcuts > 1){
- numcuts--;
- mvalo[0] = -1;
- }
- }
- else if(val && event==SKEY)
- {
- if(smooth){smooth=0;}
- else { smooth=1; }
- mvalo[0] = -1;
- }
-
- else if(val){
- holdnum = -1;
- switch(event){
- case PAD9:
- case NINEKEY:
- holdnum = 9; break;
- case PAD8:
- case EIGHTKEY:
- holdnum = 8;break;
- case PAD7:
- case SEVENKEY:
- holdnum = 7;break;
- case PAD6:
- case SIXKEY:
- holdnum = 6;break;
- case PAD5:
- case FIVEKEY:
- holdnum = 5;break;
- case PAD4:
- case FOURKEY:
- holdnum = 4;break;
- case PAD3:
- case THREEKEY:
- holdnum = 3; break;
- case PAD2:
- case TWOKEY:
- holdnum = 2;break;
- case PAD1:
- case ONEKEY:
- holdnum = 1; break;
- case PAD0:
- case ZEROKEY:
- holdnum = 0;break;
- case BACKSPACEKEY:
- holdnum = -2;break;
- }
- if(holdnum >= 0 && numcuts*10 < 130){
- if(keys == 0){ // first level numeric entry
- if(holdnum > 0){
- numcuts = holdnum;
- keys++;
- }
- } else if(keys > 0){//highrt level numeric entry
- numcuts *= 10;
- numcuts += holdnum;
- keys++;
- }
- } else if (holdnum == -2){// backspace
- if (keys > 1){
- numcuts /= 10;
- keys--;
- } else {
- numcuts=1;
- keys = 0;
- }
- }
- mvalo[0] = -1;
- break;
- } // End Numeric Entry
- } //End while(qtest())
- } // End Choosing
-
- if(cancel){
- return;
- }
- /* clean selection */
- for(eed=em->edges.first; eed; eed = eed->next){
- EM_select_edge(eed,0);
- }
- /* select edge ring */
- edgering_sel(em, nearest, 1, 0);
-
- /* now cut the loops */
- if(smooth){
- fac= 1.0f;
-// XXX if(fbutton(&fac, 0.0f, 5.0f, 10, 10, "Smooth:")==0) return;
- fac= 0.292f*fac;
- esubdivideflag(obedit, em, SELECT,fac,0,B_SMOOTH,numcuts, SUBDIV_CORNER_PATH, SUBDIV_SELECT_LOOPCUT);
- } else {
- esubdivideflag(obedit, em, SELECT,0,0,0,numcuts,SUBDIV_CORNER_PATH, SUBDIV_SELECT_LOOPCUT);
- }
- /* if this was a single cut, enter edgeslide mode */
- if(numcuts == 1 && hasHidden == 0){
- if(cuthalf)
- EdgeSlide(em, op, 1,0.0);
- else {
- if(EdgeSlide(em, op, 0,0.0) == -1){
- BIF_undo();
- }
- }
- }
-
- if(em->selectmode != selectmode){
- em->selectmode = selectmode;
- EM_selectmode_set(em);
- }
-
-// DAG_id_tag_update(obedit->data, 0);
- return;
-}
-#endif
-
-/* *************** LOOP SELECT ************* */
-#if 0
-static short edgeFaces(EditMesh *em, EditEdge *e)
-{
- EditFace *search=NULL;
- short count = 0;
-
- search = em->faces.first;
- while(search){
- if((search->e1 == e || search->e2 == e) || (search->e3 == e || search->e4 == e))
- count++;
- search = search->next;
- }
- return count;
-}
-#endif
-
-
-
-/* ***************** TRAIL ************************
-
-Read a trail of mouse coords and return them as an array of CutCurve structs
-len returns number of mouse coords read before commiting with RETKEY
-It is up to the caller to free the block when done with it,
-
-XXX Is only used here, so local inside this file (ton)
- */
-
-#define TRAIL_POLYLINE 1 /* For future use, They don't do anything yet */
-#define TRAIL_FREEHAND 2
-#define TRAIL_MIXED 3 /* (1|2) */
-#define TRAIL_AUTO 4
-#define TRAIL_MIDPOINTS 8
-
-typedef struct CutCurve {
- float x;
- float y;
-} CutCurve;
-
-
-/* ******************************************************************** */
-/* Knife Subdivide Tool. Subdivides edges intersected by a mouse trail
- drawn by user.
-
- Currently mapped to KKey when in MeshEdit mode.
- Usage:
- Hit Shift K, Select Centers or Exact
- Hold LMB down to draw path, hit RETKEY.
- ESC cancels as expected.
-
- Contributed by Robert Wenzlaff (Det. Thorn).
-
- 2.5 revamp:
- - non modal (no menu before cutting)
- - exit on mouse release
- - polygon/segment drawing can become handled by WM cb later
-
-*/
-
-#define KNIFE_EXACT 1
-#define KNIFE_MIDPOINT 2
-#define KNIFE_MULTICUT 3
-
-static EnumPropertyItem knife_items[]= {
- {KNIFE_EXACT, "EXACT", 0, "Exact", ""},
- {KNIFE_MIDPOINT, "MIDPOINTS", 0, "Midpoints", ""},
- {KNIFE_MULTICUT, "MULTICUT", 0, "Multicut", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-/* seg_intersect() Determines if and where a mouse trail intersects an EditEdge */
-
-static float seg_intersect(EditEdge *e, CutCurve *c, int len, char mode, struct GHash *gh)
-{
-#define MAXSLOPE 100000
- float x11, y11, x12=0, y12=0, x2max, x2min, y2max;
- float y2min, dist, lastdist=0, xdiff2, xdiff1;
- float m1, b1, m2, b2, x21, x22, y21, y22, xi;
- float yi, x1min, x1max, y1max, y1min, perc=0;
- float *scr;
- float threshold;
- int i;
-
- threshold = 0.000001; /*tolerance for vertex intersection*/
- // XXX threshold = scene->toolsettings->select_thresh / 100;
-
- /* Get screen coords of verts */
- scr = BLI_ghash_lookup(gh, e->v1);
- x21=scr[0];
- y21=scr[1];
-
- scr = BLI_ghash_lookup(gh, e->v2);
- x22=scr[0];
- y22=scr[1];
-
- xdiff2=(x22-x21);
- if (xdiff2) {
- m2=(y22-y21)/xdiff2;
- b2= ((x22*y21)-(x21*y22))/xdiff2;
- }
- else {
- m2=MAXSLOPE; /* Verticle slope */
- b2=x22;
- }
-
- /*check for *exact* vertex intersection first*/
- if(mode!=KNIFE_MULTICUT){
- for (i=0; i<len; i++){
- if (i>0){
- x11=x12;
- y11=y12;
- }
- else {
- x11=c[i].x;
- y11=c[i].y;
- }
- x12=c[i].x;
- y12=c[i].y;
-
- /*test e->v1*/
- if((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)){
- e->v1->f1 = 1;
- perc = 0;
- return(perc);
- }
- /*test e->v2*/
- else if((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)){
- e->v2->f1 = 1;
- perc = 0;
- return(perc);
- }
- }
- }
-
- /*now check for edge interesect (may produce vertex intersection as well)*/
- for (i=0; i<len; i++){
- if (i>0){
- x11=x12;
- y11=y12;
- }
- else {
- x11=c[i].x;
- y11=c[i].y;
- }
- x12=c[i].x;
- y12=c[i].y;
-
- /* Perp. Distance from point to line */
- if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */
- /* change in sign. Skip extra math */
- else dist=x22-x12;
-
- if (i==0) lastdist=dist;
-
- /* if dist changes sign, and intersect point in edge's Bound Box*/
- if ((lastdist*dist)<=0){
- xdiff1=(x12-x11); /* Equation of line between last 2 points */
- if (xdiff1){
- m1=(y12-y11)/xdiff1;
- b1= ((x12*y11)-(x11*y12))/xdiff1;
- }
- else{
- m1=MAXSLOPE;
- b1=x12;
- }
- x2max=MAX2(x21,x22)+0.001; /* prevent missed edges */
- x2min=MIN2(x21,x22)-0.001; /* due to round off error */
- y2max=MAX2(y21,y22)+0.001;
- y2min=MIN2(y21,y22)-0.001;
-
- /* Found an intersect, calc intersect point */
- if (m1==m2){ /* co-incident lines */
- /* cut at 50% of overlap area*/
- x1max=MAX2(x11, x12);
- x1min=MIN2(x11, x12);
- xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0;
-
- y1max=MAX2(y11, y12);
- y1min=MIN2(y11, y12);
- yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0;
- }
- else if (m2==MAXSLOPE){
- xi=x22;
- yi=m1*x22+b1;
- }
- else if (m1==MAXSLOPE){
- xi=x12;
- yi=m2*x12+b2;
- }
- else {
- xi=(b1-b2)/(m2-m1);
- yi=(b1*m2-m1*b2)/(m2-m1);
- }
-
- /* Intersect inside bounding box of edge?*/
- if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){
- /*test for vertex intersect that may be 'close enough'*/
- if(mode!=KNIFE_MULTICUT){
- if(xi <= (x21 + threshold) && xi >= (x21 - threshold)){
- if(yi <= (y21 + threshold) && yi >= (y21 - threshold)){
- e->v1->f1 = 1;
- perc = 0;
- break;
- }
- }
- if(xi <= (x22 + threshold) && xi >= (x22 - threshold)){
- if(yi <= (y22 + threshold) && yi >= (y22 - threshold)){
- e->v2->f1 = 1;
- perc = 0;
- break;
- }
- }
- }
- if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21);
- else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/
- //isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */
-
- break;
- }
- }
- lastdist=dist;
- }
- return(perc);
-}
-
-/* for multicut */
-#define MAX_CUTS 256
-
-/* for amount of edges */
-#define MAX_CUT_EDGES 1024
-
-static int knife_cut_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- ARegion *ar= CTX_wm_region(C);
- EditEdge *eed;
- EditVert *eve;
- CutCurve curve[MAX_CUT_EDGES];
- struct GHash *gh;
- float isect=0.0;
- float *scr, co[4];
- int len=0;
- short numcuts= RNA_int_get(op->ptr, "num_cuts");
- short mode= RNA_enum_get(op->ptr, "type");
-// int corner_cut_pattern= RNA_enum_get(op->ptr,"corner_cut_pattern");
-
- /* edit-object needed for matrix, and ar->regiondata for projections to work */
- if (ELEM3(NULL, obedit, ar, ar->regiondata))
- return OPERATOR_CANCELLED;
-
- if (EM_nvertices_selected(em) < 2) {
- error("No edges are selected to operate on");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
-
- /* get the cut curve */
- RNA_BEGIN(op->ptr, itemptr, "path") {
-
- RNA_float_get_array(&itemptr, "loc", (float *)&curve[len]);
- len++;
- if(len>= MAX_CUT_EDGES) break;
- }
- RNA_END;
-
- if(len<2) {
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
-
- /*store percentage of edge cut for KNIFE_EXACT here.*/
- for(eed=em->edges.first; eed; eed= eed->next)
- eed->tmp.fp = 0.0;
-
- /*the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer*/
- gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "knife_cut_exec gh");
- for(eve=em->verts.first; eve; eve=eve->next){
- scr = MEM_mallocN(sizeof(float)*2, "Vertex Screen Coordinates");
- VECCOPY(co, eve->co);
- co[3]= 1.0;
- mul_m4_v4(obedit->obmat, co);
- project_float(ar, co, scr);
- BLI_ghash_insert(gh, eve, scr);
- eve->f1 = 0; /*store vertex intersection flag here*/
-
- }
-
- eed= em->edges.first;
- while(eed) {
- if( eed->v1->f & eed->v2->f & SELECT ){ // NOTE: uses vertex select, subdiv doesnt do edges yet
- isect= seg_intersect(eed, curve, len, mode, gh);
- if (isect!=0.0f) eed->f2= 1;
- else eed->f2=0;
- eed->tmp.fp= isect;
- }
- else {
- eed->f2=0;
- eed->f1=0;
- }
- eed= eed->next;
- }
-
- if (mode==KNIFE_MIDPOINT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, 1, SUBDIV_CORNER_INNERVERT, SUBDIV_SELECT_INNER);
- else if (mode==KNIFE_MULTICUT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, numcuts, SUBDIV_CORNER_INNERVERT, SUBDIV_SELECT_INNER);
- else esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE|B_PERCENTSUBD, 1, SUBDIV_CORNER_INNERVERT, SUBDIV_SELECT_INNER);
-
- eed=em->edges.first;
- while(eed){
- eed->f2=0;
- eed->f1=0;
- eed=eed->next;
- }
-
- BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-
-void MESH_OT_knife_cut(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- ot->name= "Knife Cut";
- ot->description= "Cut selected edges and faces into parts";
- ot->idname= "MESH_OT_knife_cut";
-
- ot->invoke= WM_gesture_lines_invoke;
- ot->modal= WM_gesture_lines_modal;
- ot->exec= knife_cut_exec;
- ot->cancel= WM_gesture_lines_cancel;
-
- ot->poll= EM_view3d_poll;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "type", knife_items, KNIFE_EXACT, "Type", "");
- prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
- RNA_def_int(ot->srna, "num_cuts", 1, 1, MAX_CUTS, "Number of Cuts", "Only for Multi-Cut", 1, MAX_CUTS);
- // doesn't work atm.. RNA_def_enum(ot->srna, "corner_cut_pattern", corner_type_items, SUBDIV_CORNER_INNERVERT, "Corner Cut Pattern", "Topology pattern to use to fill a face after cutting across its corner");
-
- /* internal */
- RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
-}
-
-/* ******************************************************* */
-
diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c
deleted file mode 100644
index 004b98e5dd7..00000000000
--- a/source/blender/editors/mesh/editmesh_mods.c
+++ /dev/null
@@ -1,4496 +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) 2004 Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/mesh/editmesh_mods.c
- * \ingroup edmesh
- */
-
-
-/*
-
-editmesh_mods.c, UI level access, no geometry changes
-
-*/
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_material_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_editVert.h"
-#include "BLI_rand.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_context.h"
-#include "BKE_displist.h"
-#include "BKE_depsgraph.h"
-#include "BKE_mesh.h"
-#include "BKE_material.h"
-#include "BKE_paint.h"
-#include "BKE_report.h"
-#include "BKE_texture.h"
-
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-
-#include "RE_render_ext.h" /* externtex */
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "ED_mesh.h"
-#include "ED_screen.h"
-#include "ED_view3d.h"
-#include "ED_uvedit.h"
-
-#include "BIF_gl.h"
-
-#include "mesh_intern.h"
-
-#include "BLO_sys_types.h" // for intptr_t support
-
-/* XXX */
-static void waitcursor(int UNUSED(val)) {}
-static int pupmenu(const char *UNUSED(arg)) {return 0;}
-
-/* ****************************** MIRROR **************** */
-
-void EM_cache_x_mirror_vert(struct Object *ob, struct EditMesh *em)
-{
- EditVert *eve, *eve_mirror;
- int index= 0;
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- eve->tmp.v= NULL;
- }
-
- for(eve= em->verts.first; eve; eve= eve->next, index++) {
- if(eve->tmp.v==NULL) {
- eve_mirror = editmesh_get_x_mirror_vert(ob, em, eve, eve->co, index);
- if(eve_mirror) {
- eve->tmp.v= eve_mirror;
- eve_mirror->tmp.v = eve;
- }
- }
- }
-}
-
-static void EM_select_mirrored(Object *obedit, EditMesh *em, int extend)
-{
-
- EditVert *eve;
-
- EM_cache_x_mirror_vert(obedit, em);
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT && eve->tmp.v && (eve->tmp.v != eve->tmp.v->tmp.v)) {
- eve->tmp.v->f |= SELECT;
-
- if(extend==FALSE)
- eve->f &= ~SELECT;
-
- /* remove the interference */
- eve->tmp.v->tmp.v= NULL;
- eve->tmp.v= NULL;
- }
- }
-}
-
-void EM_automerge(Scene *scene, Object *obedit, int update)
-{
- Mesh *me= obedit ? obedit->data : NULL; /* can be NULL */
- /* int len; */ /* UNUSED */
-
- if ((scene->toolsettings->automerge) &&
- (obedit && obedit->type==OB_MESH && (obedit->mode & OB_MODE_EDIT))
- ) {
- EditMesh *em= me->edit_mesh;
- int totvert= em->totvert, totedge= em->totedge, totface= em->totface;
-
- /* len = */ /* UNUSED */ removedoublesflag(em, 1, 1, scene->toolsettings->doublimit);
- if (totvert != em->totvert || totedge != em->totedge || totface != em->totface) {
- if (update) {
- DAG_id_tag_update(&me->id, 0);
- }
- }
- }
-}
-
-/* ****************************** SELECTION ROUTINES **************** */
-
-unsigned int em_solidoffs=0, em_wireoffs=0, em_vertoffs=0; /* set in drawobject.c ... for colorindices */
-
-/* facilities for border select and circle select */
-static char *selbuf= NULL;
-
-/* opengl doesn't support concave... */
-static void draw_triangulated(int mcords[][2], short tot)
-{
- ListBase lb={NULL, NULL};
- DispList *dl;
- float *fp;
- int a;
-
- /* make displist */
- dl= MEM_callocN(sizeof(DispList), "poly disp");
- dl->type= DL_POLY;
- dl->parts= 1;
- dl->nr= tot;
- dl->verts= fp= MEM_callocN(tot*3*sizeof(float), "poly verts");
- BLI_addtail(&lb, dl);
-
- for(a=0; a<tot; a++, fp+=3) {
- fp[0]= (float)mcords[a][0];
- fp[1]= (float)mcords[a][1];
- }
-
- /* do the fill */
- filldisplist(&lb, &lb, 0);
-
- /* do the draw */
- dl= lb.first; /* filldisplist adds in head of list */
- if(dl->type==DL_INDEX3) {
- int *index;
-
- a= dl->parts;
- fp= dl->verts;
- index= dl->index;
- glBegin(GL_TRIANGLES);
- while(a--) {
- glVertex3fv(fp+3*index[0]);
- glVertex3fv(fp+3*index[1]);
- glVertex3fv(fp+3*index[2]);
- index+= 3;
- }
- glEnd();
- }
-
- freedisplist(&lb);
-}
-
-
-/* reads rect, and builds selection array for quick lookup */
-/* returns if all is OK */
-int EM_init_backbuf_border(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
-{
- struct ImBuf *buf;
- unsigned int *dr;
- int a;
-
- if(vc->obedit==NULL || vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
-
- buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
- if(buf==NULL) return 0;
- if(em_vertoffs==0) return 0;
-
- dr = buf->rect;
-
- /* build selection lookup */
- selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
-
- a= (xmax-xmin+1)*(ymax-ymin+1);
- while(a--) {
- if(*dr>0 && *dr<=em_vertoffs)
- selbuf[*dr]= 1;
- dr++;
- }
- IMB_freeImBuf(buf);
- return 1;
-}
-
-int EM_check_backbuf(unsigned int index)
-{
- if(selbuf==NULL) return 1;
- if(index>0 && index<=em_vertoffs)
- return selbuf[index];
- return 0;
-}
-
-void EM_free_backbuf(void)
-{
- if(selbuf) MEM_freeN(selbuf);
- selbuf= NULL;
-}
-
-/* mcords is a polygon mask
- - grab backbuffer,
- - draw with black in backbuffer,
- - grab again and compare
- returns 'OK'
-*/
-int EM_mask_init_backbuf_border(ViewContext *vc, int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
-{
- unsigned int *dr, *drm;
- struct ImBuf *buf, *bufmask;
- int a;
- GLboolean is_cull;
-
- /* method in use for face selecting too */
- if(vc->obedit==NULL) {
- if(paint_facesel_test(vc->obact));
- else if(paint_vertsel_test(vc->obact));
- else return 0;
- }
- else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
-
- buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
- if(buf==NULL) return 0;
- if(em_vertoffs==0) return 0;
-
- dr = buf->rect;
-
- /* draw the mask */
- glDisable(GL_DEPTH_TEST);
-
- glColor3ub(0, 0, 0);
-
- /* some opengl drivers have problems with draw direction */
- glGetBooleanv(GL_CULL_FACE, &is_cull);
- if(is_cull) glDisable(GL_CULL_FACE);
-
- /* yah, opengl doesn't do concave... tsk! */
- ED_region_pixelspace(vc->ar);
- draw_triangulated(mcords, tot);
-
- glBegin(GL_LINE_LOOP); /* for zero sized masks, lines */
- for(a=0; a<tot; a++) glVertex2iv(mcords[a]);
- glEnd();
-
- glFinish(); /* to be sure readpixels sees mask */
-
- /* grab mask */
- bufmask= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
- drm = bufmask->rect;
- if(bufmask==NULL) return 0; /* only when mem alloc fails, go crash somewhere else! */
-
- /* build selection lookup */
- selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
-
- a= (xmax-xmin+1)*(ymax-ymin+1);
- while(a--) {
- if(*dr>0 && *dr<=em_vertoffs && *drm==0) selbuf[*dr]= 1;
- dr++; drm++;
- }
- IMB_freeImBuf(buf);
- IMB_freeImBuf(bufmask);
-
- if(is_cull) glEnable(GL_CULL_FACE);
-
- return 1;
-
-}
-
-/* circle shaped sample area */
-int EM_init_backbuf_circle(ViewContext *vc, short xs, short ys, short rads)
-{
- struct ImBuf *buf;
- unsigned int *dr;
- short xmin, ymin, xmax, ymax, xc, yc;
- int radsq;
-
- /* method in use for face selecting too */
- if(vc->obedit==NULL) {
- if(paint_facesel_test(vc->obact));
- else if (paint_vertsel_test(vc->obact));
- else return 0;
- }
- else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
-
- xmin= xs-rads; xmax= xs+rads;
- ymin= ys-rads; ymax= ys+rads;
- buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
- if(em_vertoffs==0) return 0;
- if(buf==NULL) return 0;
-
- dr = buf->rect;
-
- /* build selection lookup */
- selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
- radsq= rads*rads;
- for(yc= -rads; yc<=rads; yc++) {
- for(xc= -rads; xc<=rads; xc++, dr++) {
- if(xc*xc + yc*yc < radsq) {
- if(*dr>0 && *dr<=em_vertoffs) selbuf[*dr]= 1;
- }
- }
- }
-
- IMB_freeImBuf(buf);
- return 1;
-
-}
-
-static void findnearestvert__doClosest(void *userData, EditVert *eve, int x, int y, int index)
-{
- struct { int mval[2]; short pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } *data = userData;
-
- if (data->pass==0) {
- if (index<=data->lastIndex)
- return;
- } else {
- if (index>data->lastIndex)
- return;
- }
-
- if (data->dist>3) {
- int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y);
- if ((eve->f&1) == data->select) {
- if (data->strict == 1)
- return;
- else
- temp += 5;
- }
-
- if (temp<data->dist) {
- data->dist = temp;
- data->closest = eve;
- data->closestIndex = index;
- }
- }
-}
-
-
-
-
-static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int index)
-{
- EditMesh *em= (EditMesh *)handle;
- EditVert *eve = BLI_findlink(&em->verts, index-1);
-
- if(eve && (eve->f & SELECT)) return 0;
- return 1;
-}
-/**
- * findnearestvert
- *
- * dist (in/out): minimal distance to the nearest and at the end, actual distance
- * sel: selection bias
- * if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
- * if 0, unselected vertice are given the bias
- * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased
- */
-EditVert *findnearestvert(ViewContext *vc, int *dist, short sel, short strict)
-{
- if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)){
- int distance;
- unsigned int index;
- EditVert *eve;
-
- if(strict) index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_wireoffs, 0xFFFFFF, &distance, strict, vc->em, findnearestvert__backbufIndextest);
- else index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_wireoffs, 0xFFFFFF, &distance, 0, NULL, NULL);
-
- eve = BLI_findlink(&vc->em->verts, index-1);
-
- if(eve && distance < *dist) {
- *dist = distance;
- return eve;
- } else {
- return NULL;
- }
-
- }
- else {
- struct { int mval[2]; short pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } data;
- static int lastSelectedIndex=0;
- static EditVert *lastSelected=NULL;
-
- if (lastSelected && BLI_findlink(&vc->em->verts, lastSelectedIndex)!=lastSelected) {
- lastSelectedIndex = 0;
- lastSelected = NULL;
- }
-
- data.lastIndex = lastSelectedIndex;
- data.mval[0] = vc->mval[0];
- data.mval[1] = vc->mval[1];
- data.select = sel;
- data.dist = *dist;
- data.strict = strict;
- data.closest = NULL;
- data.closestIndex = 0;
-
- data.pass = 0;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
-
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
-
- if (data.dist>3) {
- data.pass = 1;
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
- }
-
- *dist = data.dist;
- lastSelected = data.closest;
- lastSelectedIndex = data.closestIndex;
-
- return data.closest;
- }
-}
-
-/* returns labda for closest distance v1 to line-piece v2-v3 */
-static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3)
-{
- float rc[2], len;
-
- rc[0]= v3[0]-v2[0];
- rc[1]= v3[1]-v2[1];
- len= rc[0]*rc[0]+ rc[1]*rc[1];
- if(len==0.0f)
- return 0.0f;
-
- return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
-}
-
-/* note; uses v3d, so needs active 3d window */
-static void findnearestedge__doClosest(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int UNUSED(index))
-{
- struct { ViewContext vc; float mval[2]; int dist; EditEdge *closest; } *data = userData;
- float v1[2], v2[2];
- int distance;
-
- ED_view3d_local_clipping(data->vc.rv3d, data->vc.obedit->obmat); /* for local clipping lookups */
-
- v1[0] = x0;
- v1[1] = y0;
- v2[0] = x1;
- v2[1] = y1;
-
- distance= dist_to_line_segment_v2(data->mval, v1, v2);
-
-
- if(eed->f & SELECT) distance+=5;
- if(distance < data->dist) {
- if(data->vc.rv3d->rflag & RV3D_CLIPPING) {
- float labda= labda_PdistVL2Dfl(data->mval, v1, v2);
- float vec[3];
-
- vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]);
- vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]);
- vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]);
-
- if(ED_view3d_test_clipping(data->vc.rv3d, vec, 1)==0) {
- data->dist = distance;
- data->closest = eed;
- }
- }
- else {
- data->dist = distance;
- data->closest = eed;
- }
- }
-}
-EditEdge *findnearestedge(ViewContext *vc, int *dist)
-{
-
- if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
- int distance;
- unsigned int index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_solidoffs, em_wireoffs, &distance,0, NULL, NULL);
- EditEdge *eed = BLI_findlink(&vc->em->edges, index-1);
-
- if (eed && distance<*dist) {
- *dist = distance;
- return eed;
- } else {
- return NULL;
- }
- }
- else {
- struct { ViewContext vc; float mval[2]; int dist; EditEdge *closest; } data;
-
- data.vc= *vc;
- data.mval[0] = vc->mval[0];
- data.mval[1] = vc->mval[1];
- data.dist = *dist;
- data.closest = NULL;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, 2);
-
- *dist = data.dist;
- return data.closest;
- }
-}
-
-static void findnearestface__getDistance(void *userData, EditFace *efa, int x, int y, int UNUSED(index))
-{
- struct { int mval[2]; int dist; EditFace *toFace; } *data = userData;
-
- if (efa==data->toFace) {
- int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
-
- if (temp<data->dist)
- data->dist = temp;
- }
-}
-static void findnearestface__doClosest(void *userData, EditFace *efa, int x, int y, int index)
-{
- struct { int mval[2]; short pass; int dist, lastIndex, closestIndex; EditFace *closest; } *data = userData;
-
- if (data->pass==0) {
- if (index<=data->lastIndex)
- return;
- } else {
- if (index>data->lastIndex)
- return;
- }
-
- if (data->dist>3) {
- int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
-
- if (temp<data->dist) {
- data->dist = temp;
- data->closest = efa;
- data->closestIndex = index;
- }
- }
-}
-static EditFace *findnearestface(ViewContext *vc, int *dist)
-{
-
- if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
- unsigned int index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]);
- EditFace *efa = BLI_findlink(&vc->em->faces, index-1);
-
- if (efa) {
- struct { int mval[2]; int dist; EditFace *toFace; } data;
-
- data.mval[0] = vc->mval[0];
- data.mval[1] = vc->mval[1];
- data.dist = 0x7FFF; /* largest short */
- data.toFace = efa;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, findnearestface__getDistance, &data);
-
- if(vc->em->selectmode == SCE_SELECT_FACE || data.dist<*dist) { /* only faces, no dist check */
- *dist= data.dist;
- return efa;
- }
- }
-
- return NULL;
- }
- else {
- struct { int mval[2]; short pass; int dist, lastIndex, closestIndex; EditFace *closest; } data;
- static int lastSelectedIndex=0;
- static EditFace *lastSelected=NULL;
-
- if (lastSelected && BLI_findlink(&vc->em->faces, lastSelectedIndex)!=lastSelected) {
- lastSelectedIndex = 0;
- lastSelected = NULL;
- }
-
- data.lastIndex = lastSelectedIndex;
- data.mval[0] = vc->mval[0];
- data.mval[1] = vc->mval[1];
- data.dist = *dist;
- data.closest = NULL;
- data.closestIndex = 0;
-
- data.pass = 0;
-
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
-
- if (data.dist>3) {
- data.pass = 1;
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
- }
-
- *dist = data.dist;
- lastSelected = data.closest;
- lastSelectedIndex = data.closestIndex;
-
- return data.closest;
- }
-}
-
-/* best distance based on screen coords.
- use em->selectmode to define how to use
- selected vertices and edges get disadvantage
- return 1 if found one
-*/
-static int unified_findnearest(ViewContext *vc, EditVert **eve, EditEdge **eed, EditFace **efa)
-{
- EditMesh *em= vc->em;
- int dist= 75;
-
- *eve= NULL;
- *eed= NULL;
- *efa= NULL;
-
- /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
- view3d_validate_backbuf(vc);
-
- if(em->selectmode & SCE_SELECT_VERTEX)
- *eve= findnearestvert(vc, &dist, SELECT, 0);
- if(em->selectmode & SCE_SELECT_FACE)
- *efa= findnearestface(vc, &dist);
-
- dist-= 20; /* since edges select lines, we give dots advantage of 20 pix */
- if(em->selectmode & SCE_SELECT_EDGE)
- *eed= findnearestedge(vc, &dist);
-
- /* return only one of 3 pointers, for frontbuffer redraws */
- if(*eed) {
- *efa= NULL; *eve= NULL;
- }
- else if(*efa) {
- *eve= NULL;
- }
-
- return (*eve || *eed || *efa);
-}
-
-
-/* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */
-
-/* selects new faces/edges/verts based on the existing selection */
-
-/* VERT GROUP */
-
-#define SIMVERT_NORMAL 0
-#define SIMVERT_FACE 1
-#define SIMVERT_VGROUP 2
-#define SIMVERT_TOT 3
-
-/* EDGE GROUP */
-
-#define SIMEDGE_LENGTH 101
-#define SIMEDGE_DIR 102
-#define SIMEDGE_FACE 103
-#define SIMEDGE_FACE_ANGLE 104
-#define SIMEDGE_CREASE 105
-#define SIMEDGE_SEAM 106
-#define SIMEDGE_SHARP 107
-#define SIMEDGE_TOT 108
-
-/* FACE GROUP */
-
-#define SIMFACE_MATERIAL 201
-#define SIMFACE_IMAGE 202
-#define SIMFACE_AREA 203
-#define SIMFACE_PERIMETER 204
-#define SIMFACE_NORMAL 205
-#define SIMFACE_COPLANAR 206
-#define SIMFACE_TOT 207
-
-static EnumPropertyItem prop_similar_types[] = {
- {SIMVERT_NORMAL, "NORMAL", 0, "Normal", ""},
- {SIMVERT_FACE, "FACE", 0, "Amount of Vertices in Face", ""},
- {SIMVERT_VGROUP, "VGROUP", 0, "Vertex Groups", ""},
- {SIMEDGE_LENGTH, "LENGTH", 0, "Length", ""},
- {SIMEDGE_DIR, "DIR", 0, "Direction", ""},
- {SIMEDGE_FACE, "FACE", 0, "Amount of Vertices in Face", ""},
- {SIMEDGE_FACE_ANGLE, "FACE_ANGLE", 0, "Face Angles", ""},
- {SIMEDGE_CREASE, "CREASE", 0, "Crease", ""},
- {SIMEDGE_SEAM, "SEAM", 0, "Seam", ""},
- {SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""},
- {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""},
- {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""},
- {SIMFACE_AREA, "AREA", 0, "Area", ""},
- {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
- {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
- {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-
-/* this as a way to compare the ares, perim of 2 faces thay will scale to different sizes
-*0.5 so smaller faces arnt ALWAYS selected with a thresh of 1.0 */
-#define SCALE_CMP(a,b) ((a+a*thresh >= b) && (a-(a*thresh*0.5f) <= b))
-
-static int similar_face_select__internal(EditMesh *em, int mode, float thresh)
-{
- EditFace *efa, *base_efa=NULL;
- unsigned int selcount=0; /*count how many new faces we select*/
-
- /*deselcount, count how many deselected faces are left, so we can bail out early
- also means that if there are no deselected faces, we can avoid a lot of looping */
- unsigned int deselcount=0;
- short ok=0;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if (!efa->h) {
- if (efa->f & SELECT) {
- efa->f1=1;
- ok=1;
- } else {
- efa->f1=0;
- deselcount++; /* a deselected face we may select later */
- }
- }
- }
-
- if (!ok || !deselcount) /* no data selected OR no more data to select */
- return 0;
-
- if (mode==SIMFACE_AREA) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->tmp.fp= EM_face_area(efa);
- }
- } else if (mode==SIMFACE_PERIMETER) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->tmp.fp= EM_face_perimeter(efa);
- }
- }
-
- for(base_efa= em->faces.first; base_efa; base_efa= base_efa->next) {
- if (base_efa->f1) { /* This was one of the faces originaly selected */
- if (mode==SIMFACE_MATERIAL) { /* same material */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if (
- !(efa->f & SELECT) &&
- !efa->h &&
- base_efa->mat_nr == efa->mat_nr
- ) {
- EM_select_face(efa, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- } else if (mode==SIMFACE_IMAGE) { /* same image */
- MTFace *tf, *base_tf;
-
- base_tf = (MTFace*)CustomData_em_get(&em->fdata, base_efa->data,
- CD_MTFACE);
-
- if(!base_tf)
- return selcount;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if (!(efa->f & SELECT) && !efa->h) {
- tf = (MTFace*)CustomData_em_get(&em->fdata, efa->data,
- CD_MTFACE);
-
- if(base_tf->tpage == tf->tpage) {
- EM_select_face(efa, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- }
- } else if (mode==SIMFACE_AREA || mode==SIMFACE_PERIMETER) { /* same area OR same perimeter, both use the same temp var */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if (
- (!(efa->f & SELECT) && !efa->h) &&
- SCALE_CMP(base_efa->tmp.fp, efa->tmp.fp)
- ) {
- EM_select_face(efa, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- } else if (mode==SIMFACE_NORMAL) {
- float angle;
- for(efa= em->faces.first; efa; efa= efa->next) {
- if (!(efa->f & SELECT) && !efa->h) {
- angle= RAD2DEGF(angle_v3v3(base_efa->n, efa->n));
- if (angle/180.0f<=thresh) {
- EM_select_face(efa, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- }
- } else if (mode==SIMFACE_COPLANAR) { /* same planer */
- float angle, base_dot, dot;
- base_dot= dot_v3v3(base_efa->cent, base_efa->n);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if (!(efa->f & SELECT) && !efa->h) {
- angle= RAD2DEGF(angle_v3v3(base_efa->n, efa->n));
- if (angle/180.0f<=thresh) {
- dot=dot_v3v3(efa->cent, base_efa->n);
- if (fabsf(base_dot-dot) <= thresh) {
- EM_select_face(efa, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- }
- }
- }
- }
- } /* end base_efa loop */
- return selcount;
-}
-
-static int similar_face_select_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- Mesh *me= obedit->data;
- EditMesh *em= BKE_mesh_get_editmesh(me);
-
- int selcount = similar_face_select__internal(em, RNA_enum_get(op->ptr, "type"), RNA_float_get(op->ptr, "threshold"));
-
- if (selcount) {
- /* here was an edge-mode only select flush case, has to be generalized */
- EM_selectmode_flush(em);
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(me, em);
- return OPERATOR_FINISHED;
- }
-
- BKE_mesh_end_editmesh(me, em);
- return OPERATOR_CANCELLED;
-}
-
-/* ***************************************************** */
-
-static int similar_edge_select__internal(EditMesh *em, int mode, float thresh)
-{
- EditEdge *eed, *base_eed=NULL;
- unsigned int selcount=0; /* count how many new edges we select*/
-
- /*count how many visible selected edges there are,
- so we can return when there are none left */
- unsigned int deselcount=0;
-
- short ok=0;
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (!eed->h) {
- if (eed->f & SELECT) {
- eed->f1=1;
- ok=1;
- } else {
- eed->f1=0;
- deselcount++;
- }
- /* set all eed->tmp.l to 0 we use it later.
- for counting face users*/
- eed->tmp.l=0;
- eed->f2=0; /* only for mode SIMEDGE_FACE_ANGLE, edge animations */
- }
- }
-
- if (!ok || !deselcount) /* no data selected OR no more data to select*/
- return 0;
-
- if (mode==SIMEDGE_LENGTH) { /*store length*/
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (!eed->h) /* dont calc data for hidden edges*/
- eed->tmp.fp= len_v3v3(eed->v1->co, eed->v2->co);
- }
- } else if (mode==SIMEDGE_FACE) { /*store face users*/
- EditFace *efa;
- /* cound how many faces each edge uses use tmp->l */
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->e1->tmp.l++;
- efa->e2->tmp.l++;
- efa->e3->tmp.l++;
- if (efa->e4) efa->e4->tmp.l++;
- }
- } else if (mode==SIMEDGE_FACE_ANGLE) { /*store edge angles */
- EditFace *efa;
- int j;
- /* cound how many faces each edge uses use tmp.l */
- for(efa= em->faces.first; efa; efa= efa->next) {
- /* here we use the edges temp data to assign a face
- if a face has already been assigned (eed->f2==1)
- we calculate the angle between the current face and
- the edges previously found face.
- store the angle in eed->tmp.fp (loosing the face eed->tmp.f)
- but tagging eed->f2==2, so we know not to look at it again.
- This only works for edges that connect to 2 faces. but its good enough
- */
-
- /* se we can loop through face edges*/
- j=0;
- eed= efa->e1;
- while (j<4) {
- if (j==1) eed= efa->e2;
- else if (j==2) eed= efa->e3;
- else if (j==3) {
- eed= efa->e4;
- if (!eed)
- break;
- } /* done looping */
-
- if (!eed->h) { /* dont calc data for hidden edges*/
- if (eed->f2==2)
- break;
- else if (eed->f2==0) /* first access, assign the face */
- eed->tmp.f= efa;
- else if (eed->f2==1) /* second, we assign the angle*/
- eed->tmp.fp= RAD2DEGF(angle_v3v3(eed->tmp.f->n, efa->n))/180;
- eed->f2++; /* f2==0 no face assigned. f2==1 one face found. f2==2 angle calculated.*/
- }
- j++;
- }
- }
- }
-
- for(base_eed= em->edges.first; base_eed; base_eed= base_eed->next) {
- if (base_eed->f1) {
- if (mode==SIMEDGE_LENGTH) { /* same length */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (
- !(eed->f & SELECT) &&
- !eed->h &&
- SCALE_CMP(base_eed->tmp.fp, eed->tmp.fp)
- ) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- } else if (mode==SIMEDGE_DIR) { /* same direction */
- float base_dir[3], dir[3], angle;
- sub_v3_v3v3(base_dir, base_eed->v1->co, base_eed->v2->co);
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (!(eed->f & SELECT) && !eed->h) {
- sub_v3_v3v3(dir, eed->v1->co, eed->v2->co);
- angle= RAD2DEGF(angle_v3v3(base_dir, dir));
-
- if (angle>90.0f) /* use the smallest angle between the edges */
- angle= fabsf(angle-180.0f);
-
- if (angle / 90.0f<=thresh) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- }
- } else if (mode==SIMEDGE_FACE) { /* face users */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (
- !(eed->f & SELECT) &&
- !eed->h &&
- base_eed->tmp.l==eed->tmp.l
- ) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- } else if (mode==SIMEDGE_FACE_ANGLE && base_eed->f2==2) { /* edge angles, f2==2 means the edge has an angle. */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (
- !(eed->f & SELECT) &&
- !eed->h &&
- eed->f2==2 &&
- (fabsf(base_eed->tmp.fp-eed->tmp.fp)<=thresh)
- ) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- } else if (mode==SIMEDGE_CREASE) { /* edge crease */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (
- !(eed->f & SELECT) &&
- !eed->h &&
- (fabsf(base_eed->crease-eed->crease) <= thresh)
- ) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- } else if (mode==SIMEDGE_SEAM) { /* edge seam */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (
- !(eed->f & SELECT) &&
- !eed->h &&
- (eed->seam == base_eed->seam)
- ) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- } else if (mode==SIMEDGE_SHARP) { /* edge sharp */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (
- !(eed->f & SELECT) &&
- !eed->h &&
- (eed->sharp == base_eed->sharp)
- ) {
- EM_select_edge(eed, 1);
- selcount++;
- deselcount--;
- if (!deselcount) /*have we selected all posible faces?, if so return*/
- return selcount;
- }
- }
- }
- }
- }
- return selcount;
-}
-/* wrap the above function but do selection flushing edge to face */
-static int similar_edge_select_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- Mesh *me= obedit->data;
- EditMesh *em= BKE_mesh_get_editmesh(me);
-
- int selcount = similar_edge_select__internal(em, RNA_enum_get(op->ptr, "type"), RNA_float_get(op->ptr, "threshold"));
-
- if (selcount) {
- /* here was an edge-mode only select flush case, has to be generalized */
- EM_selectmode_flush(em);
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(me, em);
- return OPERATOR_FINISHED;
- }
-
- BKE_mesh_end_editmesh(me, em);
- return OPERATOR_CANCELLED;
-}
-
-/* ********************************* */
-
-static int similar_vert_select_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- Mesh *me= obedit->data;
- EditMesh *em= BKE_mesh_get_editmesh(me);
- EditVert *eve, *base_eve=NULL;
- unsigned int selcount=0; /* count how many new edges we select*/
-
- /*count how many visible selected edges there are,
- so we can return when there are none left */
- unsigned int deselcount=0;
- int mode= RNA_enum_get(op->ptr, "type");
- float thresh = RNA_float_get(op->ptr, "threshold");
-
- short ok=0;
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- if (!eve->h) {
- if (eve->f & SELECT) {
- eve->f1=1;
- ok=1;
- } else {
- eve->f1=0;
- deselcount++;
- }
- /* set all eve->tmp.l to 0 we use them later.*/
- eve->tmp.l=0;
- }
-
- }
-
- if (!ok || !deselcount) { /* no data selected OR no more data to select*/
- BKE_mesh_end_editmesh(me, em);
- return 0;
- }
-
- if(mode == SIMVERT_FACE) {
- /* store face users */
- EditFace *efa;
-
- /* count how many faces each edge uses use tmp->l */
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->v1->tmp.l++;
- efa->v2->tmp.l++;
- efa->v3->tmp.l++;
- if (efa->v4) efa->v4->tmp.l++;
- }
- }
-
-
- for(base_eve= em->verts.first; base_eve; base_eve= base_eve->next) {
- if (base_eve->f1) {
-
- if(mode == SIMVERT_NORMAL) {
- float angle;
- for(eve= em->verts.first; eve; eve= eve->next) {
- if (!(eve->f & SELECT) && !eve->h) {
- angle= RAD2DEGF(angle_v3v3(base_eve->no, eve->no));
- if (angle/180.0f<=thresh) {
- eve->f |= SELECT;
- selcount++;
- deselcount--;
- if (!deselcount) {/*have we selected all posible faces?, if so return*/
- BKE_mesh_end_editmesh(me, em);
- return selcount;
- }
- }
- }
- }
- }
- else if(mode == SIMVERT_FACE) {
- for(eve= em->verts.first; eve; eve= eve->next) {
- if (
- !(eve->f & SELECT) &&
- !eve->h &&
- base_eve->tmp.l==eve->tmp.l
- ) {
- eve->f |= SELECT;
- selcount++;
- deselcount--;
- if (!deselcount) {/*have we selected all posible faces?, if so return*/
- BKE_mesh_end_editmesh(me, em);
- return selcount;
- }
- }
- }
- }
- else if(mode == SIMVERT_VGROUP) {
- MDeformVert *dvert, *base_dvert;
- short i, j; /* weight index */
-
- base_dvert= CustomData_em_get(&em->vdata, base_eve->data,
- CD_MDEFORMVERT);
-
- if (!base_dvert || base_dvert->totweight == 0) {
- BKE_mesh_end_editmesh(me, em);
- return selcount;
- }
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- dvert= CustomData_em_get(&em->vdata, eve->data,
- CD_MDEFORMVERT);
-
- if (dvert && !(eve->f & SELECT) && !eve->h && dvert->totweight) {
- /* do the extra check for selection in the following if, so were not
- checking verts that may be already selected */
- for (i=0; base_dvert->totweight >i && !(eve->f & SELECT); i++) {
- for (j=0; dvert->totweight >j; j++) {
- if (base_dvert->dw[i].def_nr==dvert->dw[j].def_nr) {
- eve->f |= SELECT;
- selcount++;
- deselcount--;
- if (!deselcount) { /*have we selected all posible faces?, if so return*/
- BKE_mesh_end_editmesh(me, em);
- return selcount;
- }
- break;
- }
- }
- }
- }
- }
- }
- }
- } /* end basevert loop */
-
- if(selcount) {
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(me, em);
- return OPERATOR_FINISHED;
- }
-
- BKE_mesh_end_editmesh(me, em);
- return OPERATOR_CANCELLED;
-}
-
-static int select_similar_exec(bContext *C, wmOperator *op)
-{
- int type= RNA_enum_get(op->ptr, "type");
-
- if(type < 100)
- return similar_vert_select_exec(C, op);
- else if(type < 200)
- return similar_edge_select_exec(C, op);
- else
- return similar_face_select_exec(C, op);
-}
-
-static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
-{
- Object *obedit= CTX_data_edit_object(C);
- EnumPropertyItem *item= NULL;
- int a, totitem= 0;
-
- if (C == NULL) {
- return prop_similar_types;
- }
-
- if(obedit && obedit->type == OB_MESH) {
- EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
-
- if(em->selectmode & SCE_SELECT_VERTEX) {
- for(a=SIMVERT_NORMAL; a<=SIMVERT_TOT; a++)
- RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
- }
- else if(em->selectmode & SCE_SELECT_EDGE) {
- for(a=SIMEDGE_LENGTH; a<=SIMEDGE_TOT; a++)
- RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
- }
- else if(em->selectmode & SCE_SELECT_FACE) {
- for(a=SIMFACE_MATERIAL; a<=SIMFACE_TOT; a++)
- RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
- }
- }
-
- RNA_enum_item_end(&item, &totitem);
- *free= 1;
-
- return item;
-}
-
-void MESH_OT_select_similar(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name= "Select Similar";
- ot->description= "Select similar vertices, edges or faces by property types";
- ot->idname= "MESH_OT_select_similar";
-
- /* api callbacks */
- ot->invoke= WM_menu_invoke;
- ot->exec= select_similar_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- prop= RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", "");
- RNA_def_enum_funcs(prop, select_similar_type_itemf);
- ot->prop= prop;
- RNA_def_float(ot->srna, "threshold", 0.01f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 100.f);
-}
-
-/* ******************************************* */
-
-
-int mesh_layers_menu_charlen(CustomData *data, int type)
-{
- int i, len = 0;
- /* see if there is a duplicate */
- for(i=0; i<data->totlayer; i++) {
- if((&data->layers[i])->type == type) {
- /* we could count the chars here but we'll just assumeme each
- * is 32 chars with some room for the menu text - 40 should be fine */
- len+=40;
- }
- }
- return len;
-}
-
-/* this function adds menu text into an existing string.
- * this string's size should be allocated with mesh_layers_menu_charlen */
-void mesh_layers_menu_concat(CustomData *data, int type, char *str)
-{
- int i, count = 0;
- char *str_pt = str;
- CustomDataLayer *layer;
-
- /* see if there is a duplicate */
- for(i=0; i<data->totlayer; i++) {
- layer = &data->layers[i];
- if(layer->type == type) {
- str_pt += sprintf(str_pt, "%s%%x%d|", layer->name, count);
- count++;
- }
- }
-}
-
-int mesh_layers_menu(CustomData *data, int type) {
- int ret;
- char *str_pt, *str;
-
- str_pt = str = MEM_mallocN(mesh_layers_menu_charlen(data, type) + 18, "layer menu");
- str[0] = '\0';
-
- str_pt += sprintf(str_pt, "Layers%%t|");
-
- mesh_layers_menu_concat(data, type, str_pt);
-
- ret = pupmenu(str);
- MEM_freeN(str);
- return ret;
-}
-
-static void EM_mesh_copy_edge(EditMesh *em, short type)
-{
- EditSelection *ese;
- short change=0;
-
- EditEdge *eed, *eed_act;
- float vec[3], vec_mid[3], eed_len, eed_len_act;
-
- if (!em) return;
-
- ese = em->selected.last;
- if (!ese) return;
-
- eed_act = (EditEdge*)ese->data;
-
- switch (type) {
- case 1: /* copy crease */
- for(eed=em->edges.first; eed; eed=eed->next) {
- if (eed->f & SELECT && eed != eed_act && eed->crease != eed_act->crease) {
- eed->crease = eed_act->crease;
- change = 1;
- }
- }
- break;
- case 2: /* copy bevel weight */
- for(eed=em->edges.first; eed; eed=eed->next) {
- if (eed->f & SELECT && eed != eed_act && eed->bweight != eed_act->bweight) {
- eed->bweight = eed_act->bweight;
- change = 1;
- }
- }
- break;
-
- case 3: /* copy length */
- eed_len_act = len_v3v3(eed_act->v1->co, eed_act->v2->co);
- for(eed=em->edges.first; eed; eed=eed->next) {
- if (eed->f & SELECT && eed != eed_act) {
-
- eed_len = len_v3v3(eed->v1->co, eed->v2->co);
-
- if (eed_len == eed_len_act) continue;
- /* if this edge is zero length we cont do anything with it*/
- if (eed_len == 0.0f) continue;
- if (eed_len_act == 0.0f) {
- add_v3_v3v3(vec_mid, eed->v1->co, eed->v2->co);
- mul_v3_fl(vec_mid, 0.5);
- VECCOPY(eed->v1->co, vec_mid);
- VECCOPY(eed->v2->co, vec_mid);
- } else {
- /* copy the edge length */
- add_v3_v3v3(vec_mid, eed->v1->co, eed->v2->co);
- mul_v3_fl(vec_mid, 0.5);
-
- /* SCALE 1 */
- sub_v3_v3v3(vec, eed->v1->co, vec_mid);
- mul_v3_fl(vec, eed_len_act/eed_len);
- add_v3_v3v3(eed->v1->co, vec, vec_mid);
-
- /* SCALE 2 */
- sub_v3_v3v3(vec, eed->v2->co, vec_mid);
- mul_v3_fl(vec, eed_len_act/eed_len);
- add_v3_v3v3(eed->v2->co, vec, vec_mid);
- }
- change = 1;
- }
- }
-
- if (change)
- recalc_editnormals(em);
-
- break;
- }
-
- if (change) {
-// DAG_id_tag_update(obedit->data, 0);
-
- }
-}
-
-static void EM_mesh_copy_face(EditMesh *em, wmOperator *op, short type)
-{
- short change=0;
-
- EditFace *efa, *efa_act;
- MTFace *tf, *tf_act = NULL;
- MCol *mcol, *mcol_act = NULL;
- if (!em) return;
- efa_act = EM_get_actFace(em, 0);
-
- if (!efa_act) return;
-
- tf_act = CustomData_em_get(&em->fdata, efa_act->data, CD_MTFACE);
- mcol_act = CustomData_em_get(&em->fdata, efa_act->data, CD_MCOL);
-
- switch (type) {
- case 1: /* copy material */
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT && efa->mat_nr != efa_act->mat_nr) {
- efa->mat_nr = efa_act->mat_nr;
- change = 1;
- }
- }
- break;
- case 2: /* copy image */
- if (!tf_act) {
- BKE_report(op->reports, RPT_WARNING, "Mesh has no uv/image layers");
- return;
- }
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT && efa != efa_act) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if (tf_act->tpage) {
- tf->tpage = tf_act->tpage;
- } else {
- tf->tpage = NULL;
- }
- tf->tile= tf_act->tile;
- change = 1;
- }
- }
- break;
-
- case 3: /* copy UV's */
- if (!tf_act) {
- BKE_report(op->reports, RPT_WARNING, "Mesh has no uv/image layers");
- return;
- }
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT && efa != efa_act) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- memcpy(tf->uv, tf_act->uv, sizeof(tf->uv));
- change = 1;
- }
- }
- break;
- case 4: /* mode's */
- if (!tf_act) {
- BKE_report(op->reports, RPT_WARNING, "Mesh has no uv/image layers");
- return;
- }
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT && efa != efa_act) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- tf->mode= tf_act->mode;
- change = 1;
- }
- }
- break;
- case 5: /* copy transp's */
- if (!tf_act) {
- BKE_report(op->reports, RPT_WARNING, "Mesh has no uv/image layers");
- return;
- }
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT && efa != efa_act) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- tf->transp= tf_act->transp;
- change = 1;
- }
- }
- break;
-
- case 6: /* copy vcols's */
- if (!mcol_act) {
- BKE_report(op->reports, RPT_WARNING, "Mesh has no color layers");
- return;
- } else {
- /* guess the 4th color if needs be */
- float val =- 1;
-
- if (!efa_act->v4) {
- /* guess the othe vale, we may need to use it
- *
- * Modifying the 4th value of the mcol is ok here since its not seen
- * on a triangle
- * */
- val = ((float)(mcol_act->r + (mcol_act+1)->r + (mcol_act+2)->r)) / 3; CLAMP(val, 0, 255);
- (mcol_act+3)->r = (char)val;
-
- val = ((float)(mcol_act->g + (mcol_act+1)->g + (mcol_act+2)->g)) / 3; CLAMP(val, 0, 255);
- (mcol_act+3)->g = (char)val;
-
- val = ((float)(mcol_act->b + (mcol_act+1)->b + (mcol_act+2)->b)) / 3; CLAMP(val, 0, 255);
- (mcol_act+3)->b = (char)val;
- }
-
-
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT && efa != efa_act) {
- /* TODO - make copy from tri to quad guess the 4th vert */
- mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
- memcpy(mcol, mcol_act, sizeof(MCol)*4);
- change = 1;
- }
- }
- }
- break;
- }
-
- if (change) {
-// DAG_id_tag_update(obedit->data, 0);
-
- }
-}
-
-
-void EM_mesh_copy_face_layer(EditMesh *em, wmOperator *op, short type)
-{
- short change=0;
-
- EditFace *efa;
- MTFace *tf, *tf_from;
- MCol *mcol, *mcol_from;
-
- if (!em) return;
-
- switch(type) {
- case 7:
- case 8:
- case 9:
- if (CustomData_number_of_layers(&em->fdata, CD_MTFACE)<2) {
- BKE_report(op->reports, RPT_WARNING, "mesh does not have multiple uv/image layers");
- return;
- } else {
- int layer_orig_idx, layer_idx;
-
- layer_idx = mesh_layers_menu(&em->fdata, CD_MTFACE);
- if (layer_idx<0) return;
-
- /* warning, have not updated mesh pointers however this is not needed since we swicth back */
- layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MTFACE);
- if (layer_idx==layer_orig_idx)
- return;
-
- /* get the tfaces */
- CustomData_set_layer_active(&em->fdata, CD_MTFACE, (int)layer_idx);
- /* store the tfaces in our temp */
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT) {
- efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- }
- }
- CustomData_set_layer_active(&em->fdata, CD_MTFACE, layer_orig_idx);
- }
- break;
-
- case 10: /* select vcol layers - make sure this stays in sync with above code */
- if (CustomData_number_of_layers(&em->fdata, CD_MCOL)<2) {
- BKE_report(op->reports, RPT_WARNING, "mesh does not have multiple color layers");
- return;
- } else {
- int layer_orig_idx, layer_idx;
-
- layer_idx = mesh_layers_menu(&em->fdata, CD_MCOL);
- if (layer_idx<0) return;
-
- /* warning, have not updated mesh pointers however this is not needed since we swicth back */
- layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MCOL);
- if (layer_idx==layer_orig_idx)
- return;
-
- /* get the tfaces */
- CustomData_set_layer_active(&em->fdata, CD_MCOL, (int)layer_idx);
- /* store the tfaces in our temp */
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT) {
- efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
- }
- }
- CustomData_set_layer_active(&em->fdata, CD_MCOL, layer_orig_idx);
-
- }
- break;
- }
-
- /* layer copy only - sanity checks done above */
- switch (type) {
- case 7: /* copy UV's only */
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT) {
- tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- memcpy(tf->uv, tf_from->uv, sizeof(tf->uv));
- change = 1;
- }
- }
- break;
- case 8: /* copy image settings only */
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT) {
- tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if (tf_from->tpage) {
- tf->tpage = tf_from->tpage;
- } else {
- tf->tpage = NULL;
- }
- tf->tile= tf_from->tile;
- change = 1;
- }
- }
- break;
- case 9: /* copy all tface info */
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT) {
- tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- memcpy(tf->uv, ((MTFace *)efa->tmp.p)->uv, sizeof(tf->uv));
- tf->tpage = tf_from->tpage;
- tf->mode = tf_from->mode;
- tf->transp = tf_from->transp;
- change = 1;
- }
- }
- break;
- case 10:
- for(efa=em->faces.first; efa; efa=efa->next) {
- if (efa->f & SELECT) {
- mcol_from = (MCol *)efa->tmp.p;
- mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
- memcpy(mcol, mcol_from, sizeof(MCol)*4);
- change = 1;
- }
- }
- break;
- }
-
- if (change) {
-// DAG_id_tag_update(obedit->data, 0);
-
- }
-}
-
-
-/* ctrl+c in mesh editmode */
-static void UNUSED_FUNCTION(mesh_copy_menu)(EditMesh *em, wmOperator *op)
-{
- EditSelection *ese;
- int ret;
- if (!em) return;
-
- ese = em->selected.last;
-
- /* Faces can have a NULL ese, so dont return on a NULL ese here */
-
- if(ese && ese->type == EDITVERT) {
- /* EditVert *ev, *ev_act = (EditVert*)ese->data;
- ret= pupmenu(""); */
- } else if(ese && ese->type == EDITEDGE) {
- ret= pupmenu("Copy Active Edge to Selected%t|Crease%x1|Bevel Weight%x2|Length%x3");
- if (ret<1) return;
-
- EM_mesh_copy_edge(em, ret);
-
- } else if(ese==NULL || ese->type == EDITFACE) {
- ret= pupmenu(
- "Copy Face Selected%t|"
- "Active Material%x1|Active Image%x2|Active UV Coords%x3|"
- "Active Mode%x4|Active Transp%x5|Active Vertex Colors%x6|%l|"
-
- "TexFace UVs from layer%x7|"
- "TexFace Images from layer%x8|"
- "TexFace All from layer%x9|"
- "Vertex Colors from layer%x10");
- if (ret<1) return;
-
- if (ret<=6) {
- EM_mesh_copy_face(em, op, ret);
- } else {
- EM_mesh_copy_face_layer(em, op, ret);
- }
- }
-}
-
-/* **************** LOOP SELECTS *************** */
-
-/* selects quads in loop direction of indicated edge */
-/* only flush over edges with valence <= 2 */
-void faceloop_select(EditMesh *em, EditEdge *startedge, int select)
-{
- EditEdge *eed;
- EditFace *efa;
- int looking= 1;
-
- /* in eed->f1 we put the valence (amount of faces in edge) */
- /* in eed->f2 we put tagged flag as correct loop */
- /* in efa->f1 we put tagged flag as correct to select */
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- eed->f1= 0;
- eed->f2= 0;
- }
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->f1= 0;
- if(efa->h==0) {
- efa->e1->f1++;
- efa->e2->f1++;
- efa->e3->f1++;
- if(efa->e4) efa->e4->f1++;
- }
- }
-
- /* tag startedge OK*/
- startedge->f2= 1;
-
- while(looking) {
- looking= 0;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0 && efa->e4 && efa->f1==0) { /* not done quad */
- if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
-
- /* if edge tagged, select opposing edge and mark face ok */
- if(efa->e1->f2) {
- efa->e3->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- else if(efa->e2->f2) {
- efa->e4->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- if(efa->e3->f2) {
- efa->e1->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- if(efa->e4->f2) {
- efa->e2->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- }
- }
- }
- }
-
- /* (de)select the faces */
- if(select!=2) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f1) EM_select_face(efa, select);
- }
- }
-}
-
-
-/* helper for edgeloop_select, checks for eed->f2 tag in faces */
-static int edge_not_in_tagged_face(EditMesh *em, EditEdge *eed)
-{
- EditFace *efa;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0) {
- if(efa->e1==eed || efa->e2==eed || efa->e3==eed || efa->e4==eed) { /* edge is in face */
- if(efa->e1->f2 || efa->e2->f2 || efa->e3->f2 || (efa->e4 && efa->e4->f2)) { /* face is tagged */
- return 0;
- }
- }
- }
- }
- return 1;
-}
-
-static void ensure_ed_vert_sel(EditMesh *em)
-{
- EditEdge *eed;
-
- /* EM_selectmode_flush() doesnt take into account that deselected edges
- * may be still connected to selected edges [#26885] */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
- eed->v1->f |= SELECT;
- eed->v2->f |= SELECT;
- }
- }
-}
-
-/* selects or deselects edges that:
-- if edges has 2 faces:
- - has vertices with valence of 4
- - not shares face with previous edge
-- if edge has 1 face:
- - has vertices with valence 4
- - not shares face with previous edge
- - but also only 1 face
-- if edge no face:
- - has vertices with valence 2
-*/
-static void edgeloop_select(EditMesh *em, EditEdge *starteed, int select)
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
- int looking= 1;
-
- /* in f1 we put the valence (amount of edges in a vertex, or faces in edge) */
- /* in eed->f2 and efa->f1 we put tagged flag as correct loop */
- for(eve= em->verts.first; eve; eve= eve->next) {
- eve->f1= 0;
- eve->f2= 0;
- }
- for(eed= em->edges.first; eed; eed= eed->next) {
- eed->f1= 0;
- eed->f2= 0;
- if((eed->h & 1)==0) { /* fgon edges add to valence too */
- eed->v1->f1++; eed->v2->f1++;
- }
- }
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->f1= 0;
- if(efa->h==0) {
- efa->e1->f1++;
- efa->e2->f1++;
- efa->e3->f1++;
- if(efa->e4) efa->e4->f1++;
- }
- }
-
- /* looped edges & vertices get tagged f2 */
- starteed->f2= 1;
- if(starteed->v1->f1<5) starteed->v1->f2= 1;
- if(starteed->v2->f1<5) starteed->v2->f2= 1;
- /* sorry, first edge isnt even ok */
- if(starteed->v1->f2==0 && starteed->v2->f2==0) looking= 0;
-
- while(looking) {
- looking= 0;
-
- /* find correct valence edges which are not tagged yet, but connect to tagged one */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0 && eed->f2==0) { /* edge not hidden, not tagged */
- if( (eed->v1->f1<5 && eed->v1->f2) || (eed->v2->f1<5 && eed->v2->f2)) { /* valence of vertex OK, and is tagged */
- /* new edge is not allowed to be in face with tagged edge */
- if(edge_not_in_tagged_face(em, eed)) {
- if(eed->f1==starteed->f1) { /* same amount of faces */
- looking= 1;
- eed->f2= 1;
- if(eed->v2->f1<5) eed->v2->f2= 1;
- if(eed->v1->f1<5) eed->v1->f2= 1;
- }
- }
- }
- }
- }
- }
- /* and we do the select */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f2) EM_select_edge(eed, select);
- }
-
- if(select == FALSE && !(em->selectmode & SCE_SELECT_VERTEX)) { /* only when not in vert sel [#26931] */
- ensure_ed_vert_sel(em);
- }
-}
-
-/*
- Almostly exactly the same code as faceloop select
-*/
-static void edgering_select(EditMesh *em, EditEdge *startedge, int select)
-{
- EditEdge *eed;
- EditFace *efa;
- int looking= 1;
-
- /* in eed->f1 we put the valence (amount of faces in edge) */
- /* in eed->f2 we put tagged flag as correct loop */
- /* in efa->f1 we put tagged flag as correct to select */
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- eed->f1= 0;
- eed->f2= 0;
- }
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->f1= 0;
- if(efa->h==0) {
- efa->e1->f1++;
- efa->e2->f1++;
- efa->e3->f1++;
- if(efa->e4) efa->e4->f1++;
- }
- }
-
- /* tag startedge OK */
- startedge->f2= 1;
-
- while(looking) {
- looking= 0;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->e4 && efa->f1==0 && !efa->h) { /* not done quad */
- if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
-
- /* if edge tagged, select opposing edge and mark face ok */
- if(efa->e1->f2) {
- efa->e3->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- else if(efa->e2->f2) {
- efa->e4->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- if(efa->e3->f2) {
- efa->e1->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- if(efa->e4->f2) {
- efa->e2->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- }
- }
- }
- }
-
- /* (de)select the edges */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f2) EM_select_edge(eed, select);
- }
-
- if(select == FALSE && !(em->selectmode & SCE_SELECT_VERTEX)) { /* only when not in vert sel [#26931] */
- ensure_ed_vert_sel(em);
- }
-}
-
-static int loop_multiselect(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- EditEdge *eed;
- EditEdge **edarray;
- int edindex, edfirstcount;
- int looptype= RNA_boolean_get(op->ptr, "ring");
-
- /* sets em->totedgesel */
- EM_nedges_selected(em);
-
- edarray = MEM_mallocN(sizeof(EditEdge*)*em->totedgesel,"edge array");
- edindex = 0;
- edfirstcount = em->totedgesel;
-
- for(eed=em->edges.first; eed; eed=eed->next){
- if(eed->f&SELECT){
- edarray[edindex] = eed;
- edindex += 1;
- }
- }
-
- if(looptype){
- for(edindex = 0; edindex < edfirstcount; edindex +=1){
- eed = edarray[edindex];
- edgering_select(em, eed,SELECT);
- }
- EM_selectmode_flush(em);
- }
- else{
- for(edindex = 0; edindex < edfirstcount; edindex +=1){
- eed = edarray[edindex];
- edgeloop_select(em, eed,SELECT);
- }
- EM_selectmode_flush(em);
- }
- MEM_freeN(edarray);
-// if (EM_texFaceCheck())
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_loop_multi_select(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Multi Select Loops";
- ot->description= "Select a loop of connected edges by connection type";
- ot->idname= "MESH_OT_loop_multi_select";
-
- /* api callbacks */
- ot->exec= loop_multiselect;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "ring", 0, "Ring", "");
-}
-
-
-/* ***************** MAIN MOUSE SELECTION ************** */
-
-
-/* ***************** loop select (non modal) ************** */
-
-static void mouse_mesh_loop(bContext *C, const int mval[2], short extend, short ring)
-{
- ViewContext vc;
- EditMesh *em;
- EditEdge *eed;
- int select= 1;
- int dist= 50;
-
- em_setup_viewcontext(C, &vc);
- vc.mval[0]= mval[0];
- vc.mval[1]= mval[1];
- em= vc.em;
-
- /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
- view3d_validate_backbuf(&vc);
-
- eed= findnearestedge(&vc, &dist);
- if(eed) {
- if(extend==0) EM_clear_flag_all(em, SELECT);
-
- if((eed->f & SELECT)==0) select=1;
- else if(extend) select=0;
-
- if(em->selectmode & SCE_SELECT_FACE) {
- faceloop_select(em, eed, select);
- }
- else if(em->selectmode & SCE_SELECT_EDGE) {
- if(ring)
- edgering_select(em, eed, select);
- else
- edgeloop_select(em, eed, select);
- }
- else if(em->selectmode & SCE_SELECT_VERTEX) {
- if(ring)
- edgering_select(em, eed, select);
- else
- edgeloop_select(em, eed, select);
- }
-
- EM_selectmode_flush(em);
-// if (EM_texFaceCheck())
-
- /* sets as active, useful for other tools */
- if(select) {
- if(em->selectmode & SCE_SELECT_VERTEX)
- EM_store_selection(em, eed->v1, EDITVERT);
- if(em->selectmode & SCE_SELECT_EDGE)
- EM_store_selection(em, eed, EDITEDGE);
- }
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data);
- }
-}
-
-static int mesh_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-
- view3d_operator_needs_opengl(C);
-
- mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"),
- RNA_boolean_get(op->ptr, "ring"));
-
- /* cannot do tweaks for as long this keymap is after transform map */
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_loop_select(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Loop Select";
- ot->description= "Select a loop of connected edges";
- ot->idname= "MESH_OT_loop_select";
-
- /* api callbacks */
- ot->invoke= mesh_select_loop_invoke;
- ot->poll= ED_operator_editmesh_region_view3d;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
- RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "");
-}
-
-/* ******************* mesh shortest path select, uses prev-selected edge ****************** */
-
-/* since you want to create paths with multiple selects, it doesn't have extend option */
-static void mouse_mesh_shortest_path(bContext *C, const int mval[2])
-{
- ViewContext vc;
- EditMesh *em;
- EditEdge *eed, *eed_act= NULL;
- int dist= 50;
-
- em_setup_viewcontext(C, &vc);
- vc.mval[0]= mval[0];
- vc.mval[1]= mval[1];
- em= vc.em;
-
- /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
- view3d_validate_backbuf(&vc);
-
- eed= findnearestedge(&vc, &dist);
- if(eed) {
- Mesh *me= vc.obedit->data;
- int path = 0;
-
- if (em->selected.last) {
- EditSelection *ese = em->selected.last;
-
- if(ese && ese->type == EDITEDGE) {
- eed_act = (EditEdge*)ese->data;
- if (eed_act != eed) {
- if (edgetag_shortest_path(vc.scene, em, eed_act, eed)) { /* <- this is where the magic happens */
- EM_remove_selection(em, eed_act, EDITEDGE);
- path = 1;
- }
- }
- }
- }
- if (path==0) {
- int act = (edgetag_context_check(vc.scene, eed)==0);
- edgetag_context_set(vc.scene, eed, act); /* switch the edge option */
- }
-
- /* even if this is selected it may not be in the selection list */
- if(edgetag_context_check(vc.scene, eed)==0) {
- EM_remove_selection(em, eed, EDITEDGE);
- }
- else {
- /* other modes need to keep the last edge tagged */
- if(eed_act) {
- if(vc.scene->toolsettings->edge_mode!=EDGE_MODE_SELECT) {
- /* for non-select modes, always de-select the previous active edge */
- EM_select_edge(eed_act, 0);
- }
- }
-
- /* set the new edge active */
- EM_select_edge(eed, 1);
- EM_store_selection(em, eed, EDITEDGE);
- }
-
- EM_selectmode_flush(em);
-
- /* force drawmode for mesh */
- switch (vc.scene->toolsettings->edge_mode) {
-
- case EDGE_MODE_TAG_SEAM:
- me->drawflag |= ME_DRAWSEAMS;
- break;
- case EDGE_MODE_TAG_SHARP:
- me->drawflag |= ME_DRAWSHARP;
- break;
- case EDGE_MODE_TAG_CREASE:
- me->drawflag |= ME_DRAWCREASES;
- break;
- case EDGE_MODE_TAG_BEVEL:
- me->drawflag |= ME_DRAWBWEIGHTS;
- break;
- }
-
- /* live unwrap while tagging */
- if( (vc.scene->toolsettings->edge_mode_live_unwrap) &&
- (vc.scene->toolsettings->edge_mode == EDGE_MODE_TAG_SEAM) &&
- (CustomData_has_layer(&em->fdata, CD_MTFACE))
- ) {
- ED_unwrap_lscm(vc.scene, vc.obedit, FALSE); /* unwrap all not just sel */
- }
-
- DAG_id_tag_update(vc.obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data);
- }
-}
-
-
-static int mesh_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
-{
-
- view3d_operator_needs_opengl(C);
-
- mouse_mesh_shortest_path(C, event->mval);
-
- return OPERATOR_FINISHED;
-}
-
-static int mesh_shortest_path_select_poll(bContext *C)
-{
- if(ED_operator_editmesh_region_view3d(C)) {
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
- return (em->selectmode & SCE_SELECT_EDGE);
- }
- return 0;
-}
-
-void MESH_OT_select_shortest_path(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Shortest Path Select";
- ot->description= "Select shortest path between two selections";
- ot->idname= "MESH_OT_select_shortest_path";
-
- /* api callbacks */
- ot->invoke= mesh_shortest_path_select_invoke;
- ot->poll= mesh_shortest_path_select_poll;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
-}
-
-
-/* ************************************************** */
-
-
-/* here actual select happens */
-/* gets called via generic mouse select operator */
-int mouse_mesh(bContext *C, const int mval[2], short extend)
-{
- ViewContext vc;
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- /* setup view context for argument to callbacks */
- em_setup_viewcontext(C, &vc);
- vc.mval[0]= mval[0];
- vc.mval[1]= mval[1];
-
- if(unified_findnearest(&vc, &eve, &eed, &efa)) {
-
- if(extend==0) EM_clear_flag_all(vc.em, SELECT);
-
- if(efa) {
- /* set the last selected face */
- EM_set_actFace(vc.em, efa);
-
- if( (efa->f & SELECT)==0 ) {
- EM_store_selection(vc.em, efa, EDITFACE);
- EM_select_face_fgon(vc.em, efa, 1);
- }
- else if(extend) {
- EM_remove_selection(vc.em, efa, EDITFACE);
- EM_select_face_fgon(vc.em, efa, 0);
- }
- }
- else if(eed) {
- if((eed->f & SELECT)==0) {
- EM_store_selection(vc.em, eed, EDITEDGE);
- EM_select_edge(eed, 1);
- }
- else if(extend) {
- EM_remove_selection(vc.em, eed, EDITEDGE);
- EM_select_edge(eed, 0);
- }
- }
- else if(eve) {
- if((eve->f & SELECT)==0) {
- eve->f |= SELECT;
- EM_store_selection(vc.em, eve, EDITVERT);
- }
- else if(extend){
- EM_remove_selection(vc.em, eve, EDITVERT);
- eve->f &= ~SELECT;
- }
- }
-
- EM_selectmode_flush(vc.em);
-
-// if (EM_texFaceCheck()) {
-
- if (efa && efa->mat_nr != vc.obedit->actcol-1) {
- vc.obedit->actcol= efa->mat_nr+1;
- vc.em->mat_nr= efa->mat_nr;
- WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, NULL);
- }
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data);
-
- return 1;
- }
-
- return 0;
-}
-
-/* *********** select linked ************* */
-
-/* for use with selectconnected_delimit_mesh only! */
-#define is_edge_delimit_ok(eed) ((eed->tmp.l == 1) && (eed->seam==0))
-#define is_face_tag(efa) is_edge_delimit_ok(efa->e1) || is_edge_delimit_ok(efa->e2) || is_edge_delimit_ok(efa->e3) || (efa->v4 && is_edge_delimit_ok(efa->e4))
-
-#define face_tag(efa)\
-if(efa->v4) efa->tmp.l= efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= efa->e4->tmp.l= 1;\
-else efa->tmp.l= efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= 1;
-
-/* all - 1) use all faces for extending the selection 2) only use the mouse face
-* sel - 1) select 0) deselect
-* */
-
-/* legacy warning, this function combines too much :) */
-static int select_linked_limited_invoke(ViewContext *vc, short all, short sel)
-{
- EditMesh *em= vc->em;
- EditFace *efa;
- EditEdge *eed;
- EditVert *eve;
- short done=1, change=0;
-
- if(em->faces.first==0) return OPERATOR_CANCELLED;
-
- /* flag all edges+faces as off*/
- for(eed= em->edges.first; eed; eed= eed->next)
- eed->tmp.l=0;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->tmp.l = 0;
- }
-
- if (all) {
- // XXX verts?
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT)
- eed->tmp.l= 1;
- }
- for(efa= em->faces.first; efa; efa= efa->next) {
-
- if (efa->f & SELECT) {
- face_tag(efa);
- } else {
- efa->tmp.l = 0;
- }
- }
- }
- else {
- if( unified_findnearest(vc, &eve, &eed, &efa) ) {
-
- if(efa) {
- efa->tmp.l = 1;
- face_tag(efa);
- }
- else if(eed)
- eed->tmp.l= 1;
- else {
- for(eed= em->edges.first; eed; eed= eed->next)
- if(eed->v1==eve || eed->v2==eve)
- break;
- eed->tmp.l= 1;
- }
- }
- else
- return OPERATOR_FINISHED;
- }
-
- while(done==1) {
- done= 0;
- /* simple algo - select all faces that have a selected edge
- * this intern selects the edge, repeat until nothing is left to do */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if ((efa->tmp.l == 0) && (!efa->h)) {
- if (is_face_tag(efa)) {
- face_tag(efa);
- done= 1;
- }
- }
- }
- }
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if (efa->tmp.l) {
- if (sel) {
- if (!(efa->f & SELECT)) {
- EM_select_face(efa, 1);
- change = 1;
- }
- } else {
- if (efa->f & SELECT) {
- EM_select_face(efa, 0);
- change = 1;
- }
- }
- }
- }
-
- if (!change)
- return OPERATOR_CANCELLED;
-
- if (!sel) /* make sure de-selecting faces didnt de-select the verts/edges connected to selected faces, this is common with boundaries */
- for(efa= em->faces.first; efa; efa= efa->next)
- if (efa->f & SELECT)
- EM_select_face(efa, 1);
-
- // if (EM_texFaceCheck())
-
- return OPERATOR_FINISHED;
-}
-
-#undef is_edge_delimit_ok
-#undef is_face_tag
-#undef face_tag
-
-static void linked_limit_default(bContext *C, wmOperator *op) {
- if(!RNA_property_is_set(op->ptr, "limit")) {
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
- if(em->selectmode == SCE_SELECT_FACE)
- RNA_boolean_set(op->ptr, "limit", TRUE);
- }
-}
-
-static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
- Object *obedit= CTX_data_edit_object(C);
- ViewContext vc;
- EditVert *eve, *v1, *v2;
- EditEdge *eed;
- EditFace *efa;
- short done=1, toggle=0;
- int sel= !RNA_boolean_get(op->ptr, "deselect");
- int limit;
-
- linked_limit_default(C, op);
-
- limit = RNA_boolean_get(op->ptr, "limit");
-
- /* unified_finednearest needs ogl */
- view3d_operator_needs_opengl(C);
-
- /* setup view context for argument to callbacks */
- em_setup_viewcontext(C, &vc);
-
- if(vc.em->edges.first==0) return OPERATOR_CANCELLED;
-
- vc.mval[0]= event->mval[0];
- vc.mval[1]= event->mval[1];
-
- /* return warning! */
- if(limit) {
- int retval= select_linked_limited_invoke(&vc, 0, sel);
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- return retval;
- }
-
- if( unified_findnearest(&vc, &eve, &eed, &efa)==0 ) {
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- return OPERATOR_CANCELLED;
- }
-
- /* clear test flags */
- for(v1= vc.em->verts.first; v1; v1= v1->next) v1->f1= 0;
-
- /* start vertex/face/edge */
- if(eve) eve->f1= 1;
- else if(eed) eed->v1->f1= eed->v2->f1= 1;
- else efa->v1->f1= efa->v2->f1= efa->v3->f1= 1;
-
- /* set flag f1 if affected */
- while(done==1) {
- done= 0;
- toggle++;
-
- if(toggle & 1) eed= vc.em->edges.first;
- else eed= vc.em->edges.last;
-
- while(eed) {
- v1= eed->v1;
- v2= eed->v2;
-
- if(eed->h==0) {
- if(v1->f1 && v2->f1==0) {
- v2->f1= 1;
- done= 1;
- }
- else if(v1->f1==0 && v2->f1) {
- v1->f1= 1;
- done= 1;
- }
- }
-
- if(toggle & 1) eed= eed->next;
- else eed= eed->prev;
- }
- }
-
- /* now use vertex f1 flag to select/deselect */
- for(eed= vc.em->edges.first; eed; eed= eed->next) {
- if(eed->v1->f1 && eed->v2->f1)
- EM_select_edge(eed, sel);
- }
- for(efa= vc.em->faces.first; efa; efa= efa->next) {
- if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1))
- EM_select_face(efa, sel);
- }
- /* no flush needed, connected geometry is done */
-
-// if (EM_texFaceCheck())
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_linked_pick(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Linked";
- ot->description= "(un)select all vertices linked to the active mesh";
- ot->idname= "MESH_OT_select_linked_pick";
-
- /* api callbacks */
- ot->invoke= select_linked_pick_invoke;
- ot->poll= ED_operator_editmesh_region_view3d;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
- RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "Limit selection by seam boundaries (faces only)");
-}
-
-
-/* ************************* */
-
-void selectconnected_mesh_all(EditMesh *em)
-{
- EditVert *v1,*v2;
- EditEdge *eed;
- short done=1, toggle=0;
-
- if(em->edges.first==0) return;
-
- while(done==1) {
- done= 0;
-
- toggle++;
- if(toggle & 1) eed= em->edges.first;
- else eed= em->edges.last;
-
- while(eed) {
- v1= eed->v1;
- v2= eed->v2;
- if(eed->h==0) {
- if(v1->f & SELECT) {
- if( (v2->f & SELECT)==0 ) {
- v2->f |= SELECT;
- done= 1;
- }
- }
- else if(v2->f & SELECT) {
- if( (v1->f & SELECT)==0 ) {
- v1->f |= SELECT;
- done= 1;
- }
- }
- }
- if(toggle & 1) eed= eed->next;
- else eed= eed->prev;
- }
- }
-
- /* now use vertex select flag to select rest */
- EM_select_flush(em);
-
- // if (EM_texFaceCheck())
-}
-
-static int select_linked_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
-
- if( RNA_boolean_get(op->ptr, "limit") ) {
- ViewContext vc;
- em_setup_viewcontext(C, &vc);
- select_linked_limited_invoke(&vc, 1, 1);
- }
- else
- selectconnected_mesh_all(em);
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-static int select_linked_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
-{
- linked_limit_default(C, op);
- return select_linked_exec(C, op);
-}
-
-void MESH_OT_select_linked(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Linked All";
- ot->description= "Select all vertices linked to the active mesh";
- ot->idname= "MESH_OT_select_linked";
-
- /* api callbacks */
- ot->exec= select_linked_exec;
- ot->invoke= select_linked_invoke;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "Limit selection by seam boundaries (faces only)");
-}
-
-
-/* ************************* */
-
-/* swap is 0 or 1, if 1 it hides not selected */
-void EM_hide_mesh(EditMesh *em, int swap)
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
- int a;
-
- if(em==NULL) return;
-
- /* hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */
- /* - vertex hidden, always means edge is hidden too
- - edge hidden, always means face is hidden too
- - face hidden, only set face hide
- - then only flush back down what's absolute hidden
- */
- if(em->selectmode & SCE_SELECT_VERTEX) {
- for(eve= em->verts.first; eve; eve= eve->next) {
- if((eve->f & SELECT)!=swap) {
- eve->f &= ~SELECT;
- eve->h= 1;
- }
- }
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->v1->h || eed->v2->h) {
- eed->h |= 1;
- eed->f &= ~SELECT;
- }
- }
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->e1->h & 1 || efa->e2->h & 1 || efa->e3->h & 1 || (efa->e4 && efa->e4->h & 1)) {
- efa->h= 1;
- efa->f &= ~SELECT;
- }
- }
- }
- else if(em->selectmode & SCE_SELECT_EDGE) {
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- if((eed->f & SELECT)!=swap) {
- eed->h |= 1;
- EM_select_edge(eed, 0);
- }
- }
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->e1->h & 1 || efa->e2->h & 1 || efa->e3->h & 1 || (efa->e4 && efa->e4->h & 1)) {
- efa->h= 1;
- efa->f &= ~SELECT;
- }
- }
- }
- else {
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if((efa->f & SELECT)!=swap) {
- efa->h= 1;
- EM_select_face(efa, 0);
- }
- }
- }
-
- /* flush down, only whats 100% hidden */
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
- for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
-
- if(em->selectmode & SCE_SELECT_FACE) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h) a= 1; else a= 2;
- efa->e1->f1 |= a;
- efa->e2->f1 |= a;
- efa->e3->f1 |= a;
- if(efa->e4) efa->e4->f1 |= a;
- /* When edges are not delt with in their own loop, we need to explicitly re-selct select edges that are joined to unselected faces */
- if (swap && (em->selectmode == SCE_SELECT_FACE) && (efa->f & SELECT)) {
- EM_select_face(efa, 1);
- }
- }
- }
-
- if(em->selectmode >= SCE_SELECT_EDGE) {
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f1==1) eed->h |= 1;
- if(eed->h & 1) a= 1; else a= 2;
- eed->v1->f1 |= a;
- eed->v2->f1 |= a;
- }
- }
-
- if(em->selectmode >= SCE_SELECT_VERTEX) {
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f1==1) eve->h= 1;
- }
- }
-
- em->totedgesel= em->totfacesel= em->totvertsel= 0;
-// if(EM_texFaceCheck())
-
- // DAG_id_tag_update(obedit->data, 0);
-}
-
-static int hide_mesh_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- EM_hide_mesh(em, RNA_boolean_get(op->ptr, "unselected"));
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_hide(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Hide Selection";
- ot->description= "Hide (un)selected vertices, edges or faces";
- ot->idname= "MESH_OT_hide";
-
- /* api callbacks */
- ot->exec= hide_mesh_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
-}
-
-void EM_reveal_mesh(EditMesh *em)
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- if(em==NULL) return;
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->h) {
- eve->h= 0;
- eve->f |= SELECT;
- }
- }
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h & 1) {
- eed->h &= ~1;
- if(em->selectmode & SCE_SELECT_VERTEX);
- else EM_select_edge(eed, 1);
- }
- }
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h) {
- efa->h= 0;
- if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX));
- else EM_select_face(efa, 1);
- }
- }
-
- EM_fgon_flags(em); /* redo flags and indices for fgons */
- EM_selectmode_flush(em);
-
-// if (EM_texFaceCheck())
-// DAG_id_tag_update(obedit->data, 0);
-}
-
-static int reveal_mesh_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- EM_reveal_mesh(em);
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_reveal(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Reveal Hidden";
- ot->description= "Reveal all hidden vertices, edges and faces";
- ot->idname= "MESH_OT_reveal";
-
- /* api callbacks */
- ot->exec= reveal_mesh_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int select_by_number_vertices_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- EditFace *efa;
- int numverts= RNA_enum_get(op->ptr, "type");
-
- /* Selects trias/qiads or isolated verts, and edges that do not have 2 neighboring
- * faces
- */
-
- /* for loose vertices/edges, we first select all, loop below will deselect */
- if(numverts==5) {
- EM_set_flag_all(em, SELECT);
- }
- else if(em->selectmode!=SCE_SELECT_FACE) {
- BKE_report(op->reports, RPT_WARNING, "Only works in face selection mode");
- return OPERATOR_CANCELLED;
- }
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if (efa->e4) {
- EM_select_face(efa, (numverts==4) );
- }
- else {
- EM_select_face(efa, (numverts==3) );
- }
- }
-
- EM_selectmode_flush(em);
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_by_number_vertices(wmOperatorType *ot)
-{
- static const EnumPropertyItem type_items[]= {
- {3, "TRIANGLES", 0, "Triangles", NULL},
- {4, "QUADS", 0, "Quads", NULL},
- {5, "OTHER", 0, "Other", NULL},
- {0, NULL, 0, NULL, NULL}};
-
- /* identifiers */
- ot->name= "Select by Number of Vertices";
- ot->description= "Select vertices or faces by vertex count";
- ot->idname= "MESH_OT_select_by_number_vertices";
-
- /* api callbacks */
- ot->exec= select_by_number_vertices_exec;
- ot->invoke= WM_menu_invoke;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- ot->prop= RNA_def_enum(ot->srna, "type", type_items, 3, "Type", "Type of elements to select");
-}
-
-
-static int select_mirror_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- int extend= RNA_boolean_get(op->ptr, "extend");
-
- EM_select_mirrored(obedit, em, extend);
- EM_selectmode_flush(em);
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_mirror(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Mirror";
- ot->description= "Select mesh items at mirrored locations";
- ot->idname= "MESH_OT_select_mirror";
-
- /* api callbacks */
- ot->exec= select_mirror_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
-}
-
-static int select_sharp_edges_exec(bContext *C, wmOperator *op)
-{
- /* Find edges that have exactly two neighboring faces,
- * check the angle between those faces, and if angle is
- * small enough, select the edge
- */
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- EditEdge *eed;
- EditFace *efa;
- EditFace **efa1;
- EditFace **efa2;
- intptr_t edgecount = 0, i = 0;
- float sharpness, fsharpness;
-
- /* 'standard' behaviour - check if selected, then apply relevant selection */
-
- if(em->selectmode==SCE_SELECT_FACE) {
- BKE_report(op->reports, RPT_WARNING, "Doesn't work in face selection mode");
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
-
- sharpness= RNA_float_get(op->ptr, "sharpness");
- fsharpness = ((180.0f - sharpness) * (float)M_PI) / 180.0f;
-
- /* count edges, use tmp.l */
- eed= em->edges.first;
- while(eed) {
- edgecount++;
- eed->tmp.l = i;
- eed= eed->next;
- ++i;
- }
-
- /* for each edge, we want a pointer to two adjacent faces */
- efa1 = MEM_callocN(edgecount*sizeof(EditFace *),
- "pairs of edit face pointers");
- efa2 = MEM_callocN(edgecount*sizeof(EditFace *),
- "pairs of edit face pointers");
-
-#define face_table_edge(eed) { \
- i = eed->tmp.l; \
- if (i != -1) { \
- if (efa1[i]) { \
- if (efa2[i]) { \
- /* invalidate, edge has more than two neighbors */ \
- eed->tmp.l = -1; \
- } \
- else { \
- efa2[i] = efa; \
- } \
- } \
- else { \
- efa1[i] = efa; \
- } \
- } \
- }
-
- /* find the adjacent faces of each edge, we want only two */
- efa= em->faces.first;
- while(efa) {
- face_table_edge(efa->e1);
- face_table_edge(efa->e2);
- face_table_edge(efa->e3);
- if (efa->e4) {
- face_table_edge(efa->e4);
- }
- efa= efa->next;
- }
-
-#undef face_table_edge
-
- eed = em->edges.first;
- while(eed) {
- i = eed->tmp.l;
- if (i != -1) {
- /* edge has two or less neighboring faces */
- if ( (efa1[i]) && (efa2[i]) ) {
- /* edge has exactly two neighboring faces, check angle */
- float angle;
- angle = saacos(efa1[i]->n[0]*efa2[i]->n[0] +
- efa1[i]->n[1]*efa2[i]->n[1] +
- efa1[i]->n[2]*efa2[i]->n[2]);
- if (fabsf(angle) >= fsharpness)
- EM_select_edge(eed, 1);
- }
- }
-
- eed= eed->next;
- }
-
- MEM_freeN(efa1);
- MEM_freeN(efa2);
-
-// if (EM_texFaceCheck())
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); //TODO is this needed ?
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_edges_select_sharp(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Sharp Edges";
- ot->description= "Marked selected edges as sharp";
- ot->idname= "MESH_OT_edges_select_sharp";
-
- /* api callbacks */
- ot->exec= select_sharp_edges_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_float(ot->srna, "sharpness", 0.01f, 0.0f, FLT_MAX, "sharpness", "", 0.0f, 180.0f);
-}
-
-
-static void select_linked_flat_faces(EditMesh *em, wmOperator *op, float sharpness)
-{
- /* Find faces that are linked to selected faces that are
- * relatively flat (angle between faces is higher than
- * specified angle)
- */
- EditEdge *eed;
- EditFace *efa;
- EditFace **efa1;
- EditFace **efa2;
- intptr_t edgecount = 0, i, faceselcount=0, faceselcountold=0;
- float fsharpness;
-
- if(em->selectmode!=SCE_SELECT_FACE) {
- BKE_report(op->reports, RPT_WARNING, "Only works in face selection mode");
- return;
- }
-
- fsharpness = ((180.0f - sharpness) * (float)M_PI) / 180.0f;
-
- i=0;
- /* count edges, use tmp.l */
- eed= em->edges.first;
- while(eed) {
- edgecount++;
- eed->tmp.l = i;
- eed= eed->next;
- ++i;
- }
-
- /* for each edge, we want a pointer to two adjacent faces */
- efa1 = MEM_callocN(edgecount*sizeof(EditFace *),
- "pairs of edit face pointers");
- efa2 = MEM_callocN(edgecount*sizeof(EditFace *),
- "pairs of edit face pointers");
-
-#define face_table_edge(eed) { \
- i = eed->tmp.l; \
- if (i != -1) { \
- if (efa1[i]) { \
- if (efa2[i]) { \
- /* invalidate, edge has more than two neighbors */ \
- eed->tmp.l = -1; \
- } \
- else { \
- efa2[i] = efa; \
- } \
- } \
- else { \
- efa1[i] = efa; \
- } \
- } \
- }
-
- /* find the adjacent faces of each edge, we want only two */
- efa= em->faces.first;
- while(efa) {
- face_table_edge(efa->e1);
- face_table_edge(efa->e2);
- face_table_edge(efa->e3);
- if (efa->e4) {
- face_table_edge(efa->e4);
- }
-
- /* while were at it, count the selected faces */
- if (efa->f & SELECT) ++faceselcount;
-
- efa= efa->next;
- }
-
-#undef face_table_edge
-
- eed= em->edges.first;
- while(eed) {
- i = eed->tmp.l;
- if (i != -1) {
- /* edge has two or less neighboring faces */
- if ( (efa1[i]) && (efa2[i]) ) {
- /* edge has exactly two neighboring faces, check angle */
- float angle;
- angle = saacos(efa1[i]->n[0]*efa2[i]->n[0] +
- efa1[i]->n[1]*efa2[i]->n[1] +
- efa1[i]->n[2]*efa2[i]->n[2]);
- /* invalidate: edge too sharp */
- if (fabsf(angle) >= fsharpness)
- eed->tmp.l = -1;
- }
- else {
- /* invalidate: less than two neighbors */
- eed->tmp.l = -1;
- }
- }
-
- eed= eed->next;
- }
-
-#define select_flat_neighbor(eed) { \
- i = eed->tmp.l; \
- if (i!=-1) { \
- if (! (efa1[i]->f & SELECT) ) { \
- EM_select_face(efa1[i], 1); \
- ++faceselcount; \
- } \
- if (! (efa2[i]->f & SELECT) ) { \
- EM_select_face(efa2[i], 1); \
- ++faceselcount; \
- } \
- } \
- }
-
- while (faceselcount != faceselcountold) {
- faceselcountold = faceselcount;
-
- efa= em->faces.first;
- while(efa) {
- if (efa->f & SELECT) {
- select_flat_neighbor(efa->e1);
- select_flat_neighbor(efa->e2);
- select_flat_neighbor(efa->e3);
- if (efa->e4) {
- select_flat_neighbor(efa->e4);
- }
- }
- efa= efa->next;
- }
- }
-
-#undef select_flat_neighbor
-
- MEM_freeN(efa1);
- MEM_freeN(efa2);
-
-// if (EM_texFaceCheck())
-
-}
-
-static int select_linked_flat_faces_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- select_linked_flat_faces(em, op, RNA_float_get(op->ptr, "sharpness"));
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_faces_select_linked_flat(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Linked Flat Faces";
- ot->description= "Select linked faces by angle";
- ot->idname= "MESH_OT_faces_select_linked_flat";
-
- /* api callbacks */
- ot->exec= select_linked_flat_faces_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_float(ot->srna, "sharpness", 135.0f, 0.0f, FLT_MAX, "sharpness", "", 0.0f, 180.0f);
-}
-
-static void select_non_manifold(EditMesh *em, wmOperator *op )
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- /* Selects isolated verts, and edges that do not have 2 neighboring
- * faces
- */
-
- if(em->selectmode==SCE_SELECT_FACE) {
- BKE_report(op->reports, RPT_WARNING, "Doesn't work in face selection mode");
- return;
- }
-
- eve= em->verts.first;
- while(eve) {
- /* this will count how many edges are connected
- * to this vert */
- eve->f1= 0;
- eve= eve->next;
- }
-
- eed= em->edges.first;
- while(eed) {
- /* this will count how many faces are connected to
- * this edge */
- eed->f1= 0;
- /* increase edge count for verts */
- ++eed->v1->f1;
- ++eed->v2->f1;
- eed= eed->next;
- }
-
- efa= em->faces.first;
- while(efa) {
- /* increase face count for edges */
- ++efa->e1->f1;
- ++efa->e2->f1;
- ++efa->e3->f1;
- if (efa->e4)
- ++efa->e4->f1;
- efa= efa->next;
- }
-
- /* select verts that are attached to an edge that does not
- * have 2 neighboring faces */
- eed= em->edges.first;
- while(eed) {
- if (eed->h==0 && eed->f1 != 2) {
- EM_select_edge(eed, 1);
- }
- eed= eed->next;
- }
-
- /* select isolated verts */
- if(em->selectmode & SCE_SELECT_VERTEX) {
- eve= em->verts.first;
- while(eve) {
- if (eve->f1 == 0) {
- if (!eve->h) eve->f |= SELECT;
- }
- eve= eve->next;
- }
- }
-
-// if (EM_texFaceCheck())
-
-}
-
-static int select_non_manifold_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- select_non_manifold(em, op);
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_non_manifold(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Non Manifold";
- ot->description= "Select all non-manifold vertices or edges";
- ot->idname= "MESH_OT_select_non_manifold";
-
- /* api callbacks */
- ot->exec= select_non_manifold_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-void EM_select_swap(EditMesh *em) /* exported for UV */
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- if(em->selectmode & SCE_SELECT_VERTEX) {
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->h==0) {
- if(eve->f & SELECT) eve->f &= ~SELECT;
- else eve->f|= SELECT;
- }
- }
- }
- else if(em->selectmode & SCE_SELECT_EDGE) {
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0) {
- EM_select_edge(eed, !(eed->f & SELECT));
- }
- }
- }
- else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0) {
- EM_select_face(efa, !(efa->f & SELECT));
- }
- }
- }
-
- EM_selectmode_flush(em);
-
-// if (EM_texFaceCheck())
-
-}
-
-static int select_inverse_mesh_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- EM_select_swap(em);
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_inverse(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Inverse";
- ot->description= "Select inverse of (un)selected vertices, edges or faces";
- ot->idname= "MESH_OT_select_inverse";
-
- /* api callbacks */
- ot->exec= select_inverse_mesh_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/* ******************** (de)select all operator **************** */
-
-void EM_toggle_select_all(EditMesh *em) /* exported for UV */
-{
- if(EM_nvertices_selected(em))
- EM_clear_flag_all(em, SELECT);
- else
- EM_set_flag_all_selectmode(em, SELECT);
-}
-
-void EM_select_all(EditMesh *em)
-{
- EM_set_flag_all_selectmode(em, SELECT);
-}
-
-void EM_deselect_all(EditMesh *em)
-{
- EM_clear_flag_all(em, SELECT);
-}
-
-static int select_all_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- int action = RNA_enum_get(op->ptr, "action");
-
- switch (action) {
- case SEL_TOGGLE:
- EM_toggle_select_all(em);
- break;
- case SEL_SELECT:
- EM_select_all(em);
- break;
- case SEL_DESELECT:
- EM_deselect_all(em);
- break;
- case SEL_INVERT:
- EM_select_swap(em);
- break;
- }
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_all(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select or Deselect All";
- ot->description= "Change selection of all vertices, edges or faces";
- ot->idname= "MESH_OT_select_all";
-
- /* api callbacks */
- ot->exec= select_all_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- WM_operator_properties_select_all(ot);
-}
-
-/* ******************** **************** */
-
-void EM_select_more(EditMesh *em)
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) eve->f1= 1;
- else eve->f1 = 0;
- }
-
- /* set f1 flags in vertices to select 'more' */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0) {
- if (eed->v1->f & SELECT)
- eed->v2->f1 = 1;
- if (eed->v2->f & SELECT)
- eed->v1->f1 = 1;
- }
- }
-
- /* new selected edges, but not in facemode */
- if(em->selectmode <= SCE_SELECT_EDGE) {
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0) {
- if(eed->v1->f1 && eed->v2->f1) EM_select_edge(eed, 1);
- }
- }
- }
- /* new selected faces */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0) {
- if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1))
- EM_select_face(efa, 1);
- }
- }
-}
-
-static int select_more(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)) ;
-
- EM_select_more(em);
-
-// if (EM_texFaceCheck(em))
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_more(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select More";
- ot->description= "Select more vertices, edges or faces connected to initial selection";
- ot->idname= "MESH_OT_select_more";
-
- /* api callbacks */
- ot->exec= select_more;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static void EM_select_less(EditMesh *em)
-{
- EditEdge *eed;
- EditFace *efa;
-
- if(em->selectmode <= SCE_SELECT_EDGE) {
- /* eed->f1 == 1: edge with a selected and deselected vert */
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- eed->f1= 0;
- if(eed->h==0) {
-
- if ( !(eed->v1->f & SELECT) && (eed->v2->f & SELECT) )
- eed->f1= 1;
- if ( (eed->v1->f & SELECT) && !(eed->v2->f & SELECT) )
- eed->f1= 1;
- }
- }
-
- /* deselect edges with flag set */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if (eed->h==0 && eed->f1 == 1) {
- EM_select_edge(eed, 0);
- }
- }
- EM_deselect_flush(em);
-
- }
- else {
- /* deselect faces with 1 or more deselect edges */
- /* eed->f1 == mixed selection edge */
- for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0) {
- if(efa->f & SELECT) {
- efa->e1->f1 |= 1;
- efa->e2->f1 |= 1;
- efa->e3->f1 |= 1;
- if(efa->e4) efa->e4->f1 |= 1;
- }
- else {
- efa->e1->f1 |= 2;
- efa->e2->f1 |= 2;
- efa->e3->f1 |= 2;
- if(efa->e4) efa->e4->f1 |= 2;
- }
- }
- }
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0) {
- if(efa->e1->f1==3 || efa->e2->f1==3 || efa->e3->f1==3 || (efa->e4 && efa->e4->f1==3)) {
- EM_select_face(efa, 0);
- }
- }
- }
- EM_selectmode_flush(em);
-
- }
-}
-
-static int select_less(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- EM_select_less(em);
-
-// if (EM_texFaceCheck(em))
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_less(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Less";
- ot->description= "Select less vertices, edges or faces connected to initial selection";
- ot->idname= "MESH_OT_select_less";
-
- /* api callbacks */
- ot->exec= select_less;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static void selectrandom_mesh(EditMesh *em, float randfac) /* randomly selects a user-set % of vertices/edges/faces */
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
-
- BLI_srand( BLI_rand() ); /* random seed */
-
- if(em->selectmode & SCE_SELECT_VERTEX) {
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->h==0) {
- if (BLI_frand() < randfac)
- eve->f |= SELECT;
- }
- }
- EM_selectmode_flush(em);
- }
- else if(em->selectmode & SCE_SELECT_EDGE) {
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0) {
- if (BLI_frand() < randfac)
- EM_select_edge(eed, 1);
- }
- }
- EM_selectmode_flush(em);
- }
- else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0) {
- if (BLI_frand() < randfac)
- EM_select_face(efa, 1);
- }
- }
-
- EM_selectmode_flush(em);
- }
-// if (EM_texFaceCheck())
-}
-
-static int mesh_select_random_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- if(!RNA_boolean_get(op->ptr, "extend"))
- EM_deselect_all(em);
-
- selectrandom_mesh(em, RNA_float_get(op->ptr, "percent")/100.0f);
-
- WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_select_random(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Random";
- ot->description= "Randomly select vertices";
- ot->idname= "MESH_OT_select_random";
-
- /* api callbacks */
- ot->exec= mesh_select_random_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of elements to select randomly", 0.f, 100.0f);
- RNA_def_boolean(ot->srna, "extend", FALSE, "Extend Selection", "Extend selection instead of deselecting everything first");
-}
-
-void EM_select_by_material(EditMesh *em, int index)
-{
- EditFace *efa;
-
- for (efa=em->faces.first; efa; efa= efa->next) {
- if (efa->mat_nr==index) {
- EM_select_face(efa, 1);
- }
- }
-
- EM_selectmode_flush(em);
-}
-
-void EM_deselect_by_material(EditMesh *em, int index)
-{
- EditFace *efa;
-
- for (efa=em->faces.first; efa; efa= efa->next) {
- if (efa->mat_nr==index) {
- EM_select_face(efa, 0);
- }
- }
-
- EM_selectmode_flush(em);
-}
-
-/* ************************* SEAMS AND EDGES **************** */
-
-static int editmesh_mark_seam(bContext *C, wmOperator *op)
-{
- Scene *scene= CTX_data_scene(C);
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- Mesh *me= ((Mesh *)obedit->data);
- EditEdge *eed;
- int clear = RNA_boolean_get(op->ptr, "clear");
-
- /* auto-enable seams drawing */
- if(clear==0) {
- me->drawflag |= ME_DRAWSEAMS;
- }
-
- if(clear) {
- eed= em->edges.first;
- while(eed) {
- if((eed->h==0) && (eed->f & SELECT)) {
- eed->seam = 0;
- }
- eed= eed->next;
- }
- }
- else {
- eed= em->edges.first;
- while(eed) {
- if((eed->h==0) && (eed->f & SELECT)) {
- eed->seam = 1;
- }
- eed= eed->next;
- }
- }
-
- /* live unwrap while tagging */
- if( (scene->toolsettings->edge_mode_live_unwrap) &&
- (CustomData_has_layer(&em->fdata, CD_MTFACE))
- ) {
- ED_unwrap_lscm(scene, obedit, FALSE); /* unwrap all not just sel */
- }
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_mark_seam(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Mark Seam";
- ot->description= "(un)mark selected edges as a seam";
- ot->idname= "MESH_OT_mark_seam";
-
- /* api callbacks */
- ot->exec= editmesh_mark_seam;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
-}
-
-static int editmesh_mark_sharp(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- Mesh *me= ((Mesh *)obedit->data);
- int clear = RNA_boolean_get(op->ptr, "clear");
- EditEdge *eed;
-
- /* auto-enable sharp edge drawing */
- if(clear == 0) {
- me->drawflag |= ME_DRAWSHARP;
- }
-
- if(!clear) {
- eed= em->edges.first;
- while(eed) {
- if(!eed->h && (eed->f & SELECT)) eed->sharp = 1;
- eed = eed->next;
- }
- } else {
- eed= em->edges.first;
- while(eed) {
- if(!eed->h && (eed->f & SELECT)) eed->sharp = 0;
- eed = eed->next;
- }
- }
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_mark_sharp(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Mark Sharp";
- ot->description= "(un)mark selected edges as sharp";
- ot->idname= "MESH_OT_mark_sharp";
-
- /* api callbacks */
- ot->exec= editmesh_mark_sharp;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
-}
-
-/* **************** NORMALS ************** */
-
-void EM_recalc_normal_direction(EditMesh *em, int inside, int select) /* makes faces righthand turning */
-{
- EditEdge *eed, *ed1, *ed2, *ed3, *ed4;
- EditFace *efa, *startvl;
- float maxx, nor[3], cent[3];
- int totsel, found, foundone, direct, turn, tria_nr;
-
- /* based at a select-connected to witness loose objects */
-
- /* count per edge the amount of faces */
-
- /* find the ultimate left, front, upper face (not manhattan dist!!) */
- /* also evaluate both triangle cases in quad, since these can be non-flat */
-
- /* put normal to the outside, and set the first direction flags in edges */
-
- /* then check the object, and set directions / direction-flags: but only for edges with 1 or 2 faces */
- /* this is in fact the 'select connected' */
-
- /* in case (selected) faces were not done: start over with 'find the ultimate ...' */
-
- waitcursor(1);
-
- eed= em->edges.first;
- while(eed) {
- eed->f2= 0; /* edge direction */
- eed->f1= 0; /* counter */
- eed= eed->next;
- }
-
- /* count faces and edges */
- totsel= 0;
- efa= em->faces.first;
- while(efa) {
- if(select==0 || (efa->f & SELECT) ) {
- efa->f1= 1;
- totsel++;
- efa->e1->f1++;
- efa->e2->f1++;
- efa->e3->f1++;
- if(efa->v4) efa->e4->f1++;
- }
- else efa->f1= 0;
-
- efa= efa->next;
- }
-
- while(totsel>0) {
- /* from the outside to the inside */
-
- efa= em->faces.first;
- startvl= NULL;
- maxx= -1.0e10;
- tria_nr= 0;
-
- while(efa) {
- if(efa->f1) {
- cent_tri_v3(cent, efa->v1->co, efa->v2->co, efa->v3->co);
- cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
-
- if(cent[0]>maxx) {
- maxx= cent[0];
- startvl= efa;
- tria_nr= 0;
- }
- if(efa->v4) {
- cent_tri_v3(cent, efa->v1->co, efa->v3->co, efa->v4->co);
- cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
-
- if(cent[0]>maxx) {
- maxx= cent[0];
- startvl= efa;
- tria_nr= 1;
- }
- }
- }
- efa= efa->next;
- }
-
- if (startvl==NULL)
- startvl= em->faces.first;
-
- /* set first face correct: calc normal */
-
- if(tria_nr==1) {
- normal_tri_v3( nor,startvl->v1->co, startvl->v3->co, startvl->v4->co);
- cent_tri_v3(cent, startvl->v1->co, startvl->v3->co, startvl->v4->co);
- } else {
- normal_tri_v3( nor,startvl->v1->co, startvl->v2->co, startvl->v3->co);
- cent_tri_v3(cent, startvl->v1->co, startvl->v2->co, startvl->v3->co);
- }
- /* first normal is oriented this way or the other */
- if(inside) {
- if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] > 0.0f) flipface(em, startvl);
- }
- else {
- if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0f) flipface(em, startvl);
- }
-
- eed= startvl->e1;
- if(eed->v1==startvl->v1) eed->f2= 1;
- else eed->f2= 2;
-
- eed= startvl->e2;
- if(eed->v1==startvl->v2) eed->f2= 1;
- else eed->f2= 2;
-
- eed= startvl->e3;
- if(eed->v1==startvl->v3) eed->f2= 1;
- else eed->f2= 2;
-
- eed= startvl->e4;
- if(eed) {
- if(eed->v1==startvl->v4) eed->f2= 1;
- else eed->f2= 2;
- }
-
- startvl->f1= 0;
- totsel--;
-
- /* test normals */
- found= 1;
- direct= 1;
- while(found) {
- found= 0;
- if(direct) efa= em->faces.first;
- else efa= em->faces.last;
- while(efa) {
- if(efa->f1) {
- turn= 0;
- foundone= 0;
-
- ed1= efa->e1;
- ed2= efa->e2;
- ed3= efa->e3;
- ed4= efa->e4;
-
- if(ed1->f2) {
- if(ed1->v1==efa->v1 && ed1->f2==1) turn= 1;
- if(ed1->v2==efa->v1 && ed1->f2==2) turn= 1;
- foundone= 1;
- }
- else if(ed2->f2) {
- if(ed2->v1==efa->v2 && ed2->f2==1) turn= 1;
- if(ed2->v2==efa->v2 && ed2->f2==2) turn= 1;
- foundone= 1;
- }
- else if(ed3->f2) {
- if(ed3->v1==efa->v3 && ed3->f2==1) turn= 1;
- if(ed3->v2==efa->v3 && ed3->f2==2) turn= 1;
- foundone= 1;
- }
- else if(ed4 && ed4->f2) {
- if(ed4->v1==efa->v4 && ed4->f2==1) turn= 1;
- if(ed4->v2==efa->v4 && ed4->f2==2) turn= 1;
- foundone= 1;
- }
-
- if(foundone) {
- found= 1;
- totsel--;
- efa->f1= 0;
-
- if(turn) {
- if(ed1->v1==efa->v1) ed1->f2= 2;
- else ed1->f2= 1;
- if(ed2->v1==efa->v2) ed2->f2= 2;
- else ed2->f2= 1;
- if(ed3->v1==efa->v3) ed3->f2= 2;
- else ed3->f2= 1;
- if(ed4) {
- if(ed4->v1==efa->v4) ed4->f2= 2;
- else ed4->f2= 1;
- }
-
- flipface(em, efa);
-
- }
- else {
- if(ed1->v1== efa->v1) ed1->f2= 1;
- else ed1->f2= 2;
- if(ed2->v1==efa->v2) ed2->f2= 1;
- else ed2->f2= 2;
- if(ed3->v1==efa->v3) ed3->f2= 1;
- else ed3->f2= 2;
- if(ed4) {
- if(ed4->v1==efa->v4) ed4->f2= 1;
- else ed4->f2= 2;
- }
- }
- }
- }
- if(direct) efa= efa->next;
- else efa= efa->prev;
- }
- direct= 1-direct;
- }
- }
-
- recalc_editnormals(em);
-
-// DAG_id_tag_update(obedit->data, 0);
-
- waitcursor(0);
-}
-
-
-static int normals_make_consistent_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-
- /* 'standard' behaviour - check if selected, then apply relevant selection */
-
- // XXX need other args
- EM_recalc_normal_direction(em, RNA_boolean_get(op->ptr, "inside"), 1);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); //TODO is this needed ?
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_normals_make_consistent(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Make Normals Consistent";
- ot->description= "Flip all selected vertex and face normals in a consistent direction";
- ot->idname= "MESH_OT_normals_make_consistent";
-
- /* api callbacks */
- ot->exec= normals_make_consistent_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "inside", 0, "Inside", "");
-}
-
-/* **************** VERTEX DEFORMS *************** */
-
-static int smooth_vertex(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- EditVert *eve, *eve_mir = NULL;
- EditEdge *eed;
- float *adror, *adr, fac;
- float fvec[3];
- int teller=0;
- ModifierData *md;
- int index;
-
- /* count */
- eve= em->verts.first;
- while(eve) {
- if(eve->f & SELECT) teller++;
- eve= eve->next;
- }
- if(teller==0) {
- BKE_mesh_end_editmesh(obedit->data, em);
- return OPERATOR_CANCELLED;
- }
-
- adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth");
- eve= em->verts.first;
- while(eve) {
- if(eve->f & SELECT) {
- eve->tmp.p = (void*)adr;
- eve->f1= 0;
- eve->f2= 0;
- adr+= 3;
- }
- eve= eve->next;
- }
-
- /* if there is a mirror modifier with clipping, flag the verts that
- * are within tolerance of the plane(s) of reflection
- */
- for(md=obedit->modifiers.first; md; md=md->next) {
- if((md->type==eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
- MirrorModifierData *mmd = (MirrorModifierData*) md;
-
- if(mmd->flag & MOD_MIR_CLIPPING) {
- for (eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) {
-
- switch(mmd->axis){
- case 0:
- if (fabsf(eve->co[0]) < mmd->tolerance)
- eve->f2 |= 1;
- break;
- case 1:
- if (fabsf(eve->co[1]) < mmd->tolerance)
- eve->f2 |= 2;
- break;
- case 2:
- if (fabsf(eve->co[2]) < mmd->tolerance)
- eve->f2 |= 4;
- break;
- }
- }
- }
- }
- }
- }
-
- eed= em->edges.first;
- while(eed) {
- if( (eed->v1->f & SELECT) || (eed->v2->f & SELECT) ) {
- mid_v3_v3v3(fvec, eed->v1->co, eed->v2->co);
-
- if((eed->v1->f & SELECT) && eed->v1->f1<255) {
- eed->v1->f1++;
- add_v3_v3(eed->v1->tmp.p, fvec);
- }
- if((eed->v2->f & SELECT) && eed->v2->f1<255) {
- eed->v2->f1++;
- add_v3_v3(eed->v2->tmp.p, fvec);
- }
- }
- eed= eed->next;
- }
-
- index= 0;
- eve= em->verts.first;
- while(eve) {
- if(eve->f & SELECT) {
- if(eve->f1) {
-
- int xaxis= RNA_boolean_get(op->ptr, "xaxis");
- int yaxis= RNA_boolean_get(op->ptr, "yaxis");
- int zaxis= RNA_boolean_get(op->ptr, "zaxis");
-
- if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
- eve_mir= editmesh_get_x_mirror_vert(obedit, em, eve, eve->co, index);
- }
-
- adr = eve->tmp.p;
- fac= 0.5f/(float)eve->f1;
-
- if(xaxis)
- eve->co[0]= 0.5f*eve->co[0]+fac*adr[0];
- if(yaxis)
- eve->co[1]= 0.5f*eve->co[1]+fac*adr[1];
- if(zaxis)
- eve->co[2]= 0.5f*eve->co[2]+fac*adr[2];
-
-
- /* clip if needed by mirror modifier */
- if (eve->f2) {
- if (eve->f2 & 1) {
- eve->co[0]= 0.0f;
- }
- if (eve->f2 & 2) {
- eve->co[1]= 0.0f;
- }
- if (eve->f2 & 4) {
- eve->co[2]= 0.0f;
- }
- }
-
- if (eve_mir) {
- eve_mir->co[0]=-eve->co[0];
- eve_mir->co[1]= eve->co[1];
- eve_mir->co[2]= eve->co[2];
- }
-
- }
- eve->tmp.p= NULL;
- }
- index++;
- eve= eve->next;
- }
- MEM_freeN(adror);
-
- recalc_editnormals(em);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-static int smooth_vertex_exec(bContext *C, wmOperator *op)
-{
- int repeat = RNA_int_get(op->ptr, "repeat");
- int i;
-
- if (!repeat) repeat = 1;
-
- for (i=0; i<repeat; i++) {
- smooth_vertex(C, op);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_vertices_smooth(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Smooth Vertex";
- ot->description= "Flatten angles of selected vertices";
- ot->idname= "MESH_OT_vertices_smooth";
-
- /* api callbacks */
- ot->exec= smooth_vertex_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Smooth Iterations", "", 1, INT_MAX);
- RNA_def_boolean(ot->srna, "xaxis", 1, "X-Axis", "Smooth along the X axis");
- RNA_def_boolean(ot->srna, "yaxis", 1, "Y-Axis", "Smooth along the Y axis");
- RNA_def_boolean(ot->srna, "zaxis", 1, "Z-Axis", "Smooth along the Z axis");
-}
-
-static int mesh_noise_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- Material *ma;
- Tex *tex;
- EditVert *eve;
- float fac= RNA_float_get(op->ptr, "factor");
-
- if(em==NULL) return OPERATOR_FINISHED;
-
- ma= give_current_material(obedit, obedit->actcol);
- if(ma==0 || ma->mtex[0]==0 || ma->mtex[0]->tex==0) {
- BKE_report(op->reports, RPT_WARNING, "Mesh has no material or texture assigned");
- return OPERATOR_FINISHED;
- }
- tex= give_current_material_texture(ma);
-
-
- if(tex->type==TEX_STUCCI) {
- float b2, vec[3];
- float ofs= tex->turbul/200.0f;
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) {
- b2= BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]);
- if(tex->stype) ofs*=(b2*b2);
- vec[0]= fac*(b2-BLI_hnoise(tex->noisesize, eve->co[0]+ofs, eve->co[1], eve->co[2]));
- vec[1]= fac*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1]+ofs, eve->co[2]));
- vec[2]= fac*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]+ofs));
-
- add_v3_v3(eve->co, vec);
- }
- }
- }
- else {
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) {
- float tin, dum;
- externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum, 0);
- eve->co[2]+= fac*tin;
- }
- }
- }
-
- recalc_editnormals(em);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_noise(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Noise";
- ot->description= "Use vertex coordinate as texture coordinate";
- ot->idname= "MESH_OT_noise";
-
- /* api callbacks */
- ot->exec= mesh_noise_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_float(ot->srna, "factor", 0.1f, -FLT_MAX, FLT_MAX, "Factor", "", 0.0f, 1.0f);
-}
-
-void flipface(EditMesh *em, EditFace *efa)
-{
- if(efa->v4) {
- SWAP(EditVert *, efa->v2, efa->v4);
- SWAP(EditEdge *, efa->e1, efa->e4);
- SWAP(EditEdge *, efa->e2, efa->e3);
- EM_data_interp_from_faces(em, efa, NULL, efa, 0, 3, 2, 1);
- }
- else {
- SWAP(EditVert *, efa->v2, efa->v3);
- SWAP(EditEdge *, efa->e1, efa->e3);
- efa->e2->dir= 1-efa->e2->dir;
- EM_data_interp_from_faces(em, efa, NULL, efa, 0, 2, 1, 3);
- }
-
- if(efa->v4) normal_quad_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
- else normal_tri_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co);
-}
-
-
-static int flip_normals(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- EditFace *efa;
-
- efa= em->faces.first;
- while(efa) {
- if( efa->f & SELECT ){
- flipface(em, efa);
- }
- efa= efa->next;
- }
-
- /* update vertex normals too */
- recalc_editnormals(em);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_flip_normals(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Flip Normals";
- ot->description= "Toggle the direction of selected face's vertex and face normals";
- ot->idname= "MESH_OT_flip_normals";
-
- /* api callbacks */
- ot->exec= flip_normals;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-
-static int solidify_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- float nor[3] = {0,0,1};
-
- float thickness= RNA_float_get(op->ptr, "thickness");
-
- extrudeflag(obedit, em, SELECT, nor, 1);
- EM_make_hq_normals(em);
- EM_solidify(em, thickness);
-
-
- /* update vertex normals too */
- recalc_editnormals(em);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-
-void MESH_OT_solidify(wmOperatorType *ot)
-{
- PropertyRNA *prop;
- /* identifiers */
- ot->name= "Solidify";
- ot->description= "Create a solid skin by extruding, compensating for sharp angles";
- ot->idname= "MESH_OT_solidify";
-
- /* api callbacks */
- ot->exec= solidify_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- prop= RNA_def_float(ot->srna, "thickness", 0.01f, -FLT_MAX, FLT_MAX, "Thickness", "", -10.0f, 10.0f);
- RNA_def_property_ui_range(prop, -10, 10, 0.1, 4);
-}
-
-static int mesh_select_nth_exec(bContext *C, wmOperator *op)
-{
- Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
- int nth = RNA_int_get(op->ptr, "nth");
-
- EM_deselect_nth(em, nth);
-
- BKE_mesh_end_editmesh(obedit->data, em);
-
- DAG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- return OPERATOR_FINISHED;
-}
-
-
-void MESH_OT_select_nth(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Select Nth";
- ot->description= "";
- ot->idname= "MESH_OT_select_nth";
-
- /* api callbacks */
- ot->exec= mesh_select_nth_exec;
- ot->poll= ED_operator_editmesh;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "nth", 2, 2, 100, "Nth Selection", "", 1, INT_MAX);
-}
-
diff --git a/source/blender/editors/mesh/knifetool.c b/source/blender/editors/mesh/knifetool.c
new file mode 100755
index 00000000000..b954c44c74c
--- /dev/null
+++ b/source/blender/editors/mesh/knifetool.c
@@ -0,0 +1,1989 @@
+/**
+ * $Id$
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Joseph Eagar, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <float.h>
+#define _USE_MATH_DEFINES
+#include <math.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#include "DNA_ID.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_object_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h" /*for WM_operator_pystring */
+#include "BLI_editVert.h"
+#include "BLI_array.h"
+#include "BLI_ghash.h"
+#include "BLI_memarena.h"
+#include "BLI_mempool.h"
+#include "BLI_math.h"
+#include "BLI_rand.h"
+#include "BLI_kdopbvh.h"
+#include "BLI_smallhash.h"
+#include "BLI_scanfill.h"
+
+#include "BKE_DerivedMesh.h"
+#include "BKE_blender.h"
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_scene.h"
+#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
+#include "BKE_depsgraph.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h" /* for paint cursor */
+
+#include "IMB_imbuf_types.h"
+
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_view3d.h"
+#include "ED_mesh.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "mesh_intern.h"
+#include "editbmesh_bvh.h"
+
+/* this code here is kindof messy. . .I might need to eventually rework it - joeedh*/
+
+#define MAXGROUP 30
+#define KMAXDIST 10 /*max mouse distance from edge before not detecting it*/
+
+/* knifetool operator */
+typedef struct KnifeVert {
+ BMVert *v; /*non-NULL if this is an original vert*/
+ ListBase edges;
+
+ float co[3], cageco[3], sco[3]; /*sco is screen coordinates for cageco*/
+ short flag, draw, isface, inspace;
+} KnifeVert;
+
+typedef struct Ref {
+ struct Ref *next, *prev;
+ void *ref;
+} Ref;
+
+typedef struct KnifeEdge {
+ KnifeVert *v1, *v2;
+ BMFace *basef; /*face to restrict face fill to*/
+ ListBase faces;
+ int draw;
+
+ BMEdge *e, *oe; /*non-NULL if this is an original edge*/
+} KnifeEdge;
+
+typedef struct BMEdgeHit {
+ KnifeEdge *kfe;
+ float hit[3], cagehit[3];
+ float realhit[3]; /*used in midpoint mode*/
+ float schit[3];
+ float l; /*lambda along cut line*/
+ float perc; /*lambda along hit line*/
+ KnifeVert *v; //set if snapped to a vert
+ BMFace *f;
+} BMEdgeHit;
+
+/* struct for properties used while drawing */
+typedef struct knifetool_opdata {
+ ARegion *ar; /* region that knifetool was activated in */
+ void *draw_handle; /* for drawing preview loop */
+ ViewContext vc;
+ bContext *C;
+
+ Object *ob;
+ BMEditMesh *em;
+
+ MemArena *arena;
+
+ GHash *origvertmap;
+ GHash *origedgemap;
+
+ GHash *kedgefacemap;
+
+ BMBVHTree *bmbvh;
+
+ BLI_mempool *kverts;
+ BLI_mempool *kedges;
+
+ float vthresh;
+ float ethresh;
+
+ float vertco[3], vertcage[3];
+ float prevco[3], prevcage[3];
+
+ /*used for drag-cutting*/
+ BMEdgeHit *linehits;
+ int totlinehit;
+
+ /*if curedge is NULL, attach to curvert;
+ if curvert is NULL, attach to curbmface,
+ otherwise create null vert*/
+ KnifeEdge *curedge, *prevedge;
+ KnifeVert *curvert, *prevvert;
+ BMFace *curbmface, *prevbmface;
+
+ int totkedge, totkvert, cutnr;
+
+ BLI_mempool *refs;
+
+ float projmat[4][4];
+ int is_ortho;
+ float clipsta, clipend;
+
+ enum {
+ MODE_IDLE,
+ MODE_DRAGGING,
+ MODE_CONNECT,
+ MODE_PANNING,
+ } mode;
+
+ int snap_midpoints, prevmode, extend;
+ int ignore_edge_snapping, ignore_vert_snapping;
+
+ int is_space, prev_is_space; /*1 if current cut location, vertco, isn't on the mesh*/
+ float (*cagecos)[3];
+} knifetool_opdata;
+
+static ListBase *knife_get_face_kedges(knifetool_opdata *kcd, BMFace *f);
+
+static void knife_input_ray_cast(knifetool_opdata *kcd, const int mval_i[2],
+ float r_origin[3], float r_ray[3]);
+
+static void knife_project_v3(knifetool_opdata *kcd, float co[3], float sco[3])
+{
+ if (kcd->is_ortho) {
+ mul_v3_m4v3(sco, kcd->projmat, co);
+
+ sco[0] = (float)(kcd->ar->winx/2.0f)+(kcd->ar->winx/2.0f)*sco[0];
+ sco[1] = (float)(kcd->ar->winy/2.0f)+(kcd->ar->winy/2.0f)*sco[1];
+ }
+ else {
+ ED_view3d_project_float(kcd->ar, co, sco, kcd->projmat);
+ }
+}
+
+static KnifeEdge *new_knife_edge(knifetool_opdata *kcd)
+{
+ kcd->totkedge++;
+ return BLI_mempool_calloc(kcd->kedges);
+}
+
+static KnifeVert *new_knife_vert(knifetool_opdata *kcd, float *co, float *cageco)
+{
+ KnifeVert *kfv = BLI_mempool_calloc(kcd->kverts);
+
+ kcd->totkvert++;
+
+ copy_v3_v3(kfv->co, co);
+ copy_v3_v3(kfv->cageco, cageco);
+ copy_v3_v3(kfv->sco, co);
+
+ knife_project_v3(kcd, kfv->co, kfv->sco);
+
+ return kfv;
+}
+
+/*get a KnifeVert wrapper for an existing BMVert*/
+static KnifeVert *get_bm_knife_vert(knifetool_opdata *kcd, BMVert *v)
+{
+ KnifeVert *kfv = BLI_ghash_lookup(kcd->origvertmap, v);
+
+ if (!kfv) {
+ kfv = new_knife_vert(kcd, v->co, kcd->cagecos[BM_GetIndex(v)]);
+ kfv->v = v;
+ BLI_ghash_insert(kcd->origvertmap, v, kfv);
+ }
+
+ return kfv;
+}
+
+/*get a KnifeEdge wrapper for an existing BMEdge*/
+static KnifeEdge *get_bm_knife_edge(knifetool_opdata *kcd, BMEdge *e)
+{
+ KnifeEdge *kfe = BLI_ghash_lookup(kcd->origedgemap, e);
+ if (!kfe) {
+ Ref *ref;
+ BMIter iter;
+ BMFace *f;
+
+ kfe = new_knife_edge(kcd);
+ kfe->e = e;
+ kfe->v1 = get_bm_knife_vert(kcd, e->v1);
+ kfe->v2 = get_bm_knife_vert(kcd, e->v2);
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = kfe;
+ BLI_addtail(&kfe->v1->edges, ref);
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = kfe;
+ BLI_addtail(&kfe->v2->edges, ref);
+
+ BLI_ghash_insert(kcd->origedgemap, e, kfe);
+
+ BM_ITER(f, &iter, kcd->em->bm, BM_FACES_OF_EDGE, e) {
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = f;
+ BLI_addtail(&kfe->faces, ref);
+
+ /*ensures the kedges lst for this f is initialized,
+ it automatically adds kfe by itself*/
+ knife_get_face_kedges(kcd, f);
+ }
+ }
+
+ return kfe;
+}
+
+static void knife_start_cut(knifetool_opdata *kcd)
+{
+ kcd->prevedge = kcd->curedge;
+ kcd->prevvert = kcd->curvert;
+ kcd->prevbmface = kcd->curbmface;
+ kcd->cutnr++;
+ kcd->prev_is_space = kcd->is_space;
+ kcd->is_space = 0;
+
+ copy_v3_v3(kcd->prevco, kcd->vertco);
+ copy_v3_v3(kcd->prevcage, kcd->vertcage);
+}
+
+static Ref *find_ref(ListBase *lb, void *ref)
+{
+ Ref *ref1;
+
+ for (ref1=lb->first; ref1; ref1=ref1->next) {
+ if (ref1->ref == ref)
+ return ref1;
+ }
+
+ return NULL;
+}
+
+static ListBase *knife_get_face_kedges(knifetool_opdata *kcd, BMFace *f)
+{
+ ListBase *lst = BLI_ghash_lookup(kcd->kedgefacemap, f);
+
+ if (!lst) {
+ BMIter iter;
+ BMEdge *e;
+
+ lst = BLI_memarena_alloc(kcd->arena, sizeof(ListBase));
+ lst->first = lst->last = NULL;
+
+ BM_ITER(e, &iter, kcd->em->bm, BM_EDGES_OF_FACE, f) {
+ Ref *ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = get_bm_knife_edge(kcd, e);
+ BLI_addtail(lst, ref);
+ }
+
+ BLI_ghash_insert(kcd->kedgefacemap, f, lst);
+ }
+
+ return lst;
+}
+
+/*finds the proper face to restrict face fill to*/
+static void knife_find_basef(knifetool_opdata *kcd, KnifeEdge *kfe)
+{
+ if (!kfe->basef) {
+ Ref *r1, *r2, *r3, *r4;
+
+ if (kfe->v1->isface || kfe->v2->isface) {
+ if (kfe->v2->isface)
+ kfe->basef = kcd->curbmface;
+ else
+ kfe->basef = kcd->prevbmface;
+ } else {
+ for (r1=kfe->v1->edges.first; r1 && !kfe->basef; r1=r1->next) {
+ KnifeEdge *ke1 = r1->ref;
+ for (r2=ke1->faces.first; r2 && !kfe->basef; r2=r2->next) {
+ for (r3=kfe->v2->edges.first; r3 && !kfe->basef; r3=r3->next) {
+ KnifeEdge *ke2 = r3->ref;
+
+ for (r4=ke2->faces.first; r4 && !kfe->basef; r4=r4->next) {
+ if (r2->ref == r4->ref) {
+ kfe->basef = r2->ref;
+ }
+ }
+ }
+ }
+ }
+ }
+ /*ok, at this point kfe->basef should be set if any valid possibility
+ exists*/
+ }
+}
+
+static KnifeVert *knife_split_edge(knifetool_opdata *kcd, KnifeEdge *kfe, float co[3], KnifeEdge **newkfe_out)
+{
+ KnifeEdge *newkfe = new_knife_edge(kcd);
+ ListBase *lst;
+ Ref *ref;
+ float perc, cageco[3];
+
+ perc = len_v3v3(co, kfe->v1->co) / len_v3v3(kfe->v1->co, kfe->v2->co);
+ interp_v3_v3v3(cageco, kfe->v1->cageco, kfe->v2->cageco, perc);
+
+ newkfe->v1 = kfe->v1;
+ newkfe->v2 = new_knife_vert(kcd, co, cageco);
+ newkfe->v2->draw = 1;
+ newkfe->basef = kfe->basef;
+
+ ref = find_ref(&kfe->v1->edges, kfe);
+ BLI_remlink(&kfe->v1->edges, ref);
+
+ kfe->v1 = newkfe->v2;
+ BLI_addtail(&kfe->v1->edges, ref);
+
+ for (ref=kfe->faces.first; ref; ref=ref->next) {
+ Ref *ref2 = BLI_mempool_calloc(kcd->refs);
+
+ /*add kedge ref to bm faces*/
+ lst = knife_get_face_kedges(kcd, ref->ref);
+ ref2->ref = newkfe;
+ BLI_addtail(lst, ref2);
+
+ ref2 = BLI_mempool_calloc(kcd->refs);
+ ref2->ref = ref->ref;
+ BLI_addtail(&newkfe->faces, ref2);
+ }
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = newkfe;
+ BLI_addtail(&newkfe->v1->edges, ref);
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = newkfe;
+ BLI_addtail(&newkfe->v2->edges, ref);
+
+ newkfe->draw = kfe->draw;
+ newkfe->e = kfe->e;
+
+ *newkfe_out = newkfe;
+
+ return newkfe->v2;
+}
+
+static void knife_edge_append_face(knifetool_opdata *kcd, KnifeEdge *kfe, BMFace *f)
+{
+ ListBase *lst = knife_get_face_kedges(kcd, f);
+ Ref *ref = BLI_mempool_calloc(kcd->refs);
+
+ ref->ref = kfe;
+ BLI_addtail(lst, ref);
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = f;
+ BLI_addtail(&kfe->faces, ref);
+}
+
+#if 0
+static void knife_copy_edge_facelist(knifetool_opdata *kcd, KnifeEdge *dest, KnifeEdge *source)
+{
+ Ref *ref, *ref2;
+
+ for (ref2 = source->faces.first; ref2; ref2=ref2->next) {
+ ListBase *lst = knife_get_face_kedges(kcd, ref2->ref);
+
+ /*add new edge to face knife edge list*/
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = dest;
+ BLI_addtail(lst, ref);
+
+ /*add face to new edge's face list*/
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = ref2->ref;
+ BLI_addtail(&dest->faces, ref);
+ }
+}
+#endif
+
+static void knife_add_single_cut(knifetool_opdata *kcd)
+{
+ KnifeEdge *kfe = new_knife_edge(kcd), *kfe2 = NULL, *kfe3 = NULL;
+ Ref *ref;
+
+ if (kcd->prevvert && kcd->prevvert == kcd->curvert)
+ return;
+ if (kcd->prevedge && kcd->prevedge == kcd->curedge)
+ return;
+
+ kfe->draw = 1;
+
+ if (kcd->prevvert) {
+ kfe->v1 = kcd->prevvert;
+ } else if (kcd->prevedge) {
+ kfe->v1 = knife_split_edge(kcd, kcd->prevedge, kcd->prevco, &kfe2);
+ } else {
+ kfe->v1 = new_knife_vert(kcd, kcd->prevco, kcd->prevco);
+ kfe->v1->draw = kfe->draw = !kcd->prev_is_space;
+ kfe->v1->inspace = kcd->prev_is_space;
+ kfe->draw = !kcd->prev_is_space;
+ kfe->v1->isface = 1;
+ }
+
+ if (kcd->curvert) {
+ kfe->v2 = kcd->curvert;
+ } else if (kcd->curedge) {
+ kfe->v2 = knife_split_edge(kcd, kcd->curedge, kcd->vertco, &kfe3);
+
+ kcd->curvert = kfe->v2;
+ } else {
+ kfe->v2 = new_knife_vert(kcd, kcd->vertco, kcd->vertco);
+ kfe->v2->draw = !kcd->is_space;
+ kfe->v2->isface = 1;
+ kfe->v2->inspace = kcd->is_space;
+
+ if (kcd->is_space)
+ kfe->draw = 0;
+
+ kcd->curvert = kfe->v2;
+ }
+
+ knife_find_basef(kcd, kfe);
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = kfe;
+ BLI_addtail(&kfe->v1->edges, ref);
+
+ ref = BLI_mempool_calloc(kcd->refs);
+ ref->ref = kfe;
+ BLI_addtail(&kfe->v2->edges, ref);
+
+ if (kfe->basef && !find_ref(&kfe->faces, kfe->basef))
+ knife_edge_append_face(kcd, kfe, kfe->basef);
+
+ /*sanity check to make sure we're in the right edge/face lists*/
+ if (kcd->curbmface) {
+ if (!find_ref(&kfe->faces, kcd->curbmface)) {
+ knife_edge_append_face(kcd, kfe, kcd->curbmface);
+ }
+
+ if (kcd->prevbmface && kcd->prevbmface != kcd->curbmface) {
+ if (!find_ref(&kfe->faces, kcd->prevbmface)) {
+ knife_edge_append_face(kcd, kfe, kcd->prevbmface);
+ }
+ }
+ }
+
+ /*set up for next cut*/
+ kcd->prevbmface = kcd->curbmface;
+ kcd->prevvert = kcd->curvert;
+ kcd->prevedge = kcd->curedge;
+ copy_v3_v3(kcd->prevco, kcd->vertco);
+ copy_v3_v3(kcd->prevcage, kcd->vertcage);
+ kcd->prev_is_space = kcd->is_space;
+}
+
+static int verge_linehit(const void *vlh1, const void *vlh2)
+{
+ const BMEdgeHit *lh1=vlh1, *lh2=vlh2;
+
+ if (lh1->l < lh2->l) return -1;
+ else if (lh1->l > lh2->l) return 1;
+ else return 0;
+}
+
+static void knife_add_cut(knifetool_opdata *kcd)
+{
+ /*BMEditMesh *em = kcd->em;*/ /*UNUSED*/
+ knifetool_opdata oldkcd = *kcd;
+
+ if (kcd->linehits) {
+ BMEdgeHit *lh, *lastlh, *firstlh;
+ int i;
+
+ qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit);
+
+ lh = kcd->linehits;
+ lastlh = firstlh = NULL;
+ for (i=0; i<kcd->totlinehit; i++, (lastlh=lh), lh++) {
+ BMFace *f = lastlh ? lastlh->f : lh->f;
+
+ if (lastlh && len_v3v3(lastlh->hit, lh->hit) == 0.0f) {
+ if (!firstlh)
+ firstlh = lastlh;
+ continue;
+ } else if (lastlh && firstlh) {
+ if (firstlh->v || lastlh->v) {
+ KnifeVert *kfv = firstlh->v ? firstlh->v : lastlh->v;
+
+ kcd->prevvert = kfv;
+ copy_v3_v3(kcd->prevco, firstlh->hit);
+ copy_v3_v3(kcd->prevcage, firstlh->cagehit);
+ kcd->prevedge = NULL;
+ kcd->prevbmface = f;
+ }
+ lastlh = firstlh = NULL;
+ }
+
+ if (len_v3v3(kcd->prevcage, lh->realhit) < FLT_EPSILON*80)
+ continue;
+ if (len_v3v3(kcd->vertcage, lh->realhit) < FLT_EPSILON*80)
+ continue;
+
+ if (kcd->prev_is_space || kcd->is_space) {
+ kcd->prev_is_space = kcd->is_space = 0;
+ copy_v3_v3(kcd->prevco, lh->hit);
+ copy_v3_v3(kcd->prevcage, lh->cagehit);
+ kcd->prevedge = lh->kfe;
+ kcd->curbmface = lh->f;
+ continue;
+ }
+
+ kcd->is_space = 0;
+ kcd->curedge = lh->kfe;
+ kcd->curbmface = lh->f;
+ kcd->curvert = lh->v;
+ copy_v3_v3(kcd->vertco, lh->hit);
+ copy_v3_v3(kcd->vertcage, lh->cagehit);
+
+ knife_add_single_cut(kcd);
+ }
+
+ kcd->curbmface = oldkcd.curbmface;
+ kcd->curvert = oldkcd.curvert;
+ kcd->curedge = oldkcd.curedge;
+ kcd->is_space = oldkcd.is_space;
+ copy_v3_v3(kcd->vertco, oldkcd.vertco);
+ copy_v3_v3(kcd->vertcage, oldkcd.vertcage);
+
+ knife_add_single_cut(kcd);
+
+ MEM_freeN(kcd->linehits);
+ kcd->linehits = NULL;
+ kcd->totlinehit = 0;
+ } else {
+ knife_add_single_cut(kcd);
+ }
+}
+
+static void knife_finish_cut(knifetool_opdata *UNUSED(kcd))
+{
+
+}
+
+/* modal loop selection drawing callback */
+static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
+{
+ knifetool_opdata *kcd = arg;
+
+ glDisable(GL_DEPTH_TEST);
+
+ glPolygonOffset(1.0f, 1.0f);
+
+ glPushMatrix();
+ glMultMatrixf(kcd->ob->obmat);
+
+ if (kcd->mode == MODE_DRAGGING) {
+ glColor3f(0.1, 0.1, 0.1);
+ glLineWidth(2.0);
+
+ glBegin(GL_LINES);
+ glVertex3fv(kcd->prevcage);
+ glVertex3fv(kcd->vertcage);
+ glEnd();
+
+ glLineWidth(1.0);
+ }
+
+ if (kcd->curedge) {
+ glColor3f(0.5, 0.3, 0.15);
+ glLineWidth(2.0);
+
+ glBegin(GL_LINES);
+ glVertex3fv(kcd->curedge->v1->cageco);
+ glVertex3fv(kcd->curedge->v2->cageco);
+ glEnd();
+
+ glLineWidth(1.0);
+ } else if (kcd->curvert) {
+ glColor3f(0.8, 0.2, 0.1);
+ glPointSize(11);
+
+ glBegin(GL_POINTS);
+ glVertex3fv(kcd->vertcage);
+ glEnd();
+ }
+
+ if (kcd->curbmface) {
+ glColor3f(0.1, 0.8, 0.05);
+ glPointSize(9);
+
+ glBegin(GL_POINTS);
+ glVertex3fv(kcd->vertcage);
+ glEnd();
+ }
+
+ if (kcd->totlinehit > 0) {
+ BMEdgeHit *lh;
+ int i;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ /*draw any snapped verts first*/
+ glColor4f(0.8, 0.2, 0.1, 0.4);
+ glPointSize(11);
+ glBegin(GL_POINTS);
+ lh = kcd->linehits;
+ for (i=0; i<kcd->totlinehit; i++, lh++) {
+ float sv1[3], sv2[3];
+
+ knife_project_v3(kcd, lh->kfe->v1->cageco, sv1);
+ knife_project_v3(kcd, lh->kfe->v2->cageco, sv2);
+ knife_project_v3(kcd, lh->cagehit, lh->schit);
+
+ if (len_v2v2(lh->schit, sv1) < kcd->vthresh/4) {
+ copy_v3_v3(lh->cagehit, lh->kfe->v1->cageco);
+ glVertex3fv(lh->cagehit);
+ lh->v = lh->kfe->v1;
+ } else if (len_v2v2(lh->schit, sv2) < kcd->vthresh/4) {
+ copy_v3_v3(lh->cagehit, lh->kfe->v2->cageco);
+ glVertex3fv(lh->cagehit);
+ lh->v = lh->kfe->v2;
+ }
+ }
+ glEnd();
+
+ /*now draw the rest*/
+ glColor4f(0.1, 0.8, 0.05, 0.4);
+ glPointSize(7);
+ glBegin(GL_POINTS);
+ lh = kcd->linehits;
+ for (i=0; i<kcd->totlinehit; i++, lh++) {
+ glVertex3fv(lh->cagehit);
+ }
+ glEnd();
+ glDisable(GL_BLEND);
+ }
+
+ if (kcd->totkedge > 0) {
+ BLI_mempool_iter iter;
+ KnifeEdge *kfe;
+
+ glLineWidth(1.0);
+ glBegin(GL_LINES);
+
+ BLI_mempool_iternew(kcd->kedges, &iter);
+ for (kfe=BLI_mempool_iterstep(&iter); kfe; kfe=BLI_mempool_iterstep(&iter)) {
+ if (!kfe->draw)
+ continue;
+
+ glColor3f(0.2, 0.2, 0.2);
+
+ glVertex3fv(kfe->v1->cageco);
+ glVertex3fv(kfe->v2->cageco);
+ }
+
+ glEnd();
+ glLineWidth(1.0);
+ }
+
+ if (kcd->totkvert > 0) {
+ BLI_mempool_iter iter;
+ KnifeVert *kfv;
+
+ glPointSize(5.0);
+
+ glBegin(GL_POINTS);
+ BLI_mempool_iternew(kcd->kverts, &iter);
+ for (kfv=BLI_mempool_iterstep(&iter); kfv; kfv=BLI_mempool_iterstep(&iter)) {
+ if (!kfv->draw)
+ continue;
+
+ glColor3f(0.6, 0.1, 0.2);
+
+ glVertex3fv(kfv->cageco);
+ }
+
+ glEnd();
+ }
+
+ glPopMatrix();
+ glEnable(GL_DEPTH_TEST);
+}
+
+static int kfe_vert_in_edge(KnifeEdge *e, KnifeVert *v) {
+ return e->v1 == v || e->v2 == v;
+}
+
+static int point_on_line(float p[3], float v1[3], float v2[3])
+{
+ float d = dist_to_line_segment_v3(p, v1, v2);
+ if (d < 0.01) {
+ d = len_v3v3(v1, v2);
+ if (d == 0.0)
+ return 0;
+
+ d = len_v3v3(p, v1) / d;
+
+ if (d >= -FLT_EPSILON*10 || d <= 1.0+FLT_EPSILON*10)
+ return 1;
+ }
+
+ return 0;
+}
+
+static BMEdgeHit *knife_edge_tri_isect(knifetool_opdata *kcd, BMBVHTree *bmtree, float v1[3],
+ float v2[3], float v3[3], SmallHash *ehash, bglMats *mats, int *count)
+{
+ BVHTree *tree2 = BLI_bvhtree_new(3, FLT_EPSILON*4, 8, 8), *tree = BMBVH_BVHTree(bmtree);
+ BMEdgeHit *edges = NULL;
+ BLI_array_declare(edges);
+ BVHTreeOverlap *results, *result;
+ BMLoop **ls;
+ float cos[9], uv[3], lambda, depsilon;
+ unsigned int tot=0;
+ int i, j;
+
+ copy_v3_v3(cos, v1);
+ copy_v3_v3(cos+3, v2);
+ copy_v3_v3(cos+6, v3);
+
+ /* for comparing distances, error of intersection depends on triangle scale */
+ depsilon = 50*FLT_EPSILON*MAX3(len_v3v3(v1, v2), len_v3v3(v1, v3), len_v3v3(v2, v3));
+
+ BLI_bvhtree_insert(tree2, 0, cos, 3);
+ BLI_bvhtree_balance(tree2);
+
+ result = results = BLI_bvhtree_overlap(tree, tree2, &tot);
+
+ for (i=0; i<tot; i++, result++) {
+ float p[3];
+
+ ls = (BMLoop**)kcd->em->looptris[result->indexA];
+
+ for (j=0; j<3; j++) {
+ BMLoop *l1 = ls[j];
+ BMFace *hitf;
+ ListBase *lst = knife_get_face_kedges(kcd, l1->f);
+ Ref *ref;
+
+ for (ref=lst->first; ref; ref=ref->next) {
+ KnifeEdge *kfe = ref->ref;
+
+ //if (kfe == kcd->curedge || kfe== kcd->prevedge)
+ // continue;
+
+ if (isect_line_tri_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3, &lambda, uv)) {
+ float no[3], view[3], sp[3];
+
+ interp_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco, lambda);
+
+ if (kcd->curvert && len_v3v3(kcd->curvert->cageco, p) < depsilon)
+ continue;
+ if (kcd->prevvert && len_v3v3(kcd->prevvert->cageco, p) < depsilon)
+ continue;
+ if (len_v3v3(kcd->prevcage, p) < depsilon || len_v3v3(kcd->vertcage, p) < depsilon)
+ continue;
+
+ /*check if this point is visible in the viewport*/
+ knife_project_v3(kcd, p, sp);
+ view3d_unproject(mats, view, sp[0], sp[1], 0.0f);
+ mul_m4_v3(kcd->ob->imat, view);
+
+ sub_v3_v3(view, p);
+ normalize_v3(view);
+
+ copy_v3_v3(no, view);
+ mul_v3_fl(no, 0.003);
+
+ /*go towards view a bit*/
+ add_v3_v3(p, no);
+
+ /*ray cast*/
+ hitf = BMBVH_RayCast(bmtree, p, no, NULL, NULL);
+
+ /*ok, if visible add the new point*/
+ if (!hitf && !BLI_smallhash_haskey(ehash, (intptr_t)kfe)) {
+ BMEdgeHit hit;
+
+ if (len_v3v3(p, kcd->vertco) < depsilon || len_v3v3(p, kcd->prevco) < depsilon)
+ continue;
+
+ hit.kfe = kfe;
+ hit.v = NULL;
+
+ knife_find_basef(kcd, kfe);
+ hit.f = kfe->basef;
+ hit.perc = len_v3v3(p, kfe->v1->cageco) / len_v3v3(kfe->v1->cageco, kfe->v2->cageco);
+ copy_v3_v3(hit.cagehit, p);
+
+ interp_v3_v3v3(p, kfe->v1->co, kfe->v2->co, hit.perc);
+ copy_v3_v3(hit.realhit, p);
+
+ if (kcd->snap_midpoints) {
+ float perc = hit.perc;
+
+ /* select the closest from the edge endpoints or the midpoint */
+ if (perc < 0.25f) {
+ perc = 0.0f;
+ }
+ else if (perc < 0.75f) {
+ perc = 0.5f;
+ }
+ else {
+ perc = 1.0f;
+ }
+
+ interp_v3_v3v3(hit.hit, kfe->v1->co, kfe->v2->co, perc);
+ interp_v3_v3v3(hit.cagehit, kfe->v1->cageco, kfe->v2->cageco, perc);
+ } else {
+ copy_v3_v3(hit.hit, p);
+ }
+ knife_project_v3(kcd, hit.cagehit, hit.schit);
+
+ BLI_array_append(edges, hit);
+ BLI_smallhash_insert(ehash, (intptr_t)kfe, NULL);
+ }
+ }
+ }
+ }
+ }
+
+ if (results)
+ MEM_freeN(results);
+
+ BLI_bvhtree_free(tree2);
+ *count = BLI_array_count(edges);
+
+ return edges;
+}
+
+static void knife_bgl_get_mats(knifetool_opdata *UNUSED(kcd), bglMats *mats)
+{
+ bgl_get_mats(mats);
+ //copy_m4_m4(mats->modelview, kcd->vc.rv3d->viewmat);
+ //copy_m4_m4(mats->projection, kcd->vc.rv3d->winmat);
+}
+
+/*finds (visible) edges that intersects the current screen drag line*/
+static void knife_find_line_hits(knifetool_opdata *kcd)
+{
+ bglMats mats;
+ BMEdgeHit *e1, *e2;
+ SmallHash hash, *ehash = &hash;
+ float v1[3], v2[3], v3[3], v4[4], s1[3], s2[3];
+ int i, c1, c2;
+
+ knife_bgl_get_mats(kcd, &mats);
+
+ if (kcd->linehits) {
+ MEM_freeN(kcd->linehits);
+ kcd->linehits = NULL;
+ kcd->totlinehit = 0;
+ }
+
+ copy_v3_v3(v1, kcd->prevcage);
+ copy_v3_v3(v2, kcd->vertcage);
+
+ /*project screen line's 3d coordinates back into 2d*/
+ knife_project_v3(kcd, v1, s1);
+ knife_project_v3(kcd, v2, s2);
+
+ if (len_v2v2(s1, s2) < 1)
+ return;
+
+ /*unproject screen line*/
+ ED_view3d_win_to_segment_clip(kcd->ar, kcd->vc.v3d, s1, v1, v3);
+ ED_view3d_win_to_segment_clip(kcd->ar, kcd->vc.v3d, s2, v2, v4);
+
+ mul_m4_v3(kcd->ob->imat, v1);
+ mul_m4_v3(kcd->ob->imat, v2);
+ mul_m4_v3(kcd->ob->imat, v3);
+ mul_m4_v3(kcd->ob->imat, v4);
+
+ BLI_smallhash_init(ehash);
+
+ /*test two triangles of sceen line's plane*/
+ e1 = knife_edge_tri_isect(kcd, kcd->bmbvh, v1, v2, v3, ehash, &mats, &c1);
+ e2 = knife_edge_tri_isect(kcd, kcd->bmbvh, v2, v3, v4, ehash, &mats, &c2);
+ if (c1 && c2) {
+ e1 = MEM_reallocN(e1, sizeof(BMEdgeHit)*(c1+c2));
+ memcpy(e1+c1, e2, sizeof(BMEdgeHit)*c2);
+ MEM_freeN(e2);
+ } else if (c2) {
+ e1 = e2;
+ }
+
+ kcd->linehits = e1;
+ kcd->totlinehit = c1+c2;
+
+ /*find position along screen line, used for sorting*/
+ for (i=0; i<kcd->totlinehit; i++) {
+ BMEdgeHit *lh = e1+i;
+
+ lh->l = len_v2v2(lh->schit, s1) / len_v2v2(s2, s1);
+ }
+
+ BLI_smallhash_release(ehash);
+}
+
+static void knife_input_ray_cast(knifetool_opdata *kcd, const int mval_i[2],
+ float r_origin[3], float r_ray[3])
+{
+ bglMats mats;
+ float mval[2], imat[3][3];
+
+ knife_bgl_get_mats(kcd, &mats);
+
+ mval[0] = (float)mval_i[0];
+ mval[1] = (float)mval_i[1];
+
+ /*unproject to find view ray*/
+ view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f);
+
+ if(kcd->is_ortho)
+ negate_v3_v3(r_ray, kcd->vc.rv3d->viewinv[2]);
+ else
+ sub_v3_v3v3(r_ray, r_origin, kcd->vc.rv3d->viewinv[3]);
+ normalize_v3(r_ray);
+
+ /*transform into object space*/
+ invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
+ copy_m3_m4(imat, kcd->ob->obmat);
+ invert_m3(imat);
+
+ mul_m4_v3(kcd->ob->imat, r_origin);
+ mul_m3_v3(imat, r_ray);
+}
+
+
+static BMFace *knife_find_closest_face(knifetool_opdata *kcd, float co[3], float cageco[3], int *is_space)
+{
+ BMFace *f;
+ float mval[2], imat[3][3];
+ int dist = KMAXDIST;
+ float origin[3];
+ float ray[3];
+
+ /*unproject to find view ray*/
+ knife_input_ray_cast(kcd, kcd->vc.mval, origin, ray);
+ add_v3_v3v3(co, origin, ray);
+
+ f = BMBVH_RayCast(kcd->bmbvh, origin, ray, co, cageco);
+
+ if (is_space)
+ *is_space = !f;
+
+ if (!f) {
+ /*try to use backbuffer selection method if ray casting failed*/
+ f = EDBM_findnearestface(&kcd->vc, &dist);
+
+ /* cheat for now; just put in the origin instead
+ * of a true coordinate on the face.
+ * This just puts a point 1.0f infront of the view. */
+ add_v3_v3v3(co, origin, ray);
+ }
+
+ return f;
+}
+
+/*find the 2d screen space density of vertices within a radius. used to scale snapping
+ distance for picking edges/verts.*/
+static int knife_sample_screen_density(knifetool_opdata *kcd, float radius)
+{
+ BMFace *f;
+ int is_space;
+ float co[3], cageco[3], sco[3];
+
+ f = knife_find_closest_face(kcd, co, cageco, &is_space);
+
+ if (f && !is_space) {
+ ListBase *lst;
+ Ref *ref;
+ float dis;
+ int c = 0;
+
+ knife_project_v3(kcd, cageco, sco);
+
+ lst = knife_get_face_kedges(kcd, f);
+ for (ref=lst->first; ref; ref=ref->next) {
+ KnifeEdge *kfe = ref->ref;
+ int i;
+
+ for (i=0; i<2; i++) {
+ KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
+
+ knife_project_v3(kcd, kfv->cageco, kfv->sco);
+
+ dis = len_v2v2(kfv->sco, sco);
+ if (dis < radius) {
+ if(kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float vec[3];
+
+ copy_v3_v3(vec, kfv->cageco);
+ mul_m4_v3(kcd->vc.obedit->obmat, vec);
+
+ if(ED_view3d_test_clipping(kcd->vc.rv3d, vec, 1)==0) {
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+ }
+
+ return c;
+ }
+
+ return 0;
+}
+
+/*returns snapping distance for edges/verts, scaled by the density of the
+ surrounding mesh (in screen space)*/
+static float knife_snap_size(knifetool_opdata *kcd, float maxsize)
+{
+ float density = (float)knife_sample_screen_density(kcd, maxsize*2.0f);
+
+ density = MAX2(density, 1);
+
+ return MIN2(maxsize / (density*0.5f), maxsize);
+}
+
+/*p is closest point on edge to the mouse cursor*/
+static KnifeEdge *knife_find_closest_edge(knifetool_opdata *kcd, float p[3], float cagep[3], BMFace **fptr, int *is_space)
+{
+ BMFace *f;
+ float co[3], cageco[3], sco[3], maxdist = knife_snap_size(kcd, kcd->ethresh);
+
+ if (kcd->ignore_vert_snapping)
+ maxdist *= 0.5;
+
+ f = knife_find_closest_face(kcd, co, cageco, NULL);
+ *is_space = !f;
+
+ /*set p to co, in case we don't find anything, means a face cut*/
+ copy_v3_v3(p, co);
+ copy_v3_v3(cagep, cageco);
+
+ kcd->curbmface = f;
+
+ if (f) {
+ KnifeEdge *cure = NULL;
+ ListBase *lst;
+ Ref *ref;
+ float dis, curdis=FLT_MAX;
+
+ knife_project_v3(kcd, cageco, sco);
+
+ /*look through all edges associated with this face*/
+ lst = knife_get_face_kedges(kcd, f);
+ for (ref=lst->first; ref; ref=ref->next) {
+ KnifeEdge *kfe = ref->ref;
+
+ /*project edge vertices into screen space*/
+ knife_project_v3(kcd, kfe->v1->cageco, kfe->v1->sco);
+ knife_project_v3(kcd, kfe->v2->cageco, kfe->v2->sco);
+
+ dis = dist_to_line_segment_v2(sco, kfe->v1->sco, kfe->v2->sco);
+ if (dis < curdis && dis < maxdist) {
+ if(kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float labda= labda_PdistVL2Dfl(sco, kfe->v1->sco, kfe->v2->sco);
+ float vec[3];
+
+ vec[0]= kfe->v1->cageco[0] + labda*(kfe->v2->cageco[0] - kfe->v1->cageco[0]);
+ vec[1]= kfe->v1->cageco[1] + labda*(kfe->v2->cageco[1] - kfe->v1->cageco[1]);
+ vec[2]= kfe->v1->cageco[2] + labda*(kfe->v2->cageco[2] - kfe->v1->cageco[2]);
+ mul_m4_v3(kcd->vc.obedit->obmat, vec);
+
+ if(ED_view3d_test_clipping(kcd->vc.rv3d, vec, 1)==0) {
+ cure = kfe;
+ curdis = dis;
+ }
+ } else {
+ cure = kfe;
+ curdis = dis;
+ }
+ }
+ }
+
+ if (fptr)
+ *fptr = f;
+
+ if (cure && p) {
+ if (!kcd->ignore_edge_snapping || !(cure->e)) {
+ if (kcd->snap_midpoints) {
+ interp_v3_v3v3(p, cure->v1->co, cure->v2->co, 0.5f);
+ interp_v3_v3v3(cagep, cure->v1->cageco, cure->v2->cageco, 0.5f);
+ } else {
+ float d;
+
+ closest_to_line_segment_v3(cagep, cageco, cure->v1->cageco, cure->v2->cageco);
+ d = len_v3v3(cagep, cure->v1->cageco) / len_v3v3(cure->v1->cageco, cure->v2->cageco);
+ interp_v3_v3v3(p, cure->v1->co, cure->v2->co, d);
+ }
+ } else {
+ return NULL;
+ }
+ }
+
+ return cure;
+ }
+
+ if (fptr)
+ *fptr = NULL;
+
+ return NULL;
+}
+
+/*find a vertex near the mouse cursor, if it exists*/
+static KnifeVert *knife_find_closest_vert(knifetool_opdata *kcd, float p[3], float cagep[3], BMFace **fptr, int *is_space)
+{
+ BMFace *f;
+ float co[3], cageco[3], sco[3], maxdist = knife_snap_size(kcd, kcd->vthresh);
+
+ if (kcd->ignore_vert_snapping)
+ maxdist *= 0.5;
+
+ f = knife_find_closest_face(kcd, co, cageco, is_space);
+
+ /*set p to co, in case we don't find anything, means a face cut*/
+ copy_v3_v3(p, co);
+ copy_v3_v3(cagep, p);
+ kcd->curbmface = f;
+
+ if (f) {
+ ListBase *lst;
+ Ref *ref;
+ KnifeVert *curv = NULL;
+ float dis, curdis=FLT_MAX;
+
+ knife_project_v3(kcd, cageco, sco);
+
+ lst = knife_get_face_kedges(kcd, f);
+ for (ref=lst->first; ref; ref=ref->next) {
+ KnifeEdge *kfe = ref->ref;
+ int i;
+
+ for (i=0; i<2; i++) {
+ KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
+
+ knife_project_v3(kcd, kfv->cageco, kfv->sco);
+
+ dis = len_v2v2(kfv->sco, sco);
+ if (dis < curdis && dis < maxdist) {
+ if(kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float vec[3];
+
+ copy_v3_v3(vec, kfv->cageco);
+ mul_m4_v3(kcd->vc.obedit->obmat, vec);
+
+ if(ED_view3d_test_clipping(kcd->vc.rv3d, vec, 1)==0) {
+ curv = kfv;
+ curdis = dis;
+ }
+ } else {
+ curv = kfv;
+ curdis = dis;
+ }
+ }
+ }
+ }
+
+ if (!kcd->ignore_vert_snapping || !(curv && curv->v)) {
+ if (fptr)
+ *fptr = f;
+
+ if (curv && p) {
+ copy_v3_v3(p, curv->co);
+ copy_v3_v3(cagep, curv->cageco);
+ }
+
+ return curv;
+ } else {
+ if (fptr)
+ *fptr = f;
+
+ return NULL;
+ }
+ }
+
+ if (fptr)
+ *fptr = NULL;
+
+ return NULL;
+}
+
+/*update active knife edge/vert pointers*/
+static int knife_update_active(knifetool_opdata *kcd)
+{
+ kcd->curvert = NULL; kcd->curedge = NULL; kcd->curbmface = NULL;
+
+ kcd->curvert = knife_find_closest_vert(kcd, kcd->vertco, kcd->vertcage, &kcd->curbmface, &kcd->is_space);
+ if (!kcd->curvert) {
+ kcd->curedge = knife_find_closest_edge(kcd, kcd->vertco, kcd->vertcage, &kcd->curbmface, &kcd->is_space);
+ }
+
+ /* if no hits are found this would normally default to (0,0,0) so instead
+ * get a point at the mouse ray closest to the previous point.
+ * Note that drawing lines in `free-space` isn't properly supported
+ * but theres no guarantee (0,0,0) has any geometry either - campell */
+ if(kcd->curvert == NULL && kcd->curedge == NULL) {
+ float origin[3], ray[3], co[3];
+
+ knife_input_ray_cast(kcd, kcd->vc.mval, origin, ray);
+ add_v3_v3v3(co, origin, ray);
+
+ closest_to_line_v3(kcd->vertcage, kcd->prevcage, co, origin);
+ }
+
+ if (kcd->mode == MODE_DRAGGING) {
+ knife_find_line_hits(kcd);
+ }
+ return 1;
+}
+
+#define MARK 4
+#define DEL 8
+#define VERT_ON_EDGE 16
+#define VERT_ORIG 32
+#define FACE_FLIP 64
+#define BOUNDARY 128
+#define FACE_NEW 256
+
+typedef struct facenet_entry {
+ struct facenet_entry *next, *prev;
+ KnifeEdge *kfe;
+} facenet_entry;
+
+static void rnd_offset_co(float co[3], float scale)
+{
+ int i;
+
+ for (i=0; i<3; i++) {
+ co[i] += (BLI_drand()-0.5)*scale;
+ }
+}
+
+static void remerge_faces(knifetool_opdata *kcd)
+{
+ BMesh *bm = kcd->em->bm;
+ SmallHash svisit, *visit=&svisit;
+ BMIter iter;
+ BMFace *f;
+ BMFace **stack = NULL;
+ BLI_array_declare(stack);
+ BMFace **faces = NULL;
+ BLI_array_declare(faces);
+ BMOperator bmop;
+ int idx;
+
+ BMO_InitOpf(bm, &bmop, "beautify_fill faces=%ff constrain_edges=%fe", FACE_NEW, BOUNDARY);
+
+ BMO_Exec_Op(bm, &bmop);
+ BMO_Flag_Buffer(bm, &bmop, "geomout", FACE_NEW, BM_FACE);
+
+ BMO_Finish_Op(bm, &bmop);
+
+ BLI_smallhash_init(visit);
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ BMIter eiter;
+ BMEdge *e;
+ BMFace *f2;
+
+ if (!BMO_TestFlag(bm, f, FACE_NEW))
+ continue;
+
+ if (BLI_smallhash_haskey(visit, (intptr_t)f))
+ continue;
+
+ BLI_array_empty(stack);
+ BLI_array_empty(faces);
+ BLI_array_append(stack, f);
+ BLI_smallhash_insert(visit, (intptr_t)f, NULL);
+
+ do {
+ f2 = BLI_array_pop(stack);
+
+ BLI_array_append(faces, f2);
+
+ BM_ITER(e, &eiter, bm, BM_EDGES_OF_FACE, f2) {
+ BMIter fiter;
+ BMFace *f3;
+
+ if (BMO_TestFlag(bm, e, BOUNDARY))
+ continue;
+
+ BM_ITER(f3, &fiter, bm, BM_FACES_OF_EDGE, e) {
+ if (!BMO_TestFlag(bm, f3, FACE_NEW))
+ continue;
+ if (BLI_smallhash_haskey(visit, (intptr_t)f3))
+ continue;
+
+ BLI_smallhash_insert(visit, (intptr_t)f3, NULL);
+ BLI_array_append(stack, f3);
+ }
+ }
+ } while (BLI_array_count(stack) > 0);
+
+ if (BLI_array_count(faces) > 0) {
+ idx = BM_GetIndex(faces[0]);
+
+ f2 = BM_Join_Faces(bm, faces, BLI_array_count(faces));
+ if (f2) {
+ BMO_SetFlag(bm, f2, FACE_NEW);
+ BM_SetIndex(f2, idx);
+ }
+ }
+ }
+
+ BLI_array_free(stack);
+ BLI_array_free(faces);
+}
+
+/*use edgenet to fill faces. this is a bit annoying and convoluted.*/
+static void knifenet_fill_faces(knifetool_opdata *kcd)
+{
+ BMesh *bm = kcd->em->bm;
+ BMIter bmiter;
+ BLI_mempool_iter iter;
+ BMFace *f;
+ BMEdge *e;
+ KnifeVert *kfv;
+ KnifeEdge *kfe;
+ facenet_entry *entry;
+ ListBase *face_nets = MEM_callocN(sizeof(ListBase)*bm->totface, "face_nets");
+ BMFace **faces = MEM_callocN(sizeof(BMFace*)*bm->totface, "faces knife");
+ MemArena *arena = BLI_memarena_new(1<<16, "knifenet_fill_faces");
+ SmallHash shash, *hash = &shash;
+ /* SmallHash shash2, *visited = &shash2; */ /*UNUSED*/
+ int i, j, k=0, totface=bm->totface;
+
+ BMO_push(bm, NULL);
+ bmesh_begin_edit(bm, BMOP_UNTAN_MULTIRES);
+
+ i = 0;
+ BM_ITER(f, &bmiter, bm, BM_FACES_OF_MESH, NULL) {
+ BM_SetIndex(f, i);
+ faces[i] = f;
+ i++;
+ }
+
+ BM_ITER(e, &bmiter, bm, BM_EDGES_OF_MESH, NULL) {
+ BMO_SetFlag(bm, e, BOUNDARY);
+ }
+
+ /*turn knife verts into real verts, as necassary*/
+ BLI_mempool_iternew(kcd->kverts, &iter);
+ for (kfv=BLI_mempool_iterstep(&iter); kfv; kfv=BLI_mempool_iterstep(&iter)) {
+ if (!kfv->v) {
+ /* shouldn't we be at least copying the normal? - if not some comment here should explain why - campbell */
+ kfv->v = BM_Make_Vert(bm, kfv->co, NULL);
+ kfv->flag = 1;
+ BMO_SetFlag(bm, kfv->v, DEL);
+ } else {
+ kfv->flag = 0;
+ BMO_SetFlag(bm, kfv->v, VERT_ORIG);
+ }
+
+ BMO_SetFlag(bm, kfv->v, MARK);
+ }
+
+ /*we want to only do changed faces. first, go over new edges and add to
+ face net lists.*/
+ i=0; j=0; k=0;
+ BLI_mempool_iternew(kcd->kedges, &iter);
+ for (kfe=BLI_mempool_iterstep(&iter); kfe; kfe=BLI_mempool_iterstep(&iter)) {
+ Ref *ref;
+ if (!kfe->v1 || !kfe->v2 || kfe->v1->inspace || kfe->v2->inspace)
+ continue;
+
+ i++;
+
+ if (kfe->e && kfe->v1->v == kfe->e->v1 && kfe->v2->v == kfe->e->v2) {
+ kfe->oe = kfe->e;
+ continue;
+ }
+
+ j++;
+
+ if (kfe->e) {
+ kfe->oe = kfe->e;
+
+ BMO_SetFlag(bm, kfe->e, DEL);
+ BMO_ClearFlag(bm, kfe->e, BOUNDARY);
+ kfe->e = NULL;
+ }
+
+ kfe->e = BM_Make_Edge(bm, kfe->v1->v, kfe->v2->v, NULL, 1);
+ BMO_SetFlag(bm, kfe->e, BOUNDARY);
+
+ for (ref=kfe->faces.first; ref; ref=ref->next) {
+ f = ref->ref;
+
+ entry = BLI_memarena_alloc(arena, sizeof(*entry));
+ entry->kfe = kfe;
+ BLI_addtail(face_nets+BM_GetIndex(f), entry);
+ }
+ }
+
+ /*go over original edges, and add to faces with new geometry*/
+ BLI_mempool_iternew(kcd->kedges, &iter);
+ for (kfe=BLI_mempool_iterstep(&iter); kfe; kfe=BLI_mempool_iterstep(&iter)) {
+ Ref *ref;
+
+ if (!kfe->v1 || !kfe->v2 || kfe->v1->inspace || kfe->v2->inspace)
+ continue;
+ if (!(kfe->oe && kfe->v1->v == kfe->oe->v1 && kfe->v2->v == kfe->oe->v2))
+ continue;
+
+ k++;
+
+ BMO_SetFlag(bm, kfe->e, BOUNDARY);
+ kfe->oe = kfe->e;
+
+ for (ref=kfe->faces.first; ref; ref=ref->next) {
+ f = ref->ref;
+
+ if (face_nets[BM_GetIndex(f)].first) {
+ entry = BLI_memarena_alloc(arena, sizeof(*entry));
+ entry->kfe = kfe;
+ BLI_addtail(face_nets+BM_GetIndex(f), entry);
+ }
+ }
+ }
+
+ for (i=0; i<totface; i++) {
+ EditFace *efa;
+ EditVert *eve, *lasteve;
+ int j;
+ float rndscale = FLT_EPSILON*25;
+
+ f = faces[i];
+ BLI_smallhash_init(hash);
+
+ if (face_nets[i].first)
+ BMO_SetFlag(bm, f, DEL);
+
+ BLI_begin_edgefill();
+
+ for (entry=face_nets[i].first; entry; entry=entry->next) {
+ if (!BLI_smallhash_haskey(hash, (intptr_t)entry->kfe->v1)) {
+ eve = BLI_addfillvert(entry->kfe->v1->v->co);
+ eve->xs = 0;
+ rnd_offset_co(eve->co, rndscale);
+ eve->tmp.p = entry->kfe->v1->v;
+ BLI_smallhash_insert(hash, (intptr_t)entry->kfe->v1, eve);
+ }
+
+ if (!BLI_smallhash_haskey(hash, (intptr_t)entry->kfe->v2)) {
+ eve = BLI_addfillvert(entry->kfe->v2->v->co);
+ eve->xs = 0;
+ rnd_offset_co(eve->co, rndscale);
+ eve->tmp.p = entry->kfe->v2->v;
+ BLI_smallhash_insert(hash, (intptr_t)entry->kfe->v2, eve);
+ }
+ }
+
+ for (j=0, entry=face_nets[i].first; entry; entry=entry->next, j++) {
+ lasteve = BLI_smallhash_lookup(hash, (intptr_t)entry->kfe->v1);
+ eve = BLI_smallhash_lookup(hash, (intptr_t)entry->kfe->v2);
+
+ eve->xs++;
+ lasteve->xs++;
+ }
+
+ for (j=0, entry=face_nets[i].first; entry; entry=entry->next, j++) {
+ lasteve = BLI_smallhash_lookup(hash, (intptr_t)entry->kfe->v1);
+ eve = BLI_smallhash_lookup(hash, (intptr_t)entry->kfe->v2);
+
+ if (eve->xs > 1 && lasteve->xs > 1) {
+ BLI_addfilledge(lasteve, eve);
+
+ BMO_ClearFlag(bm, entry->kfe->e->v1, DEL);
+ BMO_ClearFlag(bm, entry->kfe->e->v2, DEL);
+ } else {
+ if (lasteve->xs < 2)
+ BLI_remlink(&fillvertbase, lasteve);
+ if (eve->xs < 2)
+ BLI_remlink(&fillvertbase, eve);
+ }
+ }
+
+ BLI_edgefill(0);
+
+ for (efa=fillfacebase.first; efa; efa=efa->next) {
+ BMVert *v1=efa->v3->tmp.p, *v2=efa->v2->tmp.p, *v3=efa->v1->tmp.p;
+ BMFace *f2;
+ BMLoop *l;
+ BMVert *verts[3] = {v1, v2, v3};
+
+ if (v1 == v2 || v2 == v3 || v1 == v3)
+ continue;
+ if (BM_Face_Exists(bm, verts, 3, &f2))
+ continue;
+
+ f2 = BM_Make_QuadTri(bm, v1, v2, v3, NULL, NULL, 0);
+ BMO_SetFlag(bm, f2, FACE_NEW);
+
+ l = bm_firstfaceloop(f2);
+ do {
+ BMO_ClearFlag(bm, l->e, DEL);
+ l = l->next;
+ } while (l != bm_firstfaceloop(f2));
+
+ BMO_ClearFlag(bm, f2, DEL);
+ BM_SetIndex(f2, i);
+
+ BM_Face_UpdateNormal(bm, f2);
+ if (dot_v3v3(f->no, f2->no) < 0.0) {
+ BM_flip_normal(bm, f2);
+ }
+ }
+
+ BLI_end_edgefill();
+ BLI_smallhash_release(hash);
+ }
+
+ /* interpolate customdata */
+ BM_ITER(f, &bmiter, bm, BM_FACES_OF_MESH, NULL) {
+ BMLoop *l1;
+ BMFace *f2;
+ BMIter liter1;
+
+ if (!BMO_TestFlag(bm, f, FACE_NEW))
+ continue;
+
+ f2 = faces[BM_GetIndex(f)];
+ if (BM_GetIndex(f) < 0 || BM_GetIndex(f) >= totface) {
+ fprintf(stderr, "%s: face index out of range! (bmesh internal error)\n", __func__);
+ }
+
+ BM_Copy_Attributes(bm, bm, f2, f);
+
+ BM_ITER(l1, &liter1, bm, BM_LOOPS_OF_FACE, f) {
+ BM_loop_interp_from_face(bm, l1, f2, 1, 1);
+ }
+ }
+
+ /*merge triangles back into faces*/
+ remerge_faces(kcd);
+
+ /*delete left over faces*/
+ BMO_CallOpf(bm, "del geom=%ff context=%i", DEL, DEL_ONLYFACES);
+ BMO_CallOpf(bm, "del geom=%fe context=%i", DEL, DEL_EDGES);
+ BMO_CallOpf(bm, "del geom=%fv context=%i", DEL, DEL_VERTS);
+
+ if (face_nets)
+ MEM_freeN(face_nets);
+ if (faces)
+ MEM_freeN(faces);
+ BLI_memarena_free(arena);
+ BLI_smallhash_release(hash);
+
+ BMO_ClearStack(bm); /*remerge_faces sometimes raises errors, so make sure to clear them*/
+
+ bmesh_end_edit(bm, BMOP_UNTAN_MULTIRES);
+ BMO_pop(bm);
+}
+
+/*called on tool confirmation*/
+static void knifetool_finish(bContext *C, wmOperator *op)
+{
+ knifetool_opdata *kcd= op->customdata;
+
+ knifenet_fill_faces(kcd);
+
+ DAG_id_tag_update(kcd->ob->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, kcd->ob->data);
+}
+
+/*copied from paint_image.c*/
+static int project_knife_view_clip(View3D *v3d, RegionView3D *rv3d, float *clipsta, float *clipend)
+{
+ int orth= ED_view3d_clip_range_get(v3d, rv3d, clipsta, clipend);
+
+ if (orth) { /* only needed for ortho */
+ float fac = 2.0f / ((*clipend) - (*clipsta));
+ *clipsta *= fac;
+ *clipend *= fac;
+ }
+
+ return orth;
+}
+
+static void knife_recalc_projmat(knifetool_opdata *kcd)
+{
+ ARegion *ar = CTX_wm_region(kcd->C);
+
+ if (!ar)
+ return;
+
+ invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
+ ED_view3d_ob_project_mat_get(ar->regiondata, kcd->ob, kcd->projmat);
+ //mul_m4_m4m4(kcd->projmat, kcd->vc.rv3d->viewmat, kcd->vc.rv3d->winmat);
+
+ kcd->is_ortho = project_knife_view_clip(kcd->vc.v3d, kcd->vc.rv3d,
+ &kcd->clipsta, &kcd->clipend);
+}
+
+/* called when modal loop selection is done... */
+static void knifetool_exit (bContext *UNUSED(C), wmOperator *op)
+{
+ knifetool_opdata *kcd= op->customdata;
+
+ if (!kcd)
+ return;
+
+ /* deactivate the extra drawing stuff in 3D-View */
+ ED_region_draw_cb_exit(kcd->ar->type, kcd->draw_handle);
+
+ /* free the custom data */
+ BLI_mempool_destroy(kcd->refs);
+ BLI_mempool_destroy(kcd->kverts);
+ BLI_mempool_destroy(kcd->kedges);
+
+ BLI_ghash_free(kcd->origedgemap, NULL, NULL);
+ BLI_ghash_free(kcd->origvertmap, NULL, NULL);
+ BLI_ghash_free(kcd->kedgefacemap, NULL, NULL);
+
+ BMBVH_FreeBVH(kcd->bmbvh);
+ BLI_memarena_free(kcd->arena);
+
+ /* tag for redraw */
+ ED_region_tag_redraw(kcd->ar);
+
+ if (kcd->cagecos)
+ MEM_freeN(kcd->cagecos);
+
+ /* destroy kcd itself */
+ MEM_freeN(kcd);
+ op->customdata= NULL;
+}
+
+static void cage_mapped_verts_callback(void *userData, int index, float *co,
+ float *UNUSED(no_f), short *UNUSED(no_s))
+{
+ void **data = userData;
+ BMEditMesh *em = data[0];
+ float (*cagecos)[3] = data[1];
+ SmallHash *hash = data[2];
+
+ if (index >= 0 && index < em->bm->totvert && !BLI_smallhash_haskey(hash, index)) {
+ BLI_smallhash_insert(hash, index, NULL);
+ copy_v3_v3(cagecos[index], co);
+ }
+}
+
+/* called when modal loop selection gets set up... */
+static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut))
+{
+ knifetool_opdata *kcd;
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ DerivedMesh *cage, *final;
+ SmallHash shash;
+ BMIter iter;
+ BMVert *v;
+ int i;
+ void *data[3];
+
+ /* alloc new customdata */
+ kcd= op->customdata= MEM_callocN(sizeof(knifetool_opdata), "knifetool Modal Op Data");
+
+ /* assign the drawing handle for drawing preview line... */
+ kcd->ob = obedit;
+ kcd->ar= CTX_wm_region(C);
+ kcd->C = C;
+ kcd->draw_handle= ED_region_draw_cb_activate(kcd->ar->type, knifetool_draw, kcd, REGION_DRAW_POST_VIEW);
+ em_setup_viewcontext(C, &kcd->vc);
+
+ kcd->em= ((Mesh *)kcd->ob->data)->edit_btmesh;
+
+ BM_ITER_INDEX(v, &iter, kcd->em->bm, BM_VERTS_OF_MESH, NULL, i) {
+ BM_SetIndex(v, i);
+ }
+
+ cage = editbmesh_get_derived_cage_and_final(scene, obedit, kcd->em, &final, CD_MASK_DERIVEDMESH);
+ kcd->cagecos = MEM_callocN(sizeof(float)*3*kcd->em->bm->totvert, "knife cagecos");
+ data[0] = kcd->em;
+ data[1] = kcd->cagecos;
+ data[2] = &shash;
+
+ BLI_smallhash_init(&shash);
+ cage->foreachMappedVert(cage, cage_mapped_verts_callback, data);
+ BLI_smallhash_release(&shash);
+
+ kcd->bmbvh = BMBVH_NewBVH(kcd->em, BMBVH_USE_CAGE|BMBVH_RETURN_ORIG, scene, obedit);
+ kcd->arena = BLI_memarena_new(1<<15, "knife");
+ kcd->vthresh = KMAXDIST-1;
+ kcd->ethresh = KMAXDIST;
+
+ kcd->extend = 1;
+
+ knife_recalc_projmat(kcd);
+
+ ED_region_tag_redraw(kcd->ar);
+
+ kcd->refs = BLI_mempool_create(sizeof(Ref), 1, 2048, 0, 0);
+ kcd->kverts = BLI_mempool_create(sizeof(KnifeVert), 1, 512, 0, 1);
+ kcd->kedges = BLI_mempool_create(sizeof(KnifeEdge), 1, 512, 0, 1);
+
+ kcd->origedgemap = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "knife origedgemap");
+ kcd->origvertmap = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "knife origvertmap");
+ kcd->kedgefacemap = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "knife origvertmap");
+
+ return 1;
+}
+
+static int knifetool_cancel (bContext *C, wmOperator *op)
+{
+ /* this is just a wrapper around exit() */
+ knifetool_exit(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+static int knifetool_invoke (bContext *C, wmOperator *op, wmEvent *evt)
+{
+ knifetool_opdata *kcd;
+
+ view3d_operator_needs_opengl(C);
+
+ if (!knifetool_init(C, op, 0))
+ return OPERATOR_CANCELLED;
+
+ /* add a modal handler for this operator - handles loop selection */
+ WM_event_add_modal_handler(C, op);
+
+ kcd = op->customdata;
+ kcd->vc.mval[0] = evt->mval[0];
+ kcd->vc.mval[1] = evt->mval[1];
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+enum {
+ KNF_MODAL_CANCEL=1,
+ KNF_MODAL_CONFIRM,
+ KNF_MODAL_MIDPOINT_ON,
+ KNF_MODAL_MIDPOINT_OFF,
+ KNF_MODAL_NEW_CUT,
+ KNF_MODEL_IGNORE_SNAP_ON,
+ KNF_MODEL_IGNORE_SNAP_OFF,
+ KNF_MODAL_ADD_CUT,
+};
+
+wmKeyMap* knifetool_modal_keymap(wmKeyConfig *keyconf)
+{
+ static EnumPropertyItem modal_items[] = {
+ {KNF_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {KNF_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+ {KNF_MODAL_MIDPOINT_ON, "SNAP_MIDPOINTS_ON", 0, "Snap To Midpoints On", ""},
+ {KNF_MODAL_MIDPOINT_OFF, "SNAP_MIDPOINTS_OFF", 0, "Snap To Midpoints Off", ""},
+ {KNF_MODEL_IGNORE_SNAP_ON, "IGNORE_SNAP_ON", 0, "Ignore Snapping On", ""},
+ {KNF_MODEL_IGNORE_SNAP_OFF, "IGNORE_SNAP_OFF", 0, "Ignore Snapping Off", ""},
+ {KNF_MODAL_NEW_CUT, "NEW_CUT", 0, "End Current Cut", ""},
+ {KNF_MODAL_ADD_CUT, "ADD_CUT", 0, "Add Cut", ""},
+
+ {0, NULL, 0, NULL, NULL}};
+
+ wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "Knife Tool Modal Map");
+
+ /* this function is called for each spacetype, only needs to add map once */
+ if(keymap) return NULL;
+
+ keymap= WM_modalkeymap_add(keyconf, "Knife Tool Modal Map", modal_items);
+
+ /* items for modal map */
+ WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, KNF_MODAL_ADD_CUT);
+ WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, KNF_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, KNF_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, EKEY, KM_PRESS, 0, 0, KNF_MODAL_NEW_CUT);
+
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_MIDPOINT_ON);
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, KNF_MODAL_MIDPOINT_OFF);
+ WM_modalkeymap_add_item(keymap, RIGHTCTRLKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_MIDPOINT_ON);
+ WM_modalkeymap_add_item(keymap, RIGHTCTRLKEY, KM_RELEASE, KM_ANY, 0, KNF_MODAL_MIDPOINT_OFF);
+
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, KNF_MODEL_IGNORE_SNAP_ON);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, KNF_MODEL_IGNORE_SNAP_OFF);
+ WM_modalkeymap_add_item(keymap, RIGHTSHIFTKEY, KM_PRESS, KM_ANY, 0, KNF_MODEL_IGNORE_SNAP_ON);
+ WM_modalkeymap_add_item(keymap, RIGHTSHIFTKEY, KM_RELEASE, KM_ANY, 0, KNF_MODEL_IGNORE_SNAP_OFF);
+
+ WM_modalkeymap_assign(keymap, "MESH_OT_knifetool");
+
+ return keymap;
+}
+
+static int knifetool_modal (bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *obedit;
+ knifetool_opdata *kcd= op->customdata;
+
+ if (!C) {
+ return OPERATOR_FINISHED;
+ }
+
+ obedit = CTX_data_edit_object(C);
+ if (!obedit || obedit->type != OB_MESH || ((Mesh*)obedit->data)->edit_btmesh != kcd->em) {
+ knifetool_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+
+ view3d_operator_needs_opengl(C);
+
+ if (kcd->mode == MODE_PANNING)
+ kcd->mode = kcd->prevmode;
+
+ /* handle modal keymap */
+ if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case KNF_MODAL_CANCEL:
+ /* finish */
+ ED_region_tag_redraw(kcd->ar);
+
+ knifetool_exit(C, op);
+
+ return OPERATOR_CANCELLED;
+ case KNF_MODAL_CONFIRM:
+ /* finish */
+ ED_region_tag_redraw(kcd->ar);
+
+ knifetool_finish(C, op);
+ knifetool_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ case KNF_MODAL_MIDPOINT_ON:
+ kcd->snap_midpoints = 1;
+
+ knife_recalc_projmat(kcd);
+ knife_update_active(kcd);
+ ED_region_tag_redraw(kcd->ar);
+ break;
+ case KNF_MODAL_MIDPOINT_OFF:
+ kcd->snap_midpoints = 0;
+
+ knife_recalc_projmat(kcd);
+ knife_update_active(kcd);
+ ED_region_tag_redraw(kcd->ar);
+ break;
+ case KNF_MODEL_IGNORE_SNAP_ON:
+ ED_region_tag_redraw(kcd->ar);
+ kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 1;
+ break;
+ case KNF_MODEL_IGNORE_SNAP_OFF:
+ ED_region_tag_redraw(kcd->ar);
+ kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 0;
+ break;
+ case KNF_MODAL_NEW_CUT:
+ ED_region_tag_redraw(kcd->ar);
+ knife_finish_cut(kcd);
+ kcd->mode = MODE_IDLE;
+ break;
+ case KNF_MODAL_ADD_CUT:
+ knife_recalc_projmat(kcd);
+
+ if (kcd->mode == MODE_DRAGGING) {
+ knife_add_cut(kcd);
+ if (!kcd->extend) {
+ knife_finish_cut(kcd);
+ kcd->mode = MODE_IDLE;
+ }
+ } else if (kcd->mode != MODE_PANNING) {
+ knife_start_cut(kcd);
+ kcd->mode = MODE_DRAGGING;
+ }
+
+ ED_region_tag_redraw(kcd->ar);
+ break;
+ }
+ } else { /*non-modal-mapped events*/
+ switch (event->type) {
+ case WHEELUPMOUSE:
+ case WHEELDOWNMOUSE:
+ return OPERATOR_PASS_THROUGH;
+ case MIDDLEMOUSE:
+ if (event->val != KM_RELEASE) {
+ if (kcd->mode != MODE_PANNING)
+ kcd->prevmode = kcd->mode;
+ kcd->mode = MODE_PANNING;
+ } else {
+ kcd->mode = kcd->prevmode;
+ }
+
+ ED_region_tag_redraw(kcd->ar);
+ return OPERATOR_PASS_THROUGH;
+
+ case MOUSEMOVE: /* mouse moved somewhere to select another loop */
+ if (kcd->mode != MODE_PANNING) {
+ knife_recalc_projmat(kcd);
+ kcd->vc.mval[0] = event->mval[0];
+ kcd->vc.mval[1] = event->mval[1];
+
+ if (knife_update_active(kcd))
+ ED_region_tag_redraw(kcd->ar);
+ }
+
+ break;
+ }
+ }
+
+ /* keep going until the user confirms */
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void MESH_OT_knifetool (wmOperatorType *ot)
+{
+ /* description */
+ ot->name= "Knife Topology Tool";
+ ot->idname= "MESH_OT_knifetool";
+ ot->description= "Cut new topology";
+
+ /* callbacks */
+ ot->invoke= knifetool_invoke;
+ ot->modal= knifetool_modal;
+ ot->cancel= knifetool_cancel;
+ ot->poll= ED_operator_editmesh_view3d;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
+}
diff --git a/source/blender/editors/mesh/loopcut.c b/source/blender/editors/mesh/loopcut.c
index 9bbfea1291f..5e144341b59 100644
--- a/source/blender/editors/mesh/loopcut.c
+++ b/source/blender/editors/mesh/loopcut.c
@@ -13,7 +13,7 @@
*
* 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.
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2007 Blender Foundation.
* All rights reserved.
@@ -30,6 +30,8 @@
#include <float.h>
+#define _USE_MATH_DEFINES
+#include <math.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
@@ -39,7 +41,6 @@
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
-#include "DNA_windowmanager_types.h"
#include "MEM_guardedalloc.h"
@@ -48,7 +49,7 @@
#include "BLI_blenlib.h"
#include "BLI_dynstr.h" /*for WM_operator_pystring */
#include "BLI_editVert.h"
-#include "BLI_math.h"
+#include "BLI_array.h"
#include "BLI_utildefines.h"
#include "BKE_blender.h"
@@ -59,6 +60,8 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_array_mallocn.h"
+#include "BKE_tessmesh.h"
+#include "BKE_depsgraph.h"
#include "BIF_gl.h"
#include "BIF_glutil.h" /* for paint cursor */
@@ -93,8 +96,8 @@ typedef struct tringselOpData {
ViewContext vc;
Object *ob;
- EditMesh *em;
- EditEdge *eed;
+ BMEditMesh *em;
+ BMEdge *eed;
int extend;
int do_cut;
@@ -128,17 +131,62 @@ static void ringsel_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
}
}
+/*given two opposite edges in a face, finds the ordering of their vertices so
+ that cut preview lines won't cross each other*/
+static void edgering_find_order(BMEditMesh *em, BMEdge *lasteed, BMEdge *eed,
+ BMVert *lastv1, BMVert *v[2][2])
+{
+ BMIter liter;
+ BMLoop *l, *l2;
+ int rev;
+
+ l = eed->l;
+
+ /*find correct order for v[1]*/
+ if (!(BM_Edge_In_Face(l->f, eed) && BM_Edge_In_Face(l->f, lasteed))) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_LOOP, l) {
+ if (BM_Edge_In_Face(l->f, eed) && BM_Edge_In_Face(l->f, lasteed))
+ break;
+ }
+ }
+
+ /*this should never happen*/
+ if (!l) {
+ v[0][0] = eed->v1;
+ v[0][1] = eed->v2;
+ v[1][0] = lasteed->v1;
+ v[1][1] = lasteed->v2;
+ return;
+ }
+
+ l2 = BM_OtherFaceLoop(l->e, l->f, eed->v1);
+ rev = (l2 == l->prev);
+ while (l2->v != lasteed->v1 && l2->v != lasteed->v2) {
+ l2 = rev ? l2->prev : l2->next;
+ }
+
+ if (l2->v == lastv1) {
+ v[0][0] = eed->v1;
+ v[0][1] = eed->v2;
+ } else {
+ v[0][0] = eed->v2;
+ v[0][1] = eed->v1;
+ }
+}
+
static void edgering_sel(tringselOpData *lcd, int previewlines, int select)
{
- EditMesh *em = lcd->em;
- EditEdge *startedge = lcd->eed;
- EditEdge *eed;
- EditFace *efa;
- EditVert *v[2][2];
+ BMEditMesh *em = lcd->em;
+ BMEdge *startedge = lcd->eed;
+ BMEdge *eed, *lasteed;
+ BMVert *v[2][2], *lastv1;
+ BMWalker walker;
float (*edges)[2][3] = NULL;
- V_DYNDECLARE(edges);
+ BLI_array_declare(edges);
float co[2][3];
- int looking=1, i, tot=0;
+ int i, tot=0;
+
+ memset(v, 0, sizeof(v));
if (!startedge)
return;
@@ -150,110 +198,81 @@ static void edgering_sel(tringselOpData *lcd, int previewlines, int select)
}
if (!lcd->extend) {
- EM_clear_flag_all(lcd->em, SELECT);
+ EDBM_clear_flag_all(lcd->em, BM_SELECT);
}
- /* in eed->f1 we put the valence (amount of faces in edge) */
- /* in eed->f2 we put tagged flag as correct loop */
- /* in efa->f1 we put tagged flag as correct to select */
+ if (select) {
+ BMW_Init(&walker, em->bm, BMW_EDGERING, 0, 0);
+ eed = BMW_Begin(&walker, startedge);
+ for (; eed; eed=BMW_Step(&walker)) {
+ BM_Select(em->bm, eed, 1);
+ }
+ BMW_End(&walker);
- for(eed= em->edges.first; eed; eed= eed->next) {
- eed->f1= 0;
- eed->f2= 0;
+ return;
}
- for(efa= em->faces.first; efa; efa= efa->next) {
- efa->f1= 0;
- if(efa->h==0) {
- efa->e1->f1++;
- efa->e2->f1++;
- efa->e3->f1++;
- if(efa->e4) efa->e4->f1++;
- }
- }
-
- // tag startedge OK
- startedge->f2= 1;
-
- while(looking) {
- looking= 0;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->e4 && efa->f1==0 && efa->h == 0) { // not done quad
- if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
-
- // if edge tagged, select opposing edge and mark face ok
- if(efa->e1->f2) {
- efa->e3->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- else if(efa->e2->f2) {
- efa->e4->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- if(efa->e3->f2) {
- efa->e1->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- if(efa->e4->f2) {
- efa->e2->f2= 1;
- efa->f1= 1;
- looking= 1;
- }
- }
+ BMW_Init(&walker, em->bm, BMW_EDGERING, 0, 0);
+ eed = startedge = BMW_Begin(&walker, startedge);
+ lastv1 = NULL;
+ for (lasteed=NULL; eed; eed=BMW_Step(&walker)) {
+ if (lasteed) {
+ if (lastv1) {
+ v[1][0] = v[0][0];
+ v[1][1] = v[0][1];
+ } else {
+ v[1][0] = lasteed->v1;
+ v[1][1] = lasteed->v2;
+ lastv1 = lasteed->v1;
+ }
+
+ edgering_find_order(em, lasteed, eed, lastv1, v);
+ lastv1 = v[0][0];
+
+ for(i=1;i<=previewlines;i++){
+ co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
+ co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
+ co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
+
+ co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
+ co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
+ co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];
+
+ BLI_array_growone(edges);
+ VECCOPY(edges[tot][0], co[0]);
+ VECCOPY(edges[tot][1], co[1]);
+ tot++;
}
}
+ lasteed = eed;
}
- if(previewlines > 0 && !select){
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->v4 == NULL) { continue; }
- if(efa->h == 0){
- if(efa->e1->f2 == 1){
- if(efa->e1->h == 1 || efa->e3->h == 1 )
- continue;
-
- v[0][0] = efa->v1;
- v[0][1] = efa->v2;
- v[1][0] = efa->v4;
- v[1][1] = efa->v3;
- } else if(efa->e2->f2 == 1){
- if(efa->e2->h == 1 || efa->e4->h == 1)
- continue;
- v[0][0] = efa->v2;
- v[0][1] = efa->v3;
- v[1][0] = efa->v1;
- v[1][1] = efa->v4;
- } else { continue; }
-
- for(i=1;i<=previewlines;i++){
- co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
- co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
- co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
-
- co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
- co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
- co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];
-
- V_GROW(edges);
- VECCOPY(edges[tot][0], co[0]);
- VECCOPY(edges[tot][1], co[1]);
- tot++;
- }
- }
- }
- } else {
- select = (startedge->f & SELECT) == 0;
+ if (lasteed != startedge && BM_Edge_Share_Faces(lasteed, startedge)) {
+ v[1][0] = v[0][0];
+ v[1][1] = v[0][1];
- /* select the edges */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f2) EM_select_edge(eed, select);
+ edgering_find_order(em, lasteed, startedge, lastv1, v);
+
+ for(i=1;i<=previewlines;i++){
+ if (!v[0][0] || !v[0][1] || !v[1][0] || !v[1][1])
+ continue;
+
+ co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
+ co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
+ co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
+
+ co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
+ co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
+ co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];
+
+ BLI_array_growone(edges);
+ VECCOPY(edges[tot][0], co[0]);
+ VECCOPY(edges[tot][1], co[1]);
+ tot++;
}
}
+ BMW_End(&walker);
lcd->edges = edges;
lcd->totedge = tot;
}
@@ -263,7 +282,8 @@ static void ringsel_find_edge(tringselOpData *lcd, int cuts)
if (lcd->eed) {
edgering_sel(lcd, cuts, 0);
} else if(lcd->edges) {
- MEM_freeN(lcd->edges);
+ if (lcd->edges)
+ MEM_freeN(lcd->edges);
lcd->edges = NULL;
lcd->totedge = 0;
}
@@ -272,17 +292,18 @@ static void ringsel_find_edge(tringselOpData *lcd, int cuts)
static void ringsel_finish(bContext *C, wmOperator *op)
{
tringselOpData *lcd= op->customdata;
- int cuts= (lcd->do_cut)? RNA_int_get(op->ptr,"number_cuts"): 0;
+ int cuts= RNA_int_get(op->ptr, "number_cuts");
if (lcd->eed) {
- EditMesh *em = BKE_mesh_get_editmesh(lcd->ob->data);
-
+ BMEditMesh *em = lcd->em;
+
edgering_sel(lcd, cuts, 1);
if (lcd->do_cut) {
-
- esubdivideflag(lcd->ob, em, SELECT, 0.0f, 0.0f, 0, cuts, 0, SUBDIV_SELECT_LOOPCUT);
-
+ BM_esubdivideflag(lcd->ob, em->bm, BM_SELECT, 0.0f,
+ 0.0f, 0, cuts, SUBDIV_SELECT_LOOPCUT,
+ SUBD_PATH, 0, 0, 0);
+
/* force edge slide to edge select mode in in face select mode */
if (em->selectmode & SCE_SELECT_FACE) {
if (em->selectmode == SCE_SELECT_FACE)
@@ -290,33 +311,35 @@ static void ringsel_finish(bContext *C, wmOperator *op)
else
em->selectmode &= ~SCE_SELECT_FACE;
CTX_data_tool_settings(C)->selectmode= em->selectmode;
- EM_selectmode_set(em);
+ EDBM_selectmode_set(em);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_TOOLSETTINGS, CTX_data_scene(C));
WM_event_add_notifier(C, NC_SCENE|ND_TOOLSETTINGS, CTX_data_scene(C));
}
-
+
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT|ND_DATA, lcd->ob->data);
DAG_id_tag_update(lcd->ob->data, 0);
- WM_event_add_notifier(C, NC_GEOM|ND_DATA, lcd->ob->data);
}
else {
/* sets as active, useful for other tools */
if(em->selectmode & SCE_SELECT_VERTEX)
- EM_store_selection(em, lcd->eed->v1, EDITVERT);
+ EDBM_selectmode_flush(em);
if(em->selectmode & SCE_SELECT_EDGE)
- EM_store_selection(em, lcd->eed, EDITEDGE);
+ EDBM_selectmode_flush(em);
- EM_selectmode_flush(lcd->em);
+ EDBM_selectmode_flush(lcd->em);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, lcd->ob->data);
}
}
}
/* called when modal loop selection is done... */
-static void ringsel_exit(wmOperator *op)
+static void ringsel_exit(bContext *UNUSED(C), wmOperator *op)
{
tringselOpData *lcd= op->customdata;
-
+
/* deactivate the extra drawing stuff in 3D-View */
ED_region_draw_cb_exit(lcd->ar->type, lcd->draw_handle);
@@ -342,7 +365,7 @@ static int ringsel_init (bContext *C, wmOperator *op, int do_cut)
lcd->ar= CTX_wm_region(C);
lcd->draw_handle= ED_region_draw_cb_activate(lcd->ar->type, ringsel_draw, lcd, REGION_DRAW_POST_VIEW);
lcd->ob = CTX_data_edit_object(C);
- lcd->em= BKE_mesh_get_editmesh((Mesh *)lcd->ob->data);
+ lcd->em= ((Mesh *)lcd->ob->data)->edit_btmesh;
lcd->extend = do_cut ? 0 : RNA_boolean_get(op->ptr, "extend");
lcd->do_cut = do_cut;
em_setup_viewcontext(C, &lcd->vc);
@@ -352,55 +375,18 @@ static int ringsel_init (bContext *C, wmOperator *op, int do_cut)
return 1;
}
-static int ringcut_cancel (bContext *UNUSED(C), wmOperator *op)
+static int ringcut_cancel (bContext *C, wmOperator *op)
{
/* this is just a wrapper around exit() */
- ringsel_exit(op);
+ ringsel_exit(C, op);
return OPERATOR_CANCELLED;
}
-static int ringsel_invoke (bContext *C, wmOperator *op, wmEvent *evt)
-{
- tringselOpData *lcd;
- EditEdge *edge;
- int dist = 75;
-
- view3d_operator_needs_opengl(C);
-
- if (!ringsel_init(C, op, 0))
- return OPERATOR_CANCELLED;
-
- lcd = op->customdata;
-
- if (lcd->em->selectmode == SCE_SELECT_FACE) {
- ringsel_exit(op);
- WM_operator_name_call(C, "MESH_OT_loop_select", WM_OP_INVOKE_REGION_WIN, NULL);
- return OPERATOR_CANCELLED;
- }
-
- lcd->vc.mval[0] = evt->mval[0];
- lcd->vc.mval[1] = evt->mval[1];
-
- edge = findnearestedge(&lcd->vc, &dist);
- if(!edge) {
- ringsel_exit(op);
- return OPERATOR_CANCELLED;
- }
-
- lcd->eed = edge;
- ringsel_find_edge(lcd, 1);
-
- ringsel_finish(C, op);
- ringsel_exit(op);
-
- return OPERATOR_FINISHED;
-}
-
static int ringcut_invoke (bContext *C, wmOperator *op, wmEvent *evt)
{
Object *obedit= CTX_data_edit_object(C);
tringselOpData *lcd;
- EditEdge *edge;
+ BMEdge *edge;
int dist = 75;
if(modifiers_isDeformedByLattice(obedit) || modifiers_isDeformedByArmature(obedit))
@@ -418,7 +404,7 @@ static int ringcut_invoke (bContext *C, wmOperator *op, wmEvent *evt)
lcd->vc.mval[0] = evt->mval[0];
lcd->vc.mval[1] = evt->mval[1];
- edge = findnearestedge(&lcd->vc, &dist);
+ edge = EDBM_findnearestedge(&lcd->vc, &dist);
if (edge != lcd->eed) {
lcd->eed = edge;
ringsel_find_edge(lcd, 1);
@@ -428,22 +414,23 @@ static int ringcut_invoke (bContext *C, wmOperator *op, wmEvent *evt)
return OPERATOR_RUNNING_MODAL;
}
-static int ringcut_modal (bContext *C, wmOperator *op, wmEvent *event)
+static int loopcut_modal (bContext *C, wmOperator *op, wmEvent *event)
{
int cuts= RNA_int_get(op->ptr,"number_cuts");
tringselOpData *lcd= op->customdata;
view3d_operator_needs_opengl(C);
-
switch (event->type) {
+ case RETKEY:
case LEFTMOUSE: /* confirm */ // XXX hardcoded
if (event->val == KM_PRESS) {
/* finish */
ED_region_tag_redraw(lcd->ar);
ringsel_finish(C, op);
- ringsel_exit(op);
+ ringsel_exit(C, op);
+
ED_area_headerprint(CTX_wm_area(C), NULL);
return OPERATOR_FINISHED;
@@ -452,6 +439,11 @@ static int ringcut_modal (bContext *C, wmOperator *op, wmEvent *event)
ED_region_tag_redraw(lcd->ar);
break;
case RIGHTMOUSE: /* abort */ // XXX hardcoded
+ ED_region_tag_redraw(lcd->ar);
+ ringsel_exit(C, op);
+ ED_area_headerprint(CTX_wm_area(C), NULL);
+
+ return OPERATOR_FINISHED;
case ESCKEY:
if (event->val == KM_RELEASE) {
/* cancel */
@@ -463,33 +455,35 @@ static int ringcut_modal (bContext *C, wmOperator *op, wmEvent *event)
ED_region_tag_redraw(lcd->ar);
break;
- case WHEELUPMOUSE: /* change number of cuts */
case PAGEUPKEY:
- if (event->val == KM_PRESS) {
- cuts++;
- RNA_int_set(op->ptr, "number_cuts",cuts);
- ringsel_find_edge(lcd, cuts);
-
- ED_region_tag_redraw(lcd->ar);
- }
+ case WHEELUPMOUSE: /* change number of cuts */
+ if (event->val == KM_RELEASE)
+ break;
+
+ cuts++;
+ RNA_int_set(op->ptr,"number_cuts",cuts);
+ ringsel_find_edge(lcd, cuts);
+
+ ED_region_tag_redraw(lcd->ar);
break;
- case WHEELDOWNMOUSE: /* change number of cuts */
case PAGEDOWNKEY:
- if (event->val == KM_PRESS) {
- cuts=MAX2(cuts-1,1);
- RNA_int_set(op->ptr,"number_cuts",cuts);
- ringsel_find_edge(lcd, cuts);
-
- ED_region_tag_redraw(lcd->ar);
- }
+ case WHEELDOWNMOUSE: /* change number of cuts */
+ if (event->val == KM_RELEASE)
+ break;
+
+ cuts=MAX2(cuts-1,1);
+ RNA_int_set(op->ptr,"number_cuts",cuts);
+ ringsel_find_edge(lcd, cuts);
+
+ ED_region_tag_redraw(lcd->ar);
break;
case MOUSEMOVE: { /* mouse moved somewhere to select another loop */
int dist = 75;
- EditEdge *edge;
+ BMEdge *edge;
lcd->vc.mval[0] = event->mval[0];
lcd->vc.mval[1] = event->mval[1];
- edge = findnearestedge(&lcd->vc, &dist);
+ edge = EDBM_findnearestedge(&lcd->vc, &dist);
if (edge != lcd->eed) {
lcd->eed = edge;
@@ -505,23 +499,6 @@ static int ringcut_modal (bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-void MESH_OT_edgering_select (wmOperatorType *ot)
-{
- /* description */
- ot->name= "Edge Ring Select";
- ot->idname= "MESH_OT_edgering_select";
- ot->description= "Select an edge ring";
-
- /* callbacks */
- ot->invoke= ringsel_invoke;
- ot->poll= ED_operator_editmesh_region_view3d;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
-}
-
void MESH_OT_loopcut (wmOperatorType *ot)
{
/* description */
@@ -531,7 +508,7 @@ void MESH_OT_loopcut (wmOperatorType *ot)
/* callbacks */
ot->invoke= ringcut_invoke;
- ot->modal= ringcut_modal;
+ ot->modal= loopcut_modal;
ot->cancel= ringcut_cancel;
ot->poll= ED_operator_editmesh_region_view3d;
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index ed890fd9b90..29e3615a1ae 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -41,6 +41,7 @@
#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
+#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_editVert.h"
#include "BLI_edgehash.h"
@@ -54,6 +55,7 @@
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_report.h"
+#include "BKE_tessmesh.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -70,19 +72,31 @@
#include "mesh_intern.h"
+#define GET_CD_DATA(me, data) (me->edit_btmesh ? &me->edit_btmesh->bm->data : &me->data)
static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *layer)
{
Mesh *me = ob->data;
- CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
+ CustomData *data;
void *actlayerdata, *rndlayerdata, *clonelayerdata, *stencillayerdata, *layerdata=layer->data;
int type= layer->type;
- int index= CustomData_get_layer_index(data, type);
- int i, actindex, rndindex, cloneindex, stencilindex;
+ int index;
+ int i, actindex, rndindex, cloneindex, stencilindex, tot;
+
+ if (layer->type == CD_MLOOPCOL || layer->type == CD_MLOOPUV) {
+ data = (me->edit_btmesh)? &me->edit_btmesh->bm->ldata: &me->ldata;
+ tot = me->totloop;
+ } else {
+ data = (me->edit_btmesh)? &me->edit_btmesh->bm->pdata: &me->pdata;
+ tot = me->totpoly;
+ }
+ index = CustomData_get_layer_index(data, type);
+
/* ok, deleting a non-active layer needs to preserve the active layer indices.
to do this, we store a pointer to the .data member of both layer and the active layer,
(to detect if we're deleting the active layer or not), then use the active
layer data pointer to find where the active layer has ended up.
+
this is necassary because the deletion functions only support deleting the active
layer. */
@@ -92,15 +106,15 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *la
stencillayerdata = data->layers[CustomData_get_stencil_layer_index(data, type)].data;
CustomData_set_layer_active(data, type, layer - &data->layers[index]);
- if(me->edit_mesh) {
- EM_free_data_layer(me->edit_mesh, data, type);
+ if(me->edit_btmesh) {
+ BM_free_data_layer(me->edit_btmesh->bm, data, type);
}
else {
- CustomData_free_layer_active(data, type, me->totface);
+ CustomData_free_layer_active(data, type, tot);
mesh_update_customdata_pointers(me);
}
- if(!CustomData_has_layer(data, type) && (type == CD_MCOL && (ob->mode & OB_MODE_VERTEX_PAINT)))
+ if(!CustomData_has_layer(data, type) && (type == CD_MLOOPCOL && (ob->mode & OB_MODE_VERTEX_PAINT)))
ED_object_toggle_modes(C, OB_MODE_VERTEX_PAINT);
/* reconstruct active layer */
@@ -113,10 +127,12 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *la
break;
}
}
+
/* set index */
CustomData_set_layer_active(data, type, actindex);
}
+
if (rndlayerdata != layerdata) {
/* find index */
@@ -127,10 +143,12 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *la
break;
}
}
+
/* set index */
CustomData_set_layer_render(data, type, rndindex);
}
+
if (clonelayerdata != layerdata) {
/* find index */
@@ -141,10 +159,12 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *la
break;
}
}
+
/* set index */
CustomData_set_layer_clone(data, type, cloneindex);
}
+
if (stencillayerdata != layerdata) {
/* find index */
@@ -155,14 +175,20 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *la
break;
}
}
+
/* set index */
CustomData_set_layer_stencil(data, type, stencilindex);
}
}
-static void copy_editface_active_customdata(EditMesh *em, int type, int index)
+static void copy_editface_active_customdata(BMEditMesh *em, int type, int index)
{
+#if 1 /*BMESH_TODO*/
+ (void)em;
+ (void)type;
+ (void)index;
+#else
EditFace *efa;
int n= CustomData_get_active_layer(&em->fdata, type);
@@ -170,40 +196,56 @@ static void copy_editface_active_customdata(EditMesh *em, int type, int index)
void *data= CustomData_em_get_n(&em->fdata, efa->data, type, n);
CustomData_em_set_n(&em->fdata, efa->data, type, index, data);
}
+#endif
}
int ED_mesh_uv_texture_add(bContext *C, Mesh *me, const char *name, int active_set)
{
- EditMesh *em;
+ BMEditMesh *em;
int layernum;
- if(me->edit_mesh) {
- em= me->edit_mesh;
+ if(me->edit_btmesh) {
+ em= me->edit_btmesh;
- layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
+ layernum= CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
if(layernum >= MAX_MTFACE)
return 0;
- EM_add_data_layer(em, &em->fdata, CD_MTFACE, name);
+ BM_add_data_layer(em->bm, &em->bm->pdata, CD_MTEXPOLY);
+ CustomData_set_layer_active(&em->bm->pdata, CD_MTEXPOLY, layernum);
+ CustomData_set_layer_name(&em->bm->pdata, CD_MTEXPOLY, layernum, name);
if(layernum) /* copy data from active UV */
copy_editface_active_customdata(em, CD_MTFACE, layernum);
if(active_set || layernum==0)
- CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum);
+ CustomData_set_layer_active(&em->bm->pdata, CD_MTEXPOLY, layernum);
+
+ BM_add_data_layer(em->bm, &em->bm->ldata, CD_MLOOPUV);
+ CustomData_set_layer_name(&em->bm->ldata, CD_MLOOPUV, layernum, name);
+
+ CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPUV, layernum);
+ if(active_set || layernum==0)
+ CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPUV, layernum);
}
else {
- layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ layernum= CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
if(layernum >= MAX_MTFACE)
return 0;
- if(me->mtface)
- CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name);
- else
- CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface, name);
-
- if(active_set || layernum==0)
- CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum);
+ if(me->mtpoly) {
+ CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DUPLICATE, me->mtpoly, me->totpoly, name);
+ CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DUPLICATE, me->mloopuv, me->totloop, name);
+ } else {
+ CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, name);
+ CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, name);
+ }
+
+ if(active_set || layernum==0) {
+ CustomData_set_layer_active(&me->pdata, CD_MTEXPOLY, layernum);
+ CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, layernum);
+ }
+
mesh_update_customdata_pointers(me);
}
@@ -216,17 +258,22 @@ int ED_mesh_uv_texture_add(bContext *C, Mesh *me, const char *name, int active_s
int ED_mesh_uv_texture_remove(bContext *C, Object *ob, Mesh *me)
{
- CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
- CustomDataLayer *cdl;
+ CustomData *pdata = GET_CD_DATA(me, pdata), *ldata = GET_CD_DATA(me, ldata);
+ CustomDataLayer *cdlp, *cdlu;
int index;
- index= CustomData_get_active_layer_index(data, CD_MTFACE);
- cdl= (index == -1) ? NULL: &data->layers[index];
+ index= CustomData_get_active_layer_index(pdata, CD_MTEXPOLY);
+ cdlp= (index == -1)? NULL: &pdata->layers[index];
- if(!cdl)
+ index= CustomData_get_active_layer_index(ldata, CD_MLOOPUV);
+ cdlu= (index == -1)? NULL: &ldata->layers[index];
+
+ if (!cdlp || !cdlu)
return 0;
- delete_customdata_layer(C, ob, cdl);
+ delete_customdata_layer(C, ob, cdlp);
+ delete_customdata_layer(C, ob, cdlu);
+
DAG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
@@ -235,36 +282,37 @@ int ED_mesh_uv_texture_remove(bContext *C, Object *ob, Mesh *me)
int ED_mesh_color_add(bContext *C, Scene *UNUSED(scene), Object *UNUSED(ob), Mesh *me, const char *name, int active_set)
{
- EditMesh *em;
+ BMEditMesh *em;
int layernum;
- if(me->edit_mesh) {
- em= me->edit_mesh;
+ if(me->edit_btmesh) {
+ em= me->edit_btmesh;
- layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL);
+ layernum= CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL);
if(layernum >= MAX_MCOL)
return 0;
- EM_add_data_layer(em, &em->fdata, CD_MCOL, name);
+ BM_add_data_layer(em->bm, &em->bm->pdata, CD_MLOOPCOL);
+ CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPCOL, layernum);
if(layernum) /* copy data from active vertex color layer */
copy_editface_active_customdata(em, CD_MCOL, layernum);
if(active_set || layernum==0)
- CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum);
+ CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPCOL, layernum);
}
else {
- layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL);
- if(layernum >= MAX_MCOL)
+ layernum= CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
+ if(layernum >= CD_MLOOPCOL)
return 0;
- if(me->mcol)
- CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface, name);
+ if(me->mloopcol)
+ CustomData_add_layer_named(&me->ldata, CD_MLOOPCOL, CD_DUPLICATE, me->mloopcol, me->totloop, name);
else
- CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface, name);
+ CustomData_add_layer_named(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop, name);
if(active_set || layernum==0)
- CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
+ CustomData_set_layer_active(&me->ldata, CD_MLOOPCOL, layernum);
mesh_update_customdata_pointers(me);
}
@@ -277,12 +325,11 @@ int ED_mesh_color_add(bContext *C, Scene *UNUSED(scene), Object *UNUSED(ob), Mes
int ED_mesh_color_remove(bContext *C, Object *ob, Mesh *me)
{
- CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
CustomDataLayer *cdl;
int index;
- index= CustomData_get_active_layer_index(data, CD_MCOL);
- cdl= (index == -1)? NULL: &data->layers[index];
+ index= CustomData_get_active_layer_index(&me->ldata, CD_MLOOPCOL);
+ cdl= (index == -1)? NULL: &me->ldata.layers[index];
if(!cdl)
return 0;
@@ -320,6 +367,7 @@ void MESH_OT_uv_texture_add(wmOperatorType *ot)
ot->name= "Add UV Texture";
ot->description= "Add UV texture layer";
ot->idname= "MESH_OT_uv_texture_add";
+
/* api callbacks */
ot->poll= layers_poll;
@@ -339,16 +387,19 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event)
Object *obedit;
int exitmode= 0;
char name[32];
+
/* Check context */
if(base==NULL || base->object->type!=OB_MESH) {
BKE_report(op->reports, RPT_ERROR, "Not an Object or Mesh");
return OPERATOR_CANCELLED;
}
+
/* check input variables */
if(RNA_property_is_set(op->ptr, "filepath")) {
char path[FILE_MAX];
+
RNA_string_get(op->ptr, "filepath", path);
ima= BKE_add_image_file(path);
@@ -357,38 +408,42 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event)
RNA_string_get(op->ptr, "name", name);
ima= (Image *)find_id("IM", name);
}
+
if(!ima) {
BKE_report(op->reports, RPT_ERROR, "Not an Image");
return OPERATOR_CANCELLED;
}
+
- /* turn mesh in editmode */
- /* BKE_mesh_get/end_editmesh: ED_uvedit_assign_image also calls this */
+ /* put mesh in editmode */
obedit= base->object;
me= obedit->data;
- if(me->edit_mesh==NULL) {
- make_editMesh(scene, obedit);
+ if(me->edit_btmesh==NULL) {
+ EDBM_MakeEditBMesh(scene->toolsettings, scene, obedit);
exitmode= 1;
}
- if(me->edit_mesh==NULL)
+ if(me->edit_btmesh==NULL)
return OPERATOR_CANCELLED;
+
ED_uvedit_assign_image(scene, obedit, ima, NULL);
if(exitmode) {
- load_editMesh(scene, obedit);
- free_editMesh(me->edit_mesh);
- MEM_freeN(me->edit_mesh);
- me->edit_mesh= NULL;
+ EDBM_LoadEditBMesh(scene, obedit);
+ EDBM_FreeEditBMesh(me->edit_btmesh);
+ MEM_freeN(me->edit_btmesh);
+ me->edit_btmesh= NULL;
}
/* dummie drop support; ensure view shows a result :) */
if(v3d)
v3d->flag2 |= V3D_SOLID_TEX;
+
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
return OPERATOR_FINISHED;
}
@@ -399,13 +454,16 @@ void MESH_OT_drop_named_image(wmOperatorType *ot)
ot->name= "Assign Image to UV Texture";
ot->description= "Assigns Image to active UV layer, or creates a UV layer";
ot->idname= "MESH_OT_drop_named_image";
+
/* api callbacks */
ot->poll= layers_poll;
ot->invoke= drop_named_image_invoke;
+
/* flags */
ot->flag= OPTYPE_UNDO;
+
/* properties */
RNA_def_string(ot->srna, "name", "Image", 24, "Name", "Image name to assign");
@@ -429,6 +487,7 @@ void MESH_OT_uv_texture_remove(wmOperatorType *ot)
ot->name= "Remove UV Texture";
ot->description= "Remove UV texture layer";
ot->idname= "MESH_OT_uv_texture_remove";
+
/* api callbacks */
ot->poll= layers_poll;
@@ -458,6 +517,7 @@ void MESH_OT_vertex_color_add(wmOperatorType *ot)
ot->name= "Add Vertex Color";
ot->description= "Add vertex color layer";
ot->idname= "MESH_OT_vertex_color_add";
+
/* api callbacks */
ot->poll= layers_poll;
@@ -484,6 +544,7 @@ void MESH_OT_vertex_color_remove(wmOperatorType *ot)
ot->name= "Remove Vertex Color";
ot->description= "Remove vertex color layer";
ot->idname= "MESH_OT_vertex_color_remove";
+
/* api callbacks */
ot->exec= vertex_color_remove_exec;
@@ -519,6 +580,7 @@ void MESH_OT_sticky_add(wmOperatorType *ot)
ot->name= "Add Sticky";
ot->description= "Add sticky UV texture layer";
ot->idname= "MESH_OT_sticky_add";
+
/* api callbacks */
ot->poll= layers_poll;
@@ -551,6 +613,7 @@ void MESH_OT_sticky_remove(wmOperatorType *ot)
ot->name= "Remove Sticky";
ot->description= "Remove sticky UV texture layer";
ot->idname= "MESH_OT_sticky_remove";
+
/* api callbacks */
ot->poll= layers_poll;
@@ -564,10 +627,26 @@ void MESH_OT_sticky_remove(wmOperatorType *ot)
void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges)
{
- if(calc_edges || (mesh->totface && mesh->totedge == 0))
+ if(mesh->totface > 0 && mesh->totpoly == 0)
+ convert_mfaces_to_mpolys(mesh);
+
+ if(calc_edges || (mesh->totpoly && mesh->totedge == 0))
BKE_mesh_calc_edges(mesh, calc_edges);
- mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL);
+ mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, NULL, NULL, 0, NULL, NULL);
+
+ mesh->totface = mesh_recalcTesselation(
+ &mesh->fdata,
+ &mesh->ldata,
+ &mesh->pdata,
+ mesh->mvert,
+ mesh->totface,
+ mesh->totloop,
+ mesh->totpoly,
+ 0,
+ 0);
+
+ mesh_update_customdata_pointers(mesh);
DAG_id_tag_update(&mesh->id, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, mesh);
@@ -603,15 +682,15 @@ static void mesh_add_verts(Mesh *mesh, int len)
mesh->totvert= totvert;
}
-void ED_mesh_transform(Mesh *me, float *mat)
+void ED_mesh_transform(Mesh *mesh, float *mat)
{
int i;
- MVert *mvert= me->mvert;
+ MVert *mvert= mesh->mvert;
- for(i= 0; i < me->totvert; i++, mvert++)
+ for(i= 0; i < mesh->totvert; i++, mvert++)
mul_m4_v3((float (*)[4])mat, mvert->co);
- mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+ mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, NULL, NULL, 0, NULL, NULL);
}
static void mesh_add_edges(Mesh *mesh, int len)
@@ -644,6 +723,8 @@ static void mesh_add_edges(Mesh *mesh, int len)
mesh->totedge= totedge;
}
+
+
static void mesh_add_faces(Mesh *mesh, int len)
{
CustomData fdata;
@@ -674,10 +755,64 @@ static void mesh_add_faces(Mesh *mesh, int len)
mesh->totface= totface;
}
+static void mesh_add_loops(Mesh *mesh, int len)
+{
+ CustomData ldata;
+ int totloop;
+
+ if(len == 0)
+ return;
+
+ totloop= mesh->totloop + len; /* new face count */
+
+ /* update customdata */
+ CustomData_copy(&mesh->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloop);
+ CustomData_copy_data(&mesh->ldata, &ldata, 0, 0, mesh->totloop);
+
+ if(!CustomData_has_layer(&ldata, CD_MLOOP))
+ CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop);
+
+ CustomData_free(&mesh->ldata, mesh->totloop);
+ mesh->ldata= ldata;
+ mesh_update_customdata_pointers(mesh);
+
+ mesh->totloop= totloop;
+}
+
+static void mesh_add_polys(Mesh *mesh, int len)
+{
+ CustomData pdata;
+ MPoly *mpoly;
+ int i, totpoly;
+
+ if(len == 0)
+ return;
+
+ totpoly= mesh->totpoly + len; /* new face count */
+
+ /* update customdata */
+ CustomData_copy(&mesh->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpoly);
+ CustomData_copy_data(&mesh->pdata, &pdata, 0, 0, mesh->totpoly);
+
+ if(!CustomData_has_layer(&pdata, CD_MPOLY))
+ CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpoly);
+
+ CustomData_free(&mesh->pdata, mesh->totpoly);
+ mesh->pdata= pdata;
+ mesh_update_customdata_pointers(mesh);
+
+ /* set default flags */
+ mpoly= &mesh->mpoly[mesh->totpoly];
+ for(i=0; i<len; i++, mpoly++)
+ mpoly->flag= ME_FACE_SEL;
+
+ mesh->totpoly= totpoly;
+}
+
/*
void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces)
{
- if(mesh->edit_mesh) {
+ if(mesh->edit_btmesh) {
BKE_report(reports, RPT_ERROR, "Can't add geometry in edit mode");
return;
}
@@ -693,7 +828,7 @@ void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges,
void ED_mesh_faces_add(Mesh *mesh, ReportList *reports, int count)
{
- if(mesh->edit_mesh) {
+ if(mesh->edit_btmesh) {
BKE_report(reports, RPT_ERROR, "Can't add faces in edit mode");
return;
}
@@ -703,17 +838,18 @@ void ED_mesh_faces_add(Mesh *mesh, ReportList *reports, int count)
void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count)
{
- if(mesh->edit_mesh) {
+ if(mesh->edit_btmesh) {
BKE_report(reports, RPT_ERROR, "Can't add edges in edit mode");
- return;
+ return;
}
mesh_add_edges(mesh, count);
}
+
void ED_mesh_vertices_add(Mesh *mesh, ReportList *reports, int count)
{
- if(mesh->edit_mesh) {
+ if(mesh->edit_btmesh) {
BKE_report(reports, RPT_ERROR, "Can't add vertices in edit mode");
return;
}
@@ -721,7 +857,27 @@ void ED_mesh_vertices_add(Mesh *mesh, ReportList *reports, int count)
mesh_add_verts(mesh, count);
}
-void ED_mesh_calc_normals(Mesh *me)
+void ED_mesh_loops_add(Mesh *mesh, ReportList *reports, int count)
+{
+ if(mesh->edit_btmesh) {
+ BKE_report(reports, RPT_ERROR, "Can't add loops in edit mode.");
+ return;
+ }
+
+ mesh_add_loops(mesh, count);
+}
+
+void ED_mesh_polys_add(Mesh *mesh, ReportList *reports, int count)
+{
+ if(mesh->edit_btmesh) {
+ BKE_report(reports, RPT_ERROR, "Can't add polys in edit mode.");
+ return;
+ }
+
+ mesh_add_polys(mesh, count);
+}
+
+void ED_mesh_calc_normals(Mesh *mesh)
{
- mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+ mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, NULL, NULL, 0, NULL, NULL);
}
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 3831d858340..85133349af5 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -35,16 +35,70 @@
#ifndef MESH_INTERN_H
#define MESH_INTERN_H
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BKE_tessmesh.h"
+
+#include "BLI_editVert.h"
+
+#include "RNA_types.h"
+
struct bContext;
struct wmOperatorType;
-struct wmOperator;
struct ViewContext;
+struct BMEditMesh;
+struct BMesh;
+struct BMEdge;
+struct BMFace;
+struct wmOperator;
+struct wmKeyMap;
+struct wmKeyConfig;
+
+/* ******************** bmeshutils.c */
+
+/*
+ok: the EDBM module is for editmode bmesh stuff. in contrast, the
+ BMEdit module is for code shared with blenkernel that concerns
+ the BMEditMesh structure.
+*/
+
+/*calls a bmesh op, reporting errors to the user, etc*/
+int EDBM_CallOpf(struct BMEditMesh *em, struct wmOperator *op, const char *fmt, ...);
+
+/*calls a bmesh op, reporting errors to the user, etc.
+
+ selects an output slot specified by selslot*/
+//int EDBM_CallAndSelectOpf(struct BMEditMesh *em, struct wmOperator *op, char *selslot, char *fmt, ...);
+//moved to ED_mesh.h
+
+/*same as above, but doesn't report errors.*/
+int EDBM_CallOpfSilent(struct BMEditMesh *em, const char *fmt, ...);
+
+/*these next two functions are the split version of EDBM_CallOpf, so you can
+ do stuff with a bmesh operator, after initializing it but before executing
+ it.
+
+ execute the operator with BM_Exec_Op*/
+int EDBM_InitOpf(struct BMEditMesh *em, struct BMOperator *bmop,
+ struct wmOperator *op, const char *fmt, ...);
+/*cleans up after a bmesh operator*/
+int EDBM_FinishOp(struct BMEditMesh *em, struct BMOperator *bmop,
+ struct wmOperator *op, int report);
+
+void EDBM_clear_flag_all(struct BMEditMesh *em, int flag);
+void EDBM_store_selection(struct BMEditMesh *em, void *data);
+void EDBM_validate_selections(struct BMEditMesh *em);
+void EDBM_remove_selection(struct BMEditMesh *em, void *data);
+void EDBM_stats_update(struct BMEditMesh *em);
+
+/* TODO, move to math_geometry.c */
+float labda_PdistVL2Dfl(const float v1[3], const float v2[3], const float v3[3]);
/* ******************** editface.c */
-int edgetag_context_check(Scene *scene, EditEdge *eed);
-void edgetag_context_set(Scene *scene, EditEdge *eed, int val);
-int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge *target);
+
/* ******************* editmesh.c */
@@ -52,6 +106,10 @@ extern void free_editvert(EditMesh *em, EditVert *eve);
extern void free_editedge(EditMesh *em, EditEdge *eed);
extern void free_editface(EditMesh *em, EditFace *efa);
+/*frees dst mesh, then copies the contents of
+ *src (the struct) to dst. */
+void set_editMesh(EditMesh *dst, EditMesh *src);
+
extern void free_vertlist(EditMesh *em, ListBase *edve);
extern void free_edgelist(EditMesh *em, ListBase *lb);
extern void free_facelist(EditMesh *em, ListBase *lb);
@@ -135,13 +193,16 @@ extern struct EditFace *EM_face_from_faces(EditMesh *em, struct EditFace *efa1,
extern int EM_view3d_poll(struct bContext *C);
-/* ******************* editmesh_loop.c */
+struct wmKeyMap* knifetool_modal_keymap(struct wmKeyConfig *keyconf);
+
+/* ******************* knifetool.c */
void MESH_OT_knife_cut(struct wmOperatorType *ot);
-/* ******************* editmesh_mods.c */
+/* ******************* bmesh_select.c */
void MESH_OT_loop_select(struct wmOperatorType *ot);
void MESH_OT_select_all(struct wmOperatorType *ot);
+void MESH_OT_bmesh_test(struct wmOperatorType *ot);
void MESH_OT_select_more(struct wmOperatorType *ot);
void MESH_OT_select_less(struct wmOperatorType *ot);
void MESH_OT_select_inverse(struct wmOperatorType *ot);
@@ -151,6 +212,7 @@ void MESH_OT_select_linked_pick(struct wmOperatorType *ot);
void MESH_OT_hide(struct wmOperatorType *ot);
void MESH_OT_reveal(struct wmOperatorType *ot);
void MESH_OT_select_by_number_vertices(struct wmOperatorType *ot);
+void MESH_OT_select_loose_verts(struct wmOperatorType *ot);
void MESH_OT_select_mirror(struct wmOperatorType *ot);
void MESH_OT_normals_make_consistent(struct wmOperatorType *ot);
void MESH_OT_faces_select_linked_flat(struct wmOperatorType *ot);
@@ -163,32 +225,12 @@ void MESH_OT_mark_seam(struct wmOperatorType *ot);
void MESH_OT_mark_sharp(struct wmOperatorType *ot);
void MESH_OT_vertices_smooth(struct wmOperatorType *ot);
void MESH_OT_noise(struct wmOperatorType *ot);
+void EXPORT_MESH_OT_wavefront(struct wmOperatorType *ot);
void MESH_OT_flip_normals(struct wmOperatorType *ot);
void MESH_OT_solidify(struct wmOperatorType *ot);
void MESH_OT_select_nth(struct wmOperatorType *ot);
-
-
-extern EditEdge *findnearestedge(struct ViewContext *vc, int *dist);
-void editmesh_select_by_material(EditMesh *em, int index);
-void EM_recalc_normal_direction(EditMesh *em, int inside, int select); /* makes faces righthand turning */
-void EM_select_more(EditMesh *em);
-void selectconnected_mesh_all(EditMesh *em);
-void faceloop_select(EditMesh *em, EditEdge *startedge, int select);
-
-/**
- * findnearestvert
- *
- * dist (in/out): minimal distance to the nearest and at the end, actual distance
- * sel: selection bias
- * if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
- * if 0, unselected vertice are given the bias
- * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased
- */
-extern EditVert *findnearestvert(struct ViewContext *vc, int *dist, short sel, short strict);
-
-
-/* ******************* editmesh_tools.c */
-
+void MESH_OT_select_next_loop(struct wmOperatorType *ot);
+
#define SUBDIV_SELECT_ORIG 0
#define SUBDIV_SELECT_INNER 1
#define SUBDIV_SELECT_INNER_SEL 2
@@ -231,9 +273,12 @@ void MESH_OT_region_to_loop(struct wmOperatorType *ot);
void MESH_OT_select_axis(struct wmOperatorType *ot);
void MESH_OT_uvs_rotate(struct wmOperatorType *ot);
-void MESH_OT_uvs_mirror(struct wmOperatorType *ot);
+//void MESH_OT_uvs_mirror(struct wmOperatorType *ot);
+void MESH_OT_uvs_reverse(struct wmOperatorType *ot);
void MESH_OT_colors_rotate(struct wmOperatorType *ot);
-void MESH_OT_colors_mirror(struct wmOperatorType *ot);
+//void MESH_OT_colors_mirror(struct wmOperatorType *ot);
+
+void MESH_OT_colors_reverse(struct wmOperatorType *ot);
void MESH_OT_delete(struct wmOperatorType *ot);
void MESH_OT_rip(struct wmOperatorType *ot);
@@ -252,9 +297,23 @@ void MESH_OT_sticky_add(struct wmOperatorType *ot);
void MESH_OT_sticky_remove(struct wmOperatorType *ot);
void MESH_OT_drop_named_image(struct wmOperatorType *ot);
+/* ************* bmesh_tools.c ***********/
+void MESH_OT_vert_connect(struct wmOperatorType *ot);
+void MESH_OT_edge_split(struct wmOperatorType *ot);
+void MESH_OT_extrude_region(struct wmOperatorType *ot);
+void MESH_OT_extrude_verts_indiv(struct wmOperatorType *ot);
+void MESH_OT_extrude_edges_indiv(struct wmOperatorType *ot);
+void MESH_OT_extrude_faces_indiv(struct wmOperatorType *ot);
+void MESH_OT_bm_test(struct wmOperatorType *ot);
+
void MESH_OT_edgering_select(struct wmOperatorType *ot);
void MESH_OT_loopcut(struct wmOperatorType *ot);
+void MESH_OT_knifetool(struct wmOperatorType *ot);
+void MESH_OT_bevel(struct wmOperatorType *ot);
+
+void MESH_OT_bridge_edge_loops(struct wmOperatorType *ot);
+
/* ******************* mesh_navmesh.c */
void MESH_OT_navmesh_make(struct wmOperatorType *ot);
void MESH_OT_navmesh_face_copy(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index bd067948e59..83abfc9d7b9 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -57,6 +57,7 @@
/**************************** registration **********************************/
+void EXPORT_MESH_OT_wavefront(wmOperatorType *ot);
void ED_operatortypes_mesh(void)
{
WM_operatortype_append(MESH_OT_select_all);
@@ -70,6 +71,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_hide);
WM_operatortype_append(MESH_OT_reveal);
WM_operatortype_append(MESH_OT_select_by_number_vertices);
+ WM_operatortype_append(MESH_OT_select_loose_verts);
WM_operatortype_append(MESH_OT_select_mirror);
WM_operatortype_append(MESH_OT_normals_make_consistent);
WM_operatortype_append(MESH_OT_merge);
@@ -85,16 +87,18 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_primitive_monkey_add);
WM_operatortype_append(MESH_OT_primitive_uv_sphere_add);
WM_operatortype_append(MESH_OT_primitive_ico_sphere_add);
- WM_operatortype_append(MESH_OT_fgon_clear);
- WM_operatortype_append(MESH_OT_fgon_make);
WM_operatortype_append(MESH_OT_duplicate);
WM_operatortype_append(MESH_OT_remove_doubles);
WM_operatortype_append(MESH_OT_vertices_sort);
WM_operatortype_append(MESH_OT_vertices_randomize);
- WM_operatortype_append(MESH_OT_extrude);
WM_operatortype_append(MESH_OT_spin);
WM_operatortype_append(MESH_OT_screw);
-
+
+ WM_operatortype_append(MESH_OT_extrude_region);
+ WM_operatortype_append(MESH_OT_extrude_faces_indiv);
+ WM_operatortype_append(MESH_OT_extrude_edges_indiv);
+ WM_operatortype_append(MESH_OT_extrude_verts_indiv);
+
WM_operatortype_append(MESH_OT_split);
WM_operatortype_append(MESH_OT_extrude_repeat);
WM_operatortype_append(MESH_OT_edge_rotate);
@@ -104,9 +108,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_select_axis);
WM_operatortype_append(MESH_OT_uvs_rotate);
- WM_operatortype_append(MESH_OT_uvs_mirror);
WM_operatortype_append(MESH_OT_colors_rotate);
- WM_operatortype_append(MESH_OT_colors_mirror);
WM_operatortype_append(MESH_OT_fill);
WM_operatortype_append(MESH_OT_beautify_fill);
@@ -131,7 +133,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_vertices_smooth);
WM_operatortype_append(MESH_OT_noise);
WM_operatortype_append(MESH_OT_flip_normals);
- WM_operatortype_append(MESH_OT_knife_cut);
+ //WM_operatortype_append(MESH_OT_knife_cut);
WM_operatortype_append(MESH_OT_rip);
WM_operatortype_append(MESH_OT_blend_from_shape);
WM_operatortype_append(MESH_OT_shape_propagate_to_all);
@@ -149,6 +151,15 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_solidify);
WM_operatortype_append(MESH_OT_select_nth);
+ WM_operatortype_append(MESH_OT_vert_connect);
+ WM_operatortype_append(MESH_OT_knifetool);
+
+ WM_operatortype_append(MESH_OT_bevel);
+
+ WM_operatortype_append(MESH_OT_select_next_loop);
+
+ WM_operatortype_append(EXPORT_MESH_OT_wavefront);
+ WM_operatortype_append(MESH_OT_bridge_edge_loops);
#ifdef WITH_GAMEENGINE
WM_operatortype_append(MESH_OT_navmesh_make);
@@ -164,7 +175,7 @@ static int ED_operator_editmesh_face_select(bContext *C)
{
Object *obedit= CTX_data_edit_object(C);
if(obedit && obedit->type==OB_MESH) {
- EditMesh *em = ((Mesh *)obedit->data)->edit_mesh;
+ BMEditMesh *em = ((Mesh *)obedit->data)->edit_btmesh;
if (em && em->selectmode & SCE_SELECT_FACE) {
return 1;
}
@@ -200,31 +211,28 @@ void ED_operatormacros_mesh(void)
ot= WM_operatortype_append_macro("MESH_OT_extrude_region_move", "Extrude Region and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
ot->description = "Extrude region and move result";
- otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude");
- RNA_enum_set(otmacro->ptr, "type", 1);
+ otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude_region");
otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_enum_set(otmacro->ptr, "proportional", 0);
RNA_boolean_set(otmacro->ptr, "mirror", 0);
ot= WM_operatortype_append_macro("MESH_OT_extrude_faces_move", "Extrude Individual Faces and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
ot->description = "Extrude faces and move result";
- otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude");
- RNA_enum_set(otmacro->ptr, "type", 2);
+ otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude_faces_indiv");
otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_shrink_fatten");
RNA_enum_set(otmacro->ptr, "proportional", 0);
RNA_boolean_set(otmacro->ptr, "mirror", 0);
ot= WM_operatortype_append_macro("MESH_OT_extrude_edges_move", "Extrude Only Edges and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
ot->description = "Extrude edges and move result";
- otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude");
- RNA_enum_set(otmacro->ptr, "type", 3);
+ otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude_edges_indiv");
otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_enum_set(otmacro->ptr, "proportional", 0);
RNA_boolean_set(otmacro->ptr, "mirror", 0);
ot= WM_operatortype_append_macro("MESH_OT_extrude_vertices_move", "Extrude Only Vertices and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
ot->description = "Extrude vertices and move result";
- otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude");
+ otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude_verts_indiv");
RNA_enum_set(otmacro->ptr, "type", 4);
otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_enum_set(otmacro->ptr, "proportional", 0);
@@ -290,6 +298,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_fill", FKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "MESH_OT_beautify_fill", FKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0);
+
WM_keymap_add_item(keymap, "MESH_OT_quads_convert_to_tris", TKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "MESH_OT_tris_convert_to_quads", JKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "MESH_OT_edge_flip", FKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
@@ -307,7 +316,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_menu(keymap, "INFO_MT_mesh_add", AKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "MESH_OT_separate", PKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "MESH_OT_split", YKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "MESH_OT_vert_connect", YKEY, KM_PRESS, 0, 0);
/* use KM_CLICK because same key is used for tweaks */
WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0);
@@ -316,8 +325,8 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_delete", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MESH_OT_delete", DELKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, 0, KKEY);
- RNA_enum_set(WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, KM_SHIFT, KKEY)->ptr, "type", 2/*KNIFE_MIDPOINT*/);
+ WM_keymap_add_item(keymap, "MESH_OT_knifetool", KKEY, KM_PRESS, 0, 0);
+ //RNA_enum_set(WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, KM_SHIFT, KKEY)->ptr, "type", 2/*KNIFE_MIDPOINT*/);
WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
@@ -337,5 +346,6 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
}
ED_object_generic_keymap(keyconf, keymap, 3);
+ knifetool_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 3caafb12f82..3b93ceb7a6d 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -66,6 +66,7 @@
#include "BKE_mesh.h"
#include "BKE_material.h"
#include "BKE_report.h"
+#include "BKE_tessmesh.h"
#include "BKE_multires.h"
#include "BLO_sys_types.h" // for intptr_t support
@@ -79,14 +80,14 @@
/* own include */
#include "mesh_intern.h"
-
+#include "uvedit_intern.h"
/* * ********************** no editmode!!! *********** */
/*********************** JOIN ***************************/
/* join selected meshes into the active mesh, context sensitive
-return 0 if no join is made (error) and 1 of the join is done */
+return 0 if no join is made (error) and 1 if the join is done */
int join_mesh_exec(bContext *C, wmOperator *op)
{
@@ -98,15 +99,17 @@ int join_mesh_exec(bContext *C, wmOperator *op)
MVert *mvert, *mv;
MEdge *medge = NULL;
MFace *mface = NULL;
+ MPoly *mpoly = NULL;
+ MLoop *mloop = NULL;
Key *key, *nkey=NULL;
KeyBlock *kb, *okb, *kbn;
float imat[4][4], cmat[4][4], *fp1, *fp2, curpos;
int a, b, totcol, totmat=0, totedge=0, totvert=0, totface=0, ok=0;
- int vertofs, *matmap=NULL;
- int i, j, index, haskey=0, edgeofs, faceofs;
+ int totloop=0, totpoly=0, vertofs, *matmap=NULL;
+ int i, j, index, haskey=0, edgeofs, faceofs, loopofs, polyofs;
bDeformGroup *dg, *odg;
MDeformVert *dvert;
- CustomData vdata, edata, fdata;
+ CustomData vdata, edata, fdata, ldata, pdata;
if(scene->obedit) {
BKE_report(op->reports, RPT_WARNING, "Cant join while in editmode");
@@ -127,6 +130,8 @@ int join_mesh_exec(bContext *C, wmOperator *op)
totvert+= me->totvert;
totedge+= me->totedge;
totface+= me->totface;
+ totloop+= me->totloop;
+ totpoly+= me->totpoly;
totmat+= base->object->totcol;
if(base->object == ob)
@@ -280,14 +285,20 @@ int join_mesh_exec(bContext *C, wmOperator *op)
memset(&vdata, 0, sizeof(vdata));
memset(&edata, 0, sizeof(edata));
memset(&fdata, 0, sizeof(fdata));
+ memset(&ldata, 0, sizeof(ldata));
+ memset(&pdata, 0, sizeof(pdata));
mvert= CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
medge= CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
mface= CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);
+ mloop= CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop);
+ mpoly= CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpoly);
vertofs= 0;
edgeofs= 0;
faceofs= 0;
+ loopofs= 0;
+ polyofs= 0;
/* inverse transform for all selected meshes in this object */
invert_m4_m4(imat, ob->obmat);
@@ -411,9 +422,6 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
}
- if(base->object!=ob)
- multiresModifier_prepare_join(scene, base->object, ob);
-
CustomData_merge(&me->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface);
CustomData_copy_data(&me->fdata, &fdata, 0, faceofs, me->totface);
@@ -440,14 +448,51 @@ int join_mesh_exec(bContext *C, wmOperator *op)
medge->v1+= vertofs;
medge->v2+= vertofs;
}
+ }
+
+ if (me->totloop) {
+ if(base->object!=ob)
+ multiresModifier_prepare_join(scene, base->object, ob);
- edgeofs += me->totedge;
+ CustomData_merge(&me->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloop);
+ CustomData_copy_data(&me->ldata, &ldata, 0, loopofs, me->totloop);
+
+ for(a=0; a<me->totloop; a++, mloop++) {
+ mloop->v += vertofs;
+ mloop->e += edgeofs;
+ }
}
- /* vertofs is used to help newly added verts be reattached to their edge/face
- * (cannot be set earlier, or else reattaching goes wrong)
+ if(me->totpoly) {
+ /* make mapping for materials */
+ for(a=1; a<=base->object->totcol; a++) {
+ ma= give_current_material(base->object, a);
+
+ for(b=0; b<totcol; b++) {
+ if(ma == matar[b]) {
+ matmap[a-1]= b;
+ break;
+ }
+ }
+ }
+
+ CustomData_merge(&me->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpoly);
+ CustomData_copy_data(&me->pdata, &pdata, 0, polyofs, me->totpoly);
+
+ for(a=0; a<me->totpoly; a++, mpoly++) {
+ mpoly->loopstart += loopofs;
+ mpoly->mat_nr= matmap ? matmap[(int)mpoly->mat_nr] : 0;
+ }
+
+ polyofs += me->totpoly;
+ }
+
+ /* these are used for relinking (cannot be set earlier,
+ * or else reattaching goes wrong)
*/
vertofs += me->totvert;
+ edgeofs += me->totedge;
+ loopofs += me->totloop;
/* free base, now that data is merged */
if(base->object != ob)
@@ -462,14 +507,20 @@ int join_mesh_exec(bContext *C, wmOperator *op)
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
me->totvert= totvert;
me->totedge= totedge;
me->totface= totface;
+ me->totloop= totloop;
+ me->totpoly= totpoly;
me->vdata= vdata;
me->edata= edata;
me->fdata= fdata;
+ me->ldata= ldata;
+ me->pdata= pdata;
mesh_update_customdata_pointers(me);
@@ -528,11 +579,11 @@ int join_mesh_exec(bContext *C, wmOperator *op)
ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR|EM_DO_UNDO);
#else
/* toggle editmode using lower level functions so this can be called from python */
- make_editMesh(scene, ob);
- load_editMesh(scene, ob);
- free_editMesh(me->edit_mesh);
- MEM_freeN(me->edit_mesh);
- me->edit_mesh= NULL;
+ EDBM_MakeEditBMesh(scene->toolsettings, scene, ob);
+ EDBM_LoadEditBMesh(scene, ob);
+ EDBM_FreeEditBMesh(me->edit_btmesh);
+ MEM_freeN(me->edit_btmesh);
+ me->edit_btmesh= NULL;
DAG_id_tag_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA);
#endif
WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
@@ -759,7 +810,7 @@ static struct {
/* mode is 's' start, or 'e' end, or 'u' use */
/* if end, ob can be NULL */
-intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode)
+intptr_t mesh_octree_table(Object *ob, BMEditMesh *em, float *co, char mode)
{
MocNode **bt;
@@ -785,10 +836,11 @@ intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode)
* we are using the undeformed coordinates*/
INIT_MINMAX(min, max);
- if(em && me->edit_mesh==em) {
- EditVert *eve;
+ if(em && me->edit_btmesh==em) {
+ BMIter iter;
+ BMVert *eve;
- for(eve= em->verts.first; eve; eve= eve->next)
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL)
DO_MINMAX(eve->co, min, max)
}
else {
@@ -820,10 +872,11 @@ intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode)
MeshOctree.table= MEM_callocN(MOC_RES*MOC_RES*MOC_RES*sizeof(void *), "sym table");
- if(em && me->edit_mesh==em) {
- EditVert *eve;
+ if(em && me->edit_btmesh==em) {
+ BMVert *eve;
+ BMIter iter;
- for(eve= em->verts.first; eve; eve= eve->next) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
mesh_octree_add_nodes(MeshOctree.table, eve->co, MeshOctree.offs, MeshOctree.div, (intptr_t)(eve));
}
}
@@ -885,27 +938,23 @@ long mesh_mirrtopo_table(Object *ob, char mode)
Mesh *me= ob->data;
if( (mesh_topo_lookup==NULL) ||
(mesh_topo_lookup_mode != ob->mode) ||
- (me->edit_mesh && me->edit_mesh->totvert != mesh_topo_lookup_tot) ||
- (me->edit_mesh==NULL && me->totvert != mesh_topo_lookup_tot)
+ (me->edit_btmesh && me->edit_btmesh->bm->totvert != mesh_topo_lookup_tot) ||
+ (me->edit_btmesh==NULL && me->totvert != mesh_topo_lookup_tot)
) {
mesh_mirrtopo_table(ob, 's');
}
} else if(mode=='s') { /* start table */
Mesh *me= ob->data;
MEdge *medge;
- EditMesh *em= me->edit_mesh;
- void **eve_tmp_back= NULL; /* some of the callers are using eve->tmp so restore after */
-
-
- /* editmode*/
- EditEdge *eed;
-
- int a, last, totvert;
- int totUnique= -1, totUniqueOld= -1;
-
+ BMEditMesh *em= me->edit_btmesh;
+ BMEdge *eed;
+ BMIter iter;
MIRRHASH_TYPE *MirrTopoHash = NULL;
MIRRHASH_TYPE *MirrTopoHash_Prev = NULL;
MirrTopoPair *MirrTopoPairs;
+ int a, last, totvert;
+ int totUnique= -1, totUniqueOld= -1;
+
mesh_topo_lookup_mode= ob->mode;
/* reallocate if needed */
@@ -915,12 +964,12 @@ long mesh_mirrtopo_table(Object *ob, char mode)
}
if(em) {
- EditVert *eve;
+ BMVert *eve;
+
totvert= 0;
- eve_tmp_back= MEM_callocN( em->totvert * sizeof(void *), "TopoMirr" );
- for(eve= em->verts.first; eve; eve= eve->next) {
- eve_tmp_back[totvert]= eve->tmp.p;
- eve->tmp.l = totvert++;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(eve, totvert);
+ totvert++;
}
}
else {
@@ -931,9 +980,9 @@ long mesh_mirrtopo_table(Object *ob, char mode)
/* Initialize the vert-edge-user counts used to detect unique topology */
if(em) {
- for(eed=em->edges.first; eed; eed= eed->next) {
- MirrTopoHash[eed->v1->tmp.l]++;
- MirrTopoHash[eed->v2->tmp.l]++;
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ MirrTopoHash[BM_GetIndex(eed->v1)]++;
+ MirrTopoHash[BM_GetIndex(eed->v2)]++;
}
} else {
for(a=0, medge=me->medge; a<me->totedge; a++, medge++) {
@@ -949,9 +998,9 @@ long mesh_mirrtopo_table(Object *ob, char mode)
/* use the number of edges per vert to give verts unique topology IDs */
if(em) {
- for(eed=em->edges.first; eed; eed= eed->next) {
- MirrTopoHash[eed->v1->tmp.l] += MirrTopoHash_Prev[eed->v2->tmp.l];
- MirrTopoHash[eed->v2->tmp.l] += MirrTopoHash_Prev[eed->v1->tmp.l];
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ MirrTopoHash[BM_GetIndex(eed->v1)] += MirrTopoHash_Prev[BM_GetIndex(eed->v2)];
+ MirrTopoHash[BM_GetIndex(eed->v2)] += MirrTopoHash_Prev[BM_GetIndex(eed->v1)];
}
} else {
for(a=0, medge=me->medge; a<me->totedge; a++, medge++) {
@@ -983,19 +1032,6 @@ long mesh_mirrtopo_table(Object *ob, char mode)
memcpy(MirrTopoHash_Prev, MirrTopoHash, sizeof(MIRRHASH_TYPE) * totvert);
}
- /* restore eve->tmp.* */
- if(eve_tmp_back) {
- EditVert *eve;
- totvert= 0;
- for(eve= em->verts.first; eve; eve= eve->next) {
- eve->tmp.p= eve_tmp_back[totvert++];
- }
-
- MEM_freeN(eve_tmp_back);
- eve_tmp_back= NULL;
- }
-
-
/* Hash/Index pairs are needed for sorting to find index pairs */
MirrTopoPairs= MEM_callocN( sizeof(MirrTopoPair) * totvert, "MirrTopoPairs");
@@ -1003,7 +1039,7 @@ long mesh_mirrtopo_table(Object *ob, char mode)
mesh_topo_lookup = MEM_mallocN( totvert * sizeof(long), "mesh_topo_lookup" );
if(em) {
- EM_init_index_arrays(em,1,0,0);
+ EDBM_init_index_arrays(em,1,0,0);
}
@@ -1027,8 +1063,8 @@ long mesh_mirrtopo_table(Object *ob, char mode)
if ((a==totvert) || (MirrTopoPairs[a-1].hash != MirrTopoPairs[a].hash)) {
if (a-last==2) {
if(em) {
- mesh_topo_lookup[MirrTopoPairs[a-1].vIndex] = (long)EM_get_vert_for_index(MirrTopoPairs[a-2].vIndex);
- mesh_topo_lookup[MirrTopoPairs[a-2].vIndex] = (long)EM_get_vert_for_index(MirrTopoPairs[a-1].vIndex);
+ mesh_topo_lookup[MirrTopoPairs[a-1].vIndex] = (long)EDBM_get_vert_for_index(em, MirrTopoPairs[a-2].vIndex);
+ mesh_topo_lookup[MirrTopoPairs[a-2].vIndex] = (long)EDBM_get_vert_for_index(em, MirrTopoPairs[a-1].vIndex);
} else {
mesh_topo_lookup[MirrTopoPairs[a-1].vIndex] = MirrTopoPairs[a-2].vIndex;
mesh_topo_lookup[MirrTopoPairs[a-2].vIndex] = MirrTopoPairs[a-1].vIndex;
@@ -1038,7 +1074,7 @@ long mesh_mirrtopo_table(Object *ob, char mode)
}
}
if(em) {
- EM_free_index_arrays();
+ EDBM_free_index_arrays(em);
}
MEM_freeN( MirrTopoPairs );
@@ -1088,9 +1124,10 @@ int mesh_get_x_mirror_vert(Object *ob, int index)
} else {
return mesh_get_x_mirror_vert_spacial(ob, index);
}
+ return 0;
}
-static EditVert *editmesh_get_x_mirror_vert_spacial(Object *ob, EditMesh *em, float *co)
+static BMVert *editbmesh_get_x_mirror_vert_spacial(Object *ob, BMEditMesh *em, float *co)
{
float vec[3];
intptr_t poinval;
@@ -1108,20 +1145,28 @@ static EditVert *editmesh_get_x_mirror_vert_spacial(Object *ob, EditMesh *em, fl
poinval= mesh_octree_table(ob, em, vec, 'u');
if(poinval != -1)
- return (EditVert *)(poinval);
+ return (BMVert *)(poinval);
return NULL;
}
-static EditVert *editmesh_get_x_mirror_vert_topo(Object *ob, struct EditMesh *em, EditVert *eve, int index)
+static BMVert *editbmesh_get_x_mirror_vert_topo(Object *ob, struct BMEditMesh *em, BMVert *eve, int index)
{
long poinval;
if (mesh_mirrtopo_table(ob, 'u')==-1)
return NULL;
if (index == -1) {
- index = BLI_findindex(&em->verts, eve);
-
- if (index == -1) {
+ BMIter iter;
+ BMVert *v;
+
+ index = 0;
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (v == eve)
+ break;
+ index++;
+ }
+
+ if (index == em->bm->totvert) {
return NULL;
}
}
@@ -1129,22 +1174,23 @@ static EditVert *editmesh_get_x_mirror_vert_topo(Object *ob, struct EditMesh *em
poinval= mesh_topo_lookup[ index ];
if(poinval != -1)
- return (EditVert *)(poinval);
+ return (BMVert *)(poinval);
return NULL;
}
-EditVert *editmesh_get_x_mirror_vert(Object *ob, struct EditMesh *em, EditVert *eve, float *co, int index)
+BMVert *editbmesh_get_x_mirror_vert(Object *ob, struct BMEditMesh *em, BMVert *eve, float *co, int index)
{
+ //BMESH_TODO use this flag, ME_EDIT_MIRROR_TOPO, at appropriate places
if (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_TOPO) {
- return editmesh_get_x_mirror_vert_topo(ob, em, eve, index);
+ return editbmesh_get_x_mirror_vert_topo(ob, em, eve, index);
} else {
- return editmesh_get_x_mirror_vert_spacial(ob, em, co);
+ return editbmesh_get_x_mirror_vert_spacial(ob, em, co);
}
}
-#if 0
-float *editmesh_get_mirror_uv(int axis, float *uv, float *mirrCent, float *face_cent)
+
+static float *editmesh_get_mirror_uv(BMEditMesh *em, int axis, float *uv, float *mirrCent, float *face_cent)
{
float vec[2];
float cent_vec[2];
@@ -1172,26 +1218,29 @@ float *editmesh_get_mirror_uv(int axis, float *uv, float *mirrCent, float *face_
/* TODO - Optimize */
{
- EditFace *efa;
- int i, len;
- for(efa=em->faces.first; efa; efa=efa->next) {
- MTFace *tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- uv_center(tf->uv, cent, (void *)efa->v4);
-
+ BMIter iter;
+ BMFace *efa;
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ poly_uv_center(em, efa, cent);
+
if ( (fabs(cent[0] - cent_vec[0]) < 0.001) && (fabs(cent[1] - cent_vec[1]) < 0.001) ) {
- len = efa->v4 ? 4 : 3;
- for (i=0; i<len; i++) {
- if ( (fabs(tf->uv[i][0] - vec[0]) < 0.001) && (fabs(tf->uv[i][1] - vec[1]) < 0.001) ) {
- return tf->uv[i];
- }
+ BMIter liter;
+ BMLoop *l;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if ( (fabs(luv->uv[0] - vec[0]) < 0.001) && (fabs(luv->uv[1] - vec[1]) < 0.001) ) {
+ return luv->uv;
+
}
}
}
}
+ }
return NULL;
}
-#endif
static unsigned int mirror_facehash(const void *ptr)
{
@@ -1239,7 +1288,7 @@ static int mirror_facecmp(const void *a, const void *b)
return (mirror_facerotation((MFace*)a, (MFace*)b) == -1);
}
-int *mesh_get_x_mirror_faces(Object *ob, EditMesh *em)
+int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em)
{
Mesh *me= ob->data;
MVert *mv, *mvert= me->mvert;
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index f69f91cd08f..84a466a3d5b 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -554,7 +554,7 @@ static void freeMetaElemlist(ListBase *lb)
}
-static void undoMball_to_editMball(void *lbu, void *lbe)
+static void undoMball_to_editMball(void *lbu, void *lbe, void *UNUSED(obe))
{
ListBase *lb= lbu;
ListBase *editelems= lbe;
@@ -572,7 +572,7 @@ static void undoMball_to_editMball(void *lbu, void *lbe)
}
-static void *editMball_to_undoMball(void *lbe)
+static void *editMball_to_undoMball(void *lbe, void *UNUSED(obe))
{
ListBase *editelems= lbe;
ListBase *lb;
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index e7232524a21..05c042a4182 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenkernel
../../blenlib
../../blenloader
+ ../../bmesh
../../gpu
../../ikplugin
../../imbuf
diff --git a/source/blender/editors/object/SConscript b/source/blender/editors/object/SConscript
index d4739236ba1..883d0ca20ae 100644
--- a/source/blender/editors/object/SConscript
+++ b/source/blender/editors/object/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc ../../blenloader'
-incs += ' ../../makesrna ../../python ../../ikplugin'
+incs += ' ../../makesrna ../../python ../../ikplugin ../../bmesh'
incs += ' ../../render/extern/include ../../gpu' # for object_bake.c
incs += ' #extern/recastnavigation'
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 452e7e4857c..c5fecfe23ab 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -239,7 +239,8 @@ int ED_object_add_generic_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(ev
return op->type->exec(C, op);
}
-int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float *loc, float *rot, int *enter_editmode, unsigned int *layer)
+int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float *loc,
+ float *rot, int *enter_editmode, unsigned int *layer, int *is_view_aligned)
{
View3D *v3d = CTX_wm_view3d(C);
int a, layer_values[20];
@@ -287,7 +288,9 @@ int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float *loc, floa
else
RNA_float_get_array(op->ptr, "rotation", rot);
-
+ if (is_view_aligned)
+ *is_view_aligned = view_align;
+
RNA_float_get_array(op->ptr, "location", loc);
if(*layer == 0) {
@@ -300,7 +303,8 @@ int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float *loc, floa
/* for object add primitive operators */
/* do not call undo push in this function (users of this function have to) */
-Object *ED_object_add_type(bContext *C, int type, float *loc, float *rot, int enter_editmode, unsigned int layer)
+Object *ED_object_add_type(bContext *C, int type, float *loc, float *rot,
+ int enter_editmode, unsigned int layer)
{
Main *bmain= CTX_data_main(C);
Scene *scene= CTX_data_scene(C);
@@ -337,7 +341,7 @@ static int object_add_exec(bContext *C, wmOperator *op)
unsigned int layer;
float loc[3], rot[3];
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+ if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), loc, rot, enter_editmode, layer);
@@ -394,7 +398,7 @@ static Object *effector_add_type(bContext *C, wmOperator *op, int type)
object_add_generic_invoke_options(C, op);
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+ if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
return NULL;
if(type==PFIELD_GUIDE) {
@@ -474,7 +478,7 @@ static int object_camera_add_exec(bContext *C, wmOperator *op)
object_add_generic_invoke_options(C, op);
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+ if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
ob= ED_object_add_type(C, OB_CAMERA, loc, rot, FALSE, layer);
@@ -528,7 +532,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op)
object_add_generic_invoke_options(C, op); // XXX these props don't get set right when only exec() is called
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+ if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
if(obedit==NULL || obedit->type!=OB_MBALL) {
@@ -597,7 +601,7 @@ static int object_add_text_exec(bContext *C, wmOperator *op)
float loc[3], rot[3];
object_add_generic_invoke_options(C, op); // XXX these props don't get set right when only exec() is called
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+ if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
if(obedit && obedit->type==OB_FONT)
@@ -638,7 +642,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op)
float loc[3], rot[3];
object_add_generic_invoke_options(C, op); // XXX these props don't get set right when only exec() is called
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+ if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
if ((obedit==NULL) || (obedit->type != OB_ARMATURE)) {
@@ -704,7 +708,7 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op)
float loc[3], rot[3];
object_add_generic_invoke_options(C, op);
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+ if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
ob= ED_object_add_type(C, OB_LAMP, loc, rot, FALSE, layer);
@@ -753,7 +757,7 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
float loc[3], rot[3];
object_add_generic_invoke_options(C, op);
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+ if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
if(group) {
@@ -785,7 +789,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
object_add_generic_invoke_options(C, op);
- if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+ if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
ob= ED_object_add_type(C, OB_SPEAKER, loc, rot, FALSE, layer);
@@ -1240,7 +1244,11 @@ static int convert_exec(bContext *C, wmOperator *op)
dm= mesh_get_derived_final(scene, newob, CD_MASK_MESH);
/* dm= mesh_create_derived_no_deform(ob1, NULL); this was called original (instead of get_derived). man o man why! (ton) */
- DM_to_mesh(dm, newob->data);
+ DM_to_mesh(dm, newob->data, newob);
+
+ /* re-tesselation doesn't happen automatic, calling like this is */
+ me= newob->data;
+ me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata, me->mvert, me->totface, me->totloop, me->totpoly, 0, 0);
dm->release(dm);
object_free_modifiers(newob); /* after derivedmesh calls! */
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index e29dfaa0a23..251a86cf996 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -358,6 +358,16 @@ static int multiresbake_test_break(MultiresBakeRender *bkr)
static void do_multires_bake(MultiresBakeRender *bkr, Image* ima, MPassKnownData passKnownData,
MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData)
{
+#if 1 // BMESH_TODO
+ (void)bkr;
+ (void)ima;
+ (void)passKnownData;
+ (void)initBakeData;
+ (void)applyBakeData;
+ (void)freeBakeData;
+
+ printf("BMESH_TODO" AT "\n");
+#else
DerivedMesh *dm= bkr->lores_dm;
ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
const int lvl= bkr->lvl;
@@ -440,6 +450,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image* ima, MPassKnownData
if(freeBakeData)
freeBakeData(data.bake_data);
}
+#endif // BMESH_TODO
}
static void interp_bilinear_quad_data(float data[4][3], float u, float v, float res[3])
@@ -502,6 +513,16 @@ static void interp_bilinear_grid(DMGridData *grid, int grid_size, float crn_x, f
static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, const int lvl, const int face_index, const float u, const float v, float co[3], float n[3])
{
+#if 1 // BMESH_TODO
+ (void)lodm;
+ (void)hidm;
+ (void)lvl;
+ (void)face_index;
+ (void)u;
+ (void)v;
+ (void)co;
+ (void)n;
+#else
MFace mface;
DMGridData **grid_data;
float crn_x, crn_y;
@@ -544,6 +565,7 @@ static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, const int lvl,
if(co != NULL)
interp_bilinear_grid(grid_data[g_index + S], grid_size, crn_x, crn_y, 1, co);
+#endif
}
/* mode = 0: interpolate normals,
@@ -673,6 +695,16 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm,
const int face_index, const int lvl, const float st[2],
float UNUSED(tangmat[3][3]), const int x, const int y)
{
+#if 1 // BMESH_TODO
+ (void)lores_dm;
+ (void)hires_dm;
+ (void)bake_data;
+ (void)face_index;
+ (void)lvl;
+ (void)st;
+ (void)x;
+ (void)y;
+#else
MTFace *mtface= CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
MFace mface;
Image *ima= mtface[face_index].tpage;
@@ -732,6 +764,7 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm,
char *rrgb= (char*)ibuf->rect + pixel*4;
rrgb[3]= 255;
}
+#endif // BMESH_TODO
}
/* MultiresBake callback for normals' baking
@@ -743,6 +776,16 @@ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm,
const int face_index, const int lvl, const float st[2],
float tangmat[3][3], const int x, const int y)
{
+#if 1 // BMESH_TODO
+ (void)lores_dm;
+ (void)hires_dm;
+ (void)face_index;
+ (void)lvl;
+ (void)st;
+ (void)tangmat;
+ (void)y;
+ (void)x;
+#else
MTFace *mtface= CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
MFace mface;
Image *ima= mtface[face_index].tpage;
@@ -788,6 +831,7 @@ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm,
rrgb[2]= FTOCHAR(vec[2]);
rrgb[3]= 255;
}
+#endif
}
static void count_images(MultiresBakeRender *bkr)
@@ -974,7 +1018,7 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l
if(*lvl==0) {
DerivedMesh *tmp_dm= CDDM_from_mesh(me, ob);
- dm= CDDM_copy(tmp_dm);
+ dm= CDDM_copy(tmp_dm, 0);
tmp_dm->release(tmp_dm);
} else {
MultiresModifierData tmp_mmd= *mmd;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 04272b48d51..6dc03380027 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -79,6 +79,7 @@
#include "BKE_sca.h"
#include "BKE_softbody.h"
#include "BKE_modifier.h"
+#include "BKE_tessmesh.h"
#include "ED_armature.h"
#include "ED_curve.h"
@@ -319,22 +320,24 @@ void ED_object_exit_editmode(bContext *C, int flag)
// if(retopo_mesh_paint_check())
// retopo_end_okee();
- if(me->edit_mesh->totvert>MESH_MAX_VERTS) {
+ if(me->edit_btmesh->bm->totvert>MESH_MAX_VERTS) {
error("Too many vertices");
return;
}
- load_editMesh(scene, obedit);
+
+ EDBM_LoadEditBMesh(scene, obedit);
if(freedata) {
- free_editMesh(me->edit_mesh);
- MEM_freeN(me->edit_mesh);
- me->edit_mesh= NULL;
+ EDBM_FreeEditBMesh(me->edit_btmesh);
+ MEM_freeN(me->edit_btmesh);
+ me->edit_btmesh= NULL;
}
-
+#if 0 //BMESH_TODO
if(obedit->restore_mode & OB_MODE_WEIGHT_PAINT) {
mesh_octree_table(NULL, NULL, NULL, 'e');
mesh_mirrtopo_table(NULL, 'e');
}
+#endif
}
else if (obedit->type==OB_ARMATURE) {
ED_armature_from_edit(obedit);
@@ -443,7 +446,7 @@ void ED_object_enter_editmode(bContext *C, int flag)
ok= 1;
scene->obedit= ob; // context sees this
- make_editMesh(scene, ob);
+ EDBM_MakeEditBMesh(CTX_data_tool_settings(C), scene, ob);
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MESH, scene);
}
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 5bb1b634fe0..bc1950cd057 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -55,6 +55,7 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_deform.h"
+#include "BKE_tessmesh.h"
#include "RNA_define.h"
#include "RNA_access.h"
@@ -71,13 +72,14 @@
#include "object_intern.h"
-static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float *cent)
+static int return_editmesh_indexar(BMEditMesh *em, int *tot, int **indexar, float *cent)
{
- EditVert *eve;
+ BMVert *eve;
+ BMIter iter;
int *index, nr, totvert=0;
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) totvert++;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if(BM_TestHFlag(eve, BM_SELECT)) totvert++;
}
if(totvert==0) return 0;
@@ -86,8 +88,8 @@ static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float
nr= 0;
zero_v3(cent);
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if(BM_TestHFlag(eve, BM_SELECT)) {
*index= nr; index++;
add_v3_v3(cent, eve->co);
}
@@ -99,7 +101,7 @@ static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float
return totvert;
}
-static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, float *cent)
+static int return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *name, float *cent)
{
zero_v3(cent);
@@ -108,11 +110,12 @@ static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, floa
int totvert=0;
MDeformVert *dvert;
- EditVert *eve;
+ BMVert *eve;
+ BMIter iter;
/* find the vertices */
- for(eve= em->verts.first; eve; eve= eve->next) {
- dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
if(dvert) {
if(defvert_find_weight(dvert, defgrp_index) > 0.0f) {
@@ -132,25 +135,27 @@ static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, floa
return 0;
}
-static void select_editmesh_hook(Object *ob, HookModifierData *hmd)
+static void select_editbmesh_hook(Object *ob, HookModifierData *hmd)
{
Mesh *me= ob->data;
- EditMesh *em= BKE_mesh_get_editmesh(me);
- EditVert *eve;
+ BMEditMesh *em= me->edit_btmesh;
+ BMVert *eve;
+ BMIter iter;
int index=0, nr=0;
if (hmd->indexar == NULL)
return;
- for(eve= em->verts.first; eve; eve= eve->next, nr++) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
if(nr==hmd->indexar[index]) {
- eve->f |= SELECT;
+ BM_Select(em->bm, eve, 1);
if(index < hmd->totindex-1) index++;
}
+
+ nr++;
}
- EM_select_flush(em);
- BKE_mesh_end_editmesh(me, em);
+ EDBM_selectmode_flush(em);
}
static int return_editlattice_indexar(Lattice *editlatt, int *tot, int **indexar, float *cent)
@@ -300,20 +305,19 @@ static int object_hook_index_array(Scene *scene, Object *obedit, int *tot, int *
case OB_MESH:
{
Mesh *me= obedit->data;
- EditMesh *em;
- load_editMesh(scene, obedit);
- make_editMesh(scene, obedit);
+ BMEditMesh *em;
- em = BKE_mesh_get_editmesh(me);
+ EDBM_LoadEditBMesh(scene, obedit);
+ EDBM_MakeEditBMesh(scene->toolsettings, scene, obedit);
+
+ em = me->edit_btmesh;
/* check selected vertices first */
if( return_editmesh_indexar(em, tot, indexar, cent_r)) {
- BKE_mesh_end_editmesh(me, em);
return 1;
} else {
int ret = return_editmesh_vgroup(obedit, em, name, cent_r);
- BKE_mesh_end_editmesh(me, em);
return ret;
}
}
@@ -382,7 +386,7 @@ static void object_hook_select(Object *ob, HookModifierData *hmd)
if (hmd->indexar == NULL)
return;
- if(ob->type==OB_MESH) select_editmesh_hook(ob, hmd);
+ if(ob->type==OB_MESH) select_editbmesh_hook(ob, hmd);
else if(ob->type==OB_LATTICE) select_editlattice_hook(ob, hmd);
else if(ob->type==OB_CURVE) select_editcurve_hook(ob, hmd);
else if(ob->type==OB_SURF) select_editcurve_hook(ob, hmd);
@@ -740,6 +744,7 @@ void OBJECT_OT_hook_recenter(wmOperatorType *ot)
static int object_hook_assign_exec(bContext *C, wmOperator *op)
{
+ Scene *scene= CTX_data_scene(C);
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
int num= RNA_enum_get(op->ptr, "modifier");
Object *ob=NULL;
@@ -763,7 +768,7 @@ static int object_hook_assign_exec(bContext *C, wmOperator *op)
/* assign functionality */
- if(!object_hook_index_array(CTX_data_scene(C), ob, &tot, &indexar, name, cent)) {
+ if(!object_hook_index_array(scene, ob, &tot, &indexar, name, cent)) {
BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index a6e8d4a0a3a..b0f4304ea89 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -159,6 +159,7 @@ void OBJECT_OT_multires_external_save(struct wmOperatorType *ot);
void OBJECT_OT_multires_external_pack(struct wmOperatorType *ot);
void OBJECT_OT_meshdeform_bind(struct wmOperatorType *ot);
void OBJECT_OT_explode_refresh(struct wmOperatorType *ot);
+void OBJECT_OT_test_multires(struct wmOperatorType *ot);
/* object_constraint.c */
void OBJECT_OT_constraint_add(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c
index 7585018dfd2..2dc321d482a 100644
--- a/source/blender/editors/object/object_lattice.c
+++ b/source/blender/editors/object/object_lattice.c
@@ -365,7 +365,7 @@ typedef struct UndoLattice {
int pntsu, pntsv, pntsw;
} UndoLattice;
-static void undoLatt_to_editLatt(void *data, void *edata)
+static void undoLatt_to_editLatt(void *data, void *edata, void *UNUSED(obdata))
{
UndoLattice *ult= (UndoLattice*)data;
EditLatt *editlatt= (EditLatt *)edata;
@@ -374,7 +374,7 @@ static void undoLatt_to_editLatt(void *data, void *edata)
memcpy(editlatt->latt->def, ult->def, a*sizeof(BPoint));
}
-static void *editLatt_to_undoLatt(void *edata)
+static void *editLatt_to_undoLatt(void *edata, void *UNUSED(obdata))
{
UndoLattice *ult= MEM_callocN(sizeof(UndoLattice), "UndoLattice");
EditLatt *editlatt= (EditLatt *)edata;
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 129d9df86a5..00faf86c866 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -65,6 +65,7 @@
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_softbody.h"
+#include "BKE_tessmesh.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -214,15 +215,15 @@ int ED_object_modifier_remove(ReportList *reports, Main *bmain, Scene *scene, Ob
}
if(ok) {
- if(me->edit_mesh) {
- EditMesh *em= me->edit_mesh;
+ if(me->edit_btmesh) {
+ BMEditMesh *em= me->edit_btmesh;
/* CustomData_external_remove is used here only to mark layer as non-external
for further free-ing, so zero element count looks safer than em->totface */
- CustomData_external_remove(&em->fdata, &me->id, CD_MDISPS, 0);
- EM_free_data_layer(em, &em->fdata, CD_MDISPS);
+ CustomData_external_remove(&em->bm->ldata, &me->id, CD_MDISPS, 0);
+ BM_free_data_layer(em->bm, &em->bm->ldata, CD_MDISPS);
} else {
- CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
- CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
+ CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
+ CustomData_free_layer_active(&me->ldata, CD_MDISPS, me->totloop);
}
}
}
@@ -406,6 +407,17 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M
return 0;
}
+ /*
+ It should be ridiculously easy to extract the original verts that we want
+ and form the shape data. We can probably use the CD KEYINDEX layer (or
+ whatever I ended up calling it, too tired to check now), though this would
+ by necassity have to make some potentially ugly assumptions about the order
+ of the mesh data :-/ you can probably assume in 99% of cases that the first
+ element of a given index is the original, and any subsequent duplicates are
+ copies/interpolates, but that's an assumption that would need to be tested
+ and then predominantly stated in comments in a half dozen headers.
+ */
+
if (ob->type==OB_MESH) {
DerivedMesh *dm;
Mesh *me= ob->data;
@@ -418,7 +430,7 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M
}
mesh_pmv_off(me);
- dm = mesh_create_derived_for_modifier(scene, ob, md);
+ dm = mesh_create_derived_for_modifier(scene, ob, md, 0);
if (!dm) {
BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
return 0;
@@ -478,19 +490,19 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob,
return 0;
}
} else {
- dm = mesh_create_derived_for_modifier(scene, ob, md);
+ dm = mesh_create_derived_for_modifier(scene, ob, md, 1);
if (!dm) {
BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
return 0;
}
- DM_to_mesh(dm, me);
+ DM_to_mesh(dm, me, ob);
dm->release(dm);
if(md->type == eModifierType_Multires) {
- CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
- CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
+ CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
+ CustomData_free_layer_active(&me->ldata, CD_MDISPS, me->totloop);
}
}
}
@@ -1117,6 +1129,66 @@ void OBJECT_OT_multires_reshape(wmOperatorType *ot)
edit_modifier_properties(ot);
}
+static int multires_test_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= ED_object_active_context(C);
+ Mesh *me = ob->data;
+ MPoly *mp;
+ MDisps *mdisps;
+ int i, x = RNA_int_get(op->ptr, "x"), y = RNA_int_get(op->ptr, "y");
+
+ if (ob->type != OB_MESH || !me)
+ return OPERATOR_CANCELLED;
+
+ mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
+ if (!mdisps)
+ return OPERATOR_CANCELLED;
+
+ mp = me->mpoly;
+ for (i=0; i<me->totpoly; i++, mp++) {
+ MLoop *ml;
+ int j;
+
+ ml = me->mloop + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ MLoop *ml2 = me->mloop + mp->loopstart + (j+mp->totloop-1)%mp->totloop;
+ MLoop *ml3 = me->mloop + mp->loopstart + (j+1)%mp->totloop;
+
+ if ((me->mvert[ml->v].flag&SELECT) && (me->mvert[ml2->v].flag&SELECT) && (me->mvert[ml3->v].flag&SELECT)) {
+ MDisps *md = mdisps + mp->loopstart + j;
+ int res = sqrt(md->totdisp);
+
+ if (x >= res) x = res-1;
+ if (y >= res) y = res-1;
+
+ md->disps[y*res + x][2] += 1.0;
+ }
+ }
+ }
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_test_multires(wmOperatorType *ot)
+{
+ ot->name= "Multires Object Mode Test";
+ ot->description= "";
+ ot->idname= "OBJECT_OT_test_multires";
+
+ ot->poll= multires_poll;
+ ot->exec= multires_test_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+ RNA_def_int(ot->srna, "x", 0, 0, 100, "x", "x", 0, 100);
+ RNA_def_int(ot->srna, "y", 0, 0, 100, "y", "y", 0, 100);
+}
+
+
+
/****************** multires save external operator *********************/
static int multires_external_save_exec(bContext *C, wmOperator *op)
@@ -1129,7 +1201,7 @@ static int multires_external_save_exec(bContext *C, wmOperator *op)
if(!me)
return OPERATOR_CANCELLED;
- if(CustomData_external_test(&me->fdata, CD_MDISPS))
+ if(CustomData_external_test(&me->ldata, CD_MDISPS))
return OPERATOR_CANCELLED;
RNA_string_get(op->ptr, "filepath", path);
@@ -1137,8 +1209,8 @@ static int multires_external_save_exec(bContext *C, wmOperator *op)
if(relative)
BLI_path_rel(path, G.main->name);
- CustomData_external_add(&me->fdata, &me->id, CD_MDISPS, me->totface, path);
- CustomData_external_write(&me->fdata, &me->id, CD_MASK_MESH, me->totface, 0);
+ CustomData_external_add(&me->ldata, &me->id, CD_MDISPS, me->totloop, path);
+ CustomData_external_write(&me->ldata, &me->id, CD_MASK_MESH, me->totloop, 0);
return OPERATOR_FINISHED;
}
@@ -1158,7 +1230,7 @@ static int multires_external_save_invoke(bContext *C, wmOperator *op, wmEvent *U
if (!mmd)
return OPERATOR_CANCELLED;
- if(CustomData_external_test(&me->fdata, CD_MDISPS))
+ if(CustomData_external_test(&me->ldata, CD_MDISPS))
return OPERATOR_CANCELLED;
if(RNA_property_is_set(op->ptr, "filepath"))
@@ -1199,11 +1271,11 @@ static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = ED_object_active_context(C);
Mesh *me= ob->data;
- if(!CustomData_external_test(&me->fdata, CD_MDISPS))
+ if(!CustomData_external_test(&me->ldata, CD_MDISPS))
return OPERATOR_CANCELLED;
// XXX don't remove..
- CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
+ CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
return OPERATOR_FINISHED;
}
@@ -1403,4 +1475,3 @@ void OBJECT_OT_explode_refresh(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
edit_modifier_properties(ot);
}
-
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 2df49570ee4..fb403d92d93 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -212,8 +212,9 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_bake_image);
WM_operatortype_append(OBJECT_OT_drop_named_material);
-}
+ WM_operatortype_append(OBJECT_OT_test_multires);
+}
void ED_operatormacros_object(void)
{
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 7c049692b40..78c2b3ad01e 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -76,6 +76,7 @@
#include "BKE_scene.h"
#include "BKE_speaker.h"
#include "BKE_texture.h"
+#include "BKE_tessmesh.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -91,9 +92,9 @@
#include "ED_curve.h"
#include "ED_keyframing.h"
#include "ED_object.h"
+#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_mesh.h"
#include "object_intern.h"
@@ -109,7 +110,8 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
Main *bmain= CTX_data_main(C);
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
- EditVert *eve;
+ BMVert *eve;
+ BMIter iter;
Curve *cu;
Nurb *nu;
BezTriple *bezt;
@@ -121,16 +123,15 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
if(obedit->type==OB_MESH) {
Mesh *me= obedit->data;
- EditMesh *em;
+ BMEditMesh *em;
- load_editMesh(scene, obedit);
- make_editMesh(scene, obedit);
+ EDBM_LoadEditBMesh(scene, obedit);
+ EDBM_MakeEditBMesh(scene->toolsettings, scene, obedit);
- em = BKE_mesh_get_editmesh(me);
+ em= me->edit_btmesh;
- eve= em->verts.first;
- while(eve) {
- if(eve->f & 1) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_SELECT)) {
if(v1==0) v1= nr;
else if(v2==0) v2= nr;
else if(v3==0) v3= nr;
@@ -138,10 +139,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
else break;
}
nr++;
- eve= eve->next;
}
-
- BKE_mesh_end_editmesh(me, em);
}
else if(ELEM(obedit->type, OB_SURF, OB_CURVE)) {
ListBase *editnurb= object_editcurve_get(obedit);
@@ -1138,6 +1136,8 @@ static int move_to_layer_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, scene);
WM_event_add_notifier(C, NC_SCENE|ND_LAYER_CONTENT, scene);
+ WM_event_add_notifier(C, NC_SCENE|ND_LAYER_CONTENT, scene);
+
DAG_scene_sort(bmain, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c
index 28f9c88f950..322f8826891 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -187,10 +187,10 @@ static int object_shape_key_mirror(bContext *C, Object *ob)
Mesh *me= ob->data;
MVert *mv;
- mesh_octree_table(ob, NULL, NULL, 's');
+ //BMESH_TODO mesh_octree_table(ob, NULL, NULL, 's');
for(i1=0, mv=me->mvert; i1<me->totvert; i1++, mv++) {
- i2= mesh_get_x_mirror_vert(ob, i1);
+ i2= -1; //BMESH_TODO mesh_get_x_mirror_vert(ob, i1);
if(i2==i1) {
fp1= ((float *)kb->data) + i1*3;
fp1[0] = -fp1[0];
@@ -213,7 +213,7 @@ static int object_shape_key_mirror(bContext *C, Object *ob)
}
}
- mesh_octree_table(ob, NULL, NULL, 'e');
+ //BMESH_TODO mesh_octree_table(ob, NULL, NULL, 'e');
}
else if (ob->type == OB_LATTICE) {
Lattice *lt= ob->data;
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 1efe79fff9e..0d080c7ea01 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -51,6 +51,7 @@
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_report.h"
+#include "BKE_tessmesh.h"
#include "BKE_multires.h"
#include "BKE_armature.h"
@@ -479,7 +480,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
}
/* update normals */
- mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+ mesh_calc_normals(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL, NULL, 0, NULL, NULL);
}
else if (ob->type==OB_ARMATURE) {
ED_armature_apply_transform(ob, mat);
@@ -656,37 +657,37 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if(obedit->type==OB_MESH) {
Mesh *me= obedit->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
- EditVert *eve;
-
- if(around==V3D_CENTROID) {
- int total= 0;
- for(eve= em->verts.first; eve; eve= eve->next) {
- total++;
- add_v3_v3(cent, eve->co);
- }
- if(total) {
- mul_v3_fl(cent, 1.0f/(float)total);
+ BMEditMesh *em = me->edit_btmesh;
+ BMVert *eve;
+ BMIter iter;
+ int total = 0;
+
+ if(centermode == ORIGIN_TO_CURSOR) {
+ copy_v3_v3(cent, cursor);
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ mul_m4_v3(obedit->imat, cent);
+ } else {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if(around==V3D_CENTROID) {
+ total++;
+ add_v3_v3(cent, eve->co);
+ mul_v3_fl(cent, 1.0f/(float)total);
+ }
+ else {
+ DO_MINMAX(eve->co, min, max);
+ mid_v3_v3v3(cent, min, max);
+ }
}
}
- else {
- for(eve= em->verts.first; eve; eve= eve->next) {
- DO_MINMAX(eve->co, min, max);
- }
- mid_v3_v3v3(cent, min, max);
+
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ sub_v3_v3(eve->co, cent);
}
- if(!is_zero_v3(cent)) {
- for(eve= em->verts.first; eve; eve= eve->next) {
- sub_v3_v3(eve->co, cent);
- }
-
- recalc_editnormals(em);
- tot_change++;
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
- }
- BKE_mesh_end_editmesh(me, em);
- }
+ EDBM_RecalcNormals(em);
+ tot_change++;
+ DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ }
}
/* reset flags */
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 378e4a4f314..6280837b0a3 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -41,6 +41,7 @@
#include "DNA_curve_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
@@ -49,7 +50,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_editVert.h"
+#include "BLI_cellalloc.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -58,6 +59,7 @@
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
#include "BKE_report.h"
#include "BKE_DerivedMesh.h"
@@ -89,7 +91,7 @@ static Lattice *vgroup_edit_lattice(Object *ob)
int ED_vgroup_object_is_edit_mode(Object *ob)
{
if(ob->type == OB_MESH)
- return (((Mesh*)ob->data)->edit_mesh != NULL);
+ return (((Mesh*)ob->data)->edit_btmesh != NULL);
else if(ob->type == OB_LATTICE)
return (((Lattice*)ob->data)->editlatt != NULL);
@@ -169,23 +171,25 @@ static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_to
{
Mesh *me = (Mesh *)id;
- if(me->edit_mesh) {
- EditMesh *em = me->edit_mesh;
- EditVert *eve;
+ if(me->edit_btmesh) {
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
+ BMVert *eve;
int i;
- if (!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) {
+ if (!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT)) {
return 0;
}
- i= BLI_countlist(&em->verts);
+ i = em->bm->totvert;
*dvert_arr= MEM_mallocN(sizeof(void*)*i, "vgroup parray from me");
*dvert_tot = i;
i = 0;
- for (eve=em->verts.first; eve; eve=eve->next, i++) {
- (*dvert_arr)[i] = CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ (*dvert_arr)[i] = CustomData_em_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
+ i++;
}
return 1;
@@ -312,12 +316,12 @@ int ED_vgroup_copy_array(Object *ob, Object *ob_from)
for(i=0; i<dvert_tot; i++, dvf++, dv++) {
if((*dv)->dw)
- MEM_freeN((*dv)->dw);
+ BLI_cellalloc_free((*dv)->dw);
*(*dv)= *(*dvf);
if((*dv)->dw)
- (*dv)->dw= MEM_dupallocN((*dv)->dw);
+ (*dv)->dw= BLI_cellalloc_dupalloc((*dv)->dw);
}
MEM_freeN(dvert_array);
@@ -371,13 +375,13 @@ static void ED_vgroup_nr_vert_remove(Object *ob, int def_nr, int vertnum)
* deform weight, and reshuffle the others
*/
if(dvert->totweight) {
- newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight),
+ newdw = BLI_cellalloc_malloc(sizeof(MDeformWeight)*(dvert->totweight),
"deformWeight");
if(dvert->dw){
memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
memcpy(newdw+i, dvert->dw+i+1,
sizeof(MDeformWeight)*(dvert->totweight-i));
- MEM_freeN(dvert->dw);
+ BLI_cellalloc_free(dvert->dw);
}
dvert->dw=newdw;
}
@@ -385,7 +389,7 @@ static void ED_vgroup_nr_vert_remove(Object *ob, int def_nr, int vertnum)
* left then just remove the deform weight
*/
else {
- MEM_freeN(dvert->dw);
+ BLI_cellalloc_free(dvert->dw);
dvert->dw = NULL;
break;
}
@@ -467,11 +471,11 @@ static void ED_vgroup_nr_vert_add(Object *ob, int def_nr, int vertnum, float wei
/* if we are doing an additive assignment, then
* we need to create the deform weight
*/
- newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1),
+ newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dv->totweight+1),
"deformWeight");
if(dv->dw){
memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
- MEM_freeN(dv->dw);
+ BLI_cellalloc_free(dv->dw);
}
dv->dw=newdw;
@@ -526,7 +530,7 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum)
static float get_vert_def_nr(Object *ob, int def_nr, int vertnum)
{
MDeformVert *dvert= NULL;
- EditVert *eve;
+ BMVert *eve;
Mesh *me;
int i;
@@ -534,12 +538,12 @@ static float get_vert_def_nr(Object *ob, int def_nr, int vertnum)
if(ob->type==OB_MESH) {
me= ob->data;
- if(me->edit_mesh) {
- eve= BLI_findlink(&me->edit_mesh->verts, vertnum);
+ if(me->edit_btmesh) {
+ eve= BMIter_AtIndex(me->edit_btmesh->bm, BM_VERTS_OF_MESH, NULL, vertnum);
if(!eve) {
return 0.0f;
}
- dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
+ dvert= CustomData_bmesh_get(&me->edit_btmesh->bm->vdata, eve->head.data, CD_MDEFORMVERT);
vertnum= 0;
}
else {
@@ -594,34 +598,32 @@ void ED_vgroup_select_by_name(Object *ob, const char *name)
/* only in editmode */
static void vgroup_select_verts(Object *ob, int select)
{
- EditVert *eve;
+ BMVert *eve;
MDeformVert *dvert;
int i;
if(ob->type == OB_MESH) {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
- for(eve=em->verts.first; eve; eve=eve->next){
- dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
if(dvert && dvert->totweight){
for(i=0; i<dvert->totweight; i++){
if(dvert->dw[i].def_nr == (ob->actdef-1)){
- if(!eve->h) {
- if(select) eve->f |= SELECT;
- else eve->f &= ~SELECT;
+ if (!BM_TestHFlag(eve, BM_HIDDEN)) {
+ BM_Select(em->bm, eve, select);
+ break;
}
- break;
}
}
}
}
/* this has to be called, because this function operates on vertices only */
- if(select) EM_select_flush(em); // vertices to edges/faces
- else EM_deselect_flush(em);
-
- BKE_mesh_end_editmesh(me, em);
+ if(select) EDBM_selectmode_flush(em); // vertices to edges/faces
+ else EDBM_deselect_flush(em);
}
else if(ob->type == OB_LATTICE) {
Lattice *lt= vgroup_edit_lattice(ob);
@@ -1363,12 +1365,12 @@ static void vgroup_invert(Object *ob, int auto_assign, int auto_remove)
static void vgroup_blend(Object *ob)
{
+ BMEditMesh *em= ((Mesh *)ob->data)->edit_btmesh;
bDeformGroup *dg;
MDeformWeight *dw;
MDeformVert *dvert_array=NULL, *dvert;
int i, def_nr, dvert_tot=0;
- EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)ob->data));
// ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
if(em==NULL)
@@ -1377,46 +1379,47 @@ static void vgroup_blend(Object *ob)
dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
if(dg) {
- int sel1, sel2;
- int i1, i2;
-
- EditEdge *eed;
- EditVert *eve;
+ BMEdge *eed;
+ BMVert *eve;
+ BMIter iter;
float *vg_weights;
float *vg_users;
+ int sel1, sel2;
+ int i1, i2;
def_nr= ob->actdef-1;
i= 0;
- for(eve= em->verts.first; eve; eve= eve->next)
- eve->tmp.l= i++;
-
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(eve, i);
+ i++;
+ }
dvert_tot= i;
vg_weights= MEM_callocN(sizeof(float)*dvert_tot, "vgroup_blend_f");
vg_users= MEM_callocN(sizeof(int)*dvert_tot, "vgroup_blend_i");
- for(eed= em->edges.first; eed; eed= eed->next) {
- sel1= eed->v1->f & SELECT;
- sel2= eed->v2->f & SELECT;
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ sel1= BM_TestHFlag(eed->v1, BM_SELECT);
+ sel2= BM_TestHFlag(eed->v2, BM_SELECT);
if(sel1 != sel2) {
/* i1 is always the selected one */
if(sel1==TRUE && sel2==FALSE) {
- i1= eed->v1->tmp.l;
- i2= eed->v2->tmp.l;
+ i1= BM_GetIndex(eed->v1);
+ i2= BM_GetIndex(eed->v2);
eve= eed->v2;
}
else {
- i2= eed->v1->tmp.l;
- i1= eed->v2->tmp.l;
+ i2= BM_GetIndex(eed->v1);
+ i1= BM_GetIndex(eed->v2);
eve= eed->v1;
}
vg_users[i1]++;
/* TODO, we may want object mode blending */
- if(em) dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+ if(em) dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
else dvert= dvert_array+i2;
dw= defvert_find_index(dvert, def_nr);
@@ -1428,10 +1431,10 @@ static void vgroup_blend(Object *ob)
}
i= 0;
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT && vg_users[i] > 0) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if(BM_TestHFlag(eve, BM_SELECT) && vg_users[i] > 0) {
/* TODO, we may want object mode blending */
- if(em) dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+ if(em) dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
else dvert= dvert_array+i;
dw= defvert_verify_index(dvert, def_nr);
@@ -1559,7 +1562,10 @@ void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_v
{
#define VGROUP_MIRR_OP dvert_mirror_op(dvert, dvert_mirr, sel, sel_mirr, flip_map, mirror_weights, flip_vgroups)
+#if 0
EditVert *eve, *eve_mirr;
+#endif
+
MDeformVert *dvert, *dvert_mirr;
short sel, sel_mirr;
int *flip_map;
@@ -1571,6 +1577,11 @@ void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_v
/* only the active group */
if(ob->type == OB_MESH) {
+#if 1 //BMESH_TODO
+ (void)dvert;
+ (void)dvert_mirr;
+ (void)flip_map;
+#else
Mesh *me= ob->data;
EditMesh *em = BKE_mesh_get_editmesh(me);
@@ -1601,6 +1612,7 @@ void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_v
}
BKE_mesh_end_editmesh(me, em);
+#endif // BMESH_TODO
}
else if (ob->type == OB_LATTICE) {
Lattice *lt= ob->data;
@@ -1749,7 +1761,7 @@ static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg)
/* removes from active defgroup, if allverts==0 only selected vertices */
static void vgroup_active_remove_verts(Object *ob, const int allverts, bDeformGroup *dg)
{
- EditVert *eve;
+ BMVert *eve;
MDeformVert *dvert;
MDeformWeight *newdw;
bDeformGroup *eg;
@@ -1757,29 +1769,30 @@ static void vgroup_active_remove_verts(Object *ob, const int allverts, bDeformGr
if(ob->type == OB_MESH) {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
- for(eve=em->verts.first; eve; eve=eve->next){
- dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
- if(dvert && dvert->dw && ((eve->f & SELECT) || allverts)){
+ if(dvert && dvert->dw && (BM_TestHFlag(eve, BM_SELECT) || allverts)){
for(i=0; i<dvert->totweight; i++){
/* Find group */
eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
if(eg == dg){
dvert->totweight--;
- if(dvert->totweight){
- newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
+ if (dvert->totweight){
+ newdw = BLI_cellalloc_malloc (sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
if(dvert->dw){
memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
- MEM_freeN(dvert->dw);
+ BLI_cellalloc_free(dvert->dw);
}
dvert->dw=newdw;
}
else{
- MEM_freeN(dvert->dw);
+ BLI_cellalloc_free (dvert->dw);
dvert->dw=NULL;
break;
}
@@ -1787,7 +1800,6 @@ static void vgroup_active_remove_verts(Object *ob, const int allverts, bDeformGr
}
}
}
- BKE_mesh_end_editmesh(me, em);
}
else if(ob->type == OB_LATTICE) {
Lattice *lt= vgroup_edit_lattice(ob);
@@ -1817,19 +1829,19 @@ static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *dg)
/* Make sure that any verts with higher indices are adjusted accordingly */
if(ob->type==OB_MESH) {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
- EditVert *eve;
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
+ BMVert *eve;
MDeformVert *dvert;
- for(eve=em->verts.first; eve; eve=eve->next){
- dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
if(dvert)
for(i=0; i<dvert->totweight; i++)
if(dvert->dw[i].def_nr > dg_index)
dvert->dw[i].def_nr--;
}
- BKE_mesh_end_editmesh(me, em);
}
else if(ob->type==OB_LATTICE) {
Lattice *lt= vgroup_edit_lattice(ob);
@@ -1869,7 +1881,7 @@ static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *dg)
else if(ob->type==OB_LATTICE) {
Lattice *lt= vgroup_edit_lattice(ob);
if(lt->dvert) {
- MEM_freeN(lt->dvert);
+ BLI_cellalloc_free(lt->dvert);
lt->dvert= NULL;
}
}
@@ -1879,7 +1891,7 @@ static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *dg)
static int vgroup_object_in_edit_mode(Object *ob)
{
if(ob->type == OB_MESH)
- return (((Mesh*)ob->data)->edit_mesh != NULL);
+ return (((Mesh*)ob->data)->edit_btmesh != NULL);
else if(ob->type == OB_LATTICE)
return (((Lattice*)ob->data)->editlatt != NULL);
@@ -1909,7 +1921,7 @@ static void vgroup_delete_all(Object *ob)
else if(ob->type==OB_LATTICE) {
Lattice *lt= vgroup_edit_lattice(ob);
if(lt->dvert) {
- MEM_freeN(lt->dvert);
+ BLI_cellalloc_free(lt->dvert);
lt->dvert= NULL;
}
}
@@ -1924,7 +1936,7 @@ static void vgroup_delete_all(Object *ob)
/* only in editmode */
static void vgroup_assign_verts(Object *ob, float weight)
{
- EditVert *eve;
+ BMVert *eve;
bDeformGroup *dg, *eg;
MDeformWeight *newdw;
MDeformVert *dvert;
@@ -1936,16 +1948,17 @@ static void vgroup_assign_verts(Object *ob, float weight)
if(ob->type == OB_MESH) {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
- if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT))
- EM_add_data_layer(em, &em->vdata, CD_MDEFORMVERT, NULL);
+ if(!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT))
+ BM_add_data_layer(em->bm, &em->bm->vdata, CD_MDEFORMVERT);
/* Go through the list of editverts and assign them */
- for(eve=em->verts.first; eve; eve=eve->next){
- dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
- if(dvert && (eve->f & SELECT)){
+ if(dvert && BM_TestHFlag(eve, BM_SELECT)) {
/* See if this vert already has a reference to this group */
/* If so: Change its weight */
done=0;
@@ -1960,10 +1973,10 @@ static void vgroup_assign_verts(Object *ob, float weight)
}
/* If not: Add the group and set its weight */
if(!done){
- newdw = MEM_callocN(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
+ newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
if(dvert->dw){
memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
- MEM_freeN(dvert->dw);
+ BLI_cellalloc_free(dvert->dw);
}
dvert->dw=newdw;
@@ -1975,7 +1988,6 @@ static void vgroup_assign_verts(Object *ob, float weight)
}
}
}
- BKE_mesh_end_editmesh(me, em);
}
else if(ob->type == OB_LATTICE) {
Lattice *lt= vgroup_edit_lattice(ob);
@@ -2720,11 +2732,12 @@ static int vgroup_do_remap(Object *ob, char *name_array, wmOperator *op)
if(ob->mode == OB_MODE_EDIT) {
if(ob->type==OB_MESH) {
- EditMesh *em = BKE_mesh_get_editmesh(ob->data);
- EditVert *eve;
+ BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
+ BMIter iter;
+ BMVert *eve;
- for(eve=em->verts.first; eve; eve=eve->next){
- dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
if(dvert && dvert->totweight){
defvert_remap(dvert, sort_map);
}
diff --git a/source/blender/editors/physics/SConscript b/source/blender/editors/physics/SConscript
index 188416eb04c..a478b2afb1c 100644
--- a/source/blender/editors/physics/SConscript
+++ b/source/blender/editors/physics/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
-incs += ' ../../gpu ../../blenloader'
+incs += ' ../../gpu ../../blenloader ../../bmesh'
incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
defs = ''
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 0803fa2a7a2..fe253df8f85 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -1056,7 +1056,7 @@ static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
BLI_kdtree_free(edit->emitter_field);
- totface=dm->getNumFaces(dm);
+ totface=dm->getNumTessFaces(dm);
/*totvert=dm->getNumVerts(dm);*/ /*UNSUED*/
edit->emitter_cosnos=MEM_callocN(totface*6*sizeof(float),"emitter cosnos");
@@ -1067,7 +1067,7 @@ static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
nor=vec+3;
for(i=0; i<totface; i++, vec+=6, nor+=6) {
- MFace *mface=dm->getFaceData(dm,i,CD_MFACE);
+ MFace *mface=dm->getTessFaceData(dm,i,CD_MFACE);
MVert *mvert;
mvert=dm->getVertData(dm,mface->v1,CD_MVERT);
@@ -2592,7 +2592,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
PTCacheEditPoint *newpoint, *new_points;
POINT_P; KEY_K;
HairKey *hkey;
- int *mirrorfaces;
+ int *mirrorfaces = NULL;
int rotation, totpart, newtotpart;
if(psys->flag & PSYS_GLOBAL_HAIR)
@@ -2602,7 +2602,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
if(!psmd->dm)
return;
- mirrorfaces= mesh_get_x_mirror_faces(ob, NULL);
+ //BMESH_TODO mirrorfaces= mesh_get_x_mirror_faces(ob, NULL);
if(!edit->mirror_cache)
PE_update_mirror_cache(ob, psys);
@@ -2623,7 +2623,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
}
}
- if((point->flag & PEP_TAG) && mirrorfaces[pa->num*2] != -1)
+ if((point->flag & PEP_TAG) && mirrorfaces && mirrorfaces[pa->num*2] != -1)
newtotpart++;
}
@@ -2660,7 +2660,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
if(point->flag & PEP_HIDE)
continue;
- if(!(point->flag & PEP_TAG) || mirrorfaces[pa->num*2] == -1)
+ if(!(point->flag & PEP_TAG) || (mirrorfaces && mirrorfaces[pa->num*2] == -1))
continue;
/* duplicate */
@@ -2670,7 +2670,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
if(point->keys) newpoint->keys= MEM_dupallocN(point->keys);
/* rotate weights according to vertex index rotation */
- rotation= mirrorfaces[pa->num*2+1];
+ rotation= mirrorfaces ? mirrorfaces[pa->num*2+1] : 0;
newpa->fuv[0]= pa->fuv[2];
newpa->fuv[1]= pa->fuv[1];
newpa->fuv[2]= pa->fuv[0];
@@ -2682,7 +2682,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
SHIFT3(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2])
/* assign face inddex */
- newpa->num= mirrorfaces[pa->num*2];
+ newpa->num= mirrorfaces ? mirrorfaces[pa->num*2] : 0;
newpa->num_dmcache= psys_particle_dm_face_lookup(ob,psmd->dm,newpa->num,newpa->fuv, NULL);
/* update edit key pointers */
@@ -2704,7 +2704,8 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
point->flag &= ~PEP_TAG;
}
- MEM_freeN(mirrorfaces);
+ if (mirrorfaces)
+ MEM_freeN(mirrorfaces);
}
static int mirror_exec(bContext *C, wmOperator *UNUSED(op))
@@ -3104,8 +3105,8 @@ static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm, floa
VECCOPY(p_max,pa_minmax+3);
}
- totface=dm->getNumFaces(dm);
- mface=dm->getFaceDataArray(dm,CD_MFACE);
+ totface=dm->getNumTessFaces(dm);
+ mface=dm->getTessFaceDataArray(dm,CD_MFACE);
mvert=dm->getVertDataArray(dm,CD_MVERT);
/* lets intersect the faces */
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 101a6744e9a..7071e5d3720 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -644,7 +644,7 @@ static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
if(psmd->dm->deformedOnly)
/* we don't want to mess up psmd->dm when converting to global coordinates below */
- dm= CDDM_copy(psmd->dm);
+ dm= CDDM_copy(psmd->dm, 0);
else
dm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
@@ -670,7 +670,7 @@ static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
continue;
}
- mface = CDDM_get_face(dm,nearest.index);
+ mface = CDDM_get_tessface(dm,nearest.index);
copy_v3_v3(v[0], CDDM_get_vert(dm,mface->v1)->co);
copy_v3_v3(v[1], CDDM_get_vert(dm,mface->v2)->co);
diff --git a/source/blender/editors/render/CMakeLists.txt b/source/blender/editors/render/CMakeLists.txt
index cf6846f5f98..3c5fd0b4ef7 100644
--- a/source/blender/editors/render/CMakeLists.txt
+++ b/source/blender/editors/render/CMakeLists.txt
@@ -26,6 +26,7 @@ set(INC
../../blenloader
../../gpu
../../imbuf
+ ../../bmesh
../../makesdna
../../makesrna
../../render/extern/include
diff --git a/source/blender/editors/render/SConscript b/source/blender/editors/render/SConscript
index 53418500ea6..1f93db653f5 100644
--- a/source/blender/editors/render/SConscript
+++ b/source/blender/editors/render/SConscript
@@ -7,7 +7,7 @@ incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../gpu'
incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
-incs += ' ../../blenloader'
+incs += ' ../../blenloader ../../bmesh'
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 2f0958371f9..bef3e7f0a1a 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -187,42 +187,10 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat
/* set callbacks, exported to sequence render too.
Only call in foreground (UI) renders. */
-static void screen_render_scene_layer_set(wmOperator *op, Main *mainp, Scene **scene, SceneRenderLayer **srl)
-{
- /* single layer re-render */
- if(RNA_property_is_set(op->ptr, "scene")) {
- Scene *scn;
- char scene_name[MAX_ID_NAME-2];
-
- RNA_string_get(op->ptr, "scene", scene_name);
- scn = (Scene *)BLI_findstring(&mainp->scene, scene_name, offsetof(ID, name) + 2);
-
- if (scn) {
- /* camera switch wont have updated */
- scn->r.cfra= (*scene)->r.cfra;
- scene_camera_switch_update(scn);
-
- *scene = scn;
- }
- }
-
- if(RNA_property_is_set(op->ptr, "layer")) {
- SceneRenderLayer *rl;
- char rl_name[RE_MAXNAME];
-
- RNA_string_get(op->ptr, "layer", rl_name);
- rl = (SceneRenderLayer *)BLI_findstring(&(*scene)->r.layers, rl_name, offsetof(SceneRenderLayer, name));
-
- if (rl)
- *srl = rl;
- }
-}
-
/* executes blocking render */
static int screen_render_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
- SceneRenderLayer *srl= NULL;
Render *re= RE_NewRender(scene->id.name);
Image *ima;
View3D *v3d= CTX_wm_view3d(C);
@@ -252,13 +220,10 @@ static int screen_render_exec(bContext *C, wmOperator *op)
RE_SetReports(re, op->reports);
- /* custom scene and single layer re-render */
- screen_render_scene_layer_set(op, mainp, &scene, &srl);
-
if(is_animation)
RE_BlenderAnim(re, mainp, scene, camera_override, lay, scene->r.sfra, scene->r.efra, scene->r.frame_step);
else
- RE_BlenderFrame(re, mainp, scene, srl, camera_override, lay, scene->r.cfra, is_write_still);
+ RE_BlenderFrame(re, mainp, scene, NULL, camera_override, lay, scene->r.cfra, is_write_still);
RE_SetReports(re, NULL);
@@ -553,11 +518,28 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
jobflag= WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS;
- /* custom scene and single layer re-render */
- screen_render_scene_layer_set(op, mainp, &scene, &srl);
+ /* single layer re-render */
+ if(RNA_property_is_set(op->ptr, "layer")) {
+ SceneRenderLayer *rl;
+ Scene *scn;
+ char scene_name[MAX_ID_NAME-2], rl_name[RE_MAXNAME];
+
+ RNA_string_get(op->ptr, "layer", rl_name);
+ RNA_string_get(op->ptr, "scene", scene_name);
- if(RNA_property_is_set(op->ptr, "layer"))
+ scn = (Scene *)BLI_findstring(&mainp->scene, scene_name, offsetof(ID, name) + 2);
+ rl = (SceneRenderLayer *)BLI_findstring(&scene->r.layers, rl_name, offsetof(SceneRenderLayer, name));
+
+ if (scn && rl) {
+ /* camera switch wont have updated */
+ scn->r.cfra= scene->r.cfra;
+ scene_camera_switch_update(scn);
+
+ scene = scn;
+ srl = rl;
+ }
jobflag |= WM_JOB_SUSPEND;
+ }
/* job custom data */
rj= MEM_callocN(sizeof(RenderJob), "render job");
@@ -629,7 +611,7 @@ void RENDER_OT_render(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene");
RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)");
- RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render (used only when animation is disabled)");
- RNA_def_string(ot->srna, "scene", "", MAX_ID_NAME-2, "Scene", "Scene to render, current scene if not specified");
+ RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render");
+ RNA_def_string(ot->srna, "scene", "", MAX_ID_NAME-2, "Scene", "Re-render single layer in this scene");
}
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 35d679146fe..248cae2413a 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -63,6 +63,7 @@
#include "BKE_scene.h"
#include "BKE_texture.h"
#include "BKE_world.h"
+#include "BKE_tessmesh.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -163,13 +164,15 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
if(ob && ob->actcol>0) {
if(ob->type == OB_MESH) {
- EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
- EditFace *efa;
+ BMEditMesh *em= ((Mesh*)ob->data)->edit_btmesh;
+ BMFace *efa;
+ BMIter iter;
if(em) {
- for(efa= em->faces.first; efa; efa=efa->next)
- if(efa->f & SELECT)
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(BM_TestHFlag(efa, BM_SELECT))
efa->mat_nr= ob->actcol-1;
+ }
}
}
else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
@@ -222,13 +225,10 @@ static int material_slot_de_select(bContext *C, int select)
return OPERATOR_CANCELLED;
if(ob->type == OB_MESH) {
- EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
+ BMEditMesh *em= ((Mesh*)ob->data)->edit_btmesh;
if(em) {
- if(select)
- EM_select_by_material(em, ob->actcol-1);
- else
- EM_deselect_by_material(em, ob->actcol-1);
+ EDBM_deselect_by_material(em, ob->actcol-1, select);
}
}
else if ELEM(ob->type, OB_CURVE, OB_SURF) {
diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt
index 3614052684c..79a805cfa6e 100644
--- a/source/blender/editors/screen/CMakeLists.txt
+++ b/source/blender/editors/screen/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenkernel
../../blenlib
../../blenloader
+ ../../bmesh
../../imbuf
../../makesdna
../../makesrna
diff --git a/source/blender/editors/screen/SConscript b/source/blender/editors/screen/SConscript
index 1381c820224..ade26a0b80f 100644
--- a/source/blender/editors/screen/SConscript
+++ b/source/blender/editors/screen/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../blenfont ../../makesdna ../../imbuf'
incs += ' ../../blenloader ../../windowmanager ../../makesrna ../../gpu'
-incs += ' ../../render/extern/include'
+incs += ' ../../render/extern/include ../../bmesh'
incs += ' #/intern/guardedalloc #/extern/glew/include'
defs = ''
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 0a7e3a2763a..4fd6af092a4 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -54,6 +54,7 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_tessmesh.h"
#include "BKE_sound.h"
#include "WM_api.h"
@@ -313,7 +314,7 @@ int ED_operator_editmesh(bContext *C)
{
Object *obedit= CTX_data_edit_object(C);
if(obedit && obedit->type==OB_MESH)
- return NULL != ((Mesh *)obedit->data)->edit_mesh;
+ return NULL != ((Mesh *)obedit->data)->edit_btmesh;
return 0;
}
@@ -360,24 +361,21 @@ int ED_operator_uvedit(bContext *C)
{
SpaceImage *sima= CTX_wm_space_image(C);
Object *obedit= CTX_data_edit_object(C);
+
return ED_space_image_show_uvedit(sima, obedit);
}
int ED_operator_uvmap(bContext *C)
{
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= NULL;
+ BMEditMesh *em= NULL;
if(obedit && obedit->type==OB_MESH)
- em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ em= ((Mesh *)obedit->data)->edit_btmesh;
- if(em && (em->faces.first)) {
- BKE_mesh_end_editmesh(obedit->data, em);
+ if(em && (em->bm->totface))
return 1;
- }
- if(obedit)
- BKE_mesh_end_editmesh(obedit->data, em);
return 0;
}
@@ -2952,7 +2950,7 @@ int ED_screen_animation_play(bContext *C, int sync, int mode)
ScreenAnimData *sad= wt->customdata;
sad->ar= CTX_wm_region(C);
- }
+ }
}
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/sculpt_paint/SConscript b/source/blender/editors/sculpt_paint/SConscript
index b3927fcee68..8f1f47b5004 100644
--- a/source/blender/editors/sculpt_paint/SConscript
+++ b/source/blender/editors/sculpt_paint/SConscript
@@ -8,7 +8,7 @@ defs = []
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../render/extern/include'
-incs += ' ../../gpu ../../makesrna ../../blenloader'
+incs += ' ../../gpu ../../makesrna ../../blenloader ../../bmesh'
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index d49ce0cf49a..1d2bab1862a 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -2902,11 +2902,11 @@ static void project_paint_begin(ProjPaintState *ps)
}
ps->dm_mvert = ps->dm->getVertArray(ps->dm);
- ps->dm_mface = ps->dm->getFaceArray(ps->dm);
- ps->dm_mtface= ps->dm->getFaceDataArray(ps->dm, CD_MTFACE);
+ ps->dm_mface = ps->dm->getTessFaceArray(ps->dm);
+ ps->dm_mtface= ps->dm->getTessFaceDataArray(ps->dm, CD_MTFACE);
ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
- ps->dm_totface = ps->dm->getNumFaces(ps->dm);
+ ps->dm_totface = ps->dm->getNumTessFaces(ps->dm);
/* use clone mtface? */
@@ -2939,15 +2939,18 @@ static void project_paint_begin(ProjPaintState *ps)
}
/* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
- if(ps->dm->type != DM_TYPE_CDDM) {
+ // this seems like a bad check, since some constructive modifiers use cddm? - joeedh
+ if(1) { //ps->dm->type != DM_TYPE_CDDM) {
ps->dm_mvert= MEM_dupallocN(ps->dm_mvert);
ps->dm_mface= MEM_dupallocN(ps->dm_mface);
/* looks like these are ok for now.*/
- /*
+
ps->dm_mtface= MEM_dupallocN(ps->dm_mtface);
- ps->dm_mtface_clone= MEM_dupallocN(ps->dm_mtface_clone);
- ps->dm_mtface_stencil= MEM_dupallocN(ps->dm_mtface_stencil);
- */
+ if (ps->dm_mtface_clone)
+ ps->dm_mtface_clone= MEM_dupallocN(ps->dm_mtface_clone);
+ if (ps->dm_mtface_stencil)
+ ps->dm_mtface_stencil= MEM_dupallocN(ps->dm_mtface_stencil);
+
}
ps->viewDir[0] = 0.0f;
@@ -3424,7 +3427,8 @@ static void project_paint_end(ProjPaintState *ps)
}
/* copy for subsurf/multires, so throw away */
- if(ps->dm->type != DM_TYPE_CDDM) {
+ // this seems like a bad check, since some constructive modifiers use cddm? - joeedh
+ if(1) { //ps->dm->type != DM_TYPE_CDDM) {
if(ps->dm_mvert) MEM_freeN(ps->dm_mvert);
if(ps->dm_mface) MEM_freeN(ps->dm_mface);
/* looks like these dont need copying */
@@ -4733,9 +4737,29 @@ static int texture_paint_init(bContext *C, wmOperator *op)
pop->orig_brush_size= brush_size(brush);
if(pop->mode != PAINT_MODE_2D) {
+ Mesh *me;
+
pop->s.ob = OBACT;
+ if (!pop->ps.ob)
+ pop->ps.ob = pop->s.ob;
+
pop->s.me = get_mesh(pop->s.ob);
if (!pop->s.me) return 0;
+
+ me = pop->s.me;
+
+ /*recalc mesh tesselation so the face origindex values point
+ to the tesselation faces themselves, instead of polys*/
+ me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata,
+ &me->pdata, me->mvert, me->totface, me->totloop, me->totpoly, 0, 1);
+ mesh_update_customdata_pointers(me);
+
+ /*force customdata update*/
+ makeDerivedMesh(scene, pop->ps.ob, NULL, CD_MASK_BAREMESH, 0);
+
+ /* Dont allow brush size below 2 */
+ if (pop->ps.brush && pop->ps.brush->size<=1)
+ pop->ps.brush->size = 2;
}
else {
pop->s.image = pop->s.sima->image;
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index b1c0b571d49..5ac72d71109 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -178,9 +178,9 @@ static void imapaint_tri_weights(Object *ob, float *v1, float *v2, float *v3, fl
void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2])
{
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
- const int *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
- MTFace *tface = dm->getFaceDataArray(dm, CD_MTFACE), *tf;
- int numfaces = dm->getNumFaces(dm), a, findex;
+ const int *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ MTFace *tface = dm->getTessFaceDataArray(dm, CD_MTFACE), *tf;
+ int numfaces = dm->getNumTessFaces(dm), a, findex;
float p[2], w[3], absw, minabsw;
MFace mf;
MVert mv[4];
@@ -193,7 +193,7 @@ void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const in
findex= index ? index[a]: a;
if(findex == faceindex) {
- dm->getFace(dm, a, &mf);
+ dm->getTessFace(dm, a, &mf);
dm->getVert(dm, mf.v1, &mv[0]);
dm->getVert(dm, mf.v2, &mv[1]);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 3e2c4666528..f8c52cf9649 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -43,6 +43,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_memarena.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -197,7 +198,7 @@ unsigned int vpaint_get_current_col(VPaint *vp)
return rgba_to_mcol(brush->rgb[0], brush->rgb[1], brush->rgb[2], 1.0f);
}
-static void do_shared_vertexcol(Mesh *me)
+static void do_shared_vertex_tesscol(Mesh *me)
{
/* if no mcol: do not do */
/* if tface: only the involved faces, otherwise all */
@@ -263,19 +264,78 @@ static void do_shared_vertexcol(Mesh *me)
MEM_freeN(scolmain);
}
+void do_shared_vertexcol(Mesh *me)
+{
+ MLoop *ml = me->mloop;
+ MLoopCol *lcol = me->mloopcol;
+ MTexPoly *mtp = me->mtpoly;
+ MPoly *mp = me->mpoly;
+ float (*scol)[5];
+ int i;
+
+ /* if no mloopcol: do not do */
+ /* if mtexpoly: only the involved faces, otherwise all */
+
+ if(me->mloopcol==0 || me->totvert==0 || me->totpoly==0) return;
+
+ scol = MEM_callocN(sizeof(float)*me->totvert*5, "scol");
+
+ for (i=0; i<me->totloop; i++, ml++, lcol++) {
+ if (i >= mp->loopstart + mp->totloop) {
+ mp++;
+ if (mtp) mtp++;
+ }
+
+ if (mtp && !(mtp->mode & TF_SHAREDCOL))
+ continue;
+
+ scol[ml->v][0] += lcol->r;
+ scol[ml->v][1] += lcol->g;
+ scol[ml->v][2] += lcol->b;
+ scol[ml->v][3] += lcol->a;
+ scol[ml->v][4] += 1.0;
+ }
+
+ for (i=0; i<me->totvert; i++) {
+ if (!scol[i][4]) continue;
+
+ scol[i][0] /= scol[i][4];
+ scol[i][1] /= scol[i][4];
+ scol[i][2] /= scol[i][4];
+ scol[i][3] /= scol[i][4];
+ }
+
+ ml = me->mloop;
+ lcol = me->mloopcol;
+ for (i=0; i<me->totloop; i++, ml++, lcol++) {
+ if (!scol[ml->v][4]) continue;
+
+ lcol->r = scol[ml->v][0];
+ lcol->g = scol[ml->v][1];
+ lcol->b = scol[ml->v][2];
+ lcol->a = scol[ml->v][3];
+ }
+
+ MEM_freeN(scol);
+
+ do_shared_vertex_tesscol(me);
+}
+
static void make_vertexcol(Object *ob) /* single ob */
{
Mesh *me;
if(!ob || ob->id.lib) return;
me= get_mesh(ob);
if(me==NULL) return;
- if(me->edit_mesh) return;
+ if(me->edit_btmesh) return;
/* copies from shadedisplist to mcol */
- if(!me->mcol) {
- CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
- mesh_update_customdata_pointers(me);
- }
+ if(!me->mcol)
+ CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
+ if (!me->mloopcol)
+ CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop);
+
+ mesh_update_customdata_pointers(me);
//if(shade)
// shadeMeshMCol(scene, ob, me);
@@ -323,7 +383,7 @@ static int wpaint_mirror_vgroup_ensure(Object *ob)
return -1;
}
-static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
+static void copy_vpaint_prev(VPaint *vp, unsigned int *lcol, int tot)
{
if(vp->vpaint_prev) {
MEM_freeN(vp->vpaint_prev);
@@ -331,10 +391,10 @@ static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
}
vp->tot= tot;
- if(mcol==NULL || tot==0) return;
+ if(lcol==NULL || tot==0) return;
- vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev");
- memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot);
+ vp->vpaint_prev= MEM_mallocN(sizeof(int)*tot, "vpaint_prev");
+ memcpy(vp->vpaint_prev, lcol, sizeof(int)*tot);
}
@@ -357,9 +417,11 @@ static void copy_wpaint_prev (VPaint *wp, MDeformVert *dverts, int dcount)
void vpaint_fill(Object *ob, unsigned int paintcol)
{
Mesh *me;
- MFace *mf;
+ MFace *mf;
+ MPoly *mp;
+ MLoopCol *lcol;
unsigned int *mcol;
- int i, selected;
+ int i, j, selected;
me= get_mesh(ob);
if(me==NULL || me->totface==0) return;
@@ -379,6 +441,18 @@ void vpaint_fill(Object *ob, unsigned int paintcol)
mcol[3] = paintcol;
}
}
+
+ mp = me->mpoly;
+ lcol = me->mloopcol;
+ for (i=0; i<me->totpoly; i++, mp++) {
+ if (!(!selected || mp->flag & ME_FACE_SEL))
+ continue;
+
+ lcol = me->mloopcol + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, lcol++) {
+ *(int*)lcol = paintcol;
+ }
+ }
DAG_id_tag_update(&me->id, 0);
}
@@ -388,6 +462,7 @@ void vpaint_fill(Object *ob, unsigned int paintcol)
void wpaint_fill(VPaint *wp, Object *ob, float paintweight)
{
Mesh *me;
+ MFace *mface;
MDeformWeight *dw, *uw;
int *indexar;
unsigned int index;
@@ -406,9 +481,8 @@ void wpaint_fill(VPaint *wp, Object *ob, float paintweight)
indexar= get_indexarray(me);
if(selected) {
- MFace *mf;
- for(index=0, mf= me->mface; index<me->totface; index++, mf++) {
- if((mf->flag & ME_FACE_SEL)==0)
+ for(index=0, mface=me->mface; index<me->totface; index++, mface++) {
+ if((mface->flag & ME_FACE_SEL)==0)
indexar[index]= 0;
else
indexar[index]= index+1;
@@ -448,7 +522,7 @@ void wpaint_fill(VPaint *wp, Object *ob, float paintweight)
dw->weight= paintweight;
if(me->editflag & ME_EDIT_MIRROR_X) { /* x mirror painting */
- int j= mesh_get_x_mirror_vert(ob, vidx);
+ int j= -1; //BMESH_TODO mesh_get_x_mirror_vert(ob, faceverts[i]);
if(j>=0) {
/* copy, not paint again */
if(vgroup_mirror != -1) {
@@ -887,6 +961,7 @@ static void wpaint_blend(VPaint *wp, MDeformWeight *dw, MDeformWeight *uw, float
/* sets wp->weight to the closest weight value to vertex */
/* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */
+#if 0// BMESH_TODO
static int weight_sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
ViewContext vc;
@@ -953,6 +1028,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_CANCELLED;
}
}
+#endif
void PAINT_OT_weight_sample(wmOperatorType *ot)
{
@@ -961,7 +1037,9 @@ void PAINT_OT_weight_sample(wmOperatorType *ot)
ot->idname= "PAINT_OT_weight_sample";
/* api callbacks */
+#if 0 // BMESH_TODO
ot->invoke= weight_sample_invoke;
+#endif
ot->poll= weight_paint_mode_poll;
/* flags */
@@ -969,6 +1047,7 @@ void PAINT_OT_weight_sample(wmOperatorType *ot)
}
/* samples cursor location, and gives menu with vertex groups to activate */
+#if 0 // BMESH_TODO
static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
{
if (C) {
@@ -1035,6 +1114,7 @@ static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA
return DummyRNA_NULL_items;
}
+#endif
static int weight_sample_group_exec(bContext *C, wmOperator *op)
{
@@ -1068,12 +1148,13 @@ void PAINT_OT_weight_sample_group(wmOperatorType *ot)
/* keyingset to use (dynamic enum) */
prop= RNA_def_enum(ot->srna, "group", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
+#if 0 // BMESH_TODO
RNA_def_enum_funcs(prop, weight_paint_sample_enum_itemf);
+#endif
ot->prop= prop;
}
-#if 0 /* UNUSED */
static void do_weight_paint_auto_normalize(MDeformVert *dvert,
int paint_nr, char *map)
{
@@ -1108,7 +1189,6 @@ static void do_weight_paint_auto_normalize(MDeformVert *dvert,
}
}
}
-#endif
/* the active group should be involved in auto normalize */
static void do_weight_paint_auto_normalize_all_groups(MDeformVert *dvert, const char *vgroup_validmap, char do_auto_normalize)
@@ -1746,7 +1826,7 @@ static int set_wpaint(bContext *C, wmOperator *UNUSED(op)) /* toggle */
paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
paint_cursor_start(C, weight_paint_poll);
- mesh_octree_table(ob, NULL, NULL, 's');
+ //BMESH_TODO mesh_octree_table(ob, NULL, NULL, 's');
/* verify if active weight group is also active bone */
par= modifiers_isDeformedByArmature(ob);
@@ -1758,8 +1838,8 @@ static int set_wpaint(bContext *C, wmOperator *UNUSED(op)) /* toggle */
}
}
else {
- mesh_octree_table(NULL, NULL, NULL, 'e');
- mesh_mirrtopo_table(NULL, 'e');
+ //BMESH_TODO mesh_octree_table(NULL, NULL, NULL, 'e');
+ //BMESH_TODO mesh_mirrtopo_table(NULL, 'e');
}
WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
@@ -1880,6 +1960,13 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *UNUSED
me= get_mesh(ob);
if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
+ /*we can't assume mfaces have a correct origindex layer that indices to mpolys.
+ so instead we have to regenerate the tesselation faces altogether.*/
+ me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata,
+ me->mvert, me->totface, me->totloop, me->totpoly, 1, 0);
+ mesh_update_customdata_pointers(me);
+ makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH, 0);
+
/* if nothing was added yet, we make dverts and a vertex deform group */
if (!me->dvert) {
ED_vgroup_data_create(&me->id);
@@ -2022,22 +2109,22 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
if(wp->flag & VP_COLINDEX) {
for(index=0; index<totindex; index++) {
- if(indexar[index] && indexar[index]<=me->totface) {
- MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
- if(mface->mat_nr!=ob->actcol-1) {
+ if(mpoly->mat_nr!=ob->actcol-1) {
indexar[index]= 0;
}
}
}
}
- if((me->editflag & ME_EDIT_PAINT_MASK) && me->mface) {
+ if((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) {
for(index=0; index<totindex; index++) {
- if(indexar[index] && indexar[index]<=me->totface) {
- MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
- if((mface->flag & ME_FACE_SEL)==0) {
+ if((mpoly->flag & ME_FACE_SEL)==0) {
indexar[index]= 0;
}
}
@@ -2053,42 +2140,38 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
paintweight= ts->vgroup_weight;
for(index=0; index<totindex; index++) {
- if(indexar[index] && indexar[index]<=me->totface) {
- MFace *mface= me->mface + (indexar[index]-1);
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= me->mpoly + (indexar[index]-1);
+ MLoop *ml = me->mloop + mpoly->loopstart;
+ int i;
if(use_vert_sel) {
- me->dvert[mface->v1].flag = (me->mvert[mface->v1].flag & SELECT);
- me->dvert[mface->v2].flag = (me->mvert[mface->v2].flag & SELECT);
- me->dvert[mface->v3].flag = (me->mvert[mface->v3].flag & SELECT);
- if(mface->v4) me->dvert[mface->v4].flag = (me->mvert[mface->v4].flag & SELECT);
+ for (i=0; i<mpoly->totloop; i++, ml++) {
+ me->dvert[ml->v].flag = (me->mvert[ml->v].flag & SELECT);
+ }
}
else {
- me->dvert[mface->v1].flag= 1;
- me->dvert[mface->v2].flag= 1;
- me->dvert[mface->v3].flag= 1;
- if(mface->v4) me->dvert[mface->v4].flag= 1;
+ for (i=0; i<mpoly->totloop; i++, ml++) {
+ me->dvert[ml->v].flag = 1;
+ }
}
if(brush->vertexpaint_tool==VP_BLUR) {
MDeformWeight *dw, *(*dw_func)(MDeformVert *, const int);
- unsigned int fidx= mface->v4 ? 3:2;
if(wp->flag & VP_ONLYVGROUP)
dw_func= (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index;
else
dw_func= defvert_verify_index;
-
- do {
- unsigned int vidx= *(&mface->v1 + fidx);
-
- dw= dw_func(me->dvert+vidx, ob->actdef-1);
- if(dw) {
- paintweight+= dw->weight;
+
+ ml = me->mloop + mpoly->loopstart;
+ for (i=0; i<mpoly->totloop; i++, ml++) {
+ dw = dw_func(me->dvert+ml->v, ob->actdef-1);
+ if (dw) {
+ paintweight += dw->weight;
totw++;
}
-
- } while (fidx--);
-
+ }
}
}
}
@@ -2097,21 +2180,21 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
paintweight/= (float)totw;
for(index=0; index<totindex; index++) {
-
- if(indexar[index] && indexar[index]<=me->totface) {
- MFace *mf= me->mface + (indexar[index]-1);
- unsigned int fidx= mf->v4 ? 3:2;
- do {
- unsigned int vidx= *(&mf->v1 + fidx);
-
- if(me->dvert[vidx].flag) {
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= me->mpoly + (indexar[index]-1);
+ MLoop *ml=me->mloop+mpoly->loopstart;
+ int i;
+
+ for (i=0; i<mpoly->totloop; i++, ml++) {
+ unsigned int vidx= ml->v;
+ if (me->dvert[vidx].flag) {
alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*vidx, mval, pressure);
if(alpha) {
do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight);
}
me->dvert[vidx].flag= 0;
}
- } while (fidx--);
+ }
}
}
@@ -2251,7 +2334,7 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */
return OPERATOR_PASS_THROUGH;
}
- if(me && me->mcol==NULL) make_vertexcol(ob);
+ if(me && me->mloopcol==NULL) make_vertexcol(ob);
/* toggle: end vpaint */
if(ob->mode & OB_MODE_VERTEX_PAINT) {
@@ -2319,14 +2402,60 @@ For future:
*/
+typedef struct polyfacemap_e {
+ struct polyfacemap_e *next, *prev;
+ int facenr;
+} polyfacemap_e;
+
typedef struct VPaintData {
ViewContext vc;
unsigned int paintcol;
int *indexar;
float *vertexcosnos;
float vpimat[3][3];
+
+ /*mpoly -> mface mapping*/
+ MemArena *arena;
+ ListBase *polyfacemap;
} VPaintData;
+static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me,
+ Object *ob, Scene *scene)
+{
+ MFace *mf;
+ polyfacemap_e *e;
+ int *origIndex;
+ int i;
+
+ vd->arena = BLI_memarena_new(1<<13, "vpaint tmp");
+ BLI_memarena_use_calloc(vd->arena);
+
+ vd->polyfacemap = BLI_memarena_alloc(vd->arena, sizeof(ListBase)*me->totpoly);
+
+ /*we can't assume mfaces have a correct origindex layer that indices to mpolys.
+ so instead we have to regenerate the tesselation faces altogether.*/
+ me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata,
+ me->mvert, me->totface, me->totloop, me->totpoly, 1, 0);
+ mesh_update_customdata_pointers(me);
+ makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH, 0);
+
+ origIndex = CustomData_get_layer(&me->fdata, CD_ORIGINDEX);
+ mf = me->mface;
+
+ if (!origIndex)
+ return;
+
+ for (i=0; i<me->totface; i++, mf++, origIndex++) {
+ if (*origIndex == ORIGINDEX_NONE)
+ continue;
+
+ e = BLI_memarena_alloc(vd->arena, sizeof(polyfacemap_e));
+ e->facenr = i;
+
+ BLI_addtail(&vd->polyfacemap[*origIndex], e);
+ }
+}
+
static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *UNUSED(event))
{
ToolSettings *ts= CTX_data_tool_settings(C);
@@ -2334,15 +2463,19 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent
VPaint *vp= ts->vpaint;
struct VPaintData *vpd;
Object *ob= CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
Mesh *me;
float mat[4][4], imat[4][4];
/* context checks could be a poll() */
me= get_mesh(ob);
- if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
+ if(me==NULL || me->totpoly==0)
+ return OPERATOR_PASS_THROUGH;
- if(me->mcol==NULL) make_vertexcol(ob);
- if(me->mcol==NULL) return OPERATOR_CANCELLED;
+ if(me->mloopcol==NULL)
+ make_vertexcol(ob);
+ if(me->mloopcol==NULL)
+ return OPERATOR_CANCELLED;
/* make mode data storage */
vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData");
@@ -2352,9 +2485,10 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent
vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob);
vpd->indexar= get_indexarray(me);
vpd->paintcol= vpaint_get_current_col(vp);
+ vpaint_build_poly_facemap(vpd, me, ob, scene);
/* for filtering */
- copy_vpaint_prev(vp, (unsigned int *)me->mcol, me->totface);
+ copy_vpaint_prev(vp, (unsigned int *)me->mloopcol, me->totloop);
/* some old cruft to sort out later */
mul_m4_m4m4(mat, ob->obmat, vpd->vc.rv3d->viewmat);
@@ -2364,7 +2498,8 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent
return 1;
}
-static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, const unsigned int index, const float mval[2], float pressure, int UNUSED(flip))
+#if 0
+static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, int index, const float mval[2], float pressure, int UNUSED(flip))
{
ViewContext *vc = &vpd->vc;
Brush *brush = paint_brush(&vp->paint);
@@ -2397,6 +2532,7 @@ static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, const uns
vpaint_blend(vp, mcol+i, mcolorig+i, vpd->paintcol, (int)(alpha*255.0f));
}
}
+#endif
static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
{
@@ -2406,6 +2542,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
Brush *brush = paint_brush(&vp->paint);
ViewContext *vc= &vpd->vc;
Object *ob= vc->obact;
+ polyfacemap_e *e;
Mesh *me= ob->data;
float mat[4][4];
int *indexar= vpd->indexar;
@@ -2427,7 +2564,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
/* which faces are involved */
if(vp->flag & VP_AREA) {
- totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size(brush));
+ totindex= sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size(brush));
}
else {
indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
@@ -2437,19 +2574,114 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
swap_m4m4(vc->rv3d->persmat, mat);
- for(index=0; index<totindex; index++) {
- if(indexar[index] && indexar[index]<=me->totface)
- vpaint_paint_face(vp, vpd, ob, indexar[index]-1, mval, pressure, flip);
+ if(vp->flag & VP_COLINDEX) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
+
+ if(mpoly->mat_nr!=ob->actcol-1) {
+ indexar[index]= 0;
+ }
+ }
+ }
}
+
+ if((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
+ if((mpoly->flag & ME_FACE_SEL)==0)
+ indexar[index]= 0;
+ }
+ }
+ }
+
swap_m4m4(vc->rv3d->persmat, mat);
/* was disabled because it is slow, but necessary for blur */
if(brush->vertexpaint_tool == VP_BLUR)
do_shared_vertexcol(me);
- ED_region_tag_redraw(vc->ar);
+ for(index=0; index<totindex; index++) {
+
+ if(indexar[index] && indexar[index]<=me->totpoly) {
+ MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
+ MFace *mf;
+ MCol *mc;
+ MLoop *ml;
+ MLoopCol *mlc;
+ unsigned int *lcol = ((unsigned int*)me->mloopcol) + mpoly->loopstart;
+ unsigned int *lcolorig = ((unsigned int*)vp->vpaint_prev) + mpoly->loopstart;
+ float alpha;
+ int i, j;
+
+ if(brush->vertexpaint_tool==VP_BLUR) {
+ unsigned int blend[5] = {0};
+ char *col;
+
+ for (j=0; j<mpoly->totloop; j += 2) {
+ col = (char*)(lcol + j);
+ blend[0] += col[0];
+ blend[1] += col[1];
+ blend[2] += col[2];
+ blend[3] += col[3];
+ }
+
+ blend[0] /= mpoly->totloop;
+ blend[1] /= mpoly->totloop;
+ blend[2] /= mpoly->totloop;
+ blend[3] /= mpoly->totloop;
+ col = (char*)(blend + 4);
+ col[0] = blend[0];
+ col[1] = blend[1];
+ col[2] = blend[2];
+ col[3] = blend[3];
+
+ vpd->paintcol = *((unsigned int*)col);
+ }
+
+ ml = me->mloop + mpoly->loopstart;
+ for (i=0; i<mpoly->totloop; i++, ml++) {
+ alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat,
+ vpd->vertexcosnos+6*ml->v, mval, pressure);
+ if(alpha > 0.0f) vpaint_blend(vp, lcol+i, lcolorig+i, vpd->paintcol, (int)(alpha*255.0f));
+ }
+
+ #ifdef CPYCOL
+ #undef CPYCOL
+ #endif
+ #define CPYCOL(c, l) (c)->a = (l)->a, (c)->r = (l)->r, (c)->g = (l)->g, (c)->b = (l)->b
+
+ /*update vertex colors for tesselations incrementally,
+ rather then regenerating the tesselation altogether.*/
+ for (e=vpd->polyfacemap[(indexar[index]-1)].first; e; e=e->next) {
+ mf = me->mface + e->facenr;
+ mc = me->mcol + e->facenr*4;
+
+ ml = me->mloop + mpoly->loopstart;
+ mlc = me->mloopcol + mpoly->loopstart;
+ for (j=0; j<mpoly->totloop; j++, ml++, mlc++) {
+ if (ml->v == mf->v1)
+ CPYCOL(mc, mlc);
+ else if (ml->v == mf->v2)
+ CPYCOL(mc+1, mlc);
+ else if (ml->v == mf->v3)
+ CPYCOL(mc+2, mlc);
+ else if (mf->v4 && ml->v == mf->v4)
+ CPYCOL(mc+3, mlc);
+
+ }
+ }
+ #undef CPYCOL
+ }
+ }
+
+ swap_m4m4(vc->rv3d->persmat, mat);
+ do_shared_vertexcol(me);
+
+ ED_region_tag_redraw(vc->ar);
DAG_id_tag_update(ob->data, 0);
}
@@ -2464,7 +2696,8 @@ static void vpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
/* frees prev buffer */
copy_vpaint_prev(ts->vpaint, NULL, 0);
-
+ BLI_memarena_free(vpd->arena);
+
MEM_freeN(vpd);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 0b009dba651..9b3d12b159d 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -107,7 +107,7 @@ struct MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
Mesh *me= (Mesh*)ob->data;
ModifierData *md;
- if(!CustomData_get_layer(&me->fdata, CD_MDISPS)) {
+ if(!CustomData_get_layer(&me->ldata, CD_MDISPS)) {
/* multires can't work without displacement layer */
return NULL;
}
@@ -203,6 +203,8 @@ typedef struct StrokeCache {
float mouse[2];
float bstrength;
float tex_mouse[2];
+
+ rctf prect;
/* The rest is temporary storage that isn't saved as a property */
@@ -253,6 +255,15 @@ static int sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d,
float bb_min[3], bb_max[3], pmat[4][4];
int i, j, k;
+/* if (G.rt == 1) {
+ rect->xmin = ob->sculpt->cache->prect.xmin;
+ rect->xmax = ob->sculpt->cache->prect.xmax;
+ rect->ymin = ob->sculpt->cache->prect.ymin;
+ rect->ymax = ob->sculpt->cache->prect.ymax;
+
+ return rect->xmin < rect->xmax && rect->ymin < rect->ymax;;
+ }
+*/
ED_view3d_ob_project_mat_get(rv3d, ob, pmat);
if(!pbvh)
@@ -307,6 +318,7 @@ void sculpt_get_redraw_planes(float planes[4][4], ARegion *ar,
PBVH *pbvh= ob->sculpt->pbvh;
BoundBox bb;
bglMats mats;
+ StrokeCache *cache = ob->sculpt->cache;
rcti rect;
memset(&bb, 0, sizeof(BoundBox));
@@ -335,6 +347,13 @@ void sculpt_get_redraw_planes(float planes[4][4], ARegion *ar,
/* clear redraw flag from nodes */
if(pbvh)
BLI_pbvh_update(pbvh, PBVH_UpdateRedraw, NULL);
+
+ /*clear prect*/
+ cache->prect.xmin = FLT_MAX;
+ cache->prect.xmax = -FLT_MAX;
+ cache->prect.ymin = FLT_MAX;
+ cache->prect.ymax = -FLT_MAX;
+
}
/************************ Brush Testing *******************/
@@ -1364,7 +1383,7 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
proxy= BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
-
+
BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) {
if(sculpt_brush_test(&test, vd.co)) {
const float fade = bstrength*tex_strength(ss, brush, vd.co, test.dist)*frontface(brush, an, vd.no, vd.fno);
@@ -2193,7 +2212,6 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
float bstrength = ss->cache->bstrength;
const float radius = ss->cache->radius;
-
float an[3];
float fc[3];
float offset = get_offset(sd, ss);
@@ -2290,7 +2308,7 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
for (a= 0; a < me->totvert; a++, mvert++)
VECCOPY(mvert->co, vertCos[a]);
- mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+ mesh_calc_normals(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL, NULL, 0, NULL, NULL);
}
/* apply new coords on active key block */
@@ -2523,7 +2541,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob)
/* Modifiers could depend on mesh normals, so we should update them/
Note, then if sculpting happens on locked key, normals should be re-calculated
after applying coords from keyblock on base mesh */
- mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+ mesh_calc_normals(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL, NULL, 0, NULL, NULL);
} else if (ss->kb)
sculpt_update_keyblock(ob);
}
@@ -2677,7 +2695,7 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, int need_
if(mmd) {
ss->multires = mmd;
ss->totvert = dm->getNumVerts(dm);
- ss->totface = dm->getNumFaces(dm);
+ ss->totface = dm->getNumTessFaces(dm);
ss->mvert= NULL;
ss->mface= NULL;
ss->face_normals= NULL;
@@ -2828,6 +2846,11 @@ static void sculpt_update_cache_invariants(bContext* C, Sculpt *sd, SculptSessio
int mode;
ss->cache = cache;
+
+ cache->prect.xmin = FLT_MAX;
+ cache->prect.xmax = -FLT_MAX;
+ cache->prect.ymin = FLT_MAX;
+ cache->prect.ymax = -FLT_MAX;
/* Set scaling adjustment */
ss->cache->scale[0] = 1.0f / ob->size[0];
@@ -3445,6 +3468,7 @@ static void sculpt_stroke_done(bContext *C, struct PaintStroke *UNUSED(stroke))
sculpt_cache_free(ss->cache);
ss->cache = NULL;
+ sculpt_flush_update(C);
sculpt_undo_push_end();
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 4c54a5891b1..014cbff3e22 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -196,8 +196,8 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
tag_update= ((Mesh*)ob->data)->id.us > 1;
if(ss->modifiers_active) {
- Mesh *me= ob->data;
- mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+ Mesh *mesh= ob->data;
+ mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, NULL, NULL, 0, NULL, NULL);
free_sculptsession_deformMats(ss);
tag_update|= 1;
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index eb29dfb2ce1..7bf0f98b471 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -261,7 +261,7 @@ static void get_keyframe_extents (bAnimContext *ac, float *min, float *max, cons
float tmin, tmax;
/* get range and apply necessary scaling before processing */
- calc_fcurve_range(fcu, &tmin, &tmax, onlySel, TRUE);
+ calc_fcurve_range(fcu, &tmin, &tmax, onlySel);
if (adt) {
tmin= BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);
diff --git a/source/blender/editors/space_api/CMakeLists.txt b/source/blender/editors/space_api/CMakeLists.txt
index 6f2a0385231..611322fc1ab 100644
--- a/source/blender/editors/space_api/CMakeLists.txt
+++ b/source/blender/editors/space_api/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenkernel
../../blenlib
../../blenloader
+ ../../bmesh
../../makesdna
../../makesrna
../../windowmanager
diff --git a/source/blender/editors/space_api/SConscript b/source/blender/editors/space_api/SConscript
index d6a763a78ff..6bf901cf8ad 100644
--- a/source/blender/editors/space_api/SConscript
+++ b/source/blender/editors/space_api/SConscript
@@ -4,7 +4,7 @@ Import ('env')
sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../blenloader ../../makesdna'
-incs += ' ../../windowmanager ../../python ../../makesrna'
+incs += ' ../../windowmanager ../../python ../../makesrna ../../bmesh'
incs += ' #/intern/guardedalloc #/extern/glew/include'
defs = ''
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 99ab356ac5f..1dfcb2961c1 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -39,6 +39,8 @@
#include "BKE_context.h"
#include "BKE_screen.h"
+#include "bmesh.h"
+
#include "UI_interface.h"
#include "UI_view2d.h"
diff --git a/source/blender/editors/space_buttons/SConscript b/source/blender/editors/space_buttons/SConscript
index 740353bc1f0..7bc588c627c 100644
--- a/source/blender/editors/space_buttons/SConscript
+++ b/source/blender/editors/space_buttons/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
-incs += ' ../../makesrna ../../render/extern/include ../../blenloader'
+incs += ' ../../bmesh ../../makesrna ../../render/extern/include ../../blenloader'
defs = []
diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt
index 15c90fb701e..3975a5f56f3 100644
--- a/source/blender/editors/space_image/CMakeLists.txt
+++ b/source/blender/editors/space_image/CMakeLists.txt
@@ -25,6 +25,7 @@ set(INC
../../blenlib
../../blenloader
../../imbuf
+ ../../bmesh
../../makesdna
../../makesrna
../../render/extern/include
diff --git a/source/blender/editors/space_image/SConscript b/source/blender/editors/space_image/SConscript
index 27696e35701..cdd2133d0f5 100644
--- a/source/blender/editors/space_image/SConscript
+++ b/source/blender/editors/space_image/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
-incs += ' ../../render/extern/include ../../makesrna ../../blenloader'
+incs += ' ../../bmesh ../../render/extern/include ../../makesrna ../../blenloader'
defs = []
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 3b9876329ec..14956016449 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -274,12 +274,11 @@ int ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
return 0;
if(obedit && obedit->type == OB_MESH) {
- EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
+ struct BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
int ret;
- ret = EM_texFaceCheck(em);
+ ret = EDBM_texFaceCheck(em);
- BKE_mesh_end_editmesh(obedit->data, em);
return ret;
}
@@ -293,12 +292,11 @@ int ED_space_image_show_uvshadow(SpaceImage *sima, Object *obedit)
if(ED_space_image_show_paint(sima))
if(obedit && obedit->type == OB_MESH) {
- EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
+ struct BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
int ret;
- ret = EM_texFaceCheck(em);
+ ret = EDBM_texFaceCheck(em);
- BKE_mesh_end_editmesh(obedit->data, em);
return ret;
}
@@ -585,13 +583,13 @@ static void image_refresh(const bContext *C, ScrArea *UNUSED(sa))
if(ima && (ima->source==IMA_SRC_VIEWER || sima->pin));
else if(obedit && obedit->type == OB_MESH) {
Mesh *me= (Mesh*)obedit->data;
- EditMesh *em= BKE_mesh_get_editmesh(me);
- MTFace *tf;
+ struct BMEditMesh *em= me->edit_btmesh;
+ MTexPoly *tf;
- if(em && EM_texFaceCheck(em)) {
+ if(em && EDBM_texFaceCheck(em)) {
sima->image= NULL;
- tf = EM_get_active_mtface(em, NULL, NULL, 1); /* partially selected face is ok */
+ tf = EDBM_get_active_mtexpoly(em, NULL, 1); /* partially selected face is ok */
if(tf) {
/* don't need to check for pin here, see above */
@@ -601,8 +599,6 @@ static void image_refresh(const bContext *C, ScrArea *UNUSED(sa))
else sima->curtile= tf->tile;
}
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
}
}
diff --git a/source/blender/editors/space_info/CMakeLists.txt b/source/blender/editors/space_info/CMakeLists.txt
index 4c1c13c1092..7cf5b1fc3fb 100644
--- a/source/blender/editors/space_info/CMakeLists.txt
+++ b/source/blender/editors/space_info/CMakeLists.txt
@@ -25,6 +25,7 @@ set(INC
../../blenlib
../../blenloader
../../imbuf
+ ../../bmesh
../../makesdna
../../makesrna
../../windowmanager
diff --git a/source/blender/editors/space_info/SConscript b/source/blender/editors/space_info/SConscript
index 697ee4319b8..746edadccc2 100644
--- a/source/blender/editors/space_info/SConscript
+++ b/source/blender/editors/space_info/SConscript
@@ -4,7 +4,7 @@ Import ('env')
sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf ../../blenfont'
-incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include ../../blenloader'
+incs += ' ../../bmesh ../../windowmanager #/intern/guardedalloc #/extern/glew/include ../../blenloader'
defs = []
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 25e1d2f2816..529e976a904 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -46,6 +46,7 @@
#include "BKE_key.h"
#include "BKE_mesh.h"
#include "BKE_particle.h"
+#include "BKE_tessmesh.h"
#include "ED_info.h"
#include "ED_armature.h"
@@ -138,26 +139,16 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
static void stats_object_edit(Object *obedit, SceneStats *stats)
{
if(obedit->type==OB_MESH) {
- /* Mesh Edit */
- EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
+ BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
+
+ stats->totvert = em->bm->totvert;
+ stats->totvertsel = em->bm->totvertsel;
- for(eve= em->verts.first; eve; eve=eve->next) {
- stats->totvert++;
- if(eve->f & SELECT) stats->totvertsel++;
- }
- for(eed= em->edges.first; eed; eed=eed->next) {
- stats->totedge++;
- if(eed->f & SELECT) stats->totedgesel++;
- }
- for(efa= em->faces.first; efa; efa=efa->next) {
- stats->totface++;
- if(efa->f & SELECT) stats->totfacesel++;
- }
+ stats->totedge = em->bm->totedge;
+ stats->totedgesel = em->bm->totedgesel;
- EM_validate_selections(em);
+ stats->totface = em->bm->totface;
+ stats->totfacesel = em->bm->totfacesel;
}
else if(obedit->type==OB_ARMATURE){
/* Armature Edit */
diff --git a/source/blender/editors/space_node/SConscript b/source/blender/editors/space_node/SConscript
index c4309dcfca3..a21b27502a8 100644
--- a/source/blender/editors/space_node/SConscript
+++ b/source/blender/editors/space_node/SConscript
@@ -14,7 +14,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
if env['CC'] == 'gcc':
#cf.append('-Werror')
pass
-
+
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'
incs += ' ../../../extern/binreloc/include'
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 608a3c4c0b2..10ca482ae0e 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -310,19 +310,11 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
}
/* Check the library target exists */
if (te->idcode == ID_LI) {
- Library *lib= (Library *)tselem->id;
- char expanded[FILE_MAX];
-
- BLI_strncpy(expanded, lib->name, sizeof(expanded));
-
- /* even though we already set the name this syncs the absolute
- * path, this is intentionally not already expanded yet to
- * avoid copying lib->name to its self. */
- BKE_library_filepath_set(lib, expanded);
-
+ char expanded[FILE_MAXDIR + FILE_MAXFILE];
+ BLI_strncpy(expanded, ((Library *)tselem->id)->name, FILE_MAXDIR + FILE_MAXFILE);
BLI_path_abs(expanded, G.main->name);
if (!BLI_exists(expanded)) {
- BKE_reportf(CTX_wm_reports(C), RPT_ERROR, "Library path '%s' does not exist, correct this before saving", expanded);
+ BKE_report(CTX_wm_reports(C), RPT_ERROR, "This path does not exist, correct this before saving");
}
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index a4f67f91763..78907fbd1ed 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -310,7 +310,9 @@ static void object_delete_cb(bContext *C, Scene *scene, TreeElement *te, TreeSto
static void id_local_cb(bContext *UNUSED(C), Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem)
{
if (tselem->id->lib && (tselem->id->flag & LIB_EXTERN)) {
- id_clear_lib_data(NULL, tselem->id);
+ tselem->id->lib= NULL;
+ tselem->id->flag= LIB_LOCAL;
+ new_id(NULL, tselem->id, NULL);
}
}
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index ffcf2606a04..b200a6269f1 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -2224,7 +2224,7 @@ static int scroll_invoke(bContext *C, wmOperator *op, wmEvent *event)
text_update_character_width(st);
tsc->old[0] = event->x;
- tsc->old[1] = event->y;
+ tsc->old[1] = event->x;
/* Sensitivity of scroll set to 4pix per line/char */
tsc->delta[0] = (event->x - event->prevx)*st->cwidth/4;
tsc->delta[1] = (event->y - event->prevy)*st->lheight/4;
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index f1ef35936fa..e78bad62ba5 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenkernel
../../blenlib
../../blenloader
+ ../../bmesh
../../gpu
../../imbuf
../../makesdna
diff --git a/source/blender/editors/space_view3d/SConscript b/source/blender/editors/space_view3d/SConscript
index 84ba8d1fe86..53bd7828b63 100644
--- a/source/blender/editors/space_view3d/SConscript
+++ b/source/blender/editors/space_view3d/SConscript
@@ -7,7 +7,7 @@ defs = [ 'GLEW_STATIC' ]
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../render/extern/include ../../blenloader'
-incs += ' ../../gpu ../../makesrna ../../blenfont'
+incs += ' ../../gpu ../../makesrna ../../blenfont ../../bmesh'
incs += ' #/intern/smoke/extern'
incs += ' #source/gameengine/BlenderRoutines'
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index 670943afdd3..ec114fbfcde 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -32,6 +32,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
@@ -44,6 +45,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
#include "DNA_object_types.h"
#include "BKE_DerivedMesh.h"
@@ -52,6 +54,7 @@
#include "BKE_material.h"
#include "BKE_paint.h"
#include "BKE_property.h"
+#include "BKE_tessmesh.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -224,7 +227,7 @@ static int set_draw_settings_cached(int clearcache, MTFace *texface, Material *m
static int c_lit;
Object *litob = NULL; //to get mode to turn off mipmap in painting mode
- int backculled = GEMAT_BACKCULL;
+ int backculled = 0;
int alphablend = 0;
int textured = 0;
int lit = 0;
@@ -418,15 +421,15 @@ static int draw_tface__set_draw(MTFace *tface, int has_mcol, int matnr)
static void add_tface_color_layer(DerivedMesh *dm)
{
MTFace *tface = DM_get_face_data_layer(dm, CD_MTFACE);
- MFace *mface = DM_get_face_data_layer(dm, CD_MFACE);
+ MFace *mface = dm->getTessFaceArray(dm);
MCol *finalCol;
int i,j;
- MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
+ MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
if(!mcol)
- mcol = dm->getFaceDataArray(dm, CD_MCOL);
+ mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
- finalCol = MEM_mallocN(sizeof(MCol)*4*dm->getNumFaces(dm),"add_tface_color_layer");
- for(i=0;i<dm->getNumFaces(dm);i++) {
+ finalCol = MEM_mallocN(sizeof(MCol)*4*dm->getNumTessFaces(dm),"add_tface_color_layer");
+ for(i=0;i<dm->getNumTessFaces(dm);i++) {
Material *ma= give_current_material(Gtexdraw.ob, mface[i].mat_nr+1);
if (ma && (ma->game.flag&GEMAT_INVISIBLE)) {
@@ -494,28 +497,52 @@ static void add_tface_color_layer(DerivedMesh *dm)
static int draw_tface_mapped__set_draw(void *userData, int index)
{
Mesh *me = (Mesh*)userData;
- MTFace *tface = (me->mtface)? &me->mtface[index]: NULL;
- MFace *mface = &me->mface[index];
- const int matnr = mface->mat_nr;
- if (mface->flag & ME_HIDE) return 0;
- return draw_tface__set_draw(tface, (me->mcol != NULL), matnr);
+ MTexPoly *tpoly = (me->mtpoly)? &me->mtpoly[index]: NULL;
+ MPoly *mpoly = (me->mpoly)? &me->mpoly[index]: NULL;
+ MTFace mtf;
+ int matnr = me->mpoly[index].mat_nr;
+
+ if (mpoly && mpoly->flag&ME_HIDE) return 0;
+
+ memset(&mtf, 0, sizeof(mtf));
+ if (tpoly) {
+ mtf.flag = tpoly->flag;
+ mtf.tpage = tpoly->tpage;
+ mtf.transp = tpoly->transp;
+ mtf.mode = tpoly->mode;
+ mtf.tile = tpoly->tile;
+ mtf.unwrap = tpoly->unwrap;
+ }
+
+ return draw_tface__set_draw(&mtf, (me->mcol != NULL), matnr);
}
static int draw_em_tf_mapped__set_draw(void *userData, int index)
{
- struct {EditMesh *em; short has_mcol; short has_mtface;} *data = userData;
- EditMesh *em = data->em;
- EditFace *efa= EM_get_face_for_index(index);
- MTFace *tface;
- int matnr;
+ struct {BMEditMesh *em; short has_mcol; short has_mtface;} *data = userData;
+ BMEditMesh *em = data->em;
+ BMFace *efa= EDBM_get_face_for_index(em, index);
- if (efa->h)
+ if (efa==NULL || BM_TestHFlag(efa, BM_HIDDEN)) {
return 0;
+ }
+ else {
+ MTFace mtf= {{{0}}};
+ int matnr = efa->mat_nr;
+
+ if (data->has_mtface) {
+ MTexPoly *tpoly = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ mtf.flag = tpoly->flag;
+ mtf.tpage = tpoly->tpage;
+ mtf.transp = tpoly->transp;
+ mtf.mode = tpoly->mode;
+ mtf.tile = tpoly->tile;
+ mtf.unwrap = tpoly->unwrap;
- tface = data->has_mtface ? CustomData_em_get(&em->fdata, efa->data, CD_MTFACE) : NULL;
- matnr = efa->mat_nr;
+ }
- return draw_tface__set_draw_legacy(tface, data->has_mcol, matnr);
+ return draw_tface__set_draw_legacy(&mtf, data->has_mcol, matnr);
+ }
}
static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
@@ -633,11 +660,11 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *o
glColor4f(1.0f,1.0f,1.0f,1.0f);
if(ob->mode & OB_MODE_EDIT) {
- struct {EditMesh *em; short has_mcol; short has_mtface;} data;
+ struct {BMEditMesh *em; short has_mcol; short has_mtface;} data;
- data.em= me->edit_mesh;
- data.has_mcol= CustomData_has_layer(&me->edit_mesh->fdata, CD_MCOL);
- data.has_mtface= CustomData_has_layer(&me->edit_mesh->fdata, CD_MTFACE);
+ data.em= me->edit_btmesh;
+ data.has_mcol= CustomData_has_layer(&me->edit_btmesh->bm->ldata, CD_MLOOPCOL);
+ data.has_mtface= CustomData_has_layer(&me->edit_btmesh->bm->pdata, CD_MTEXPOLY);
dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, &data);
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index a6424b183d1..13c89de374e 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -47,6 +47,7 @@
#include "DNA_world_types.h"
#include "DNA_armature_types.h"
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_editVert.h"
@@ -75,6 +76,8 @@
#include "BKE_pointcache.h"
#include "BKE_unit.h"
+#include "BKE_tessmesh.h"
+
#include "smoke_API.h"
#include "IMB_imbuf.h"
@@ -1656,16 +1659,18 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
* use the object matrix in the useual way */
static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
{
- struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
- EditVert *eve = EM_get_vert_for_index(index);
+ struct { void (*func)(void *userData, BMVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
+ BMVert *eve = EDBM_get_vert_for_index(data->vc.em, index);
- if (eve->h==0) {
+ if (!BM_TestHFlag(eve, BM_HIDDEN)) {
short s[2]= {IS_CLIPPED, 0};
if (data->clipVerts) {
view3d_project_short_clip(data->vc.ar, co, s, 1);
} else {
- view3d_project_short_noclip(data->vc.ar, co, s);
+ float co2[2];
+ mul_v3_m4v3(co2, data->vc.obedit->obmat, co);
+ project_short_noclip(data->vc.ar, co2, s);
}
if (s[0]!=IS_CLIPPED)
@@ -1673,22 +1678,22 @@ static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co
}
}
-void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
+void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BMVert *eve, int x, int y, int index), void *userData, int clipVerts)
{
- struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
- DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
+ struct { void (*func)(void *userData, BMVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
+ DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
data.vc= *vc;
data.func = func;
data.userData = userData;
data.clipVerts = clipVerts;
+ EDBM_init_index_arrays(vc->em, 1, 0, 0);
if(clipVerts)
ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
- EM_init_index_arrays(vc->em, 1, 0, 0);
dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
- EM_free_index_arrays();
+ EDBM_free_index_arrays(vc->em);
dm->release(dm);
}
@@ -1721,17 +1726,23 @@ static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
}
static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
{
- struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
- EditEdge *eed = EM_get_edge_for_index(index);
- short s[2][2];
+ struct { void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
+ BMEdge *eed = EDBM_get_edge_for_index(data->vc.em, index);
+
+ if (!BM_TestHFlag(eed, BM_HIDDEN)) {
+ short s[2][2];
- if (eed->h==0) {
if (data->clipVerts==1) {
view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
} else {
- view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
- view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
+ float v1_co[3], v2_co[3];
+
+ mul_v3_m4v3(v1_co, data->vc.obedit->obmat, v0co);
+ mul_v3_m4v3(v2_co, data->vc.obedit->obmat, v1co);
+
+ project_short_noclip(data->vc.ar, v1_co, s[0]);
+ project_short_noclip(data->vc.ar, v2_co, s[1]);
if (data->clipVerts==2) {
if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
@@ -1744,34 +1755,37 @@ static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0
}
}
-void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
+void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
{
- struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
- DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
+ struct { void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
+ DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
data.vc= *vc;
data.func = func;
data.userData = userData;
data.clipVerts = clipVerts;
+ EDBM_init_index_arrays(vc->em, 0, 1, 0);
if(clipVerts)
ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
- EM_init_index_arrays(vc->em, 0, 1, 0);
dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
- EM_free_index_arrays();
+ EDBM_free_index_arrays(vc->em);
dm->release(dm);
}
static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
{
- struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
- EditFace *efa = EM_get_face_for_index(index);
- short s[2];
+ struct { void (*func)(void *userData, BMFace *efa, int x, int y, int index); void *userData; ViewContext vc; float pmat[4][4], vmat[4][4]; } *data = userData;
+ BMFace *efa = EDBM_get_face_for_index(data->vc.em, index);
+
+ if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
+ float cent2[3];
+ short s[2];
- if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
- view3d_project_short_clip(data->vc.ar, cent, s, 1);
+ mul_v3_m4v3(cent2, data->vc.obedit->obmat, cent);
+ project_short(data->vc.ar, cent2, s);
if (s[0] != IS_CLIPPED) {
data->func(data->userData, efa, s[0], s[1], index);
@@ -1779,21 +1793,21 @@ static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *ce
}
}
-void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
+void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, BMFace *efa, int x, int y, int index), void *userData)
{
- struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
- DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
+ struct { void (*func)(void *userData, BMFace *efa, int x, int y, int index); void *userData; ViewContext vc; float pmat[4][4], vmat[4][4]; } data;
+ DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
data.vc= *vc;
data.func = func;
data.userData = userData;
+ EDBM_init_index_arrays(vc->em, 0, 0, 1);
//if(clipVerts)
ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
- EM_init_index_arrays(vc->em, 0, 0, 1);
dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
- EM_free_index_arrays();
+ EDBM_free_index_arrays(vc->em);
dm->release(dm);
}
@@ -1860,46 +1874,53 @@ void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb
static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
{
- ToolSettings *ts= ((Scene *)userData)->toolsettings;
- EditFace *efa = EM_get_face_for_index(index);
+ Scene *scene= ((void **)userData)[0];
+ BMEditMesh *em = ((void **)userData)[1];
+ BMFace *efa = EDBM_get_face_for_index(em, index);
+ ToolSettings *ts= scene->toolsettings;
- if (efa->h==0 && efa->fgonf!=EM_FGON) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN)) {
glVertex3fv(cent);
glVertex3f( cent[0] + no[0]*ts->normalsize,
cent[1] + no[1]*ts->normalsize,
cent[2] + no[2]*ts->normalsize);
}
}
-static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm)
+static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
{
+ void *ptrs[2] = {scene, em};
+
glBegin(GL_LINES);
- dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
+ dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, ptrs);
glEnd();
}
static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
{
- EditFace *efa = EM_get_face_for_index(index);
- int sel = *((int*) userData);
-
- if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
+ BMFace *efa = EDBM_get_face_for_index(((void **)userData)[0], index);
+ int sel = *(((int **)userData)[1]);
+
+ if (efa && !BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)==sel) {
bglVertex3fv(cent);
}
}
-static void draw_dm_face_centers(DerivedMesh *dm, int sel)
+static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, int sel)
{
+ void *ptrs[2] = {em, &sel};
+
bglBegin(GL_POINTS);
- dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
+ dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs);
bglEnd();
}
static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
{
- Scene *scene= (Scene *)userData;
+ Scene *scene= ((void **)userData)[0];
ToolSettings *ts= scene->toolsettings;
- EditVert *eve = EM_get_vert_for_index(index);
+ BMEditMesh *em = ((void **)userData)[1];
+ BMVert *eve = EDBM_get_vert_for_index(em, index);
- if (eve->h==0) {
+ if (!BM_TestHFlag(eve, BM_HIDDEN)) {
glVertex3fv(co);
if (no_f) {
@@ -1913,20 +1934,22 @@ static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co,
}
}
}
-static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm)
+static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
{
+ void *ptrs[2] = {scene, em};
+
glBegin(GL_LINES);
- dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
+ dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, ptrs);
glEnd();
}
- /* Draw verts with color set based on selection */
+/* Draw verts with color set based on selection */
static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
{
- struct { int sel; EditVert *eve_act; } * data = userData;
- EditVert *eve = EM_get_vert_for_index(index);
+ struct { BMEditMesh *em; int sel; BMVert *eve_act; } *data = userData;
+ BMVert *eve = EDBM_get_vert_for_index(data->em, index);
- if (eve->h==0 && (eve->f&SELECT)==data->sel) {
+ if (!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)==data->sel) {
/* draw active larger - need to stop/start point drawing for this :/ */
if (eve==data->eve_act) {
float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
@@ -1948,11 +1971,16 @@ static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *
}
}
-static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
+static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act)
{
- struct { int sel; EditVert *eve_act; } data;
+ struct { BMEditMesh *em; int sel; BMVert *eve_act; } data;
data.sel = sel;
data.eve_act = eve_act;
+ data.em = em;
+
+ bglBegin(GL_POINTS);
+ dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
+ bglEnd();
bglBegin(GL_POINTS);
dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
@@ -1962,16 +1990,18 @@ static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
/* Draw edges with color set based on selection */
static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
{
- EditEdge *eed = EM_get_edge_for_index(index);
+ BMEdge *eed;
//unsigned char **cols = userData, *col;
- struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
+ struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } * data = userData;
unsigned char *col;
- if (eed->h==0) {
+ eed = EDBM_get_edge_for_index(data->em, index);
+
+ if (!BM_TestHFlag(eed, BM_HIDDEN)) {
if (eed==data->eed_act) {
glColor4ubv(data->actCol);
} else {
- if (eed->f&SELECT) {
+ if (BM_TestHFlag(eed, BM_SELECT)) {
col = data->selCol;
} else {
col = data->baseCol;
@@ -1986,38 +2016,40 @@ static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
return 0;
}
}
-static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
+static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
+ unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act)
{
- struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
+ struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } data;
data.baseCol = baseCol;
data.selCol = selCol;
data.actCol = actCol;
+ data.em = em;
data.eed_act = eed_act;
dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
}
/* Draw edges */
-static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
+static int draw_dm_edges__setDrawOptions(void *userData, int index)
{
- return EM_get_edge_for_index(index)->h==0;
+ return !BM_TestHFlag(EDBM_get_edge_for_index(userData, index), BM_HIDDEN);
}
-static void draw_dm_edges(DerivedMesh *dm)
+static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm)
{
- dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
+ dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em);
}
/* Draw edges with color interpolated based on selection */
-static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
+static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
{
- return EM_get_edge_for_index(index)->h==0;
+ return !BM_TestHFlag(EDBM_get_edge_for_index(((void**)userData)[0], index), BM_HIDDEN);
}
static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
{
- EditEdge *eed = EM_get_edge_for_index(index);
+ BMEdge *eed = EDBM_get_edge_for_index(((void**)userData)[0], index);
unsigned char **cols = userData;
- unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
- unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
+ unsigned char *col0 = cols[(BM_TestHFlag(eed->v1, BM_SELECT))?2:1];
+ unsigned char *col1 = cols[(BM_TestHFlag(eed->v2, BM_SELECT))?2:1];
glColor4ub( col0[0] + (col1[0]-col0[0])*t,
col0[1] + (col1[1]-col0[1])*t,
@@ -2025,36 +2057,36 @@ static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int i
col0[3] + (col1[3]-col0[3])*t);
}
-static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
+static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
{
- unsigned char *cols[2];
- cols[0]= baseCol;
- cols[1]= selCol;
+ void *cols[3] = {em, baseCol, selCol};
+
dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
}
/* Draw only seam edges */
-static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
+static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
{
- EditEdge *eed = EM_get_edge_for_index(index);
+ BMEdge *eed = EDBM_get_edge_for_index(userData, index);
- return (eed->h==0 && eed->seam);
+ return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SEAM);
}
-static void draw_dm_edges_seams(DerivedMesh *dm)
+
+static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
{
- dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
+ dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em);
}
/* Draw only sharp edges */
-static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
+static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
{
- EditEdge *eed = EM_get_edge_for_index(index);
+ BMEdge *eed = EDBM_get_edge_for_index(userData, index);
- return (eed->h==0 && eed->sharp);
+ return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SHARP);
}
-static void draw_dm_edges_sharp(DerivedMesh *dm)
+static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
{
- dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
+ dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
}
@@ -2062,16 +2094,19 @@ static void draw_dm_edges_sharp(DerivedMesh *dm)
* return 2 for the active face so it renders with stipple enabled */
static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
{
- struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
- EditFace *efa = EM_get_face_for_index(index);
+ struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} *data = userData;
+ BMFace *efa = EDBM_get_face_for_index(data->em, index);
unsigned char *col;
- if (efa->h==0) {
+ if (!efa)
+ return 0;
+
+ if (!BM_TestHFlag(efa, BM_HIDDEN)) {
if (efa == data->efa_act) {
glColor4ubv(data->cols[2]);
return 2; /* stipple */
} else {
- col = data->cols[(efa->f&SELECT)?1:0];
+ col = data->cols[BM_TestHFlag(efa, BM_SELECT)?1:0];
if (col[3]==0) return 0;
glColor4ubv(col);
return 1;
@@ -2082,9 +2117,9 @@ static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNU
static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
{
- struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
- EditFace *efa = EM_get_face_for_index(index);
- EditFace *next_efa = EM_get_face_for_index(next_index);
+ struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} * data = userData;
+ BMFace *efa = EDBM_get_face_for_index(data->em, index);
+ BMFace *next_efa = EDBM_get_face_for_index(data->em, next_index);
unsigned char *col, *next_col;
if(efa == next_efa)
@@ -2093,8 +2128,8 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int
if(efa == data->efa_act || next_efa == data->efa_act)
return 0;
- col = data->cols[(efa->f&SELECT)?1:0];
- next_col = data->cols[(next_efa->f&SELECT)?1:0];
+ col = data->cols[BM_TestHFlag(efa, BM_SELECT)?1:0];
+ next_col = data->cols[BM_TestHFlag(next_efa, BM_SELECT)?1:0];
if(col[3]==0 || next_col[3]==0)
return 0;
@@ -2103,68 +2138,87 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int
}
/* also draws the active face */
-static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
+static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
+ unsigned char *selCol, unsigned char *actCol, BMFace *efa_act, Mesh *me)
{
- struct { unsigned char *cols[3]; EditFace *efa_act; } data;
+ struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} data;
+
data.cols[0] = baseCol;
+ data.em = em;
data.cols[1] = selCol;
data.cols[2] = actCol;
data.efa_act = efa_act;
+ data.me = me;
dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions);
}
-static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
+static int draw_dm_creases__setDrawOptions(void *userData, int index)
{
- EditEdge *eed = EM_get_edge_for_index(index);
-
- if (eed->h==0 && eed->crease != 0.0f) {
- UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
+ BMEditMesh *em = userData;
+ BMEdge *eed = EDBM_get_edge_for_index(userData, index);
+ float *crease = eed ? bm_get_cd_float(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
+
+ if (!crease)
+ return 0;
+
+ if (!BM_TestHFlag(eed, BM_HIDDEN) && *crease!=0.0f) {
+ UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
return 1;
} else {
return 0;
}
}
-static void draw_dm_creases(DerivedMesh *dm)
+static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
{
glLineWidth(3.0);
- dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
+ dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
glLineWidth(1.0);
}
-static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
+static int draw_dm_bweights__setDrawOptions(void *userData, int index)
{
- EditEdge *eed = EM_get_edge_for_index(index);
+ BMEditMesh *em = userData;
+ BMEdge *eed = EDBM_get_edge_for_index(userData, index);
+ float *bweight = bm_get_cd_float(&em->bm->edata, eed->head.data, CD_BWEIGHT);
- if (eed->h==0 && eed->bweight != 0.0f) {
- UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
+ if (!bweight)
+ return 0;
+
+ if (!BM_TestHFlag(eed, BM_HIDDEN) && *bweight!=0.0f) {
+ UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
return 1;
} else {
return 0;
}
}
-static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
+static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
{
- EditVert *eve = EM_get_vert_for_index(index);
-
- if (eve->h==0 && eve->bweight != 0.0f) {
- UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
+ BMEditMesh *em = userData;
+ BMVert *eve = EDBM_get_vert_for_index(userData, index);
+ float *bweight = bm_get_cd_float(&em->bm->vdata, eve->head.data, CD_BWEIGHT);
+
+ if (!bweight)
+ return;
+
+ if (!BM_TestHFlag(eve, BM_HIDDEN) && *bweight!=0.0f) {
+ UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, *bweight);
bglVertex3fv(co);
}
}
-static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
+static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
{
ToolSettings *ts= scene->toolsettings;
if (ts->selectmode & SCE_SELECT_VERTEX) {
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
bglBegin(GL_POINTS);
- dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
+ dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
bglEnd();
}
else {
glLineWidth(3.0);
- dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
+ dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
glLineWidth(1.0);
}
}
@@ -2178,7 +2232,8 @@ static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
/* EditMesh drawing routines*/
-static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
+static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
+ BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act)
{
ToolSettings *ts= scene->toolsettings;
int sel;
@@ -2215,13 +2270,13 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, Deriv
if(ts->selectmode & SCE_SELECT_VERTEX) {
glPointSize(size);
glColor4ubv(col);
- draw_dm_verts(cageDM, sel, eve_act);
+ draw_dm_verts(em, cageDM, sel, eve_act);
}
if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
glPointSize(fsize);
glColor4ubv(fcol);
- draw_dm_face_centers(cageDM, sel);
+ draw_dm_face_centers(em, cageDM, sel);
}
if (pass==0) {
@@ -2235,7 +2290,9 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, Deriv
glPointSize(1.0);
}
-static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
+static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
+ Mesh *me, DerivedMesh *cageDM, short sel_only,
+ BMEdge *eed_act)
{
ToolSettings *ts= scene->toolsettings;
int pass;
@@ -2268,21 +2325,21 @@ static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh
}
if(ts->selectmode == SCE_SELECT_FACE) {
- draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
+ draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
}
else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {
if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
glShadeModel(GL_SMOOTH);
- draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
+ draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
glShadeModel(GL_FLAT);
} else {
- draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
+ draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
}
}
else {
if (!sel_only) {
glColor4ubv(wireCol);
- draw_dm_edges(cageDM);
+ draw_dm_edges(em, cageDM);
}
}
@@ -2293,13 +2350,11 @@ static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh
}
}
-static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
+static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d,
+ Object *ob, BMEditMesh *em, UnitSettings *unit)
{
Mesh *me= ob->data;
- EditEdge *eed;
- EditFace *efa;
- float v1[3], v2[3], v3[3], v4[3], vmid[3];
- float fvec[3];
+ float v1[3], v2[3], v3[3], vmid[3], fvec[3];
char val[32]; /* Stores the measurement display text here */
const char *conv_float; /* Use a float conversion matching the grid size */
unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
@@ -2309,6 +2364,9 @@ static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, E
const int do_global= v3d->flag & V3D_GLOBAL_STATS;
const int do_moving= G.moving;
+ BMIter iter;
+ int i;
+
/* make the precision of the pronted value proportionate to the gridsize */
if (grid < 0.01f) conv_float= "%.6g";
@@ -2323,11 +2381,16 @@ static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, E
if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
+ BMEdge *eed;
+
UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
- for(eed= em->edges.first; eed; eed= eed->next) {
- /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
- if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
+ eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ for(; eed; eed=BMIter_Step(&iter)) {
+ /* draw selected edges, or edges next to selected verts while draging */
+ if(BM_TestHFlag(eed, BM_SELECT) ||
+ (do_moving && (BM_TestHFlag(eed->v1, BM_SELECT) || BM_TestHFlag(eed->v2, BM_SELECT) ))) {
+
copy_v3_v3(v1, eed->v1->co);
copy_v3_v3(v2, eed->v2->co);
@@ -2348,92 +2411,91 @@ static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, E
}
if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
-// XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
+ /* would be nice to use BM_face_area, but that is for 2d faces
+ so instead add up tessalation triangle areas */
+ BMFace *f;
+ int n;
+
+#define DRAW_EM_MEASURE_STATS_FACEAREA()\
+ if (BM_TestHFlag(f, BM_SELECT)) {\
+ mul_v3_fl(vmid, 1.0/n);\
+ if(unit->system)\
+ bUnit_AsString(val, sizeof(val), area*unit->scale_length,\
+ 3, unit->system, B_UNIT_LENGTH, do_split, FALSE);\
+ else\
+ sprintf(val, conv_float, area);\
+ view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);\
+ }
+
UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
- copy_v3_v3(v1, efa->v1->co);
- copy_v3_v3(v2, efa->v2->co);
- copy_v3_v3(v3, efa->v3->co);
- if (efa->v4) {
- copy_v3_v3(v4, efa->v4->co);
- }
- if(do_global) {
- mul_mat3_m4_v3(ob->obmat, v1);
- mul_mat3_m4_v3(ob->obmat, v2);
- mul_mat3_m4_v3(ob->obmat, v3);
- if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
- }
-
- if (efa->v4)
- area= area_quad_v3(v1, v2, v3, v4);
- else
- area = area_tri_v3(v1, v2, v3);
-
- if(unit->system)
- bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
- else
- sprintf(val, conv_float, area);
-
- view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
+ f = NULL;
+ area = 0.0;
+ zero_v3(vmid);
+ n = 0;
+ for(i = 0; i < em->tottri; i++) {
+ BMLoop **l = em->looptris[i];
+ if(f && l[0]->f != f) {
+ DRAW_EM_MEASURE_STATS_FACEAREA();
+ zero_v3(vmid);
+ area = 0.0;
+ n = 0;
}
- }
- }
- if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
- EditEdge *e1, *e2, *e3, *e4;
- UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
- for(efa= em->faces.first; efa; efa= efa->next) {
- copy_v3_v3(v1, efa->v1->co);
- copy_v3_v3(v2, efa->v2->co);
- copy_v3_v3(v3, efa->v3->co);
- if(efa->v4) {
- copy_v3_v3(v4, efa->v4->co);
- }
- else {
- copy_v3_v3(v4, v3);
- }
+ f = l[0]->f;
+ copy_v3_v3(v1, l[0]->v->co);
+ copy_v3_v3(v2, l[1]->v->co);
+ copy_v3_v3(v3, l[2]->v->co);
if(do_global) {
mul_mat3_m4_v3(ob->obmat, v1);
mul_mat3_m4_v3(ob->obmat, v2);
mul_mat3_m4_v3(ob->obmat, v3);
- mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
}
-
- e1= efa->e1;
- e2= efa->e2;
- e3= efa->e3;
- if(efa->e4) e4= efa->e4; else e4= e3;
-
- /* Calculate the angles */
-
- if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
- /* Vec 1 */
- sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
- interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
- view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
- }
- if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
- /* Vec 2 */
- sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
- interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
- view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
- }
- if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
- /* Vec 3 */
- if(efa->v4)
- sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
- else
- sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
- interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
- view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
- }
- /* Vec 4 */
- if(efa->v4) {
- if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
- sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
- interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
+ area += area_tri_v3(v1, v2, v3);
+ add_v3_v3(vmid, v1);
+ add_v3_v3(vmid, v2);
+ add_v3_v3(vmid, v3);
+ n += 3;
+ }
+
+ if(f){
+ DRAW_EM_MEASURE_STATS_FACEAREA();
+ }
+#undef DRAW_EM_MEASURE_STATS_FACEAREA
+ }
+
+ if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
+ BMFace *efa;
+
+ UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
+
+
+ for(efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ efa; efa=BMIter_Step(&iter)) {
+ BMIter liter;
+ BMLoop *loop;
+
+ BM_Compute_Face_Center(em->bm, efa, vmid);
+
+ for(loop = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
+ loop; loop = BMIter_Step(&liter)) {
+
+ float v1[3], v2[3], v3[3];
+
+ copy_v3_v3(v1, loop->prev->v->co);
+ copy_v3_v3(v2, loop->v->co);
+ copy_v3_v3(v3, loop->next->v->co);
+
+ if(do_global){
+ mul_mat3_m4_v3(ob->obmat, v1);
+ mul_mat3_m4_v3(ob->obmat, v2);
+ mul_mat3_m4_v3(ob->obmat, v3);
+ }
+
+ if(BM_TestHFlag(efa, BM_SELECT) ||
+ (do_moving && BM_TestHFlag(loop->v, BM_SELECT))){
+ sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
+ interp_v3_v3v3(fvec, vmid, v2, 0.8f);
view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
}
}
@@ -2443,12 +2505,32 @@ static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, E
/* useful for debugging index vs shape key index */
#if 0
{
- EditVert *eve;
- int j;
+ BMIter iter;
+ BMVert *eve;
+ int j=0;
+
UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
- for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
- sprintf(val, "%d:%d", j, eve->keyindex);
- view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
+
+ if(CustomData_has_layer(&em->bm->vdata, CD_SHAPE_KEYINDEX)) {
+ int *keyi;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ keyi = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
+ if(keyi && *keyi != ORIGINDEX_NONE) {
+ sprintf(val, "%d:%d", j, *keyi);
+ }
+ else {
+ sprintf(val, "%d", j);
+ }
+ view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
+ i++;
+ }
+ }
+ else {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ sprintf(val, "%d", j);
+ view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
+ j++;
+ }
}
}
#endif
@@ -2459,11 +2541,11 @@ static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, E
}
}
-static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
+static int draw_em_fancy__setFaceOpts(void *userData, int index, int *UNUSED(drawSmooth_r))
{
- EditFace *efa = EM_get_face_for_index(index);
+ BMFace *efa = EDBM_get_face_for_index(userData, index);
- if (efa->h==0) {
+ if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
GPU_enable_material(efa->mat_nr+1, NULL);
return 1;
}
@@ -2471,33 +2553,35 @@ static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UN
return 0;
}
-static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
+static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
{
- EditFace *efa = EM_get_face_for_index(index);
+ BMFace *efa = EDBM_get_face_for_index(userData, index);
- return (efa->h==0);
+ return !BM_TestHFlag(efa, BM_HIDDEN);
}
-static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
+static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob,
+ BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
+
{
Mesh *me = ob->data;
- EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
- EditEdge *eed_act = NULL;
- EditVert *eve_act = NULL;
+ BMFace *efa_act = BM_get_actFace(em->bm, 0); /* annoying but active faces is stored differently */
+ BMEdge *eed_act = NULL;
+ BMVert *eve_act = NULL;
- if (em->selected.last) {
- EditSelection *ese = em->selected.last;
+ if (em->bm->selected.last) {
+ BMEditSelection *ese = em->bm->selected.last;
/* face is handeled above */
- /*if (ese->type == EDITFACE ) {
- efa_act = (EditFace *)ese->data;
- } else */ if ( ese->type == EDITEDGE ) {
- eed_act = (EditEdge *)ese->data;
- } else if ( ese->type == EDITVERT ) {
- eve_act = (EditVert *)ese->data;
+ /*if (ese->type == BM_FACE ) {
+ efa_act = (BMFace *)ese->data;
+ } else */ if ( ese->type == BM_EDGE ) {
+ eed_act = (BMEdge *)ese->data;
+ } else if ( ese->type == BM_VERT ) {
+ eve_act = (BMVert *)ese->data;
}
}
- EM_init_index_arrays(em, 1, 1, 1);
+ EDBM_init_index_arrays(em, 1, 1, 1);
if(dt>OB_WIRE) {
if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
@@ -2505,7 +2589,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
- draw_em_fancy__setGLSLFaceOpts, NULL);
+ draw_em_fancy__setGLSLFaceOpts, em);
GPU_disable_material();
glFrontFace(GL_CCW);
@@ -2520,8 +2604,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
glEnable(GL_LIGHTING);
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
-
- finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material, NULL);
+ finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, me->edit_btmesh, 0, GPU_enable_material, NULL);
glFrontFace(GL_CCW);
glDisable(GL_LIGHTING);
@@ -2555,7 +2638,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
if CHECK_OB_DRAWTEXTURE(v3d, dt)
col1[3] = 0;
- draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
+ draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me);
glDisable(GL_BLEND);
glDepthMask(1); // restore write in zbuffer
@@ -2570,7 +2653,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
glEnable(GL_BLEND);
glDepthMask(0); // disable write in zbuffer, needed for nice transp
- draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
+ draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me);
glDisable(GL_BLEND);
glDepthMask(1); // restore write in zbuffer
@@ -2582,14 +2665,14 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
/* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
/* only draw selected edges otherwise there is no way of telling if a face is selected */
- draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
+ draw_em_fancy_edges(em, scene, v3d, me, cageDM, 1, eed_act);
} else {
if(me->drawflag & ME_DRAWSEAMS) {
UI_ThemeColor(TH_EDGE_SEAM);
glLineWidth(2);
- draw_dm_edges_seams(cageDM);
+ draw_dm_edges_seams(em, cageDM);
glColor3ub(0,0,0);
glLineWidth(1);
@@ -2599,33 +2682,33 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
UI_ThemeColor(TH_EDGE_SHARP);
glLineWidth(2);
- draw_dm_edges_sharp(cageDM);
+ draw_dm_edges_sharp(em, cageDM);
glColor3ub(0,0,0);
glLineWidth(1);
}
- if(me->drawflag & ME_DRAWCREASES) {
- draw_dm_creases(cageDM);
+ if(me->drawflag & ME_DRAWCREASES && CustomData_has_layer(&em->bm->edata, CD_CREASE)) {
+ draw_dm_creases(em, cageDM);
}
if(me->drawflag & ME_DRAWBWEIGHTS) {
- draw_dm_bweights(scene, cageDM);
+ draw_dm_bweights(em, scene, cageDM);
}
-
- draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
+
+ draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act);
}
if(em) {
// XXX retopo_matrix_update(v3d);
- draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
+ draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
if(me->drawflag & ME_DRAWNORMALS) {
UI_ThemeColor(TH_NORMAL);
- draw_dm_face_normals(scene, cageDM);
+ draw_dm_face_normals(em, scene, cageDM);
}
if(me->drawflag & ME_DRAW_VNORMALS) {
UI_ThemeColor(TH_VNORMAL);
- draw_dm_vert_normals(scene, cageDM);
+ draw_dm_vert_normals(em, scene, cageDM);
}
if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
@@ -2638,7 +2721,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
GPU_disable_material();
}
- EM_free_index_arrays();
+ EDBM_free_index_arrays(em);
}
/* Mesh drawing routines */
@@ -2693,7 +2776,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
/* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
totedge = dm->getNumEdges(dm);
- totface = dm->getNumFaces(dm);
+ totface = dm->getNumTessFaces(dm);
/* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
if(dt!=OB_SHADED)
@@ -2924,7 +3007,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
Object *ob= base->object;
Object *obedit= scene->obedit;
Mesh *me= ob->data;
- EditMesh *em= me->edit_mesh;
+ BMEditMesh *em= me->edit_btmesh;
int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha, i;
/* If we are drawing shadows and any of the materials don't cast a shadow,
@@ -2948,9 +3031,9 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
DerivedMesh *finalDM, *cageDM;
if (obedit!=ob)
- finalDM = cageDM = editmesh_get_derived_base(ob, em);
+ finalDM = cageDM = editbmesh_get_derived_base(ob, em);
else
- cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
+ cageDM = editbmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
scene->customdata_mask);
if(dt>OB_WIRE) {
@@ -6555,44 +6638,51 @@ static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *dm, int offset)
static void bbs_mesh_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
{
- int offset = (intptr_t) userData;
- EditVert *eve = EM_get_vert_for_index(index);
+ void **ptrs = userData;
+ int offset = (intptr_t) ptrs[0];
+ BMVert *eve = EDBM_get_vert_for_index(ptrs[1], index);
- if (eve->h==0) {
+ if (!BM_TestHFlag(eve, BM_HIDDEN)) {
WM_set_framebuffer_index_color(offset+index);
bglVertex3fv(co);
}
}
-static void bbs_mesh_verts(DerivedMesh *dm, int offset)
+static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset)
{
+ void *ptrs[2] = {(void*)(intptr_t) offset, em};
+
glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) );
bglBegin(GL_POINTS);
- dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, (void*)(intptr_t) offset);
+ dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, ptrs);
bglEnd();
glPointSize(1.0);
}
static int bbs_mesh_wire__setDrawOptions(void *userData, int index)
{
- int offset = (intptr_t) userData;
- EditEdge *eed = EM_get_edge_for_index(index);
+ void **ptrs = userData;
+ int offset = (intptr_t) ptrs[0];
+ BMEdge *eed = EDBM_get_edge_for_index(ptrs[1], index);
- if (eed->h==0) {
+ if (!BM_TestHFlag(eed, BM_HIDDEN)) {
WM_set_framebuffer_index_color(offset+index);
return 1;
} else {
return 0;
}
}
-static void bbs_mesh_wire(DerivedMesh *dm, int offset)
+static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
{
- dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, (void*)(intptr_t) offset);
+ void *ptrs[2] = {(void*)(intptr_t) offset, em};
+ dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, ptrs);
}
static int bbs_mesh_solid__setSolidDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
{
- if (EM_get_face_for_index(index)->h==0) {
- if (userData) {
+ BMFace *efa = EDBM_get_face_for_index(((void**)userData)[0], index);
+
+ if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
+ if (((void**)userData)[1]) {
WM_set_framebuffer_index_color(index+1);
}
return 1;
@@ -6601,11 +6691,11 @@ static int bbs_mesh_solid__setSolidDrawOptions(void *userData, int index, int *U
}
}
-static void bbs_mesh_solid__drawCenter(void *UNUSED(userData), int index, float *cent, float *UNUSED(no))
+static void bbs_mesh_solid__drawCenter(void *userData, int index, float *cent, float *UNUSED(no))
{
- EditFace *efa = EM_get_face_for_index(index);
+ BMFace *efa = EDBM_get_face_for_index(((void**)userData)[0], index);
- if (efa->h==0 && efa->fgonf!=EM_FGON) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN)) {
WM_set_framebuffer_index_color(index+1);
bglVertex3fv(cent);
@@ -6613,23 +6703,26 @@ static void bbs_mesh_solid__drawCenter(void *UNUSED(userData), int index, float
}
/* two options, facecolors or black */
-static void bbs_mesh_solid_EM(Scene *scene, View3D *v3d, Object *ob, DerivedMesh *dm, int facecol)
+static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d,
+ Object *ob, DerivedMesh *dm, int facecol)
{
+ void *ptrs[2] = {em, NULL}; //second one being null means to draw black
cpack(0);
if (facecol) {
- dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(intptr_t) 1, 0, GPU_enable_material, NULL);
+ ptrs[1] = (void*)(intptr_t) 1;
+ dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, ptrs, 0, GPU_enable_material, NULL);
if(check_ob_drawface_dot(scene, v3d, ob->dt)) {
glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
bglBegin(GL_POINTS);
- dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, NULL);
+ dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, ptrs);
bglEnd();
}
} else {
- dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*) 0, 0, GPU_enable_material, NULL);
+ dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, ptrs, 0, GPU_enable_material, NULL);
}
}
@@ -6688,36 +6781,36 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
case OB_MESH:
if(ob->mode & OB_MODE_EDIT) {
Mesh *me= ob->data;
- EditMesh *em= me->edit_mesh;
+ BMEditMesh *em= me->edit_btmesh;
- DerivedMesh *dm = editmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
+ DerivedMesh *dm = editbmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
- EM_init_index_arrays(em, 1, 1, 1);
+ EDBM_init_index_arrays(em, 1, 1, 1);
- bbs_mesh_solid_EM(scene, v3d, ob, dm, ts->selectmode & SCE_SELECT_FACE);
+ bbs_mesh_solid_EM(em, scene, v3d, ob, dm, ts->selectmode & SCE_SELECT_FACE);
if(ts->selectmode & SCE_SELECT_FACE)
- em_solidoffs = 1+em->totface;
+ bm_solidoffs = 1+em->bm->totface;
else
- em_solidoffs= 1;
+ bm_solidoffs= 1;
bglPolygonOffset(rv3d->dist, 1.0);
// we draw edges always, for loop (select) tools
- bbs_mesh_wire(dm, em_solidoffs);
- em_wireoffs= em_solidoffs + em->totedge;
+ bbs_mesh_wire(em, dm, bm_solidoffs);
+ bm_wireoffs= bm_solidoffs + em->bm->totedge;
// we draw verts if vert select mode or if in transform (for snap).
if(ts->selectmode & SCE_SELECT_VERTEX || G.moving & G_TRANSFORM_EDIT) {
- bbs_mesh_verts(dm, em_wireoffs);
- em_vertoffs= em_wireoffs + em->totvert;
+ bbs_mesh_verts(em, dm, bm_wireoffs);
+ bm_vertoffs= bm_wireoffs + em->bm->totvert;
}
- else em_vertoffs= em_wireoffs;
+ else bm_vertoffs= bm_wireoffs;
bglPolygonOffset(rv3d->dist, 0.0);
dm->release(dm);
- EM_free_index_arrays();
+ EDBM_free_index_arrays(em);
}
else {
Mesh *me= ob->data;
@@ -6732,7 +6825,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
bbs_obmode_mesh_verts(ob, dm, 1);
- em_vertoffs = me->totvert+1;
+ bm_vertoffs = me->totvert+1;
dm->release(dm);
}
else {
@@ -6761,7 +6854,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
int glsl;
if(ob->mode & OB_MODE_EDIT)
- edm= editmesh_get_derived_base(ob, me->edit_mesh);
+ edm= editbmesh_get_derived_base(ob, me->edit_btmesh);
else
dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 7c89ce0f689..97311035939 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -38,6 +38,7 @@
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_editVert.h"
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index f868cda485f..0a69abe88c6 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -481,6 +481,7 @@ static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
if( ED_view3d_give_base_under_cursor(C, event->mval) ) {
return 0;
}
+
return view3d_ima_drop_poll(C, drag, event);
}
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 5e0a32c41c8..dd9202d96f6 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -58,6 +58,7 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_screen.h"
+#include "BKE_tessmesh.h"
#include "BKE_deform.h"
#include "WM_api.h"
@@ -151,32 +152,36 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
if(ob->type==OB_MESH) {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
- EditVert *eve, *evedef=NULL;
- EditEdge *eed;
+ BMEditMesh *em = me->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMVert *eve, *evedef=NULL;
+ BMEdge *eed;
+ BMIter iter;
- eve= em->verts.first;
- while(eve) {
- if(eve->f & SELECT) {
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if(BM_TestHFlag(eve, BM_SELECT)) {
evedef= eve;
tot++;
add_v3_v3(median, eve->co);
}
- eve= eve->next;
}
- eed= em->edges.first;
- while(eed) {
- if((eed->f & SELECT)) {
+
+ BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if(BM_TestHFlag(eed, BM_SELECT)) {
+ float *f;
+
totedge++;
- median[3]+= eed->crease;
- median[6]+= eed->bweight;
+ f = bm_get_cd_float(&bm->edata, eed->head.data, CD_CREASE);
+ median[3]+= f ? *f : 0.0f;
+
+ f = bm_get_cd_float(&bm->edata, eed->head.data, CD_BWEIGHT);
+ median[6]+= f ? *f : 0.0f;
}
- eed= eed->next;
}
/* check for defgroups */
if(evedef)
- dvert= CustomData_em_get(&em->vdata, evedef->data, CD_MDEFORMVERT);
+ dvert= CustomData_bmesh_get(&em->bm->vdata, evedef->head.data, CD_MDEFORMVERT);
if(tot==1 && dvert && dvert->totweight) {
bDeformGroup *dg;
int i, max=1, init=1;
@@ -200,8 +205,6 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
tfp->defweightp= &dvert->dw[0].weight;
}
}
-
- BKE_mesh_end_editmesh(me, em);
}
else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
Curve *cu= ob->data;
@@ -394,31 +397,34 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
if(ob->type==OB_MESH) {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
+ BMEditMesh *em = me->edit_btmesh;
+ BMVert *eve;
+ BMIter iter;
- /* allow for some rounding error becasue of matrix transform */
if(len_v3(median) > 0.000001f) {
- EditVert *eve;
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if(BM_TestHFlag(eve, BM_SELECT)) {
add_v3_v3(eve->co, median);
}
}
-
- recalc_editnormals(em);
+
+ EDBM_RecalcNormals(em);
}
-
+
if(median[3] != 0.0f) {
- EditEdge *eed;
+ BMEdge *eed;
const float fixed_crease= (ve_median[3] <= 0.0f ? 0.0f : (ve_median[3] >= 1.0f ? 1.0f : FLT_MAX));
-
+
if(fixed_crease != FLT_MAX) {
/* simple case */
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
- eed->crease= fixed_crease;
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if(BM_TestHFlag(eed, BM_SELECT)) {
+ float *crease = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE);
+ if (!crease) break;
+
+ *crease= fixed_crease;
}
}
}
@@ -435,10 +441,14 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
/* scale down */
const float sca= median_new / median_orig;
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
- eed->crease *= sca;
- CLAMP(eed->crease, 0.0f, 1.0f);
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if(BM_TestHFlag(eed, BM_SELECT) && !BM_TestHFlag(eed, BM_HIDDEN)) {
+ float *crease = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE);
+
+ if (!crease) break;
+
+ *crease *= sca;
+ CLAMP(*crease, 0.0f, 1.0f);
}
}
}
@@ -446,17 +456,20 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
/* scale up */
const float sca= (1.0f - median_new) / (1.0f - median_orig);
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
- eed->crease = 1.0f - ((1.0f - eed->crease) * sca);
- CLAMP(eed->crease, 0.0f, 1.0f);
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if(BM_TestHFlag(eed, BM_SELECT) && !BM_TestHFlag(eed, BM_HIDDEN)) {
+ float *crease = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE);
+ if (!crease) break;
+
+ *crease = 1.0f - ((1.0f - *crease) * sca);
+ CLAMP(*crease, 0.0f, 1.0f);
}
}
}
}
}
-
if (median[6] != 0.0f) {
+#if 0 // BMESH_TODO
EditEdge *eed;
const float fixed_bweight= (ve_median[6] <= 0.0f ? 0.0f : (ve_median[6] >= 1.0f ? 1.0f : FLT_MAX));
@@ -501,8 +514,9 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
}
}
+#endif // BMESH_TODO
}
- BKE_mesh_end_editmesh(me, em);
+ EDBM_RecalcNormals(em);
}
else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
Curve *cu= ob->data;
@@ -579,37 +593,35 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
#define B_VGRP_PNL_EDIT_SINGLE 8 /* or greater */
#define B_VGRP_PNL_COPY_SINGLE 16384 /* or greater */
-static void act_vert_def(Object *ob, EditVert **eve, MDeformVert **dvert)
+static void act_vert_def(Object *ob, BMVert **eve, MDeformVert **dvert)
{
if(ob && ob->mode & OB_MODE_EDIT && ob->type==OB_MESH && ob->defbase.first) {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
- EditSelection *ese = ((EditSelection*)em->selected.last);
+ BMEditMesh *em = me->edit_btmesh;
+ BMEditSelection *ese = ((BMEditSelection*)em->bm->selected.last);
- if(ese && ese->type == EDITVERT) {
- *eve= (EditVert*)ese->data;
- *dvert= CustomData_em_get(&em->vdata, (*eve)->data, CD_MDEFORMVERT);
+ if(ese && ese->type == BM_VERT) {
+ *eve= (BMVert*)ese->data;
+ *dvert= CustomData_bmesh_get(&em->bm->vdata, (*eve)->head.data, CD_MDEFORMVERT);
return;
}
-
- BKE_mesh_end_editmesh(me, em);
}
*eve= NULL;
*dvert= NULL;
}
-static void editvert_mirror_update(Object *ob, EditVert *eve, int def_nr, int index)
+static void editvert_mirror_update(Object *ob, BMVert *eve, int def_nr, int index)
{
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
- EditVert *eve_mirr;
+ BMEditMesh *em = me->edit_btmesh;
+ BMVert *eve_mirr;
- eve_mirr= editmesh_get_x_mirror_vert(ob, em, eve, eve->co, index);
+ eve_mirr= editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, index);
if(eve_mirr && eve_mirr != eve) {
- MDeformVert *dvert_src= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
- MDeformVert *dvert_dst= CustomData_em_get(&em->vdata, eve_mirr->data, CD_MDEFORMVERT);
+ MDeformVert *dvert_src= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
+ MDeformVert *dvert_dst= CustomData_bmesh_get(&em->bm->vdata, eve_mirr->head.data, CD_MDEFORMVERT);
if(dvert_dst) {
if(def_nr == -1) {
/* all vgroups, add groups where neded */
@@ -631,7 +643,7 @@ static void editvert_mirror_update(Object *ob, EditVert *eve, int def_nr, int in
static void vgroup_adjust_active(Object *ob, int def_nr)
{
- EditVert *eve_act;
+ BMVert *eve_act;
MDeformVert *dvert_act;
act_vert_def(ob, &eve_act, &dvert_act);
@@ -644,7 +656,7 @@ static void vgroup_adjust_active(Object *ob, int def_nr)
static void vgroup_copy_active_to_sel(Object *ob)
{
- EditVert *eve_act;
+ BMVert *eve_act;
MDeformVert *dvert_act;
act_vert_def(ob, &eve_act, &dvert_act);
@@ -654,14 +666,15 @@ static void vgroup_copy_active_to_sel(Object *ob)
}
else {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
- EditVert *eve;
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
+ BMVert *eve;
MDeformVert *dvert;
int index= 0;
- for(eve= em->verts.first; eve; eve= eve->next, index++) {
- if(eve->f & SELECT && eve != eve_act) {
- dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if(BM_TestHFlag(eve, BM_SELECT) && eve != eve_act) {
+ dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
if(dvert) {
defvert_copy(dvert, dvert_act);
@@ -670,13 +683,15 @@ static void vgroup_copy_active_to_sel(Object *ob)
}
}
+
+ index++;
}
}
}
static void vgroup_copy_active_to_sel_single(Object *ob, int def_nr)
{
- EditVert *eve_act;
+ BMVert *eve_act;
MDeformVert *dvert_act;
act_vert_def(ob, &eve_act, &dvert_act);
@@ -686,8 +701,9 @@ static void vgroup_copy_active_to_sel_single(Object *ob, int def_nr)
}
else {
Mesh *me= ob->data;
- EditMesh *em = BKE_mesh_get_editmesh(me);
- EditVert *eve;
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
+ BMVert *eve;
MDeformVert *dvert;
MDeformWeight *dw;
float act_weight = -1.0f;
@@ -703,10 +719,11 @@ static void vgroup_copy_active_to_sel_single(Object *ob, int def_nr)
if(act_weight < -0.5f)
return;
-
- for(eve= em->verts.first; eve; eve= eve->next, index++) {
- if(eve->f & SELECT && eve != eve_act) {
- dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for (index=0; eve; eve=BMIter_Step(&iter), index++) {
+ if(BM_TestHFlag(eve, BM_SELECT) && eve != eve_act) {
+ dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
if(dvert) {
for(i=0, dw=dvert->dw; i < dvert->totweight; i++, dw++) {
if(def_nr == dw->def_nr) {
@@ -730,7 +747,7 @@ static void vgroup_copy_active_to_sel_single(Object *ob, int def_nr)
static void vgroup_normalize_active(Object *ob)
{
- EditVert *eve_act;
+ BMVert *eve_act;
MDeformVert *dvert_act;
act_vert_def(ob, &eve_act, &dvert_act);
@@ -778,7 +795,7 @@ static int view3d_panel_vgroup_poll(const bContext *C, PanelType *UNUSED(pt))
{
Scene *scene= CTX_data_scene(C);
Object *ob= OBACT;
- EditVert *eve_act;
+ BMVert *eve_act;
MDeformVert *dvert_act;
act_vert_def(ob, &eve_act, &dvert_act);
@@ -793,7 +810,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
Scene *scene= CTX_data_scene(C);
Object *ob= OBACT;
- EditVert *eve;
+ BMVert *eve;
MDeformVert *dvert;
act_vert_def(ob, &eve, &dvert);
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index fa6611b9925..b30030a6b9d 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -55,6 +55,7 @@
#include "BKE_modifier.h"
#include "BKE_paint.h"
#include "BKE_screen.h"
+#include "BKE_tessmesh.h"
#include "ED_mesh.h"
#include "ED_util.h"
@@ -286,16 +287,16 @@ static char *view3d_modeselect_pup(Scene *scene)
BLI_strncpy(str, title, sizeof(string));
str += modeselect_addmode(str, N_("Object Mode"), OB_MODE_OBJECT, ICON_OBJECT_DATA);
-
+
if(ob==NULL || ob->data==NULL) return string;
if(ob->id.lib) return string;
-
+
if(!((ID *)ob->data)->lib) {
/* if active object is editable */
if ( ((ob->type == OB_MESH)
|| (ob->type == OB_CURVE) || (ob->type == OB_SURF) || (ob->type == OB_FONT)
|| (ob->type == OB_MBALL) || (ob->type == OB_LATTICE))) {
-
+
str += modeselect_addmode(str, N_("Edit Mode"), OB_MODE_EDIT, ICON_EDITMODE_HLT);
}
else if (ob->type == OB_ARMATURE) {
@@ -313,7 +314,7 @@ static char *view3d_modeselect_pup(Scene *scene)
str += modeselect_addmode(str, N_("Weight Paint"), OB_MODE_WEIGHT_PAINT, ICON_WPAINT_HLT);
}
}
-
+
/* if active object is an armature */
if (ob->type==OB_ARMATURE) {
str += modeselect_addmode(str, N_("Pose Mode"), OB_MODE_POSE, ICON_POSE_HLT);
@@ -334,12 +335,12 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event)
ScrArea *sa= CTX_wm_area(C);
View3D *v3d= sa->spacedata.first;
Object *obedit = CTX_data_edit_object(C);
- EditMesh *em= NULL;
+ BMEditMesh *em= NULL;
int ctrl= win->eventstate->ctrl, shift= win->eventstate->shift;
PointerRNA props_ptr;
if(obedit && obedit->type==OB_MESH) {
- em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ em= ((Mesh *)obedit->data)->edit_btmesh;
}
/* watch it: if sa->win does not exist, check that when calling direct drawing routines */
@@ -360,7 +361,7 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event)
if(shift==0 || em->selectmode==0)
em->selectmode= SCE_SELECT_VERTEX;
ts->selectmode= em->selectmode;
- EM_selectmode_set(em);
+ EDBM_selectmode_set(em);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
ED_undo_push(C, "Selectmode Set: Vertex");
}
@@ -369,12 +370,12 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event)
if(em) {
if(shift==0 || em->selectmode==0){
if( (em->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX){
- if(ctrl) EM_convertsel(em, SCE_SELECT_VERTEX,SCE_SELECT_EDGE);
+ if(ctrl) EDBM_convertsel(em, SCE_SELECT_VERTEX,SCE_SELECT_EDGE);
}
em->selectmode = SCE_SELECT_EDGE;
}
ts->selectmode= em->selectmode;
- EM_selectmode_set(em);
+ EDBM_selectmode_set(em);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
ED_undo_push(C, "Selectmode Set: Edge");
}
@@ -382,14 +383,13 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event)
case B_SEL_FACE:
if(em) {
if( shift==0 || em->selectmode==0){
- if( ((em->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((em->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)){
- if(ctrl)
- EM_convertsel(em, (em->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE);
+ if( ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)){
+ if(ctrl) EDBM_convertsel(em, (ts->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE);
}
em->selectmode = SCE_SELECT_FACE;
}
ts->selectmode= em->selectmode;
- EM_selectmode_set(em);
+ EDBM_selectmode_set(em);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
ED_undo_push(C, "Selectmode Set: Face");
}
@@ -422,9 +422,6 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event)
default:
break;
}
-
- if(obedit && obedit->type==OB_MESH)
- BKE_mesh_end_editmesh(obedit->data, em);
}
/* Returns the icon associated with an object mode */
@@ -449,7 +446,7 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
uiBlockSetHandleFunc(block, do_view3d_header_buttons, NULL);
if(obedit && (obedit->type == OB_MESH)) {
- EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
uiLayout *row;
row= uiLayoutRow(layout, 1);
@@ -457,8 +454,6 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, 0,0,UI_UNIT_X,UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode");
uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, 0,0,UI_UNIT_X,UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Edge select mode");
uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, 0,0,UI_UNIT_X,UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Face select mode");
-
- BKE_mesh_end_editmesh(obedit->data, em);
}
}
@@ -488,11 +483,17 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
uiBlockSetEmboss(block, UI_EMBOSS);
/* mode */
- if(ob)
+ if(ob) {
+ /*sanity point checkpoint, put here to avoid seeding
+ this same code in 10 different other places.*/
+ if (!ob->mode)
+ ob->mode = OB_MODE_OBJECT;
+
v3d->modeselect = ob->mode;
- else
+ } else {
v3d->modeselect = OB_MODE_OBJECT;
-
+ }
+
uiBlockBeginAlign(block);
uiDefIconTextButS(block, MENU, B_MODESELECT, object_mode_icon(v3d->modeselect), view3d_modeselect_pup(scene) ,
0,0,126 * dpi_fac, UI_UNIT_Y, &(v3d->modeselect), 0, 0, 0, 0, TIP_("Mode"));
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 6e26fb15873..5df61619ece 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -161,6 +161,17 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", HOMEKEY, KM_PRESS, 0, 0)->ptr, "center", 0); /* only without camera view */
RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", CKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "center", 1);
+ /* 3D mouse */
+ WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit", NDOF_MOTION, 0, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_pan", NDOF_MOTION, 0, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BACK, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BACK);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_LEFT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_LEFT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_RIGHT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_TOP);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BOTTOM, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BOTTOM);
+
/* numpad view hotkeys*/
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD0, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_CAMERA);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD1, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
@@ -209,17 +220,6 @@ void view3d_keymap(wmKeyConfig *keyconf)
kmi= WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD7, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_BOTTOM);
RNA_boolean_set(kmi->ptr, "align_active", TRUE);
-
- /* 3D mouse */
- WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit", NDOF_MOTION, 0, 0, 0);
- WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_pan", NDOF_MOTION, 0, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
- RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
- RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BACK, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BACK);
- RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_LEFT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_LEFT);
- RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_RIGHT);
- RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_TOP);
- RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BOTTOM, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BOTTOM);
/* 3D mouse align */
kmi= WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, KM_SHIFT, 0);
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 94d3469dc8c..d719ac188e5 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -60,7 +60,7 @@
#include "BKE_context.h"
#include "BKE_paint.h"
#include "BKE_armature.h"
-
+#include "BKE_tessmesh.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -159,43 +159,49 @@ void view3d_get_transformation(ARegion *ar, RegionView3D *rv3d, Object *ob, bglM
/* local prototypes */
-static void EM_backbuf_checkAndSelectVerts(EditMesh *em, int select)
+static void EDBM_backbuf_checkAndSelectVerts(BMEditMesh *em, int select)
{
- EditVert *eve;
- int index= em_wireoffs;
+ BMVert *eve;
+ BMIter iter;
+ int index= bm_wireoffs;
- for(eve= em->verts.first; eve; eve= eve->next, index++) {
- if(eve->h==0) {
- if(EM_check_backbuf(index)) {
- eve->f = select?(eve->f|1):(eve->f&~1);
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for ( ; eve; eve=BMIter_Step(&iter), index++) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN)) {
+ if(EDBM_check_backbuf(index)) {
+ BM_Select_Vert(em->bm, eve, select);
}
}
}
}
-static void EM_backbuf_checkAndSelectEdges(EditMesh *em, int select)
+static void EDBM_backbuf_checkAndSelectEdges(BMEditMesh *em, int select)
{
- EditEdge *eed;
- int index= em_solidoffs;
+ BMEdge *eed;
+ BMIter iter;
+ int index= bm_solidoffs;
- for(eed= em->edges.first; eed; eed= eed->next, index++) {
- if(eed->h==0) {
- if(EM_check_backbuf(index)) {
- EM_select_edge(eed, select);
+ eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
+ for ( ; eed; eed=BMIter_Step(&iter), index++) {
+ if(!BM_TestHFlag(eed, BM_HIDDEN)) {
+ if(EDBM_check_backbuf(index)) {
+ BM_Select_Edge(em->bm, eed, select);
}
}
}
}
-static void EM_backbuf_checkAndSelectFaces(EditMesh *em, int select)
+static void EDBM_backbuf_checkAndSelectFaces(BMEditMesh *em, int select)
{
- EditFace *efa;
+ BMFace *efa;
+ BMIter iter;
int index= 1;
- for(efa= em->faces.first; efa; efa= efa->next, index++) {
- if(efa->h==0) {
- if(EM_check_backbuf(index)) {
- EM_select_face_fgon(em, efa, select);
+ efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for ( ; efa; efa=BMIter_Step(&iter), index++) {
+ if(!BM_TestHFlag(efa, BM_HIDDEN)) {
+ if(EDBM_check_backbuf(index)) {
+ BM_Select_Face(em->bm, efa, select);
}
}
}
@@ -203,14 +209,14 @@ static void EM_backbuf_checkAndSelectFaces(EditMesh *em, int select)
/* object mode, EM_ prefix is confusing here, rename? */
-static void EM_backbuf_checkAndSelectVerts_obmode(Mesh *me, int select)
+static void EDBM_backbuf_checkAndSelectVerts_obmode(Mesh *me, int select)
{
MVert *mv = me->mvert;
int a;
if (mv) {
for(a=1; a<=me->totvert; a++, mv++) {
- if(EM_check_backbuf(a)) {
+ if(EDBM_check_backbuf(a)) {
if(!(mv->flag & ME_HIDE)) {
mv->flag = select?(mv->flag|SELECT):(mv->flag&~SELECT);
}
@@ -219,15 +225,16 @@ static void EM_backbuf_checkAndSelectVerts_obmode(Mesh *me, int select)
}
}
/* object mode, EM_ prefix is confusing here, rename? */
-static void EM_backbuf_checkAndSelectTFaces(Mesh *me, int select)
+
+static void EDBM_backbuf_checkAndSelectTFaces(Mesh *me, int select)
{
- MFace *mface = me->mface;
+ MPoly *mpoly = me->mpoly;
int a;
- if (mface) {
- for(a=1; a<=me->totface; a++, mface++) {
- if(EM_check_backbuf(a)) {
- mface->flag = select?(mface->flag|ME_FACE_SEL):(mface->flag&~ME_FACE_SEL);
+ if (mpoly) {
+ for(a=1; a<=me->totpoly; a++, mpoly++) {
+ if(EDBM_check_backbuf(a)) {
+ mpoly->flag = select?(mpoly->flag|ME_FACE_SEL):(mpoly->flag&~ME_FACE_SEL);
}
}
}
@@ -447,39 +454,39 @@ static void lasso_select_boundbox(rcti *rect, int mcords[][2], short moves)
}
}
-static void do_lasso_select_mesh__doSelectVert(void *userData, EditVert *eve, int x, int y, int UNUSED(index))
+static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, int x, int y, int UNUSED(index))
{
struct { ViewContext vc; rcti *rect; int (*mcords)[2], moves, select, pass, done; } *data = userData;
if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
- eve->f = data->select?(eve->f|1):(eve->f&~1);
+ BM_Select(data->vc.em->bm, eve, data->select);
}
}
-static void do_lasso_select_mesh__doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
+static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index)
{
struct { ViewContext vc; rcti *rect; int (*mcords)[2], moves, select, pass, done; } *data = userData;
- if (EM_check_backbuf(em_solidoffs+index)) {
+ if (EDBM_check_backbuf(bm_solidoffs+index)) {
if (data->pass==0) {
if ( edge_fully_inside_rect(data->rect, x0, y0, x1, y1) &&
lasso_inside(data->mcords, data->moves, x0, y0) &&
lasso_inside(data->mcords, data->moves, x1, y1)) {
- EM_select_edge(eed, data->select);
+ BM_Select(data->vc.em->bm, eed, data->select);
data->done = 1;
}
} else {
if (lasso_inside_edge(data->mcords, data->moves, x0, y0, x1, y1)) {
- EM_select_edge(eed, data->select);
+ BM_Select(data->vc.em->bm, eed, data->select);
}
}
}
}
-static void do_lasso_select_mesh__doSelectFace(void *userData, EditFace *efa, int x, int y, int UNUSED(index))
+static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, int x, int y, int UNUSED(index))
{
struct { ViewContext vc; rcti *rect; int (*mcords)[2], moves, select, pass, done; } *data = userData;
if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
- EM_select_face_fgon(data->vc.em, efa, data->select);
+ BM_Select(data->vc.em->bm, efa, data->select);
}
}
@@ -493,7 +500,7 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves,
lasso_select_boundbox(&rect, mcords, moves);
/* set editmesh */
- vc->em= ((Mesh *)vc->obedit->data)->edit_mesh;
+ vc->em= ((Mesh *)vc->obedit->data)->edit_btmesh;
data.vc= *vc;
data.rect = &rect;
@@ -504,17 +511,17 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves,
data.pass = 0;
if (extend == 0 && select)
- EM_deselect_all(vc->em);
+ EDBM_clear_flag_all(vc->em, BM_SELECT);
/* for non zbuf projections, dont change the GL state */
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
glLoadMatrixf(vc->rv3d->viewmat);
- bbsel= EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ bbsel= EDBM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
if(ts->selectmode & SCE_SELECT_VERTEX) {
if (bbsel) {
- EM_backbuf_checkAndSelectVerts(vc->em, select);
+ EDBM_backbuf_checkAndSelectVerts(vc->em, select);
}
else {
mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, 1);
@@ -533,15 +540,15 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves,
if(ts->selectmode & SCE_SELECT_FACE) {
if (bbsel) {
- EM_backbuf_checkAndSelectFaces(vc->em, select);
+ EDBM_backbuf_checkAndSelectFaces(vc->em, select);
}
else {
mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data);
}
}
- EM_free_backbuf();
- EM_selectmode_flush(vc->em);
+ EDBM_free_backbuf();
+ EDBM_selectmode_flush(vc->em);
}
#if 0
@@ -819,14 +826,14 @@ static void do_lasso_select_paintvert(ViewContext *vc, int mcords[][2], short mo
if(extend==0 && select)
paintvert_deselect_all_visible(ob, SEL_DESELECT, FALSE); /* flush selection at the end */
- em_vertoffs= me->totvert+1; /* max index array */
+ bm_vertoffs= me->totvert+1; /* max index array */
lasso_select_boundbox(&rect, mcords, moves);
- EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ EDBM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- EM_backbuf_checkAndSelectVerts_obmode(me, select);
+ EDBM_backbuf_checkAndSelectVerts_obmode(me, select);
- EM_free_backbuf();
+ EDBM_free_backbuf();
paintvert_flush_flags(ob);
}
@@ -842,14 +849,14 @@ static void do_lasso_select_paintface(ViewContext *vc, int mcords[][2], short mo
if(extend==0 && select)
paintface_deselect_all_visible(ob, SEL_DESELECT, FALSE); /* flush selection at the end */
- em_vertoffs= me->totface+1; /* max index array */
+ bm_vertoffs= me->totpoly+1; /* max index array */
lasso_select_boundbox(&rect, mcords, moves);
- EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ EDBM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- EM_backbuf_checkAndSelectTFaces(me, select);
+ EDBM_backbuf_checkAndSelectTFaces(me, select);
- EM_free_backbuf();
+ EDBM_free_backbuf();
paintface_flush_flags(ob);
}
@@ -1543,37 +1550,37 @@ static int do_lattice_box_select(ViewContext *vc, rcti *rect, int select, int ex
return OPERATOR_FINISHED;
}
-static void do_mesh_box_select__doSelectVert(void *userData, EditVert *eve, int x, int y, int UNUSED(index))
+static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, int x, int y, int UNUSED(index))
{
struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
if (BLI_in_rcti(data->rect, x, y)) {
- eve->f = data->select?(eve->f|1):(eve->f&~1);
+ BM_Select(data->vc.em->bm, eve, data->select);
}
}
-static void do_mesh_box_select__doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
+static void do_mesh_box_select__doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index)
{
struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
- if(EM_check_backbuf(em_solidoffs+index)) {
+ if(EDBM_check_backbuf(bm_solidoffs+index)) {
if (data->pass==0) {
if (edge_fully_inside_rect(data->rect, x0, y0, x1, y1)) {
- EM_select_edge(eed, data->select);
+ BM_Select(data->vc.em->bm, eed, data->select);
data->done = 1;
}
} else {
if (edge_inside_rect(data->rect, x0, y0, x1, y1)) {
- EM_select_edge(eed, data->select);
+ BM_Select(data->vc.em->bm, eed, data->select);
}
}
}
}
-static void do_mesh_box_select__doSelectFace(void *userData, EditFace *efa, int x, int y, int UNUSED(index))
+static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, int x, int y, int UNUSED(index))
{
struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
if (BLI_in_rcti(data->rect, x, y)) {
- EM_select_face_fgon(data->vc.em, efa, data->select);
+ BM_Select(data->vc.em->bm, efa, data->select);
}
}
static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int extend)
@@ -1589,17 +1596,17 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten
data.done = 0;
if (extend == 0 && select)
- EM_deselect_all(vc->em);
+ EDBM_clear_flag_all(vc->em, BM_SELECT);
/* for non zbuf projections, dont change the GL state */
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
glLoadMatrixf(vc->rv3d->viewmat);
- bbsel= EM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ bbsel= EDBM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
if(ts->selectmode & SCE_SELECT_VERTEX) {
if (bbsel) {
- EM_backbuf_checkAndSelectVerts(vc->em, select);
+ EDBM_backbuf_checkAndSelectVerts(vc->em, select);
} else {
mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, 1);
}
@@ -1618,15 +1625,15 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten
if(ts->selectmode & SCE_SELECT_FACE) {
if(bbsel) {
- EM_backbuf_checkAndSelectFaces(vc->em, select);
+ EDBM_backbuf_checkAndSelectFaces(vc->em, select);
} else {
mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data);
}
}
- EM_free_backbuf();
+ EDBM_free_backbuf();
- EM_selectmode_flush(vc->em);
+ EDBM_selectmode_flush(vc->em);
return OPERATOR_FINISHED;
}
@@ -1860,7 +1867,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
if(vc.obedit) {
switch(vc.obedit->type) {
case OB_MESH:
- vc.em= ((Mesh *)vc.obedit->data)->edit_mesh;
+ vc.em= ((Mesh *)vc.obedit->data)->edit_btmesh;
ret= do_mesh_box_select(&vc, &rect, select, extend);
// if (EM_texFaceCheck())
if(ret & OPERATOR_FINISHED) {
@@ -2077,32 +2084,32 @@ void VIEW3D_OT_select(wmOperatorType *ot)
/* -------------------- circle select --------------------------------------------- */
-static void mesh_circle_doSelectVert(void *userData, EditVert *eve, int x, int y, int UNUSED(index))
+static void mesh_circle_doSelectVert(void *userData, BMVert *eve, int x, int y, int UNUSED(index))
{
struct {ViewContext *vc; short select; int mval[2]; float radius; } *data = userData;
int mx = x - data->mval[0], my = y - data->mval[1];
float r = sqrt(mx*mx + my*my);
if (r<=data->radius) {
- eve->f = data->select?(eve->f|1):(eve->f&~1);
+ BM_Select(data->vc->em->bm, eve, data->select);
}
}
-static void mesh_circle_doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int UNUSED(index))
+static void mesh_circle_doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int UNUSED(index))
{
struct {ViewContext *vc; short select; int mval[2]; float radius; } *data = userData;
if (edge_inside_circle(data->mval[0], data->mval[1], (short) data->radius, x0, y0, x1, y1)) {
- EM_select_edge(eed, data->select);
+ BM_Select(data->vc->em->bm, eed, data->select);
}
}
-static void mesh_circle_doSelectFace(void *userData, EditFace *efa, int x, int y, int UNUSED(index))
+static void mesh_circle_doSelectFace(void *userData, BMFace *efa, int x, int y, int UNUSED(index))
{
struct {ViewContext *vc; short select; int mval[2]; float radius; } *data = userData;
int mx = x - data->mval[0], my = y - data->mval[1];
float r = sqrt(mx*mx + my*my);
if (r<=data->radius) {
- EM_select_face_fgon(data->vc->em, efa, data->select);
+ BM_Select(data->vc->em->bm, efa, data->select);
}
}
@@ -2112,10 +2119,10 @@ static void mesh_circle_select(ViewContext *vc, int select, const int mval[2], f
int bbsel;
struct {ViewContext *vc; short select; int mval[2]; float radius; } data;
- bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0f));
+ bbsel= EDBM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
- vc->em= ((Mesh *)vc->obedit->data)->edit_mesh;
+ vc->em= ((Mesh *)vc->obedit->data)->edit_btmesh;
data.vc = vc;
data.select = select;
@@ -2125,7 +2132,7 @@ static void mesh_circle_select(ViewContext *vc, int select, const int mval[2], f
if(ts->selectmode & SCE_SELECT_VERTEX) {
if(bbsel) {
- EM_backbuf_checkAndSelectVerts(vc->em, select==LEFTMOUSE);
+ EDBM_backbuf_checkAndSelectVerts(vc->em, select==LEFTMOUSE);
} else {
mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, 1);
}
@@ -2133,7 +2140,7 @@ static void mesh_circle_select(ViewContext *vc, int select, const int mval[2], f
if(ts->selectmode & SCE_SELECT_EDGE) {
if (bbsel) {
- EM_backbuf_checkAndSelectEdges(vc->em, select==LEFTMOUSE);
+ EDBM_backbuf_checkAndSelectEdges(vc->em, select==LEFTMOUSE);
} else {
mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, 0);
}
@@ -2141,14 +2148,14 @@ static void mesh_circle_select(ViewContext *vc, int select, const int mval[2], f
if(ts->selectmode & SCE_SELECT_FACE) {
if(bbsel) {
- EM_backbuf_checkAndSelectFaces(vc->em, select==LEFTMOUSE);
+ EDBM_backbuf_checkAndSelectFaces(vc->em, select==LEFTMOUSE);
} else {
mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data);
}
}
- EM_free_backbuf();
- EM_selectmode_flush(vc->em);
+ EDBM_free_backbuf();
+ EDBM_selectmode_flush(vc->em);
}
static void paint_facesel_circle_select(ViewContext *vc, int select, const int mval[2], float rad)
@@ -2158,11 +2165,11 @@ static void paint_facesel_circle_select(ViewContext *vc, int select, const int m
/* int bbsel; */ /* UNUSED */
if (me) {
- em_vertoffs= me->totface+1; /* max index array */
+ bm_vertoffs= me->totpoly+1; /* max index array */
- /* bbsel= */ /* UNUSED */ EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0f));
- EM_backbuf_checkAndSelectTFaces(me, select==LEFTMOUSE);
- EM_free_backbuf();
+ /* bbsel= */ /* UNUSED */ EDBM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
+ EDBM_backbuf_checkAndSelectTFaces(me, select==LEFTMOUSE);
+ EDBM_free_backbuf();
}
}
@@ -2174,11 +2181,11 @@ static void paint_vertsel_circle_select(ViewContext *vc, int select, const int m
/* int bbsel; */ /* UNUSED */
/* struct {ViewContext *vc; short select; int mval[2]; float radius; } data = {NULL}; */ /* UNUSED */
if (me) {
- em_vertoffs= me->totvert+1; /* max index array */
+ bm_vertoffs= me->totvert+1; /* max index array */
- /* bbsel= */ /* UNUSED */ EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0f));
- EM_backbuf_checkAndSelectVerts_obmode(me, select==LEFTMOUSE);
- EM_free_backbuf();
+ /* bbsel= */ /* UNUSED */ EDBM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0f));
+ EDBM_backbuf_checkAndSelectVerts_obmode(me, select==LEFTMOUSE);
+ EDBM_free_backbuf();
paintvert_flush_flags(ob);
}
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 8000a3b03f1..654cc6b3080 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -55,6 +55,8 @@
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_object.h"
+#include "BKE_tessmesh.h"
+#include "BKE_DerivedMesh.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -78,10 +80,11 @@ extern float originmat[3][3]; /* XXX object.c */
typedef struct TransVert {
float *loc;
- float oldloc[3], fac;
+ float oldloc[3], maploc[3], fac;
float *val, oldval;
int flag;
float *nor;
+ int f1;
} TransVert;
static TransVert *transvmain=NULL;
@@ -97,7 +100,7 @@ static void special_transvert_update(Object *obedit)
if(obedit->type==OB_MESH) {
Mesh *me= obedit->data;
- recalc_editnormals(me->edit_mesh); // does face centers too
+ BM_Compute_Normals(me->edit_btmesh->bm); // does face centers too
}
else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
Curve *cu= obedit->data;
@@ -188,6 +191,19 @@ static void special_transvert_update(Object *obedit)
}
}
+static void set_mapped_co(void *vuserdata, int index, float *co, float *UNUSED(no), short *UNUSED(no_s))
+{
+ void ** userdata = vuserdata;
+ BMEditMesh *em = userdata[0];
+ TransVert *tv = userdata[1];
+ BMVert *eve = EDBM_get_vert_for_index(em, index);
+
+ if (BM_GetIndex(eve) != -1 && !tv[BM_GetIndex(eve)].f1) {
+ copy_v3_v3(tv[BM_GetIndex(eve)].maploc, co);
+ tv[BM_GetIndex(eve)].f1 = 1;
+ }
+}
+
/* copied from editobject.c, needs to be replaced with new transform code still */
/* mode flags: */
#define TM_ALL_JOINTS 1 /* all joints (for bones only) */
@@ -199,7 +215,7 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
BPoint *bp;
TransVert *tv=NULL;
MetaElem *ml;
- EditVert *eve;
+ BMVert *eve;
EditBone *ebo;
float total, center[3], centroid[3];
int a;
@@ -211,52 +227,87 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
if(obedit->type==OB_MESH) {
Mesh *me= obedit->data;
- EditMesh *em= me->edit_mesh;
+ BMEditMesh *em= me->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMIter iter;
+ void *userdata[2] = {em, NULL};
+ /*int proptrans= 0; */ /*UNUSED*/
// transform now requires awareness for select mode, so we tag the f1 flags in verts
tottrans= 0;
- if(em->selectmode & SCE_SELECT_VERTEX) {
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->h==0 && (eve->f & SELECT)) {
- eve->f1= SELECT;
+ if(em->bm->selectmode & SCE_SELECT_VERTEX) {
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)) {
+ BM_SetIndex(eve, 1);
tottrans++;
}
- else eve->f1= 0;
+ else BM_SetIndex(eve, 0);
}
}
- else if(em->selectmode & SCE_SELECT_EDGE) {
- EditEdge *eed;
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0 && (eed->f & SELECT)) eed->v1->f1= eed->v2->f1= SELECT;
+ else if(em->bm->selectmode & SCE_SELECT_EDGE) {
+ BMEdge *eed;
+
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
+ BM_SetIndex(eve, 0);
+
+ BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if(!BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SELECT))
+ BM_SetIndex(eed->v1, 1), BM_SetIndex(eed->v2, 1);
}
- for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
+
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
+ if(BM_GetIndex(eve)) tottrans++;
}
else {
- EditFace *efa;
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0 && (efa->f & SELECT)) {
- efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
- if(efa->v4) efa->v4->f1= SELECT;
+ BMFace *efa;
+
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
+ BM_SetIndex(eve, 0);
+
+ BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ if(!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)) {
+ BMIter liter;
+ BMLoop *l;
+
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
+ BM_SetIndex(l->v, 1);
+ }
}
}
- for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
+
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
+ if(BM_GetIndex(eve)) tottrans++;
}
/* and now make transverts */
if(tottrans) {
tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
-
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f1) {
+
+ a = 0;
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if(BM_GetIndex(eve)) {
+ BM_SetIndex(eve, a);
VECCOPY(tv->oldloc, eve->co);
tv->loc= eve->co;
if(eve->no[0] != 0.0f || eve->no[1] != 0.0f ||eve->no[2] != 0.0f)
tv->nor= eve->no; // note this is a hackish signal (ton)
- tv->flag= eve->f1 & SELECT;
+ tv->flag= BM_GetIndex(eve) & SELECT;
tv++;
- }
+ a++;
+ } else BM_SetIndex(eve, -1);
+ }
+
+ userdata[1] = transvmain;
+ }
+
+ if (transvmain && em->derivedCage) {
+ EDBM_init_index_arrays(em, 1, 0, 0);
+ em->derivedCage->foreachMappedVert(em->derivedCage, set_mapped_co, userdata);
+ EDBM_free_index_arrays(em);
+ } else if (transvmain) {
+ tv = transvmain;
+ for (a=0; a<tottrans; a++, tv++) {
+ copy_v3_v3(tv->maploc, tv->loc);
}
}
}
@@ -870,10 +921,10 @@ static int snap_curs_to_active(bContext *C, wmOperator *UNUSED(op))
if (obedit->type == OB_MESH) {
/* check active */
Mesh *me= obedit->data;
- EditSelection ese;
+ BMEditSelection ese;
- if (EM_get_actSelection(me->edit_mesh, &ese)) {
- EM_editselection_center(curs, &ese);
+ if (EDBM_get_actSelection(me->edit_btmesh, &ese)) {
+ EDBM_editselection_center(me->edit_btmesh, curs, &ese);
}
mul_m4_v3(obedit->obmat, curs);
@@ -958,7 +1009,7 @@ int minmax_verts(Object *obedit, float *min, float *max)
tv= transvmain;
for(a=0; a<tottrans; a++, tv++) {
- VECCOPY(vec, tv->loc);
+ VECCOPY(vec, tv->maploc);
mul_m3_v3(bmat, vec);
add_v3_v3(vec, obedit->obmat[3]);
add_v3_v3(centroid, vec);
@@ -970,4 +1021,3 @@ int minmax_verts(Object *obedit, float *min, float *max)
return 1;
}
-
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index 5d65202d7df..d226815a1de 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -267,3 +267,4 @@ void VIEW3D_OT_toolshelf(wmOperatorType *ot)
/* flags */
ot->flag= 0;
}
+
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 93c577619de..2ede76e925e 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -696,7 +696,6 @@ void ED_view3d_ob_project_mat_get(RegionView3D *rv3d, Object *ob, float pmat[4][
mul_m4_m4m4(pmat, vmat, rv3d->winmat);
}
-#if 0
/* Uses window coordinates (x,y) and depth component z to find a point in
modelspace */
void view3d_unproject(bglMats *mats, float out[3], const short x, const short y, const float z)
@@ -709,16 +708,15 @@ void view3d_unproject(bglMats *mats, float out[3], const short x, const short y,
out[1] = uy;
out[2] = uz;
}
-#endif
/* use view3d_get_object_project_mat to get projecting mat */
void ED_view3d_project_float(ARegion *ar, const float vec[3], float adr[2], float mat[4][4])
{
float vec4[4];
- adr[0]= IS_CLIPPED;
copy_v3_v3(vec4, vec);
vec4[3]= 1.0;
+ adr[0]= IS_CLIPPED;
mul_m4_v4(mat, vec4);
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index a659afbbada..98461918151 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenkernel
../../blenlib
../../blenloader
+ ../../bmesh
../../makesdna
../../makesrna
../../windowmanager
diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript
index f2d5baecfb3..0cf3875aa2e 100644
--- a/source/blender/editors/transform/SConscript
+++ b/source/blender/editors/transform/SConscript
@@ -6,6 +6,6 @@ sources = env.Glob('*.c')
incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../render/extern/include'
-incs += ' ../../gpu ../../makesrna ../../blenloader'
+incs += ' ../../gpu ../../makesrna ../../blenloader ../../bmesh'
env.BlenderLib ( 'bf_editors_transform', sources, Split(incs), [], libtype=['core'], priority=[40] )
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 2fc1182a280..92ccbdb1ecf 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -82,6 +82,8 @@
#include "BLI_editVert.h"
#include "BLI_ghash.h"
#include "BLI_linklist.h"
+#include "BLI_smallhash.h"
+#include "BLI_array.h"
#include "UI_resources.h"
@@ -91,6 +93,8 @@
#include "transform.h"
+#include <stdio.h>
+
void drawTransformApply(const struct bContext *C, struct ARegion *ar, void *arg);
int doEdgeSlide(TransInfo *t, float perc);
@@ -3454,7 +3458,8 @@ static void applyTranslation(TransInfo *t, float vec[3]) {
protectedTransBits(td->protectflag, tvec);
- add_v3_v3v3(td->loc, td->iloc, tvec);
+ if (td->loc)
+ add_v3_v3v3(td->loc, td->iloc, tvec);
constraintTransLim(t, td);
}
@@ -4247,506 +4252,464 @@ int BoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
}
/* ******************** Edge Slide *************** */
+static BMEdge *get_other_edge(BMesh *bm, BMVert *v, BMEdge *e)
+{
+ BMIter iter;
+ BMEdge *e2;
+
+ BM_ITER(e2, &iter, bm, BM_EDGES_OF_VERT, v) {
+ if (BM_TestHFlag(e2, BM_SELECT) && e2 != e)
+ return e2;
+ }
+
+ return NULL;
+}
+
+static BMLoop *get_next_loop(BMesh *UNUSED(bm), BMVert *v, BMLoop *l,
+ BMEdge *olde, BMEdge *nexte, float vec[3])
+{
+ BMLoop *firstl;
+ float a[3] = {0.0f, 0.0f, 0.0f}, n[3] = {0.0f, 0.0f, 0.0f};
+ int i=0;
+
+ firstl = l;
+ do {
+ l = BM_OtherFaceLoop(l->e, l->f, v);
+ if (l->radial_next == l)
+ return NULL;
+
+ if (l->e == nexte) {
+ if (i) {
+ mul_v3_fl(a, 1.0f / (float)i);
+ } else {
+ float f1[3], f2[3], f3[3];
+
+ sub_v3_v3v3(f1, BM_OtherEdgeVert(olde, v)->co, v->co);
+ sub_v3_v3v3(f2, BM_OtherEdgeVert(nexte, v)->co, v->co);
+
+ cross_v3_v3v3(f3, f1, l->f->no);
+ cross_v3_v3v3(a, f2, l->f->no);
+ mul_v3_fl(a, -1.0f);
+
+ add_v3_v3(a, f3);
+ mul_v3_fl(a, 0.5f);
+ }
+
+ copy_v3_v3(vec, a);
+ return l;
+ } else {
+ sub_v3_v3v3(n, BM_OtherEdgeVert(l->e, v)->co, v->co);
+ add_v3_v3v3(a, a, n);
+ i += 1;
+ }
+
+ if (BM_OtherFaceLoop(l->e, l->f, v)->e == nexte) {
+ if (i)
+ mul_v3_fl(a, 1.0f / (float)i);
+
+ copy_v3_v3(vec, a);
+ return BM_OtherFaceLoop(l->e, l->f, v);
+ }
+
+ l = l->radial_next;
+ } while (l != firstl);
+
+ if (i)
+ mul_v3_fl(a, 1.0f / (float)i);
+
+ copy_v3_v3(vec, a);
+
+ return NULL;
+}
static int createSlideVerts(TransInfo *t)
{
Mesh *me = t->obedit->data;
- EditMesh *em = me->edit_mesh;
- EditFace *efa;
- EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL;
- EditVert *ev, *nearest = NULL;
- LinkNode *edgelist = NULL, *vertlist=NULL, *look;
- GHash *vertgh;
+ BMEditMesh *em = me->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMIter iter, iter2;
+ BMEdge *e, *e1, *ee, *le;
+ BMVert *v, *v2, *first;
+ BMLoop *l, *l1, *l2;
TransDataSlideVert *tempsv;
- int i, j, numsel, numadded=0, timesthrough = 0, vertsel=0;
- /* UV correction vars */
- GHash **uvarray= NULL;
+ BMBVHTree *btree = BMBVH_NewBVH(em, 0, NULL, NULL);
+ SmallHash table;
SlideData *sld = MEM_callocN(sizeof(*sld), "sld");
- const int uvlay_tot= (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) ? CustomData_number_of_layers(&em->fdata, CD_MTFACE) : 0;
- int uvlay_idx;
- TransDataSlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL;
- RegionView3D *v3d = t->ar ? t->ar->regiondata : NULL; /* background mode support */
+ View3D *v3d = t->sa ? t->sa->spacedata.first : NULL;
+ RegionView3D *rv3d = t->ar ? t->ar->regiondata : NULL; /* background mode support */
+ ARegion *ar = t->ar;
float projectMat[4][4];
- float start[3] = {0.0f, 0.0f, 0.0f}, end[3] = {0.0f, 0.0f, 0.0f};
- float vec[3];
- float totvec=0.0;
+ float start[3] = {0.0f, 0.0f, 0.0f}, dir[3], end[3] = {0.0f, 0.0f, 0.0f};
+ float vec[3], vec2[3], lastvec[3], size, dis=0.0, z;
+ int numsel, i, j;
if (!v3d) {
/*ok, let's try to survive this*/
unit_m4(projectMat);
} else {
- ED_view3d_ob_project_mat_get(v3d, t->obedit, projectMat);
+ ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat);
}
- numsel =0;
-
- // Get number of selected edges and clear some flags
- for(eed=em->edges.first;eed;eed=eed->next) {
- eed->f1 = 0;
- eed->f2 = 0;
- if(eed->f & SELECT) numsel++;
- }
-
- for(ev=em->verts.first;ev;ev=ev->next) {
- ev->f1 = 0;
- }
+ BLI_smallhash_init(&sld->vhash);
+ BLI_smallhash_init(&sld->origfaces);
+ BLI_smallhash_init(&table);
+
+ /*ensure valid selection*/
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(v, BM_SELECT)) {
+ numsel = 0;
+ BM_ITER(e, &iter2, em->bm, BM_EDGES_OF_VERT, v) {
+ if (BM_TestHFlag(e, BM_SELECT)) {
+ /*BMESH_TODO: this is probably very evil,
+ set v->e to a selected edge*/
+ v->e = e;
- //Make sure each edge only has 2 faces
- // make sure loop doesn't cross face
- for(efa=em->faces.first;efa;efa=efa->next) {
- int ct = 0;
- if(efa->e1->f & SELECT) {
- ct++;
- efa->e1->f1++;
- if(efa->e1->f1 > 2) {
- //BKE_report(op->reports, RPT_ERROR, "3+ face edge");
- MEM_freeN(sld);
- return 0;
- }
- }
- if(efa->e2->f & SELECT) {
- ct++;
- efa->e2->f1++;
- if(efa->e2->f1 > 2) {
- //BKE_report(op->reports, RPT_ERROR, "3+ face edge");
- MEM_freeN(sld);
- return 0;
- }
- }
- if(efa->e3->f & SELECT) {
- ct++;
- efa->e3->f1++;
- if(efa->e3->f1 > 2) {
- //BKE_report(op->reports, RPT_ERROR, "3+ face edge");
- MEM_freeN(sld);
- return 0;
+ numsel++;
+ }
}
- }
- if(efa->e4 && efa->e4->f & SELECT) {
- ct++;
- efa->e4->f1++;
- if(efa->e4->f1 > 2) {
- //BKE_report(op->reports, RPT_ERROR, "3+ face edge");
- MEM_freeN(sld);
- return 0;
+
+ if (numsel == 0 || numsel > 2) {
+ return 0; //invalid edge selection
}
}
- // Make sure loop is not 2 edges of same face
- if(ct > 1) {
- //BKE_report(op->reports, RPT_ERROR, "Loop crosses itself");
- MEM_freeN(sld);
- return 0;
+ }
+
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(e, BM_SELECT)) {
+ if (BM_Edge_FaceCount(e) != 2)
+ return 0; //can only handle exactly 2 faces around each edge
}
}
- // Get # of selected verts
- for(ev=em->verts.first;ev;ev=ev->next) {
- if(ev->f & SELECT) vertsel++;
+ j = 0;
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(v, BM_SELECT)) {
+ BM_SetIndex(v, 1);
+ BLI_smallhash_insert(&table, (uintptr_t)v, SET_INT_IN_POINTER(j));
+ j += 1;
+ } else BM_SetIndex(v, 0);
}
- // Test for multiple segments
- if(vertsel > numsel+1) {
- //BKE_report(op->reports, RPT_ERROR, "Please choose a single edge loop");
- MEM_freeN(sld);
+ if (!j)
return 0;
- }
- // Get the edgeloop in order - mark f1 with SELECT once added
- for(eed=em->edges.first;eed;eed=eed->next) {
- if((eed->f & SELECT) && !(eed->f1 & SELECT)) {
- // If this is the first edge added, just put it in
- if(!edgelist) {
- BLI_linklist_prepend(&edgelist,eed);
- numadded++;
- first = eed;
- last = eed;
- eed->f1 = SELECT;
- } else {
- if(editedge_getSharedVert(eed, last)) {
- BLI_linklist_append(&edgelist,eed);
- eed->f1 = SELECT;
- numadded++;
- last = eed;
- } else if(editedge_getSharedVert(eed, first)) {
- BLI_linklist_prepend(&edgelist,eed);
- eed->f1 = SELECT;
- numadded++;
- first = eed;
- }
- }
- }
- if(eed->next == NULL && numadded != numsel) {
- eed=em->edges.first;
- timesthrough++;
- }
+ tempsv = MEM_callocN(sizeof(TransDataSlideVert)*j, "tempsv");
+
+ j = 0;
+ while (1) {
+ v = NULL;
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_GetIndex(v))
+ break;
- // It looks like there was an unexpected case - Hopefully should not happen
- if(timesthrough >= numsel*2) {
- BLI_linklist_free(edgelist,NULL);
- //BKE_report(op->reports, RPT_ERROR, "Could not order loop");
- MEM_freeN(sld);
- return 0;
}
- }
- // Put the verts in order in a linklist
- look = edgelist;
- while(look) {
- eed = look->link;
- if(!vertlist) {
- if(look->next) {
- temp = look->next->link;
+ if (!v)
+ break;
- //This is the first entry takes care of extra vert
- if(eed->v1 != temp->v1 && eed->v1 != temp->v2) {
- BLI_linklist_append(&vertlist,eed->v1);
- eed->v1->f1 = 1;
- } else {
- BLI_linklist_append(&vertlist,eed->v2);
- eed->v2->f1 = 1;
- }
- } else {
- //This is the case that we only have 1 edge
- BLI_linklist_append(&vertlist,eed->v1);
- eed->v1->f1 = 1;
- }
- }
- // for all the entries
- if(eed->v1->f1 != 1) {
- BLI_linklist_append(&vertlist,eed->v1);
- eed->v1->f1 = 1;
- } else if(eed->v2->f1 != 1) {
- BLI_linklist_append(&vertlist,eed->v2);
- eed->v2->f1 = 1;
- }
- look = look->next;
- }
-
- // populate the SlideVerts
-
- vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createSlideVerts gh");
- look = vertlist;
- while(look) {
- i=0;
- j=0;
- ev = look->link;
- tempsv = (struct TransDataSlideVert*)MEM_mallocN(sizeof(struct TransDataSlideVert),"SlideVert");
- tempsv->up = NULL;
- tempsv->down = NULL;
- tempsv->origvert.co[0] = ev->co[0];
- tempsv->origvert.co[1] = ev->co[1];
- tempsv->origvert.co[2] = ev->co[2];
- tempsv->origvert.no[0] = ev->no[0];
- tempsv->origvert.no[1] = ev->no[1];
- tempsv->origvert.no[2] = ev->no[2];
- // i is total edges that vert is on
- // j is total selected edges that vert is on
-
- for(eed=em->edges.first;eed;eed=eed->next) {
- if(eed->v1 == ev || eed->v2 == ev) {
- i++;
- if(eed->f & SELECT) {
- j++;
- }
- }
- }
- // If the vert is in the middle of an edge loop, it touches 2 selected edges and 2 unselected edges
- if(i == 4 && j == 2) {
- for(eed=em->edges.first;eed;eed=eed->next) {
- if(editedge_containsVert(eed, ev)) {
- if(!(eed->f & SELECT)) {
- if(!tempsv->up) {
- tempsv->up = eed;
- } else if (!(tempsv->down)) {
- tempsv->down = eed;
- }
- }
- }
- }
- }
- // If it is on the end of the loop, it touches 1 selected and as least 2 more unselected
- if(i >= 3 && j == 1) {
- for(eed=em->edges.first;eed;eed=eed->next) {
- if(editedge_containsVert(eed, ev) && eed->f & SELECT) {
- for(efa = em->faces.first;efa;efa=efa->next) {
- if(editface_containsEdge(efa, eed)) {
- if(editedge_containsVert(efa->e1, ev) && efa->e1 != eed) {
- if(!tempsv->up) {
- tempsv->up = efa->e1;
- } else if (!(tempsv->down)) {
- tempsv->down = efa->e1;
- }
- }
- if(editedge_containsVert(efa->e2, ev) && efa->e2 != eed) {
- if(!tempsv->up) {
- tempsv->up = efa->e2;
- } else if (!(tempsv->down)) {
- tempsv->down = efa->e2;
- }
- }
- if(editedge_containsVert(efa->e3, ev) && efa->e3 != eed) {
- if(!tempsv->up) {
- tempsv->up = efa->e3;
- } else if (!(tempsv->down)) {
- tempsv->down = efa->e3;
- }
- }
- if(efa->e4) {
- if(editedge_containsVert(efa->e4, ev) && efa->e4 != eed) {
- if(!tempsv->up) {
- tempsv->up = efa->e4;
- } else if (!(tempsv->down)) {
- tempsv->down = efa->e4;
- }
- }
- }
+ if (!v->e)
+ continue;
+
+ first = v;
- }
- }
- }
+ /*walk along the edge loop*/
+ e = v->e;
+
+ /*first, rewind*/
+ numsel = 0;
+ do {
+ e = get_other_edge(bm, v, e);
+ if (!e) {
+ e = v->e;
+ break;
}
- }
- if(i > 4 && j == 2) {
- BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
- BLI_linklist_free(vertlist,NULL);
- BLI_linklist_free(edgelist,NULL);
- return 0;
- }
- BLI_ghash_insert(vertgh,ev,tempsv);
- look = look->next;
- }
+ numsel += 1;
- // make sure the UPs and DOWNs are 'faceloops'
- // Also find the nearest slidevert to the cursor
+ if (!BM_GetIndex(BM_OtherEdgeVert(e, v)))
+ break;
- look = vertlist;
- nearest = NULL;
- while(look) {
- tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
+ v = BM_OtherEdgeVert(e, v);
+ } while (e != first->e);
- if(!tempsv->up || !tempsv->down) {
- //BKE_report(op->reports, RPT_ERROR, "Missing rails");
- BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
- BLI_linklist_free(vertlist,NULL);
- BLI_linklist_free(edgelist,NULL);
- return 0;
- }
+ BM_SetIndex(v, 0);
- if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
- if(!(tempsv->up->f & SELECT)) {
- tempsv->up->f |= SELECT;
- tempsv->up->f2 |= 16;
- } else {
- tempsv->up->f2 |= ~16;
- }
- if(!(tempsv->down->f & SELECT)) {
- tempsv->down->f |= SELECT;
- tempsv->down->f2 |= 16;
- } else {
- tempsv->down->f2 |= ~16;
- }
- }
+ l1 = l2 = l = NULL;
+ l1 = e->l;
+ l2 = e->l->radial_next;
- if(look->next != NULL) {
- TransDataSlideVert *sv;
-
- ev = (EditVert*)look->next->link;
- sv = BLI_ghash_lookup(vertgh, ev);
+ l = BM_OtherFaceLoop(l1->e, l1->f, v);
+ sub_v3_v3v3(vec, BM_OtherEdgeVert(l->e, v)->co, v->co);
- if(sv) {
- float co[3], co2[3], tvec[3];
+ if (l2 != l1) {
+ l = BM_OtherFaceLoop(l2->e, l2->f, v);
+ sub_v3_v3v3(vec2, BM_OtherEdgeVert(l->e, v)->co, v->co);
+ } else {
+ l2 = NULL;
+ }
- ev = (EditVert*)look->link;
+ /*iterate over the loop*/
+ first = v;
+ do {
+ TransDataSlideVert *sv = tempsv + j;
- if(!sharesFace(em, tempsv->up,sv->up)) {
- EditEdge *swap;
- swap = sv->up;
- sv->up = sv->down;
- sv->down = swap;
- }
-
- if (v3d) {
- ED_view3d_project_float(t->ar, tempsv->up->v1->co, co, projectMat);
- ED_view3d_project_float(t->ar, tempsv->up->v2->co, co2, projectMat);
- }
+ sv->v = v;
+ sv->origvert = *v;
+ VECCOPY(sv->upvec, vec);
+ if (l2)
+ VECCOPY(sv->downvec, vec2);
- if (ev == tempsv->up->v1) {
- sub_v3_v3v3(tvec, co, co2);
- } else {
- sub_v3_v3v3(tvec, co2, co);
- }
+ l = BM_OtherFaceLoop(l1->e, l1->f, v);
+ sv->up = BM_OtherEdgeVert(l->e, v);
- add_v3_v3(start, tvec);
+ if (l2) {
+ l = BM_OtherFaceLoop(l2->e, l2->f, v);
+ sv->down = BM_OtherEdgeVert(l->e, v);
+ }
- if (v3d) {
- ED_view3d_project_float(t->ar, tempsv->down->v1->co, co, projectMat);
- ED_view3d_project_float(t->ar, tempsv->down->v2->co, co2, projectMat);
- }
+ v2=v, v = BM_OtherEdgeVert(e, v);
- if (ev == tempsv->down->v1) {
- sub_v3_v3v3(tvec, co2, co);
- } else {
- sub_v3_v3v3(tvec, co, co2);
- }
+ e1 = e;
+ e = get_other_edge(bm, v, e);
+ if (!e) {
+ //v2=v, v = BM_OtherEdgeVert(l1->e, v);
- add_v3_v3(end, tvec);
+ sv = tempsv + j + 1;
+ sv->v = v;
+ sv->origvert = *v;
+
+ l = BM_OtherFaceLoop(l1->e, l1->f, v);
+ sv->up = BM_OtherEdgeVert(l->e, v);
+ sub_v3_v3v3(sv->upvec, BM_OtherEdgeVert(l->e, v)->co, v->co);
+
+ if (l2) {
+ l = BM_OtherFaceLoop(l2->e, l2->f, v);
+ sv->down = BM_OtherEdgeVert(l->e, v);
+ sub_v3_v3v3(sv->downvec, BM_OtherEdgeVert(l->e, v)->co, v->co);
+ }
- totvec += 1.0f;
- nearest = (EditVert*)look->link;
+ BM_SetIndex(v, 0);
+ BM_SetIndex(v2, 0);
+
+ j += 2;
+ break;
}
- }
+ l1 = get_next_loop(bm, v, l1, e1, e, vec);
+ l2 = l2 ? get_next_loop(bm, v, l2, e1, e, vec2) : NULL;
+ j += 1;
- look = look->next;
+ BM_SetIndex(v, 0);
+ BM_SetIndex(v2, 0);
+ } while (e != first->e && l1);
}
- add_v3_v3(start, end);
- mul_v3_fl(start, 0.5f*(1.0f/totvec));
- copy_v3_v3(vec, start);
- start[0] = t->mval[0];
- start[1] = t->mval[1];
- add_v3_v3v3(end, start, vec);
+ //EDBM_clear_flag_all(em, BM_SELECT);
+ sld->sv = tempsv;
+ sld->totsv = j;
+
+ /*find mouse vector*/
+ dis = z = -1.0f;
+ size = 50.0;
+ zero_v3(lastvec); zero_v3(dir);
+ ee = le = NULL;
+ BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(e, BM_SELECT)) {
+ BMIter iter2;
+ BMEdge *e2;
+ float vec1[3], dis2, mval[2] = {t->mval[0], t->mval[1]}, d;
+
+ /*search cross edges for visible edge to the mouse cursor,
+ then use the shared vertex to calculate screen vector*/
+ dis2 = -1.0f;
+ for (i=0; i<2; i++) {
+ v = i?e->v1:e->v2;
+ BM_ITER(e2, &iter2, em->bm, BM_EDGES_OF_VERT, v) {
+ if (BM_TestHFlag(e2, BM_SELECT))
+ continue;
+
+ if (!BMBVH_EdgeVisible(btree, e2, ar, v3d, t->obedit))
+ continue;
+
+ j = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v));
+
+ if (tempsv[j].down) {
+ ED_view3d_project_float_v3(ar, tempsv[j].down->co, vec1, projectMat);
+ } else {
+ add_v3_v3v3(vec1, v->co, tempsv[j].downvec);
+ ED_view3d_project_float_v3(ar, vec1, vec1, projectMat);
+ }
+
+ if (tempsv[j].up) {
+ ED_view3d_project_float_v3(ar, tempsv[j].up->co, vec2, projectMat);
+ } else {
+ add_v3_v3v3(vec1, v->co, tempsv[j].upvec);
+ ED_view3d_project_float_v3(ar, vec2, vec2, projectMat);
+ }
- /* Ensure minimum screen distance, when looking top down on edge loops */
-#define EDGE_SLIDE_MIN 30
- if (len_squared_v2v2(start, end) < (EDGE_SLIDE_MIN * EDGE_SLIDE_MIN)) {
- if(ABS(start[0]-end[0]) + ABS(start[1]-end[1]) < 4.0f) {
- /* even more exceptional case, points are ontop of each other */
- end[0]= start[0];
- end[1]= start[1] + EDGE_SLIDE_MIN;
- }
- else {
- sub_v2_v2(end, start);
- normalize_v2(end);
- mul_v2_fl(end, EDGE_SLIDE_MIN);
- add_v2_v2(end, start);
+ d = dist_to_line_segment_v2(mval, vec1, vec2);
+ if (dis2 == -1.0f || d < dis2) {
+ dis2 = d;
+ ee = e2;
+ size = len_v3v3(vec1, vec2);
+ sub_v3_v3v3(dir, vec1, vec2);
+ }
+ }
+ }
}
}
-#undef EDGE_SLIDE_MIN
+
+ em->bm->ob = t->obedit;
+ bmesh_begin_edit(em->bm, BMOP_UNTAN_MULTIRES);
+ /*create copies of faces for customdata projection*/
+ tempsv = sld->sv;
+ for (i=0; i<sld->totsv; i++, tempsv++) {
+ BMIter fiter, liter;
+ BMFace *f;
+ BMLoop *l;
+
+ BM_ITER(f, &fiter, em->bm, BM_FACES_OF_VERT, tempsv->v) {
+
+ if (!BLI_smallhash_haskey(&sld->origfaces, (uintptr_t)f)) {
+ BMFace *copyf = BM_Copy_Face(em->bm, f, 1, 1);
+
+ BM_Select(em->bm, copyf, 0);
+ BM_SetHFlag(copyf, BM_HIDDEN);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, copyf) {
+ BM_Select(em->bm, l->v, 0);
+ BM_SetHFlag(l->v, BM_HIDDEN);
+ BM_Select(em->bm, l->e, 0);
+ BM_SetHFlag(l->e, BM_HIDDEN);
+ }
+
+ BLI_smallhash_insert(&sld->origfaces, (uintptr_t)f, copyf);
+ }
+ }
- sld->start[0] = (int) start[0];
- sld->start[1] = (int) start[1];
- sld->end[0] = (int) end[0];
- sld->end[1] = (int) end[1];
+ BLI_smallhash_insert(&sld->vhash, (uintptr_t)tempsv->v, tempsv);
+ }
+
+ sld->em = em;
+
+ /*zero out start*/
+ zero_v3(start);
+
+ /*dir holds a vector along edge loop*/
+ copy_v3_v3(end, dir);
+ mul_v3_fl(end, 0.5);
- if (uvlay_tot) {
- int maxnum = 0;
+ sld->start[0] = t->mval[0] + start[0];
+ sld->start[1] = t->mval[1] + start[1];
- uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array");
- sld->totuv = uvlay_tot;
- suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(TransDataSlideUv), "SlideUVs"); /* uvLayers * verts */
- suv = NULL;
+ sld->end[0] = t->mval[0] + end[0];
+ sld->end[1] = t->mval[1] + end[1];
+
+ sld->perc = 0.0f;
+
+ t->customData = sld;
+
+ BLI_smallhash_release(&table);
+ BMBVH_FreeBVH(btree);
+
+ return 1;
+}
- for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
+void projectSVData(TransInfo *t, int final)
+{
+ SlideData *sld = t->customData;
+ TransDataSlideVert *tempsv;
+ BMEditMesh *em = sld->em;
+ SmallHash visit;
+ int i;
+
+ if (!em)
+ return;
+
+ /* BMESH_TODO, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)
+ * currently all vertex data is interpolated which is nice mostly
+ * except for shape keys where you dont want to modify UVs for eg.
+ * current BMesh code doesnt make it easy to pick which data we interpolate
+ * - campbell */
- uvarray[uvlay_idx] = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createSlideVerts2 gh");
+ BLI_smallhash_init(&visit);
+
+ for (i=0, tempsv=sld->sv; i<sld->totsv; i++, tempsv++) {
+ BMIter fiter;
+ BMFace *f;
+
+ BM_ITER(f, &fiter, em->bm, BM_FACES_OF_VERT, tempsv->v) {
+ BMIter liter2;
+ BMFace *copyf, *copyf2;
+ BMLoop *l2;
+ int sel, hide, do_vdata;
+
+ if (BLI_smallhash_haskey(&visit, (uintptr_t)f))
+ continue;
+
+ BLI_smallhash_insert(&visit, (uintptr_t)f, NULL);
+
+ /*the face attributes of the copied face will get
+ copied over, so its necessary to save the selection
+ and hidden state*/
+ sel = BM_TestHFlag(f, BM_SELECT);
+ hide = BM_TestHFlag(f, BM_HIDDEN);
+
+ copyf2 = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)f);
+
+ /*project onto copied projection face*/
+ BM_ITER(l2, &liter2, em->bm, BM_LOOPS_OF_FACE, f) {
+ copyf = copyf2;
+ do_vdata = l2->v==tempsv->v;
+
+ if (BM_TestHFlag(l2->e, BM_SELECT) || BM_TestHFlag(l2->prev->e, BM_SELECT)) {
+ BMLoop *l3 = l2;
+
+ do_vdata = 1;
+
+ if (!BM_TestHFlag(l2->e, BM_SELECT))
+ l3 = l3->prev;
+
+ if (sld->perc < 0.0 && BM_Vert_In_Face(l3->radial_next->f, tempsv->down)) {
+ copyf = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)l3->radial_next->f);
+ } else if (sld->perc > 0.0 && BM_Vert_In_Face(l3->radial_next->f, tempsv->up)) {
+ copyf = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)l3->radial_next->f);
+ }
+ if (!copyf)
+ continue; /* shouldn't happen, but protection */
+ }
+
+ BM_loop_interp_from_face(em->bm, l2, copyf, do_vdata, 0);
- for(ev=em->verts.first;ev;ev=ev->next) {
- ev->tmp.l = 0;
- }
- look = vertlist;
- while(look) {
- float *uv_new;
- tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
-
- ev = look->link;
- suv = NULL;
- for(efa = em->faces.first;efa;efa=efa->next) {
- if (ev->tmp.l != -1) { /* test for self, in this case its invalid */
- int k=-1; /* face corner */
-
- /* Is this vert in the faces corner? */
- if (efa->v1==ev) k=0;
- else if (efa->v2==ev) k=1;
- else if (efa->v3==ev) k=2;
- else if (efa->v4 && efa->v4==ev) k=3;
-
- if (k != -1) {
- MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx);
- EditVert *ev_up, *ev_down;
-
- uv_new = tf->uv[k];
-
- if (ev->tmp.l) {
- if (fabsf(suv->origuv[0]-uv_new[0]) > 0.0001f || fabs(suv->origuv[1]-uv_new[1]) > 0.0001f) {
- ev->tmp.l = -1; /* Tag as invalid */
- BLI_linklist_free(suv->fuv_list,NULL);
- suv->fuv_list = NULL;
- BLI_ghash_remove(uvarray[uvlay_idx],ev, NULL, NULL);
- suv = NULL;
- break;
- }
- } else {
- ev->tmp.l = 1;
- suv = suv_last;
-
- suv->fuv_list = NULL;
- suv->uv_up = suv->uv_down = NULL;
- suv->origuv[0] = uv_new[0];
- suv->origuv[1] = uv_new[1];
-
- BLI_linklist_prepend(&suv->fuv_list, uv_new);
- BLI_ghash_insert(uvarray[uvlay_idx],ev,suv);
-
- suv_last++; /* advance to next slide UV */
- maxnum++;
- }
-
- /* Now get the uvs along the up or down edge if we can */
- if (suv) {
- if (!suv->uv_up) {
- ev_up = editedge_getOtherVert(tempsv->up,ev);
- if (efa->v1==ev_up) suv->uv_up = tf->uv[0];
- else if (efa->v2==ev_up) suv->uv_up = tf->uv[1];
- else if (efa->v3==ev_up) suv->uv_up = tf->uv[2];
- else if (efa->v4 && efa->v4==ev_up) suv->uv_up = tf->uv[3];
- }
- if (!suv->uv_down) { /* if the first face was apart of the up edge, it cant be apart of the down edge */
- ev_down = editedge_getOtherVert(tempsv->down,ev);
- if (efa->v1==ev_down) suv->uv_down = tf->uv[0];
- else if (efa->v2==ev_down) suv->uv_down = tf->uv[1];
- else if (efa->v3==ev_down) suv->uv_down = tf->uv[2];
- else if (efa->v4 && efa->v4==ev_down) suv->uv_down = tf->uv[3];
- }
-
- /* Copy the pointers to the face UV's */
- BLI_linklist_prepend(&suv->fuv_list, uv_new);
- }
- }
+ if (final) {
+ BM_loop_interp_multires(em->bm, l2, copyf);
+ if (copyf2 != copyf) {
+ BM_loop_interp_multires(em->bm, l2, copyf2);
}
}
- look = look->next;
}
- } /* end uv layer loop */
- } /* end uvlay_tot */
-
- sld->uvhash = uvarray;
- sld->slideuv = slideuvs;
- sld->vhash = vertgh;
- sld->nearest = nearest;
- sld->vertlist = vertlist;
- sld->edgelist = edgelist;
- sld->suv_last = suv_last;
- sld->uvlay_tot = uvlay_tot;
-
- // we should have enough info now to slide
-
- t->customData = sld;
-
- return 1;
+
+ /*make sure face-attributes are correct (e.g. MTexPoly)*/
+ BM_Copy_Attributes(em->bm, em->bm, copyf2, f);
+
+ /*restore selection and hidden flags*/
+ BM_Select(em->bm, f, sel);
+ BM_Hide(em->bm, f, hide);
+ }
+ }
+
+ BLI_smallhash_release(&visit);
}
void freeSlideVerts(TransInfo *t)
{
- TransDataSlideUv *suv;
SlideData *sld = t->customData;
- Mesh *me = t->obedit->data;
- int uvlay_idx;
-
+ SmallHashIter hiter;
+ BMFace *copyf;
+
+#if 0 /*BMESH_TODO*/
if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
TransDataSlideVert *tempsv;
LinkNode *look = sld->vertlist;
@@ -4760,31 +4723,38 @@ void freeSlideVerts(TransInfo *t)
look = look->next;
}
}
-
- //BLI_ghash_free(edgesgh, freeGHash, NULL);
- BLI_ghash_free(sld->vhash, NULL, (GHashValFreeFP)MEM_freeN);
- BLI_linklist_free(sld->vertlist, NULL);
- BLI_linklist_free(sld->edgelist, NULL);
-
- if (sld->uvlay_tot) {
- for (uvlay_idx=0; uvlay_idx<sld->uvlay_tot; uvlay_idx++) {
- BLI_ghash_free(sld->uvhash[uvlay_idx], NULL, NULL);
- }
-
- suv = sld->suv_last-1;
- while (suv >= sld->slideuv) {
- if (suv->fuv_list) {
- BLI_linklist_free(suv->fuv_list,NULL);
- }
- suv--;
- }
-
- MEM_freeN(sld->slideuv);
- MEM_freeN(sld->uvhash);
+#endif
+
+ if (!sld)
+ return;
+
+ /*handle multires reprojection, done
+ on transform completion since it's
+ really slow -joeedh*/
+ if (t->state != TRANS_CANCEL) {
+ projectSVData(t, 1);
+ } else {
+ sld->perc = 0.0;
+ projectSVData(t, 0);
+ }
+
+ copyf = BLI_smallhash_iternew(&sld->origfaces, &hiter, NULL);
+ for (; copyf; copyf=BLI_smallhash_iternext(&hiter, NULL)) {
+ BM_Kill_Face_Verts(sld->em->bm, copyf);
}
+
+ sld->em->bm->ob = t->obedit;
+ bmesh_end_edit(sld->em->bm, BMOP_UNTAN_MULTIRES);
+ BLI_smallhash_release(&sld->vhash);
+ BLI_smallhash_release(&sld->origfaces);
+
+ MEM_freeN(sld->sv);
MEM_freeN(sld);
+
t->customData = NULL;
+
+ recalcData(t);
}
void initEdgeSlide(TransInfo *t)
@@ -4824,108 +4794,27 @@ void initEdgeSlide(TransInfo *t)
int doEdgeSlide(TransInfo *t, float perc)
{
SlideData *sld = t->customData;
- EditVert *ev, *nearest = sld->nearest;
- EditVert *centerVert, *upVert, *downVert;
- LinkNode *vertlist=sld->vertlist, *look;
- GHash *vertgh = sld->vhash;
- TransDataSlideVert *tempsv;
- float len;
- int prop=1, flip=0;
- /* UV correction vars */
- GHash **uvarray= sld->uvhash;
- const int uvlay_tot= sld->uvlay_tot;
- int uvlay_idx;
- TransDataSlideUv *suv;
- float uv_tmp[2];
- LinkNode *fuv_link;
-
- tempsv = BLI_ghash_lookup(vertgh,nearest);
-
- centerVert = editedge_getSharedVert(tempsv->up, tempsv->down);
- upVert = editedge_getOtherVert(tempsv->up, centerVert);
- downVert = editedge_getOtherVert(tempsv->down, centerVert);
-
- len = MIN2(perc, len_v3v3(upVert->co,downVert->co));
- len = MAX2(len, 0);
-
- //Adjust Edgeloop
- if(prop) {
- look = vertlist;
- while(look) {
- EditVert *tempev;
- ev = look->link;
- tempsv = BLI_ghash_lookup(vertgh,ev);
-
- tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev);
- interp_v3_v3v3(ev->co, tempsv->origvert.co, tempev->co, fabs(perc));
-
- if (uvlay_tot) {
- for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
- suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
- if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
- interp_v2_v2v2(uv_tmp, suv->origuv, (perc>=0)?suv->uv_up:suv->uv_down, fabs(perc));
- fuv_link = suv->fuv_list;
- while (fuv_link) {
- VECCOPY2D(((float *)fuv_link->link), uv_tmp);
- fuv_link = fuv_link->next;
- }
- }
- }
- }
+ TransDataSlideVert *svlist = sld->sv, *sv;
+ float vec[3];
+ int i;
- look = look->next;
- }
- }
- else {
- //Non prop code
- look = vertlist;
- while(look) {
- float newlen, edgelen;
- ev = look->link;
- tempsv = BLI_ghash_lookup(vertgh,ev);
- edgelen = len_v3v3(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co);
- newlen = (edgelen != 0.0f)? (len / edgelen): 0.0f;
- if(newlen > 1.0f) {newlen = 1.0;}
- if(newlen < 0.0f) {newlen = 0.0;}
- if(flip == 0) {
- interp_v3_v3v3(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen));
- if (uvlay_tot) {
- /* dont do anything if no UVs */
- for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
- suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
- if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
- interp_v2_v2v2(uv_tmp, suv->uv_down, suv->uv_up, fabs(newlen));
- fuv_link = suv->fuv_list;
- while (fuv_link) {
- VECCOPY2D(((float *)fuv_link->link), uv_tmp);
- fuv_link = fuv_link->next;
- }
- }
- }
- }
- } else{
- interp_v3_v3v3(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen));
-
- if (uvlay_tot) {
- /* dont do anything if no UVs */
- for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
- suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
- if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
- interp_v2_v2v2(uv_tmp, suv->uv_up, suv->uv_down, fabs(newlen));
- fuv_link = suv->fuv_list;
- while (fuv_link) {
- VECCOPY2D(((float *)fuv_link->link), uv_tmp);
- fuv_link = fuv_link->next;
- }
- }
- }
- }
- }
- look = look->next;
- }
+ sld->perc = perc;
+ sv = svlist;
+ for (i=0; i<sld->totsv; i++, sv++) {
+ if (perc > 0.0f) {
+ copy_v3_v3(vec, sv->upvec);
+ mul_v3_fl(vec, perc);
+ add_v3_v3v3(sv->v->co, sv->origvert.co, vec);
+ } else {
+ copy_v3_v3(vec, sv->downvec);
+ mul_v3_fl(vec, -perc);
+ add_v3_v3v3(sv->v->co, sv->origvert.co, vec);
+ }
}
-
+
+ projectSVData(t, 0);
+
return 1;
}
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 77e7cfb4d12..7138fd01fdd 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -39,6 +39,8 @@
#include "DNA_listBase.h"
#include "BLI_editVert.h"
+#include "BLI_smallhash.h"
+#include "BKE_tessmesh.h"
/* ************************** Types ***************************** */
@@ -64,6 +66,7 @@ struct wmEvent;
struct wmTimer;
struct ARegion;
struct ReportList;
+struct SmallHash;
/*
The ctrl value has different meaning:
@@ -190,25 +193,34 @@ struct LinkNode;
struct EditEdge;
struct EditVert;
struct GHash;
-typedef struct TransDataSlideUv {
- float origuv[2];
- float *uv_up, *uv_down;
- //float *fuv[4];
- struct LinkNode *fuv_list;
-} TransDataSlideUv;
typedef struct TransDataSlideVert {
- struct EditEdge *up, *down;
- struct EditVert origvert;
+ struct BMVert vup, vdown;
+ struct BMVert origvert;
+
+ struct BMVert *up, *down;
+ struct BMVert *v;
+
+ float upvec[3], downvec[3];
} TransDataSlideVert;
typedef struct SlideData {
+ TransDataSlideVert *sv;
+ int totsv;
+
+ struct SmallHash vhash;
+ struct SmallHash origfaces;
+
+ /*
TransDataSlideUv *slideuv, *suv_last;
int totuv, uvlay_tot;
struct GHash *vhash, **uvhash;
struct EditVert *nearest;
struct LinkNode *edgelist, *vertlist;
+ */
int start[2], end[2];
+ struct BMEditMesh *em;
+ float perc;
} SlideData;
typedef struct TransData {
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index a9f9208346c..6e1fc6da5d7 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -72,6 +72,7 @@
#include "BKE_sequencer.h"
#include "BKE_pointcache.h"
#include "BKE_bmesh.h"
+#include "BKE_tessmesh.h"
#include "BKE_scene.h"
#include "BKE_report.h"
@@ -95,13 +96,16 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
+#include "BLI_array.h"
#include "BLI_utildefines.h"
+#include "BLI_smallhash.h"
#include "RNA_access.h"
extern ListBase editelems;
#include "transform.h"
+#include "bmesh.h"
#include "BLO_sys_types.h" // for intptr_t support
@@ -287,18 +291,20 @@ static void createTransTexspace(TransInfo *t)
/* ********************* edge (for crease) ***** */
static void createTransEdge(TransInfo *t) {
- EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
+ BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
TransData *td = NULL;
- EditEdge *eed;
+ BMEdge *eed;
+ BMIter iter;
float mtx[3][3], smtx[3][3];
int count=0, countsel=0;
int propmode = t->flag & T_PROP_EDIT;
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0) {
- if (eed->f & SELECT) countsel++;
- if (propmode) count++;
- }
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(eed, BM_HIDDEN))
+ continue;
+
+ if (BM_TestHFlag(eed, BM_SELECT)) countsel++;
+ if (propmode) count++;
}
if (countsel == 0)
@@ -316,14 +322,17 @@ static void createTransEdge(TransInfo *t) {
copy_m3_m4(mtx, t->obedit->obmat);
invert_m3_m3(smtx, mtx);
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0 && (eed->f & SELECT || propmode)) {
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if(!BM_TestHFlag(eed, BM_HIDDEN) && (BM_TestHFlag(eed, BM_SELECT) || propmode)) {
+ float *bweight = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT);
+ float *crease = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE);
+
/* need to set center for center calculations */
add_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
mul_v3_fl(td->center, 0.5f);
td->loc= NULL;
- if (eed->f & SELECT)
+ if (BM_TestHFlag(eed, BM_SELECT))
td->flag= TD_SELECTED;
else
td->flag= 0;
@@ -334,12 +343,12 @@ static void createTransEdge(TransInfo *t) {
td->ext = NULL;
if (t->mode == TFM_BWEIGHT) {
- td->val = &(eed->bweight);
- td->ival = eed->bweight;
+ td->val = bweight;
+ td->ival = bweight ? *bweight : 1.0f;
}
else {
- td->val = &(eed->crease);
- td->ival = eed->crease;
+ td->val = crease;
+ td->ival = crease ? *crease : 0.0f;
}
td++;
@@ -1807,113 +1816,144 @@ void flushTransParticles(TransInfo *t)
/* proportional distance based on connectivity */
#define THRESHOLDFACTOR (1.0f-0.0001f)
-static int connectivity_edge(float mtx[][3], EditVert *v1, EditVert *v2)
+/*I did this wrong, it should be a breadth-first search
+ but instead it's a depth-first search, fudged
+ to report shortest distances. I have no idea how fast
+ or slow this is.*/
+static void editmesh_set_connectivity_distance(BMEditMesh *em, float mtx[][3], float *dists)
{
- float edge_vec[3];
- float edge_len;
- int done = 0;
-
- /* note: hidden verts are not being checked for, this assumes
- * flushing of hidden faces & edges is working right */
-
- if (v1->f2 + v2->f2 == 4)
- return 0;
+ BMVert **queue = NULL;
+ float *dqueue = NULL;
+ int *tots = MEM_callocN(sizeof(int)*em->bm->totvert, "tots editmesh_set_connectivity_distance");
+ BLI_array_declare(queue);
+ BLI_array_declare(dqueue);
+ SmallHash svisit, *visit=&svisit;
+ BMVert *v;
+ BMIter viter;
+ int i, start;
- sub_v3_v3v3(edge_vec, v1->co, v2->co);
- mul_m3_v3(mtx, edge_vec);
-
- edge_len = len_v3(edge_vec);
-
- if (v1->f2) {
- if (v2->f2) {
- if (v2->tmp.fp + edge_len < THRESHOLDFACTOR * v1->tmp.fp) {
- v1->tmp.fp = v2->tmp.fp + edge_len;
- done = 1;
- } else if (v1->tmp.fp + edge_len < THRESHOLDFACTOR * v2->tmp.fp) {
- v2->tmp.fp = v1->tmp.fp + edge_len;
- done = 1;
- }
- }
- else {
- v2->f2 = 1;
- v2->tmp.fp = v1->tmp.fp + edge_len;
- done = 1;
- }
- }
- else if (v2->f2) {
- v1->f2 = 1;
- v1->tmp.fp = v2->tmp.fp + edge_len;
- done = 1;
+ i = 0;
+ BM_ITER(v, &viter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(v, i);
+ dists[i] = FLT_MAX;
+ i++;
}
+
+ BLI_smallhash_init(visit);
- return done;
-}
-
-static void editmesh_set_connectivity_distance(EditMesh *em, float mtx[][3])
-{
- EditVert *eve;
- EditEdge *eed;
- EditFace *efa;
- int done= 1;
-
- /* f2 flag is used for 'selection' */
- /* tmp.l is offset on scratch array */
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->h==0) {
- eve->tmp.fp = 0;
-
- if(eve->f & SELECT) {
- eve->f2= 2;
- }
- else {
- eve->f2 = 0;
- }
- }
+ BM_ITER(v, &viter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(v, BM_SELECT)==0 || BM_TestHFlag(v, BM_HIDDEN))
+ continue;
+
+
+ BLI_smallhash_insert(visit, (uintptr_t)v, NULL);
+ BLI_array_append(queue, v);
+ BLI_array_append(dqueue, 0.0f);
+ dists[BM_GetIndex(v)] = 0.0f;
}
+
+ start = 0;
+ while (start < BLI_array_count(queue)) {
+ BMIter eiter;
+ BMEdge *e;
+ BMVert *v3, *v2;
+ float d, vec[3];
+
+ v2 = queue[start];
+ d = dqueue[start];
+
+ BM_ITER(e, &eiter, em->bm, BM_EDGES_OF_VERT, v2) {
+ float d2;
+ v3 = BM_OtherEdgeVert(e, v2);
+
+ if (BM_TestHFlag(v3, BM_SELECT) || BM_TestHFlag(v3, BM_HIDDEN))
+ continue;
+
+ sub_v3_v3v3(vec, v2->co, v3->co);
+ mul_m3_v3(mtx, vec);
+
+ d2 = d + len_v3(vec);
+
+ if (dists[BM_GetIndex(v3)] != FLT_MAX)
+ dists[BM_GetIndex(v3)] = MIN2(d2, dists[BM_GetIndex(v3)]);
+ else
+ dists[BM_GetIndex(v3)] = d2;
+
+ tots[BM_GetIndex(v3)] = 1;
-
- /* Floodfill routine */
- /*
- At worst this is n*n of complexity where n is number of edges
- Best case would be n if the list is ordered perfectly.
- Estimate is n log n in average (so not too bad)
- */
- while(done) {
- done= 0;
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0) {
- done |= connectivity_edge(mtx, eed->v1, eed->v2);
- }
+ if (BLI_smallhash_haskey(visit, (uintptr_t)v3))
+ continue;
+
+ BLI_smallhash_insert(visit, (uintptr_t)v3, NULL);
+
+ BLI_array_append(queue, v3);
+ BLI_array_append(dqueue, d2);
}
+
+ start++;
+ }
- /* do internal edges for quads */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if (efa->v4 && efa->h==0) {
- done |= connectivity_edge(mtx, efa->v1, efa->v3);
- done |= connectivity_edge(mtx, efa->v2, efa->v4);
- }
- }
+ BLI_smallhash_release(visit);
+
+ for (i=0; i<em->bm->totvert; i++) {
+ if (tots[i])
+ dists[i] /= (float)tots[i];
}
+
+ BLI_array_free(queue);
+ BLI_array_free(dqueue);
+ MEM_freeN(tots);
}
/* loop-in-a-loop I know, but we need it! (ton) */
-static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
+ static void get_face_center(float *centout, BMesh *bm, BMVert *eve)
+
{
- EditFace *efa;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter;
+ float cent[3] = {0.0, 0.0, 0.0};
- for(efa= em->faces.first; efa; efa= efa->next)
- if(efa->f & SELECT)
- if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
- break;
- if(efa) {
- copy_v3_v3(cent, efa->cent);
+ efa = BMIter_New(&iter, bm, BM_FACES_OF_VERT, eve);
+ if (efa) {
+ l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
+ for ( ; l; l=BMIter_Step(&iter)) {
+ VECADD(cent, cent, l->v->co);
+ }
+
+ mul_v3_fl(cent, 1.0f / (float)efa->len);
}
+
+ if (cent[0] == 0.0f && cent[1] == 0.0f && cent[2] == 0.0f) cent[2] = 1.0f;
+ copy_v3_v3(centout, cent);
}
+#define VertsToTransData(t, td, em, eve, bweight) \
+ td->flag = 0;\
+ td->loc = eve->co;\
+ copy_v3_v3(td->center, td->loc);\
+ if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))\
+ get_face_center(td->center, em, eve);\
+ copy_v3_v3(td->iloc, td->loc);\
+ copy_v3_v3(td->axismtx[2], eve->no);\
+ td->axismtx[0][0] =\
+ td->axismtx[0][1] =\
+ td->axismtx[0][2] =\
+ td->axismtx[1][0] =\
+ td->axismtx[1][1] =\
+ td->axismtx[1][2] = 0.0f;\
+ td->ext = NULL;\
+ td->val = NULL;\
+ td->extra = NULL;\
+ if (t->mode == TFM_BWEIGHT) {\
+ td->val = bweight;\
+ td->ival = bweight ? *(bweight) : 1.0f;\
+ }
+
+#if 0
//way to overwrite what data is edited with transform
//static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
-static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
+inline void VertsToTransData(TransInfo *t, TransData *td, BMesh *em, BMVert *eve)
{
td->flag = 0;
//if(key)
@@ -1943,50 +1983,99 @@ static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert
td->ival = eve->bweight;
}
}
+#endif
-#if 0
-static void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
- BME_Vert *v;
- BME_TransData *vtd;
- TransData *tob;
- int i;
+/* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
+
+static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
+{
+ float *vec = userData;
- tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
+ vec+= 3*index;
+ VECCOPY(vec, co);
+}
- for (i=0,v=bm->verts.first;v;v=v->next) {
- if ( (vtd = BME_get_transdata(td,v)) ) {
- tob->loc = vtd->loc;
- tob->val = &vtd->factor;
- copy_v3_v3(tob->iloc,vtd->co);
- copy_v3_v3(tob->center,vtd->org);
- copy_v3_v3(tob->axismtx[0],vtd->vec);
- tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
- tob++;
- i++;
- }
+static int modifiers_disable_subsurf_temporary(Object *ob)
+{
+ ModifierData *md;
+ int disabled = 0;
+
+ for(md=ob->modifiers.first; md; md=md->next)
+ if(md->type==eModifierType_Subsurf)
+ if(md->mode & eModifierMode_OnCage) {
+ md->mode ^= eModifierMode_DisableTemporary;
+ disabled= 1;
+ }
+
+ return disabled;
+}
+
+/* disable subsurf temporal, get mapped cos, and enable it */
+static float *get_crazy_mapped_editverts(TransInfo *t)
+{
+ Mesh *me= t->obedit->data;
+ DerivedMesh *dm;
+ float *vertexcos;
+
+ /* disable subsurf temporal, get mapped cos, and enable it */
+ if(modifiers_disable_subsurf_temporary(t->obedit)) {
+ /* need to make new derivemesh */
+ makeDerivedMesh(t->scene, t->obedit, me->edit_btmesh, CD_MASK_BAREMESH, 0);
}
- /* since td is a memarena, it can hold more transdata than actual elements
- * (i.e. we can't depend on td->len to determine the number of actual elements) */
- t->total = i;
+
+ /* now get the cage */
+ dm= editbmesh_get_derived_cage(t->scene, t->obedit, me->edit_btmesh, CD_MASK_BAREMESH);
+
+ vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_btmesh->bm->totvert, "vertexcos map");
+ dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
+
+ dm->release(dm);
+
+ /* set back the flag, no new cage needs to be built, transform does it */
+ modifiers_disable_subsurf_temporary(t->obedit);
+
+ return vertexcos;
}
-#endif
+
+#define TAN_MAKE_VEC(a, b, c) a[0]= b[0] + 0.2f*(b[0]-c[0]); a[1]= b[1] + 0.2f*(b[1]-c[1]); a[2]= b[2] + 0.2f*(b[2]-c[2])
+static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
+{
+ float vecu[3], vecv[3];
+ float q1[4], q2[4];
+
+ TAN_MAKE_VEC(vecu, v1, v2);
+ TAN_MAKE_VEC(vecv, v1, v3);
+ tri_to_quat( q1,v1, vecu, vecv);
+
+ TAN_MAKE_VEC(vecu, def1, def2);
+ TAN_MAKE_VEC(vecv, def1, def3);
+ tri_to_quat( q2,def1, vecu, vecv);
+
+ sub_qt_qtqt(quat, q2, q1);
+}
+#undef TAN_MAKE_VEC
static void createTransEditVerts(bContext *C, TransInfo *t)
{
ToolSettings *ts = CTX_data_tool_settings(C);
TransData *tob = NULL;
- EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
- EditVert *eve;
- EditVert *eve_act = NULL;
+ BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
+ BMesh *bm = em->bm;
+ BMVert *eve;
+ BMIter iter;
+ BMVert *eve_act = NULL;
float *mappedcos = NULL, *quats= NULL;
float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
- int count=0, countsel=0, a, totleft;
+ float *dists=NULL;
+ int count=0, countsel=0, a, totleft, *selstate = NULL;
+ BLI_array_declare(selstate);
int propmode = (t->flag & T_PROP_EDIT) ? (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) : 0;
int mirror = 0;
short selectmode = ts->selectmode;
if (t->flag & T_MIRROR)
{
+ EDBM_CacheMirrorVerts(em);
mirror = 1;
}
@@ -1997,53 +2086,83 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
// transform now requires awareness for select mode, so we tag the f1 flags in verts
if(selectmode & SCE_SELECT_VERTEX) {
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->h==0 && (eve->f & SELECT))
- eve->f1= SELECT;
- else
- eve->f1= 0;
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_Selected(bm, eve)) {
+ BM_SetIndex(eve, SELECT);
+ }
+ else {
+ BM_SetIndex(eve, 0);
+ }
}
}
else if(selectmode & SCE_SELECT_EDGE) {
- EditEdge *eed;
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0 && (eed->f & SELECT))
- eed->v1->f1= eed->v2->f1= SELECT;
+ BMEdge *eed;
+
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for( ; eve; eve=BMIter_Step(&iter)) BM_SetIndex(eve, 0);
+
+ eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
+ for( ; eed; eed=BMIter_Step(&iter)) {
+ if (BM_Selected(bm, eed)) {
+ BM_SetIndex(eed->v1, SELECT);
+ BM_SetIndex(eed->v2, SELECT);
+ }
}
}
else {
- EditFace *efa;
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0 && (efa->f & SELECT)) {
- efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
- if(efa->v4) efa->v4->f1= SELECT;
+ BMFace *efa;
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for( ; eve; eve=BMIter_Step(&iter)) BM_SetIndex(eve, 0);
+
+ efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
+ for( ; efa; efa=BMIter_Step(&iter)) {
+ if (BM_Selected(bm, efa)) {
+ BMIter liter;
+ BMLoop *l;
+
+ l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, efa);
+ for (; l; l=BMIter_Step(&liter)) {
+ BM_SetIndex(l->v, SELECT);
+ }
}
}
}
- /* now we can count */
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->h==0) {
- if(eve->f1) countsel++;
- if(propmode) count++;
+ /* now we can count. we store selection state in selstate, since
+ get_crazy_mapped_editverts messes up the index state of the
+ verts*/
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for(a=0; eve; eve=BMIter_Step(&iter), a++) {
+ BLI_array_growone(selstate);
+
+ if(BM_GetIndex(eve)) {
+ selstate[a] = 1;
+ countsel++;
}
+ if(propmode) count++;
}
- /* note: in prop mode we need at least 1 selected */
- if (countsel==0) return;
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel == 0) {
+ goto cleanup;
+ }
/* check active */
- if (em->selected.last) {
- EditSelection *ese = em->selected.last;
- if ( ese->type == EDITVERT ) {
- eve_act = (EditVert *)ese->data;
+ if (em->bm->selected.last) {
+ BMEditSelection *ese = em->bm->selected.last;
+ if ( ese->type == BM_VERT ) {
+ eve_act = (BMVert *)ese->data;
}
}
- if(propmode) t->total = count;
+ if(propmode) {
+ t->total = count;
+
+ /* allocating scratch arrays */
+ if (propmode & T_PROP_CONNECTED)
+ dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears");
+ }
else t->total = countsel;
tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
@@ -2051,16 +2170,15 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
copy_m3_m4(mtx, t->obedit->obmat);
invert_m3_m3(smtx, mtx);
- if(propmode & T_PROP_CONNECTED) {
- editmesh_set_connectivity_distance(em, mtx);
- }
+ if(propmode & T_PROP_CONNECTED)
+ editmesh_set_connectivity_distance(em, mtx, dists);
/* detect CrazySpace [tm] */
if(modifiers_getCageIndex(t->scene, t->obedit, NULL, 1)>=0) {
if(modifiers_isCorrectableDeformed(t->obedit)) {
/* check if we can use deform matrices for modifier from the
start up to stack, they are more accurate than quats */
- totleft= editmesh_get_first_deform_matrices(t->scene, t->obedit, em, &defmats, &defcos);
+ totleft= editbmesh_get_first_deform_matrices(t->scene, t->obedit, em, &defmats, &defcos);
/* if we still have more modifiers, also do crazyspace
correction with quats, relative to the coordinates after
@@ -2080,8 +2198,9 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
/* find out which half we do */
if(mirror) {
- for (eve=em->verts.first; eve; eve=eve->next) {
- if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for(a=0; eve; eve=BMIter_Step(&iter), a++) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN) && selstate[a] && eve->co[0]!=0.0f) {
if(eve->co[0]<0.0f)
{
t->mirror = -1;
@@ -2092,34 +2211,36 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
}
}
- for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
- if(eve->h==0) {
- if(propmode || eve->f1) {
- VertsToTransData(t, tob, em, eve);
+ eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for(a=0; eve; eve=BMIter_Step(&iter), a++) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN)) {
+ if(propmode || selstate[a]) {
+ float *bweight = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_BWEIGHT);
+
+ VertsToTransData(t, tob, bm, eve, bweight);
/* selected */
- if(eve->f1) tob->flag |= TD_SELECTED;
+ if(selstate[a]) tob->flag |= TD_SELECTED;
/* active */
if(eve == eve_act) tob->flag |= TD_ACTIVE;
if(propmode) {
- if (eve->f2) {
- tob->dist= eve->tmp.fp;
- }
- else {
+ if (propmode & T_PROP_CONNECTED) {
+ tob->dist = dists[a];
+ } else {
tob->flag |= TD_NOTCONNECTED;
tob->dist = MAXFLOAT;
}
}
/* CrazySpace */
- if(defmats || (quats && eve->tmp.p)) {
- float mat[3][3], imat[3][3], qmat[3][3];
+ if(defmats || (quats && BM_GetIndex(eve) != -1)) {
+ float mat[3][3], qmat[3][3], imat[3][3];
/* use both or either quat and defmat correction */
- if(quats && eve->tmp.f) {
- quat_to_mat3( qmat,eve->tmp.p);
+ if(quats && BM_GetIndex(eve) != -1) {
+ quat_to_mat3(qmat, quats + 4*BM_GetIndex(eve));
if(defmats)
mul_serie_m3(mat, mtx, qmat, defmats[a],
@@ -2141,9 +2262,11 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
}
/* Mirror? */
+
+ //BMESH_TODO
if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
- EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, eve, tob->iloc, a); /* initializes octree on first call */
- if(vmir != eve) {
+ BMVert *vmir= EDBM_GetMirrorVert(em, eve); //t->obedit, em, eve, tob->iloc, a);
+ if(vmir && vmir != eve) {
tob->extra = vmir;
}
}
@@ -2163,12 +2286,23 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
}
}
}
-
+
+cleanup:
/* crazy space free */
if(quats)
MEM_freeN(quats);
if(defmats)
MEM_freeN(defmats);
+ if (dists)
+ MEM_freeN(dists);
+
+ BLI_array_free(selstate);
+
+ if (t->flag & T_MIRROR)
+ {
+ EDBM_EndMirrorCache(em);
+ mirror = 1;
+ }
}
/* *** NODE EDITOR *** */
@@ -2340,30 +2474,33 @@ static void createTransUVs(bContext *C, TransInfo *t)
Scene *scene = t->scene;
TransData *td = NULL;
TransData2D *td2d = NULL;
- MTFace *tf;
+ MTexPoly *tf;
+ MLoopUV *luv;
+ BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
int count=0, countsel=0;
int propmode = t->flag & T_PROP_EDIT;
- EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
- EditFace *efa;
-
if(!ED_space_image_show_uvedit(sima, t->obedit)) return;
/* count */
- for (efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- efa->tmp.p = tf;
+ if(!uvedit_face_visible(scene, ima, efa, tf)) {
+ BM_SetIndex(efa, 0);
+ continue;
+ }
+
+ BM_SetIndex(efa, 1);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l))
+ countsel++;
- if (uvedit_uv_selected(scene, efa, tf, 0)) countsel++;
- if (uvedit_uv_selected(scene, efa, tf, 1)) countsel++;
- if (uvedit_uv_selected(scene, efa, tf, 2)) countsel++;
- if (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) countsel++;
if(propmode)
- count += (efa->v4)? 4: 3;
- } else {
- efa->tmp.p = NULL;
+ count++;
}
}
@@ -2382,20 +2519,17 @@ static void createTransUVs(bContext *C, TransInfo *t)
td= t->data;
td2d= t->data2d;
- for (efa= em->faces.first; efa; efa= efa->next) {
- if ((tf=(MTFace *)efa->tmp.p)) {
- if (propmode) {
- UVsToTransData(sima, td++, td2d++, tf->uv[0], uvedit_uv_selected(scene, efa, tf, 0));
- UVsToTransData(sima, td++, td2d++, tf->uv[1], uvedit_uv_selected(scene, efa, tf, 1));
- UVsToTransData(sima, td++, td2d++, tf->uv[2], uvedit_uv_selected(scene, efa, tf, 2));
- if(efa->v4)
- UVsToTransData(sima, td++, td2d++, tf->uv[3], uvedit_uv_selected(scene, efa, tf, 3));
- } else {
- if(uvedit_uv_selected(scene, efa, tf, 0)) UVsToTransData(sima, td++, td2d++, tf->uv[0], 1);
- if(uvedit_uv_selected(scene, efa, tf, 1)) UVsToTransData(sima, td++, td2d++, tf->uv[1], 1);
- if(uvedit_uv_selected(scene, efa, tf, 2)) UVsToTransData(sima, td++, td2d++, tf->uv[2], 1);
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) UVsToTransData(sima, td++, td2d++, tf->uv[3], 1);
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
+
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (!propmode && !uvedit_uv_selected(em, scene, l))
+ continue;
+
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ UVsToTransData(sima, td++, td2d++, luv->uv, uvedit_uv_selected(em, scene, l));
}
}
@@ -2417,6 +2551,8 @@ void flushTransUVs(TransInfo *t)
/* flush to 2d vector from internally used 3d vector */
for(a=0, td= t->data2d; a<t->total; a++, td++) {
+ if (!td->loc2d) continue;
+
td->loc2d[0]= td->loc[0]*invx;
td->loc2d[1]= td->loc[1]*invy;
@@ -4759,7 +4895,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
if (t->spacetype==SPACE_VIEW3D) {
if (t->obedit) {
if (cancelled==0) {
- EM_automerge(t->scene, t->obedit, 1);
+ EDBM_automerge(t->scene, t->obedit, 1);
}
}
}
@@ -4998,9 +5134,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
else if (t->obedit) {
if (t->obedit->type == OB_MESH)
{
- EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
+ // BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
/* table needs to be created for each edit command, since vertices can move etc */
- mesh_octree_table(t->obedit, em, NULL, 'e');
+ // BMESH_TODO mesh_octree_table(t->obedit, em, NULL, 'e');
}
}
else if ((t->flag & T_POSE) && (t->poseobj)) {
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 103556accd8..8fc1b57c7ac 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -70,6 +70,7 @@
#include "BKE_mesh.h"
#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_tessmesh.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@@ -230,10 +231,10 @@ static void clipMirrorModifier(TransInfo *t, Object *ob)
}
/* assumes obedit set to mesh object */
-static void editmesh_apply_to_mirror(TransInfo *t)
+static void editbmesh_apply_to_mirror(TransInfo *t)
{
TransData *td = t->data;
- EditVert *eve;
+ BMVert *eve;
int i;
for(i = 0 ; i < t->total; i++, td++) {
@@ -368,7 +369,6 @@ static void recalcData_actedit(TransInfo *t)
BLI_freelistN(&anim_data);
}
}
-
/* helper for recalcData() - for Graph Editor transforms */
static void recalcData_graphedit(TransInfo *t)
{
@@ -639,6 +639,7 @@ static void recalcData_view3d(TransInfo *t)
calchandlesNurb(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
nu= nu->next;
}
+
}
else {
/* Normal updating */
@@ -661,7 +662,7 @@ static void recalcData_view3d(TransInfo *t)
if(la->editlatt->latt->flag & LT_OUTSIDE) outside_lattice(la->editlatt->latt);
}
else if (t->obedit->type == OB_MESH) {
- EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh;
+ BMEditMesh *em = ((Mesh*)t->obedit->data)->edit_btmesh;
/* mirror modifier clipping? */
if(t->state != TRANS_CANCEL) {
/* apply clipping after so we never project past the clip plane [#25423] */
@@ -669,11 +670,12 @@ static void recalcData_view3d(TransInfo *t)
clipMirrorModifier(t, t->obedit);
}
if((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR))
- editmesh_apply_to_mirror(t);
+ editbmesh_apply_to_mirror(t);
DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
- recalc_editnormals(em);
+ EDBM_RecalcNormals(em);
+ BMEdit_RecalcTesselation(em);
}
else if(t->obedit->type==OB_ARMATURE) { /* no recalc flag, does pose */
bArmature *arm= t->obedit->data;
@@ -1489,13 +1491,13 @@ void calculateCenter(TransInfo *t)
/* EDIT MODE ACTIVE EDITMODE ELEMENT */
if (t->obedit && t->obedit->type == OB_MESH) {
- EditSelection ese;
- EditMesh *em = BKE_mesh_get_editmesh(t->obedit->data);
+ BMEditSelection ese;
+ BMEditMesh *em = ((Mesh*)t->obedit->data)->edit_btmesh;
- if (EM_get_actSelection(em, &ese)) {
- EM_editselection_center(t->center, &ese);
- calculateCenter2D(t);
- break;
+ if (EDBM_get_actSelection(em, &ese)) {
+ EDBM_editselection_center(em, t->center, &ese);
+ calculateCenter2D(t);
+ break;
}
} /* END EDIT MODE ACTIVE ELEMENT */
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 5b275a572cb..70272c1cea0 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -60,6 +60,7 @@
#include "BKE_mesh.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
+#include "BKE_tessmesh.h"
#include "BLI_math.h"
#include "BLI_editVert.h"
@@ -297,72 +298,63 @@ int calc_manipulator_stats(const bContext *C)
if((ob->lay & v3d->lay)==0) return 0;
if(obedit->type==OB_MESH) {
- EditMesh *em = BKE_mesh_get_editmesh(obedit->data);
- EditVert *eve;
- EditSelection ese;
+ BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
+ BMEditSelection ese;
float vec[3]= {0,0,0};
/* USE LAST SELECTE WITH ACTIVE */
- if (v3d->around==V3D_ACTIVE && EM_get_actSelection(em, &ese)) {
- EM_editselection_center(vec, &ese);
+ if (v3d->around==V3D_ACTIVE && EDBM_get_actSelection(em, &ese)) {
+ EDBM_editselection_center(em, vec, &ese);
calc_tw_center(scene, vec);
totsel= 1;
- } else {
+ }
+ else {
+ BMesh *bm = em->bm;
+ BMVert *eve;
+
+ BMIter iter;
+
/* do vertices/edges/faces for center depending on selection
mode. note we can't use just vertex selection flag because
it is not flush down on changes */
if(ts->selectmode & SCE_SELECT_VERTEX) {
- for(eve= em->verts.first; eve; eve= eve->next) {
- if(eve->f & SELECT) {
- totsel++;
- calc_tw_center(scene, eve->co);
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN)) {
+ if(BM_TestHFlag(eve, BM_SELECT)) {
+ totsel++;
+ calc_tw_center(scene, eve->co);
+ }
}
}
}
else if(ts->selectmode & SCE_SELECT_EDGE) {
- EditEdge *eed;
-
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->h==0 && (eed->f & SELECT)) {
- if(!eed->v1->f1) {
- eed->v1->f1= 1;
- totsel++;
- calc_tw_center(scene, eed->v1->co);
- }
- if(!eed->v2->f1) {
- eed->v2->f1= 1;
- totsel++;
- calc_tw_center(scene, eed->v2->co);
+ BMIter itersub;
+ BMEdge *eed;
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN)) {
+ /* check the vertex has a selected edge, only add it once */
+ BM_ITER(eed, &itersub, bm, BM_EDGES_OF_VERT, eve) {
+ if(BM_TestHFlag(eed, BM_SELECT)) {
+ totsel++;
+ calc_tw_center(scene, eve->co);
+ break;
+ }
}
}
}
}
else {
- EditFace *efa;
-
- for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->h==0 && (efa->f & SELECT)) {
- if(!efa->v1->f1) {
- efa->v1->f1= 1;
- totsel++;
- calc_tw_center(scene, efa->v1->co);
- }
- if(!efa->v2->f1) {
- efa->v2->f1= 1;
- totsel++;
- calc_tw_center(scene, efa->v2->co);
- }
- if(!efa->v3->f1) {
- efa->v3->f1= 1;
- totsel++;
- calc_tw_center(scene, efa->v3->co);
- }
- if(efa->v4 && !efa->v4->f1) {
- efa->v4->f1= 1;
- totsel++;
- calc_tw_center(scene, efa->v4->co);
+ BMIter itersub;
+ BMFace *efa;
+ BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+ if(!BM_TestHFlag(eve, BM_HIDDEN)) {
+ /* check the vertex has a selected face, only add it once */
+ BM_ITER(efa, &itersub, bm, BM_FACES_OF_VERT, eve) {
+ if(BM_TestHFlag(efa, BM_SELECT)) {
+ totsel++;
+ calc_tw_center(scene, eve->co);
+ break;
+ }
}
}
}
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index a09778726d5..440d40ef0c3 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -41,6 +41,7 @@
#include "BKE_armature.h"
#include "BKE_curve.h"
#include "BKE_context.h"
+#include "BKE_tessmesh.h"
#include "BKE_report.h"
#include "BLI_math.h"
@@ -572,56 +573,57 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
if(ob->type==OB_MESH)
{
Mesh *me= ob->data;
- EditMesh *em = me->edit_mesh;
- EditVert *eve;
- EditSelection ese;
+ BMEditMesh *em = me->edit_btmesh;
+ BMVert *eve;
+ BMEditSelection ese;
float vec[3]= {0,0,0};
/* USE LAST SELECTED WITH ACTIVE */
- if (activeOnly && EM_get_actSelection(em, &ese))
+ if (activeOnly && EDBM_get_actSelection(em, &ese))
{
- EM_editselection_normal(normal, &ese);
- EM_editselection_plane(plane, &ese);
+ EDBM_editselection_normal(normal, &ese);
+ EDBM_editselection_plane(em, plane, &ese);
switch (ese.type)
{
- case EDITVERT:
+ case BM_VERT:
result = ORIENTATION_VERT;
break;
- case EDITEDGE:
+ case BM_EDGE:
result = ORIENTATION_EDGE;
break;
- case EDITFACE:
+ case BM_FACE:
result = ORIENTATION_FACE;
break;
}
}
else
{
- if (em->totfacesel >= 1)
+ if (em->bm->totfacesel >= 1)
{
- EditFace *efa;
-
- for(efa= em->faces.first; efa; efa= efa->next)
- {
- if(efa->f & SELECT)
- {
- VECADD(normal, normal, efa->n);
- sub_v3_v3v3(vec, efa->v2->co, efa->v1->co);
+ BMFace *efa;
+ BMIter iter;
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(BM_TestHFlag(efa, BM_SELECT)) {
+ VECADD(normal, normal, efa->no);
+ sub_v3_v3v3(vec,
+ ((BMLoopList*)efa->loops.first)->first->v->co,
+ (((BMLoopList*)efa->loops.first)->first->next)->v->co);
VECADD(plane, plane, vec);
}
}
result = ORIENTATION_FACE;
}
- else if (em->totvertsel == 3)
+ else if (em->bm->totvertsel == 3)
{
- EditVert *v1 = NULL, *v2 = NULL, *v3 = NULL;
+ BMVert *v1 = NULL, *v2 = NULL, *v3 = NULL;
+ BMIter iter;
float cotangent[3];
- for (eve = em->verts.first; eve; eve = eve->next)
- {
- if ( eve->f & SELECT ) {
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_SELECT)) {
if (v1 == NULL) {
v1 = eve;
}
@@ -640,12 +642,13 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
}
/* if there's an edge available, use that for the tangent */
- if (em->totedgesel >= 1)
+ if (em->bm->totedgesel >= 1)
{
- EditEdge *eed = NULL;
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
+ BMEdge *eed = NULL;
+ BMIter iter;
+
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if(BM_TestHFlag(eed, BM_SELECT)) {
sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
break;
}
@@ -654,12 +657,13 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
result = ORIENTATION_FACE;
}
- else if (em->totedgesel == 1)
+ else if (em->bm->totedgesel == 1)
{
- EditEdge *eed;
-
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->f & SELECT) {
+ BMEdge *eed = NULL;
+ BMIter iter;
+
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if(BM_TestHFlag(eed, BM_SELECT)) {
/* use average vert normals as plane and edge vector as normal */
copy_v3_v3(plane, eed->v1->no);
VECADD(plane, plane, eed->v2->no);
@@ -669,13 +673,13 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
}
result = ORIENTATION_EDGE;
}
- else if (em->totvertsel == 2)
+ else if (em->bm->totvertsel == 2)
{
- EditVert *v1 = NULL, *v2 = NULL;
-
- for (eve = em->verts.first; eve; eve = eve->next)
- {
- if ( eve->f & SELECT ) {
+ BMVert *v1 = NULL, *v2 = NULL;
+ BMIter iter;
+
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_SELECT)) {
if (v1 == NULL) {
v1 = eve;
}
@@ -691,24 +695,25 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
}
result = ORIENTATION_EDGE;
}
- else if (em->totvertsel == 1)
+ else if (em->bm->totvertsel == 1)
{
- for (eve = em->verts.first; eve; eve = eve->next)
- {
- if ( eve->f & SELECT ) {
+ BMIter iter;
+
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_SELECT)) {
copy_v3_v3(normal, eve->no);
break;
}
}
result = ORIENTATION_VERT;
}
- else if (em->totvertsel > 3)
+ else if (em->bm->totvertsel > 3)
{
- normal[0] = normal[1] = normal[2] = 0;
-
- for (eve = em->verts.first; eve; eve = eve->next)
- {
- if ( eve->f & SELECT ) {
+ BMIter iter;
+ normal[0] = normal[1] = normal[2] = 0.0f;
+
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (BM_TestHFlag(eve, BM_SELECT)) {
add_v3_v3(normal, eve->no);
}
}
@@ -898,6 +903,14 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
copy_v3_v3(normal, ob->obmat[2]);
copy_v3_v3(plane, ob->obmat[1]);
}
+ else {
+ normal[0] = 0.0f;
+ normal[1] = 0.0f;
+ normal[2] = 1.0f;
+ plane[0] = 1.0f;
+ plane[1] = 0.0f;
+ plane[2] = 0.0f;
+ }
result = ORIENTATION_NORMAL;
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index fa19d12d5ad..1e508794045 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -68,6 +68,8 @@
#include "BKE_object.h"
#include "BKE_anim.h" /* for duplis */
#include "BKE_context.h"
+#include "BKE_tessmesh.h"
+#include "BKE_mesh.h"
#include "ED_armature.h"
#include "ED_image.h"
@@ -1281,11 +1283,14 @@ static int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm
return retval;
}
-static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, EditMesh *em, float obmat[][4], float ray_start[3], float ray_normal[3], float mval[2], float *loc, float *no, int *dist, float *depth)
+static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob,
+ DerivedMesh *dm, BMEditMesh *em, float obmat[][4],
+ float ray_start[3], float ray_normal[3], float mval[2],
+ float *loc, float *no, int *dist, float *depth)
{
int retval = 0;
int totvert = dm->getNumVerts(dm);
- int totface = dm->getNumFaces(dm);
+ int totface = dm->getNumTessFaces(dm);
if (totvert > 0) {
float imat[4][4];
@@ -1353,19 +1358,19 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
#else
MVert *verts = dm->getVertArray(dm);
- MFace *faces = dm->getFaceArray(dm);
+ MFace *faces = dm->getTessFaceArray(dm);
int *index_array = NULL;
int index = 0;
int i;
if (em != NULL)
{
- index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX);
- EM_init_index_arrays(em, 0, 0, 1);
+ index_array = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ EDBM_init_index_arrays(em, 0, 0, 1);
}
for( i = 0; i < totface; i++) {
- EditFace *efa = NULL;
+ BMFace *efa = NULL;
MFace *f = faces + i;
test = 1; /* reset for every face */
@@ -1387,11 +1392,22 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
}
else
{
- efa = EM_get_face_for_index(index);
+ efa = EDBM_get_face_for_index(em, index);
- if (efa && (efa->h || (efa->v1->f & SELECT) || (efa->v2->f & SELECT) || (efa->v3->f & SELECT) || (efa->v4 && efa->v4->f & SELECT)))
+ if (efa && BM_TestHFlag(efa, BM_HIDDEN))
{
test = 0;
+ } else if (efa) {
+ BMIter iter;
+ BMLoop *l;
+
+ l = BMIter_New(&iter, em->bm, BM_LOOPS_OF_FACE, efa);
+ for ( ; l; l=BMIter_Step(&iter)) {
+ if (BM_TestHFlag(l->v, BM_SELECT)) {
+ test = 0;
+ break;
+ }
+ }
}
}
}
@@ -1419,7 +1435,7 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
if (em != NULL)
{
- EM_free_index_arrays();
+ EDBM_free_index_arrays(em);
}
#endif
break;
@@ -1434,11 +1450,11 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
if (em != NULL)
{
index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
- EM_init_index_arrays(em, 1, 0, 0);
+ EDBM_init_index_arrays(em, 1, 0, 0);
}
for( i = 0; i < totvert; i++) {
- EditVert *eve = NULL;
+ BMVert *eve = NULL;
MVert *v = verts + i;
test = 1; /* reset for every vert */
@@ -1460,9 +1476,9 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
}
else
{
- eve = EM_get_vert_for_index(index);
+ eve = EDBM_get_vert_for_index(em, index);
- if (eve && (eve->h || (eve->f & SELECT)))
+ if (eve && (BM_TestHFlag(eve, BM_HIDDEN) || BM_TestHFlag(eve, BM_SELECT)))
{
test = 0;
}
@@ -1478,7 +1494,7 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
if (em != NULL)
{
- EM_free_index_arrays();
+ EDBM_free_index_arrays(em);
}
break;
}
@@ -1494,11 +1510,11 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
if (em != NULL)
{
index_array = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
- EM_init_index_arrays(em, 0, 1, 0);
+ EDBM_init_index_arrays(em, 0, 1, 0);
}
for( i = 0; i < totedge; i++) {
- EditEdge *eed = NULL;
+ BMEdge *eed = NULL;
MEdge *e = edges + i;
test = 1; /* reset for every vert */
@@ -1520,9 +1536,11 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
}
else
{
- eed = EM_get_edge_for_index(index);
+ eed = EDBM_get_edge_for_index(em, index);
- if (eed && (eed->h || (eed->v1->f & SELECT) || (eed->v2->f & SELECT)))
+ if (eed && (BM_TestHFlag(eed, BM_HIDDEN) ||
+ BM_TestHFlag(eed->v1, BM_SELECT) ||
+ BM_TestHFlag(eed->v2, BM_SELECT)))
{
test = 0;
}
@@ -1538,7 +1556,7 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
if (em != NULL)
{
- EM_free_index_arrays();
+ EDBM_free_index_arrays(em);
}
break;
}
@@ -1555,14 +1573,14 @@ static int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, flo
int retval = 0;
if (ob->type == OB_MESH) {
- EditMesh *em;
+ BMEditMesh *em;
DerivedMesh *dm;
if (editobject)
{
- em = ((Mesh *)ob->data)->edit_mesh;
- /* dm = editmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH); */
- dm = editmesh_get_derived_base(ob, em); /* limitation, em & dm MUST have the same number of faces */
+ em = ((Mesh *)ob->data)->edit_btmesh;
+ /* dm = editbmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH); */
+ dm = editbmesh_get_derived_base(ob, em); /* limitation, em & dm MUST have the same number of faces */
}
else
{
@@ -1710,7 +1728,7 @@ static int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float
{
int retval = 0;
int totvert = dm->getNumVerts(dm);
- int totface = dm->getNumFaces(dm);
+ int totface = dm->getNumTessFaces(dm);
if (totvert > 0) {
float imat[4][4];
@@ -1740,7 +1758,7 @@ static int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float
if (test == 1) {
MVert *verts = dm->getVertArray(dm);
- MFace *faces = dm->getFaceArray(dm);
+ MFace *faces = dm->getTessFaceArray(dm);
int i;
for( i = 0; i < totface; i++) {
@@ -1836,6 +1854,7 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L
Object *dob = dupli_ob->ob;
if (dob->type == OB_MESH) {
+#if 0 //BMESH_TODO
EditMesh *em;
DerivedMesh *dm = NULL;
int val;
@@ -1857,6 +1876,7 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L
retval = retval || val;
dm->release(dm);
+#endif
}
}
@@ -1864,7 +1884,7 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L
}
if (ob->type == OB_MESH) {
- EditMesh *em;
+ BMEditMesh *em;
DerivedMesh *dm = NULL;
int val;
@@ -1876,8 +1896,8 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L
}
else
{
- em = ((Mesh *)ob->data)->edit_mesh;
- dm = editmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
+ em = ((Mesh *)ob->data)->edit_btmesh;
+ dm = editbmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
}
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 69f576d8aa7..1badfb458ee 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenkernel
../../blenlib
../../blenloader
+ ../../bmesh
../../makesdna
../../makesrna
../../windowmanager
@@ -74,6 +75,7 @@ set(SRC
../include/ED_sound.h
../include/ED_space_api.h
../include/ED_text.h
+ ../include/ED_toolmode.h
../include/ED_transform.h
../include/ED_types.h
../include/ED_util.h
diff --git a/source/blender/editors/util/SConscript b/source/blender/editors/util/SConscript
index cfbc735eb5c..16501c59551 100644
--- a/source/blender/editors/util/SConscript
+++ b/source/blender/editors/util/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
-incs += ' ../../makesrna'
+incs += ' ../../makesrna ../../bmesh'
incs += ' ../../blenloader'
env.BlenderLib ( 'bf_editors_util', sources, Split(incs), [], libtype=['core','player'], priority=[330,210] )
diff --git a/source/blender/editors/util/crazyspace.c b/source/blender/editors/util/crazyspace.c
index 9ca990c4193..b3dbd6f6085 100644
--- a/source/blender/editors/util/crazyspace.c
+++ b/source/blender/editors/util/crazyspace.c
@@ -41,6 +41,7 @@
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -106,18 +107,18 @@ float *crazyspace_get_mapped_editverts(Scene *scene, Object *obedit)
Mesh *me= obedit->data;
DerivedMesh *dm;
float *vertexcos;
- int nverts= me->edit_mesh->totvert;
+ int nverts= me->edit_btmesh->bm->totvert;
short *flags;
MappedUserData userData;
/* disable subsurf temporal, get mapped cos, and enable it */
if(modifiers_disable_subsurf_temporary(obedit)) {
/* need to make new derivemesh */
- makeDerivedMesh(scene, obedit, me->edit_mesh, CD_MASK_BAREMESH);
+ makeDerivedMesh(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH, 0);
}
/* now get the cage */
- dm= editmesh_get_derived_cage(scene, obedit, me->edit_mesh, CD_MASK_BAREMESH);
+ dm= editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH);
vertexcos= MEM_callocN(3*sizeof(float)*nverts, "vertexcos map");
flags= MEM_callocN(sizeof(short)*nverts, "vertexcos flags");
@@ -136,10 +137,62 @@ float *crazyspace_get_mapped_editverts(Scene *scene, Object *obedit)
return vertexcos;
}
-void crazyspace_set_quats_editmesh(EditMesh *em, float *origcos, float *mappedcos, float *quats)
+void crazyspace_set_quats_editmesh(BMEditMesh *em, float *origcos, float *mappedcos, float *quats)
{
- EditVert *eve, *prev;
- EditFace *efa;
+ BMVert *v;
+ BMIter iter, liter;
+ BMLoop *l;
+ float *v1, *v2, *v3, *co1, *co2, *co3;
+ int *vert_table = MEM_callocN(sizeof(int)*em->bm->totvert, "vert_table");
+ int index = 0;
+
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(v, index);
+ index++;
+ }
+
+ index = 0;
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (!BM_TestHFlag(v, BM_SELECT) || BM_TestHFlag(v, BM_HIDDEN))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_VERT, v) {
+ BMLoop *l2 = BM_OtherFaceLoop(l->e, l->f, v);
+
+ /* retrieve mapped coordinates */
+ v1= mappedcos + 3*BM_GetIndex(l->v);
+ v2= mappedcos + 3*BM_GetIndex(BM_OtherEdgeVert(l2->e, l->v));
+ v3= mappedcos + 3*BM_GetIndex(BM_OtherEdgeVert(l->e, l->v));
+
+ co1= (origcos)? origcos + 3*BM_GetIndex(l->v) : l->v->co;
+ co2= (origcos)? origcos + 3*BM_GetIndex(BM_OtherEdgeVert(l2->e, l->v)) : BM_OtherEdgeVert(l2->e, l->v)->co;
+ co3= (origcos)? origcos + 3*BM_GetIndex(BM_OtherEdgeVert(l->e, l->v)) : BM_OtherEdgeVert(l->e, l->v)->co;
+
+ set_crazy_vertex_quat(quats, v1, v2, v3, co1, co2, co3);
+ quats+= 4;
+
+ vert_table[BM_GetIndex(l->v)] = index+1;
+
+ index++;
+ break; /*just do one corner*/
+ }
+ }
+
+ index = 0;
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ if (vert_table[index] != 0)
+ BM_SetIndex(v, vert_table[index]-1);
+ else
+ BM_SetIndex(v, -1);
+
+ index++;
+ }
+
+ MEM_freeN(vert_table);
+#if 0
+ BMEditVert *eve, *prev;
+ BMEditFace *efa;
+ BMIter iter;
float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
intptr_t index= 0;
@@ -204,7 +257,7 @@ void crazyspace_set_quats_editmesh(EditMesh *em, float *origcos, float *mappedco
/* restore abused prev pointer */
for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
eve->prev= prev;
-
+#endif
}
void crazyspace_set_quats_mesh(Mesh *me, float *origcos, float *mappedcos, float *quats)
@@ -267,7 +320,8 @@ void crazyspace_set_quats_mesh(Mesh *me, float *origcos, float *mappedcos, float
}
}
-int editmesh_get_first_deform_matrices(Scene *scene, Object *ob, EditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3])
+int editbmesh_get_first_deform_matrices(Scene *scene, Object *ob, BMEditMesh *em,
+ float (**deformmats)[3][3], float (**deformcos)[3])
{
ModifierData *md;
DerivedMesh *dm;
@@ -286,13 +340,13 @@ int editmesh_get_first_deform_matrices(Scene *scene, Object *ob, EditMesh *em, f
for(i = 0; md && i <= cageIndex; i++, md = md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if(!editmesh_modifier_is_enabled(scene, md, dm))
+ if(!editbmesh_modifier_is_enabled(scene, md, dm))
continue;
if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatricesEM) {
if(!defmats) {
- dm= editmesh_get_derived(em, NULL);
- deformedVerts= editmesh_get_vertex_cos(em, &numVerts);
+ dm= getEditDerivedBMesh(em, ob, NULL);
+ deformedVerts= editbmesh_get_vertex_cos(em, &numVerts);
defmats= MEM_callocN(sizeof(*defmats)*numVerts, "defmats");
for(a=0; a<numVerts; a++)
@@ -307,7 +361,7 @@ int editmesh_get_first_deform_matrices(Scene *scene, Object *ob, EditMesh *em, f
}
for(; md && i <= cageIndex; md = md->next, i++)
- if(editmesh_modifier_is_enabled(scene, md, dm) && modifier_isCorrectableDeformed(md))
+ if(editbmesh_modifier_is_enabled(scene, md, dm) && modifier_isCorrectableDeformed(md))
numleft++;
if(dm)
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index fef42866e29..52ac749ce67 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -107,10 +107,10 @@ void ED_editors_exit(bContext *C)
if(ob) {
if(ob->type==OB_MESH) {
Mesh *me= ob->data;
- if(me->edit_mesh) {
- free_editMesh(me->edit_mesh);
- MEM_freeN(me->edit_mesh);
- me->edit_mesh= NULL;
+ if(me->edit_btmesh) {
+ EDBM_FreeEditBMesh(me->edit_btmesh);
+ MEM_freeN(me->edit_btmesh);
+ me->edit_btmesh= NULL;
}
}
else if(ob->type==OB_ARMATURE) {
@@ -121,8 +121,8 @@ void ED_editors_exit(bContext *C)
}
/* global in meshtools... */
- mesh_octree_table(NULL, NULL, NULL, 'e');
- mesh_mirrtopo_table(NULL, 'e');
+ //BMESH_TODO mesh_octree_table(NULL, NULL, NULL, 'e');
+ //BMESH_TODO mesh_mirrtopo_table(NULL, 'e');
}
diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c
index a312b0abbb4..4aa7a657e95 100644
--- a/source/blender/editors/util/editmode_undo.c
+++ b/source/blender/editors/util/editmode_undo.c
@@ -96,8 +96,8 @@ typedef struct UndoElem {
char name[MAXUNDONAME];
void * (*getdata)(bContext *C);
void (*freedata)(void *);
- void (*to_editmode)(void *, void *);
- void * (*from_editmode)(void *);
+ void (*to_editmode)(void *, void *, void *);
+ void * (*from_editmode)(void *, void *);
int (*validate_undo)(void *, void *);
} UndoElem;
@@ -107,10 +107,10 @@ static UndoElem *curundo= NULL;
/* ********************* xtern api calls ************* */
-static void undo_restore(UndoElem *undo, void *editdata)
+static void undo_restore(UndoElem *undo, void *editdata, void *obdata)
{
if(undo) {
- undo->to_editmode(undo->undodata, editdata);
+ undo->to_editmode(undo->undodata, editdata, obdata);
}
}
@@ -118,8 +118,8 @@ static void undo_restore(UndoElem *undo, void *editdata)
void undo_editmode_push(bContext *C, const char *name,
void * (*getdata)(bContext *C),
void (*freedata)(void *),
- void (*to_editmode)(void *, void *),
- void *(*from_editmode)(void *),
+ void (*to_editmode)(void *, void *, void *),
+ void *(*from_editmode)(void *, void *),
int (*validate_undo)(void *, void *))
{
UndoElem *uel;
@@ -168,7 +168,7 @@ void undo_editmode_push(bContext *C, const char *name,
/* copy */
memused= MEM_get_memory_in_use();
editdata= getdata(C);
- curundo->undodata= curundo->from_editmode(editdata);
+ curundo->undodata= curundo->from_editmode(editdata, obedit->data);
curundo->undosize= MEM_get_memory_in_use() - memused;
curundo->ob= obedit;
curundo->id= obedit->id;
@@ -248,7 +248,7 @@ void undo_editmode_step(bContext *C, int step)
undo_clean_stack(C);
if(step==0) {
- undo_restore(curundo, curundo->getdata(C));
+ undo_restore(curundo, curundo->getdata(C), obedit->data);
}
else if(step==1) {
@@ -256,7 +256,7 @@ void undo_editmode_step(bContext *C, int step)
else {
if(G.f & G_DEBUG) printf("undo %s\n", curundo->name);
curundo= curundo->prev;
- undo_restore(curundo, curundo->getdata(C));
+ undo_restore(curundo, curundo->getdata(C), obedit->data);
}
}
else {
@@ -264,7 +264,7 @@ void undo_editmode_step(bContext *C, int step)
if(curundo==NULL || curundo->next==NULL) error("No more steps to redo");
else {
- undo_restore(curundo->next, curundo->getdata(C));
+ undo_restore(curundo->next, curundo->getdata(C), obedit->data);
curundo= curundo->next;
if(G.f & G_DEBUG) printf("redo %s\n", curundo->name);
}
@@ -272,7 +272,7 @@ void undo_editmode_step(bContext *C, int step)
/* special case for editmesh, mode must be copied back to the scene */
if(obedit->type == OB_MESH) {
- EM_selectmode_to_scene(CTX_data_scene(C), obedit);
+ EDBM_selectmode_to_scene(C);
}
DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt
index ce078c2b1f1..d59cea3e77e 100644
--- a/source/blender/editors/uvedit/CMakeLists.txt
+++ b/source/blender/editors/uvedit/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenkernel
../../blenlib
../../blenloader
+ ../../bmesh
../../makesdna
../../makesrna
../../windowmanager
diff --git a/source/blender/editors/uvedit/SConscript b/source/blender/editors/uvedit/SConscript
index 2523de005d0..d236b18a8fd 100644
--- a/source/blender/editors/uvedit/SConscript
+++ b/source/blender/editors/uvedit/SConscript
@@ -5,6 +5,6 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
-incs += ' ../../makesrna #/intern/opennl/extern ../../gpu ../../blenloader'
+incs += ' ../../bmesh ../../makesrna #/intern/opennl/extern ../../gpu ../../blenloader'
env.BlenderLib ( 'bf_editors_uvedit', sources, Split(incs), [], libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c
index a6712bf8efa..9759ab447f6 100644
--- a/source/blender/editors/uvedit/uvedit_buttons.c
+++ b/source/blender/editors/uvedit/uvedit_buttons.c
@@ -47,6 +47,7 @@
#include "BKE_customdata.h"
#include "BKE_mesh.h"
#include "BKE_screen.h"
+#include "BKE_tessmesh.h"
#include "ED_image.h"
#include "ED_uvedit.h"
@@ -61,32 +62,20 @@
/* UV Utilities */
-static int uvedit_center(Scene *scene, EditMesh *em, Image *ima, float center[2])
+static int uvedit_center(Scene *scene, BMEditMesh *em, Image *UNUSED(ima), float center[2])
{
- EditFace *efa;
- MTFace *tf;
- int tot= 0;
-
+ BMFace *f;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ int tot = 0.0;
+
zero_v2(center);
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0)) {
- add_v2_v2(center, tf->uv[0]);
- tot++;
- }
- if(uvedit_uv_selected(scene, efa, tf, 1)) {
- add_v2_v2(center, tf->uv[1]);
- tot++;
- }
- if(uvedit_uv_selected(scene, efa, tf, 2)) {
- add_v2_v2(center, tf->uv[2]);
- tot++;
- }
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
- add_v2_v2(center, tf->uv[3]);
+ BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (uvedit_uv_selected(em, scene, l)) {
+ add_v2_v2(center, luv->uv);
tot++;
}
}
@@ -100,23 +89,19 @@ static int uvedit_center(Scene *scene, EditMesh *em, Image *ima, float center[2]
return tot;
}
-static void uvedit_translate(Scene *scene, EditMesh *em, Image *ima, float delta[2])
+static void uvedit_translate(Scene *scene, BMEditMesh *em, Image *UNUSED(ima), float delta[2])
{
- EditFace *efa;
- MTFace *tf;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0))
- add_v2_v2(tf->uv[0], delta);
- if(uvedit_uv_selected(scene, efa, tf, 1))
- add_v2_v2(tf->uv[1], delta);
- if(uvedit_uv_selected(scene, efa, tf, 2))
- add_v2_v2(tf->uv[2], delta);
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
- add_v2_v2(tf->uv[3], delta);
+ BMFace *f;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+
+ BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (uvedit_uv_selected(em, scene, l)) {
+ add_v2_v2(luv->uv, delta);
+ }
}
}
}
@@ -131,13 +116,13 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= sima->image;
+ BMEditMesh *em;
float center[2];
int imx, imy, step, digits;
- EditMesh *em;
ED_space_image_size(sima, &imx, &imy);
- em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ em= ((Mesh *)obedit->data)->edit_btmesh;
if(uvedit_center(scene, em, ima, center)) {
copy_v2_v2(uvedit_old_center, center);
@@ -161,8 +146,6 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
uiDefButF(block, NUM, B_UVEDIT_VERTEX, "Y:", 165, 10, 145, 19, &uvedit_old_center[1], -10*imy, 10.0*imy, step, digits, "");
uiBlockEndAlign(block);
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
}
static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event)
@@ -171,14 +154,14 @@ static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event)
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= sima->image;
- EditMesh *em;
+ BMEditMesh *em;
float center[2], delta[2];
int imx, imy;
if(event != B_UVEDIT_VERTEX)
return;
- em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
+ em= ((Mesh *)obedit->data)->edit_btmesh;
ED_space_image_size(sima, &imx, &imy);
uvedit_center(scene, em, ima, center);
@@ -194,8 +177,6 @@ static void do_uvedit_vertex(bContext *C, void *UNUSED(arg), int event)
uvedit_translate(scene, em, ima, delta);
- BKE_mesh_end_editmesh(obedit->data, em);
-
WM_event_add_notifier(C, NC_IMAGE, sima->image);
}
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 8a50ec28bd6..1d56740f91e 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -31,7 +31,11 @@
#include <float.h>
#include <math.h>
#include <stdlib.h>
+#include <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -44,7 +48,9 @@
#include "BKE_DerivedMesh.h"
#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
+#include "BLI_array.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -121,34 +127,33 @@ static int draw_uvs_face_check(Scene *scene)
static void draw_uvs_shadow(Object *obedit)
{
- EditMesh *em;
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
- em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ em= ((Mesh*)obedit->data)->edit_btmesh;
/* draws the grey mesh when painting */
glColor3ub(112, 112, 112);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
glBegin(GL_LINE_LOOP);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv= CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ glVertex2fv(luv->uv);
+ }
glEnd();
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
}
static int draw_uvs_dm_shadow(DerivedMesh *dm)
{
/* draw shadow mesh - this is the mesh with the modifier applied */
- if(dm && dm->drawUVEdges && CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
+ if(dm && dm->drawUVEdges && CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
glColor3ub(112, 112, 112);
dm->drawUVEdges(dm);
return 1;
@@ -157,13 +162,19 @@ static int draw_uvs_dm_shadow(DerivedMesh *dm)
return 0;
}
-static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFace *activetf)
+static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTexPoly *activetf)
{
- EditFace *efa;
- MTFace *tf;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
Image *ima= sima->image;
- float aspx, aspy, col[4], tf_uv[4][2];
-
+ BLI_array_declare(tf_uv);
+ BLI_array_declare(tf_uvorig);
+ float aspx, aspy, col[4], (*tf_uv)[2] = NULL, (*tf_uvorig)[2] = NULL;
+ int i;
+
ED_space_image_uv_aspect(sima, &aspx, &aspy);
switch(sima->dt_uvstretch) {
@@ -171,21 +182,37 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac
{
float totarea=0.0f, totuvarea=0.0f, areadiff, uvarea, area;
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- uv_copy_aspect(tf->uv, tf_uv, aspx, aspy);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+
+ BLI_array_empty(tf_uv);
+ BLI_array_empty(tf_uvorig);
+
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv= CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ BLI_array_growone(tf_uv);
+ BLI_array_growone(tf_uvorig);
+
+ tf_uvorig[i][0] = luv->uv[0];
+ tf_uvorig[i][1] = luv->uv[1];
- totarea += EM_face_area(efa);
+ i++;
+ }
+
+ poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa->len);
+
+ totarea += BM_face_area(efa);
//totuvarea += tf_area(tf, efa->v4!=0);
- totuvarea += uv_area(tf_uv, efa->v4 != NULL);
+ totuvarea += poly_uv_area(tf_uv, efa->len);
if(uvedit_face_visible(scene, ima, efa, tf)) {
- efa->tmp.p = tf;
+ BM_SetIndex(efa, 1);
}
else {
if(tf == activetf)
activetf= NULL;
- efa->tmp.p = NULL;
+ BM_SetIndex(efa, 0);
}
}
@@ -193,24 +220,41 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac
col[0] = 1.0;
col[1] = col[2] = 0.0;
glColor3fv(col);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if((tf=(MTFace *)efa->tmp.p)) {
- glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(BM_GetIndex(efa)) {
+ glBegin(GL_POLYGON);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ }
glEnd();
}
}
}
else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if((tf=(MTFace *)efa->tmp.p)) {
- area = EM_face_area(efa) / totarea;
- uv_copy_aspect(tf->uv, tf_uv, aspx, aspy);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(BM_GetIndex(efa)) {
+ area = BM_face_area(efa) / totarea;
+
+ BLI_array_empty(tf_uv);
+ BLI_array_empty(tf_uvorig);
+
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv= CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ BLI_array_growone(tf_uv);
+ BLI_array_growone(tf_uvorig);
+
+ tf_uvorig[i][0] = luv->uv[0];
+ tf_uvorig[i][1] = luv->uv[1];
+
+ i++;
+ }
+
+ poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa->len);
+
//uvarea = tf_area(tf, efa->v4!=0) / totuvarea;
- uvarea = uv_area(tf_uv, efa->v4 != NULL) / totuvarea;
+ uvarea = poly_uv_area(tf_uv, efa->len) / totuvarea;
if(area < FLT_EPSILON || uvarea < FLT_EPSILON)
areadiff = 1.0f;
@@ -222,11 +266,11 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac
weight_to_rgb(areadiff, col, col+1, col+2);
glColor3fv(col);
- glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
+ glBegin(GL_POLYGON);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ }
glEnd();
}
}
@@ -235,6 +279,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac
}
case SI_UVDT_STRETCH_ANGLE:
{
+#if 0 //BMESH_TODO
float uvang1,uvang2,uvang3,uvang4;
float ang1,ang2,ang3,ang4;
float av1[3], av2[3], av3[3], av4[3]; /* use for 2d and 3d angle vectors */
@@ -245,7 +290,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac
glShadeModel(GL_SMOOTH);
for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ tf= CustomData_em_get(&em->fdata, efa->head.data, CD_MTFACE);
if(uvedit_face_visible(scene, ima, efa, tf)) {
efa->tmp.p = tf;
@@ -376,11 +421,13 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac
glShadeModel(GL_FLAT);
break;
+
+#endif
}
}
}
-static void draw_uvs_other(Scene *scene, Object *obedit, MTFace *activetf)
+static void draw_uvs_other(Scene *scene, Object *obedit, MTexPoly *activetf)
{
Base *base;
Image *curimage;
@@ -400,17 +447,19 @@ static void draw_uvs_other(Scene *scene, Object *obedit, MTFace *activetf)
Mesh *me= ob->data;
if(me->mtface) {
- MFace *mface= me->mface;
- MTFace *tface= me->mtface;
- int a;
+ MPoly *mface= me->mpoly;
+ MTexPoly *tface= me->mtpoly;
+ MLoopUV *mloopuv;
+ int a, b;
- for(a=me->totface; a>0; a--, tface++, mface++) {
+ for(a=me->totpoly; a>0; a--, tface++, mface++) {
if(tface->tpage == curimage) {
glBegin(GL_LINE_LOOP);
- glVertex2fv(tface->uv[0]);
- glVertex2fv(tface->uv[1]);
- glVertex2fv(tface->uv[2]);
- if(mface->v4) glVertex2fv(tface->uv[3]);
+
+ mloopuv = me->mloopuv + mface->loopstart;
+ for (b=0; b<mface->totloop; b++, mloopuv++) {
+ glVertex2fv(mloopuv->uv);
+ }
glEnd();
}
}
@@ -424,18 +473,21 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
{
ToolSettings *ts;
Mesh *me= obedit->data;
- EditMesh *em;
- EditFace *efa, *efa_act;
- MTFace *tf, *activetf = NULL;
+ BMEditMesh *em;
+ BMFace *efa, *efa_act, *activef;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf, *activetf = NULL;
+ MLoopUV *luv;
DerivedMesh *finaldm, *cagedm;
unsigned char col1[4], col2[4];
float pointsize;
int drawfaces, interpedges;
Image *ima= sima->image;
- em= BKE_mesh_get_editmesh(me);
- activetf= EM_get_active_mtface(em, &efa_act, NULL, 0); /* will be set to NULL if hidden */
-
+ em= me->edit_btmesh;
+ activetf= EDBM_get_active_mtexpoly(em, &efa_act, 0); /* will be set to NULL if hidden */
+ activef = BM_get_actFace(em->bm, 0);
ts= scene->toolsettings;
drawfaces= draw_uvs_face_check(scene);
@@ -454,7 +506,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
/* first try existing derivedmesh */
if(!draw_uvs_dm_shadow(em->derivedFinal)) {
/* create one if it does not exist */
- cagedm = editmesh_get_derived_cage_and_final(scene, obedit, em, &finaldm, CD_MASK_BAREMESH|CD_MASK_MTFACE);
+ cagedm = editbmesh_get_derived_cage_and_final(scene, obedit, me->edit_btmesh, &finaldm, CD_MASK_BAREMESH|CD_MASK_MTFACE);
/* when sync selection is enabled, all faces are drawn (except for hidden)
* so if cage is the same as the final, theres no point in drawing this */
@@ -479,45 +531,46 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
if(uvedit_face_visible(scene, ima, efa, tf)) {
- efa->tmp.p = tf;
- if(tf==activetf) continue; /* important the temp pointer is set above */
+ BM_SetIndex(efa, 1);
+ if(tf==activetf) continue; /* important the temp boolean is set above */
- if(uvedit_face_selected(scene, efa, tf))
+ if(uvedit_face_selected(scene, em, efa))
glColor4ubv((GLubyte *)col2);
else
glColor4ubv((GLubyte *)col1);
-
- glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
+
+ glBegin(GL_POLYGON);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ }
glEnd();
}
else {
if(tf == activetf)
activetf= NULL;
- efa->tmp.p = NULL;
+ BM_SetIndex(efa, 0);
}
}
glDisable(GL_BLEND);
}
else {
/* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
if(uvedit_face_visible(scene, ima, efa, tf)) {
- efa->tmp.p = tf;
+ BM_SetIndex(efa, 1);
}
else {
if(tf == activetf)
activetf= NULL;
- efa->tmp.p = NULL;
+ BM_SetIndex(efa, 0);
}
}
@@ -525,7 +578,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
/* 3. draw active face stippled */
- if(activetf) {
+ if(activef) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
UI_ThemeColor4(TH_EDITMESH_ACTIVE);
@@ -533,11 +586,11 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glEnable(GL_POLYGON_STIPPLE);
glPolygonStipple(stipple_quarttone);
- glBegin(efa_act->v4? GL_QUADS: GL_TRIANGLES);
- glVertex2fv(activetf->uv[0]);
- glVertex2fv(activetf->uv[1]);
- glVertex2fv(activetf->uv[2]);
- if(efa_act->v4) glVertex2fv(activetf->uv[3]);
+ glBegin(GL_POLYGON);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, activef) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ }
glEnd();
glDisable(GL_POLYGON_STIPPLE);
@@ -554,39 +607,38 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
switch(sima->dt_uv) {
case SI_UVDT_DASH:
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
if(tf) {
cpack(0x111111);
glBegin(GL_LINE_LOOP);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ }
glEnd();
-
+
setlinestyle(2);
cpack(0x909090);
- glBegin(GL_LINE_STRIP);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glEnd();
-
- glBegin(GL_LINE_STRIP);
- glVertex2fv(tf->uv[0]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
- else glVertex2fv(tf->uv[2]);
- glEnd();
-
- glBegin(GL_LINE_STRIP);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
+ glBegin(GL_LINE_LOOP);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ }
glEnd();
+ /*glBegin(GL_LINE_STRIP);
+ luv = CustomData_bmesh_get(&em->bm->ldata, efa->lbase->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ luv = CustomData_bmesh_get(&em->bm->ldata, efa->lbase->next->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ glEnd();*/
+
setlinestyle(0);
}
}
@@ -596,34 +648,32 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
if(sima->dt_uv==SI_UVDT_WHITE) glColor3f(1.0f, 1.0f, 1.0f);
else glColor3f(0.0f, 0.0f, 0.0f);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
- if(tf) {
- glBegin(GL_LINE_LOOP);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
- glEnd();
+ glBegin(GL_LINE_LOOP);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
}
+ glEnd();
}
break;
case SI_UVDT_OUTLINE:
glLineWidth(3);
cpack(0x0);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
-
- if(tf) {
- glBegin(GL_LINE_LOOP);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
- glEnd();
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
+
+ glBegin(GL_LINE_LOOP);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
}
+ glEnd();
}
glLineWidth(1);
@@ -631,89 +681,62 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glColor4ubv((unsigned char *)col2);
if(me->drawflag & ME_DRAWEDGES) {
- int lastsel= 0, sel;
+ int sel, lastsel = -1;
UI_GetThemeColor4ubv(TH_VERTEX_SELECT, col1);
if(interpedges) {
glShadeModel(GL_SMOOTH);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
-
- if(tf) {
- glBegin(GL_LINE_LOOP);
- sel = (uvedit_uv_selected(scene, efa, tf, 0)? 1 : 0);
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[0]);
-
- sel = uvedit_uv_selected(scene, efa, tf, 1)? 1 : 0;
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[1]);
-
- sel = uvedit_uv_selected(scene, efa, tf, 2)? 1 : 0;
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[2]);
-
- if(efa->v4) {
- sel = uvedit_uv_selected(scene, efa, tf, 3)? 1 : 0;
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[3]);
- }
-
- glEnd();
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
+
+ glBegin(GL_LINE_LOOP);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ sel = (uvedit_uv_selected(em, scene, l)? 1 : 0);
+ glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2);
+
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
}
+ glEnd();
}
glShadeModel(GL_FLAT);
}
else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
-
- if(tf) {
- glBegin(GL_LINES);
- sel = (uvedit_edge_selected(scene, efa, tf, 0)? 1 : 0);
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
-
- sel = uvedit_edge_selected(scene, efa, tf, 1)? 1 : 0;
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
-
- sel = uvedit_edge_selected(scene, efa, tf, 2)? 1 : 0;
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[2]);
-
- if(efa->v4) {
- glVertex2fv(tf->uv[3]);
-
- sel = uvedit_edge_selected(scene, efa, tf, 3)? 1 : 0;
- if(sel != lastsel) { glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; }
- glVertex2fv(tf->uv[3]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
+
+ glBegin(GL_LINES);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ sel = (uvedit_edge_selected(em, scene, l)? 1 : 0);
+ if(sel != lastsel){
+ glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2);
+ lastsel = sel;
}
-
- glVertex2fv(tf->uv[0]);
-
- glEnd();
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
}
+ glEnd();
}
}
}
else {
/* no nice edges */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
-
- if(tf) {
- glBegin(GL_LINE_LOOP);
- glVertex2fv(tf->uv[0]);
- glVertex2fv(tf->uv[1]);
- glVertex2fv(tf->uv[2]);
- if(efa->v4) glVertex2fv(tf->uv[3]);
- glEnd();
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
+
+ glBegin(GL_LINE_LOOP);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ glVertex2fv(luv->uv);
}
+ glEnd();
}
}
@@ -737,11 +760,12 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
UI_ThemeColor(TH_WIRE);
bglBegin(GL_POINTS);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
- if(tf && !uvedit_face_selected(scene, efa, tf)) {
- uv_center(tf->uv, cent, efa->v4 != NULL);
+ if(!uvedit_face_selected(scene, em, efa)) {
+ poly_uv_center(em, efa, cent);
bglVertex2fv(cent);
}
}
@@ -751,11 +775,12 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
UI_ThemeColor(TH_FACE_DOT);
bglBegin(GL_POINTS);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
- if(tf && uvedit_face_selected(scene, efa, tf)) {
- uv_center(tf->uv, cent, efa->v4 != NULL);
+ if(uvedit_face_selected(scene, em, efa)) {
+ poly_uv_center(em, efa, cent);
bglVertex2fv(cent);
}
}
@@ -771,18 +796,14 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glPointSize(pointsize);
bglBegin(GL_POINTS);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
-
- if(tf) {
- if(!uvedit_uv_selected(scene, efa, tf, 0))
- bglVertex2fv(tf->uv[0]);
- if(!uvedit_uv_selected(scene, efa, tf, 1))
- bglVertex2fv(tf->uv[1]);
- if(!uvedit_uv_selected(scene, efa, tf, 2))
- bglVertex2fv(tf->uv[2]);
- if(efa->v4 && !uvedit_uv_selected(scene, efa, tf, 3))
- bglVertex2fv(tf->uv[3]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if(!uvedit_uv_selected(em, scene, l))
+ bglVertex2fv(luv->uv);
}
}
bglEnd();
@@ -793,18 +814,15 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
cpack(0xFF);
bglBegin(GL_POINTS);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
-
- if(tf) {
- if(tf->unwrap & TF_PIN1)
- bglVertex2fv(tf->uv[0]);
- if(tf->unwrap & TF_PIN2)
- bglVertex2fv(tf->uv[1]);
- if(tf->unwrap & TF_PIN3)
- bglVertex2fv(tf->uv[2]);
- if(efa->v4 && (tf->unwrap & TF_PIN4))
- bglVertex2fv(tf->uv[3]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if(luv->flag & MLOOPUV_PINNED)
+ bglVertex2fv(luv->uv);
}
}
bglEnd();
@@ -814,25 +832,21 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glPointSize(pointsize);
bglBegin(GL_POINTS);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= (MTFace *)efa->tmp.p; /* visible faces cached */
-
- if(tf) {
- if(uvedit_uv_selected(scene, efa, tf, 0))
- bglVertex2fv(tf->uv[0]);
- if(uvedit_uv_selected(scene, efa, tf, 1))
- bglVertex2fv(tf->uv[1]);
- if(uvedit_uv_selected(scene, efa, tf, 2))
- bglVertex2fv(tf->uv[2]);
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
- bglVertex2fv(tf->uv[3]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if(uvedit_uv_selected(em, scene, l))
+ bglVertex2fv(luv->uv);
}
}
bglEnd();
}
glPointSize(1.0);
- BKE_mesh_end_editmesh(obedit->data, em);
}
void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit)
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 7d83f529d92..e7156c65491 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -33,23 +33,33 @@
#define ED_UVEDIT_INTERN_H
struct SpaceImage;
-struct EditFace;
-struct MTFace;
+struct MTexPoly;
struct Scene;
struct Image;
struct Object;
struct wmOperatorType;
+struct BMEditMesh;
+struct BMFace;
+struct BMLoop;
+struct BMEdge;
+struct BMVert;
/* id can be from 0 to 3 */
#define TF_PIN_MASK(id) (TF_PIN1 << id)
#define TF_SEL_MASK(id) (TF_SEL1 << id)
+/* visibility and selection */
+int uvedit_face_visible_nolocal(struct Scene *scene, struct BMFace *efa);
/* geometric utilities */
void uv_center(float uv[][2], float cent[2], int quad);
float uv_area(float uv[][2], int quad);
void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy);
+float poly_uv_area(float uv[][2], int len);
+void poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len);
+void poly_uv_center(struct BMEditMesh *em, struct BMFace *f, float cent[2]);
+
/* operators */
void UV_OT_average_islands_scale(struct wmOperatorType *ot);
void UV_OT_cube_project(struct wmOperatorType *ot);
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 3593d94b400..f54d2366050 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -33,16 +33,20 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_object_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_image_types.h"
+#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
+#include "BLI_array.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -52,6 +56,7 @@
#include "BKE_library.h"
#include "BKE_mesh.h"
#include "BKE_report.h"
+#include "BKE_tessmesh.h"
#include "ED_image.h"
#include "ED_mesh.h"
@@ -70,19 +75,23 @@
#include "uvedit_intern.h"
+#define EFA_F1_FLAG 2
+
/************************* state testing ************************/
int ED_uvedit_test(Object *obedit)
{
- EditMesh *em;
+ BMEditMesh *em;
int ret;
- if(!obedit || obedit->type != OB_MESH)
+ if (!obedit)
+ return 0;
+
+ if(obedit->type != OB_MESH)
return 0;
- em = BKE_mesh_get_editmesh(obedit->data);
- ret = EM_texFaceCheck(em);
- BKE_mesh_end_editmesh(obedit->data, em);
+ em = ((Mesh*)obedit->data)->edit_btmesh;
+ ret = EDBM_texFaceCheck(em);
return ret;
}
@@ -91,9 +100,10 @@ int ED_uvedit_test(Object *obedit)
void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *previma)
{
- EditMesh *em;
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em;
+ BMFace *efa;
+ BMIter iter;
+ MTexPoly *tf;
int update= 0;
/* skip assigning these procedural images... */
@@ -104,21 +114,21 @@ void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *pre
if(!obedit || (obedit->type != OB_MESH))
return;
- em= BKE_mesh_get_editmesh(((Mesh*)obedit->data));
- if(!em || !em->faces.first) {
- BKE_mesh_end_editmesh(obedit->data, em);
+ em= ((Mesh*)obedit->data)->edit_btmesh;
+ if(!em || !em->bm->totface) {
return;
}
/* ensure we have a uv layer */
- if(!CustomData_has_layer(&em->fdata, CD_MTFACE)) {
- EM_add_data_layer(em, &em->fdata, CD_MTFACE, NULL);
+ if(!CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) {
+ BM_add_data_layer(em->bm, &em->bm->pdata, CD_MTEXPOLY);
+ BM_add_data_layer(em->bm, &em->bm->ldata, CD_MLOOPUV);
update= 1;
}
/* now assign to all visible faces */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
if(uvedit_face_visible(scene, previma, efa, tf)) {
if(ima) {
@@ -138,17 +148,16 @@ void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *pre
/* and update depdency graph */
if(update)
DAG_id_tag_update(obedit->data, 0);
-
- BKE_mesh_end_editmesh(obedit->data, em);
}
/* dotile - 1, set the tile flag (from the space image)
* 2, set the tile index for the faces. */
static int uvedit_set_tile(Object *obedit, Image *ima, int curtile)
{
- EditMesh *em;
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em;
+ BMFace *efa;
+ BMIter iter;
+ MTexPoly *tf;
/* verify if we have something to do */
if(!ima || !ED_uvedit_test(obedit))
@@ -161,17 +170,16 @@ static int uvedit_set_tile(Object *obedit, Image *ima, int curtile)
if(ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE)
return 0;
- em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ em= ((Mesh*)obedit->data)->edit_btmesh;
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- if(efa->h==0 && efa->f & SELECT)
+ if(!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT))
tf->tile= curtile; /* set tile index */
}
DAG_id_tag_update(obedit->data, 0);
- BKE_mesh_end_editmesh(obedit->data, em);
return 1;
}
@@ -182,13 +190,7 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist
{
int width, height;
- if(sima) {
- ED_space_image_size(sima, &width, &height);
- }
- else {
- width= 256;
- height= 256;
- }
+ ED_space_image_size(sima, &width, &height);
dist[0]= pixeldist/width;
dist[1]= pixeldist/height;
@@ -196,18 +198,17 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist
/*************** visibility and selection utilities **************/
-int uvedit_face_visible_nolocal(Scene *scene, EditFace *efa)
+int uvedit_face_visible_nolocal(Scene *scene, BMFace *efa)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION)
- return (efa->h==0);
+ return (BM_TestHFlag(efa, BM_HIDDEN)==0);
else
- return (efa->h==0 && (efa->f & SELECT));
+ return (BM_TestHFlag(efa, BM_HIDDEN)==0 && BM_TestHFlag(efa, BM_SELECT));
}
-int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf)
-{
+int uvedit_face_visible(Scene *scene, Image *ima, BMFace *efa, MTexPoly *tf) {
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SHOW_SAME_IMAGE)
@@ -216,131 +217,195 @@ int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf)
return uvedit_face_visible_nolocal(scene, efa);
}
-int uvedit_face_selected(Scene *scene, EditFace *efa, MTFace *tf)
+int uvedit_face_selected(Scene *scene, BMEditMesh *em, BMFace *efa)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION)
- return (efa->f & SELECT);
- else
- return (!(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) &&(!efa->v4 || tf->flag & TF_SEL4));
+ return (BM_TestHFlag(efa, BM_SELECT));
+ else {
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter liter;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (!(luv->flag & MLOOPUV_VERTSEL))
+ return 0;
+ }
+
+ return 1;
+ }
}
-void uvedit_face_select(Scene *scene, EditFace *efa, MTFace *tf)
+int uvedit_face_select(Scene *scene, BMEditMesh *em, BMFace *efa)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION)
- EM_select_face(efa, 1);
- else
- tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ BM_Select(em->bm, efa, 1);
+ else {
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter liter;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+
+ return 1;
+ }
+
+ return 0;
}
-void uvedit_face_deselect(Scene *scene, EditFace *efa, MTFace *tf)
+int uvedit_face_deselect(Scene *scene, BMEditMesh *em, BMFace *efa)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION)
- EM_select_face(efa, 0);
- else
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ BM_Select(em->bm, efa, 0);
+ else {
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter liter;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ }
+
+ return 1;
+ }
+
+ return 0;
}
-int uvedit_edge_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
+int uvedit_edge_selected(BMEditMesh *em, Scene *scene, BMLoop *l)
{
ToolSettings *ts= scene->toolsettings;
- int nvert= (efa->v4)? 4: 3;
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode & SCE_SELECT_FACE)
- return (efa->f & SELECT);
- else if(ts->selectmode & SCE_SELECT_EDGE)
- return (*(&efa->e1 + i))->f & SELECT;
- else
- return (((efa->v1 + i)->f & SELECT) && ((efa->v1 + (i+1)%nvert)->f & SELECT));
+ return BM_TestHFlag(l->f, BM_SELECT);
+ else if(ts->selectmode == SCE_SELECT_EDGE) {
+ return BM_TestHFlag(l->e, BM_SELECT);
+ } else
+ return BM_TestHFlag(l->v, BM_SELECT) &&
+ BM_TestHFlag(l->next->v, BM_SELECT);
+ }
+ else {
+ MLoopUV *luv1, *luv2;
+
+ luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv2 = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
+
+ return (luv1->flag & MLOOPUV_VERTSEL) && (luv2->flag & MLOOPUV_VERTSEL);
}
- else
- return (tf->flag & TF_SEL_MASK(i)) && (tf->flag & TF_SEL_MASK((i+1)%nvert));
}
-void uvedit_edge_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
+void uvedit_edge_select(BMEditMesh *em, Scene *scene, BMLoop *l)
+
{
ToolSettings *ts= scene->toolsettings;
- int nvert= (efa->v4)? 4: 3;
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode & SCE_SELECT_FACE)
- EM_select_face(efa, 1);
+ BM_Select(em->bm, l->f, 1);
else if(ts->selectmode & SCE_SELECT_EDGE)
- EM_select_edge((*(&efa->e1 + i)), 1);
+ BM_Select(em->bm, l->e, 1);
else {
- (efa->v1 + i)->f |= SELECT;
- (efa->v1 + (i+1)%nvert)->f |= SELECT;
+ BM_Select(em->bm, l->e->v1, 1);
+ BM_Select(em->bm, l->e->v2, 1);
}
}
- else
- tf->flag |= TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert);
+ else {
+ MLoopUV *luv1, *luv2;
+
+ luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv2 = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
+
+ luv1->flag |= MLOOPUV_VERTSEL;
+ luv2->flag |= MLOOPUV_VERTSEL;
+ }
}
-void uvedit_edge_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
+void uvedit_edge_deselect(BMEditMesh *em, Scene *scene, BMLoop *l)
+
{
ToolSettings *ts= scene->toolsettings;
- int nvert= (efa->v4)? 4: 3;
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode & SCE_SELECT_FACE)
- EM_select_face(efa, 0);
+ BM_Select(em->bm, l->f, 0);
else if(ts->selectmode & SCE_SELECT_EDGE)
- EM_select_edge((*(&efa->e1 + i)), 0);
+ BM_Select(em->bm, l->e, 0);
else {
- (efa->v1 + i)->f &= ~SELECT;
- (efa->v1 + (i+1)%nvert)->f &= ~SELECT;
+ BM_Select(em->bm, l->e->v1, 0);
+ BM_Select(em->bm, l->e->v2, 0);
}
}
- else
- tf->flag &= ~(TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert));
+ else {
+ MLoopUV *luv1, *luv2;
+
+ luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv2 = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
+
+ luv1->flag &= ~MLOOPUV_VERTSEL;
+ luv2->flag &= ~MLOOPUV_VERTSEL;
+ }
}
-int uvedit_uv_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
+int uvedit_uv_selected(BMEditMesh *em, Scene *scene, BMLoop *l)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode & SCE_SELECT_FACE)
- return (efa->f & SELECT);
+ return BM_TestHFlag(l->f, BM_SELECT);
else
- return (*(&efa->v1 + i))->f & SELECT;
+ return BM_TestHFlag(l->v, BM_SELECT);
+ }
+ else {
+ MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ return luv->flag & MLOOPUV_VERTSEL;
}
- else
- return tf->flag & TF_SEL_MASK(i);
}
-void uvedit_uv_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
+void uvedit_uv_select(BMEditMesh *em, Scene *scene, BMLoop *l)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode & SCE_SELECT_FACE)
- EM_select_face(efa, 1);
+ BM_Select(em->bm, l->f, 1);
else
- (*(&efa->v1 + i))->f |= SELECT;
+ BM_Select(em->bm, l->v, 1);
+ }
+ else {
+ MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ luv->flag |= MLOOPUV_VERTSEL;
}
- else
- tf->flag |= TF_SEL_MASK(i);
}
-void uvedit_uv_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
+void uvedit_uv_deselect(BMEditMesh *em, Scene *scene, BMLoop *l)
{
ToolSettings *ts= scene->toolsettings;
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode & SCE_SELECT_FACE)
- EM_select_face(efa, 0);
+ BM_Select(em->bm, l->f, 0);
else
- (*(&efa->v1 + i))->f &= ~SELECT;
+ BM_Select(em->bm, l->v, 0);
+ }
+ else {
+ MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ luv->flag &= ~MLOOPUV_VERTSEL;
}
- else
- tf->flag &= ~TF_SEL_MASK(i);
}
/*********************** live unwrap utilities ***********************/
@@ -355,6 +420,24 @@ static void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *ob
}
/*********************** geometric utilities ***********************/
+void poly_uv_center(BMEditMesh *em, BMFace *f, float cent[2])
+{
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter liter;
+
+ cent[0] = cent[1] = 0.0f;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ cent[0] += luv->uv[0];
+ cent[1] += luv->uv[1];
+ }
+
+ cent[0] /= (float) f->len;
+ cent[1] /= (float) f->len;
+}
+
void uv_center(float uv[][2], float cent[2], int quad)
{
@@ -376,6 +459,28 @@ float uv_area(float uv[][2], int quad)
return area_tri_v2(uv[0], uv[1], uv[2]);
}
+float poly_uv_area(float uv[][2], int len)
+{
+ //BMESH_TODO: make this not suck
+ //maybe use scanfill? I dunno.
+
+ if(len >= 4)
+ return area_tri_v2(uv[0], uv[1], uv[2]) + area_tri_v2(uv[0], uv[2], uv[3]);
+ else
+ return area_tri_v2(uv[0], uv[1], uv[2]);
+
+ return 1.0;
+}
+
+void poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len)
+{
+ int i;
+ for (i=0; i<len; i++) {
+ uv[i][0] = uv_orig[i][0]*aspx;
+ uv[i][1] = uv_orig[i][1]*aspy;
+ }
+}
+
void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy)
{
uv[0][0] = uv_orig[0][0]*aspx;
@@ -393,56 +498,66 @@ void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy)
int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float *min, float *max)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
int sel;
INIT_MINMAX2(min, max);
sel= 0;
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0)) { DO_MINMAX2(tf->uv[0], min, max); sel = 1; }
- if(uvedit_uv_selected(scene, efa, tf, 1)) { DO_MINMAX2(tf->uv[1], min, max); sel = 1; }
- if(uvedit_uv_selected(scene, efa, tf, 2)) { DO_MINMAX2(tf->uv[2], min, max); sel = 1; }
- if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3))) { DO_MINMAX2(tf->uv[3], min, max); sel = 1; }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ DO_MINMAX2(luv->uv, min, max);
+ sel = 1;
+ }
}
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
+
return sel;
}
static int ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[3])
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
unsigned int sel= 0;
zero_v3(co);
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0)) { add_v3_v3(co, tf->uv[0]); sel++; }
- if(uvedit_uv_selected(scene, efa, tf, 1)) { add_v3_v3(co, tf->uv[1]); sel++; }
- if(uvedit_uv_selected(scene, efa, tf, 2)) { add_v3_v3(co, tf->uv[2]); sel++; }
- if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3))) { add_v3_v3(co, tf->uv[3]); sel++; }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (uvedit_uv_selected(em, scene, l)) {
+ add_v2_v2(co, luv->uv);
+ sel++;
+ }
}
}
mul_v3_fl(co, 1.0f/(float)sel);
- BKE_mesh_end_editmesh(obedit->data, em);
return (sel != 0);
}
static int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent, char mode)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
float min[2], max[2];
int change= 0;
@@ -462,108 +577,147 @@ static int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent,
}
if(change) {
- BKE_mesh_end_editmesh(obedit->data, em);
return 1;
}
- BKE_mesh_end_editmesh(obedit->data, em);
return 0;
}
/************************** find nearest ****************************/
typedef struct NearestHit {
- EditFace *efa;
- MTFace *tf;
-
- int vert, uv;
- int edge, vert2;
+ BMFace *efa;
+ MTexPoly *tf;
+ BMLoop *l, *nextl;
+ MLoopUV *luv, *nextluv;
+ int lindex; //index of loop within face
+ int vert1, vert2; //index in mesh of edge vertices
} NearestHit;
-static void find_nearest_uv_edge(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit)
+static void find_nearest_uv_edge(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit)
{
- MTFace *tf;
- EditFace *efa;
- EditVert *eve;
+ MTexPoly *tf;
+ BMFace *efa;
+ BMLoop *l;
+ BMVert *eve;
+ BMIter iter, liter;
+ MLoopUV *luv, *nextluv;
float mindist, dist;
- int i, nverts;
+ int i;
mindist= 1e10f;
memset(hit, 0, sizeof(*hit));
- for(i=0, eve=em->verts.first; eve; eve=eve->next, i++)
- eve->tmp.l = i;
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++) {
+ BM_SetIndex(eve, i);
+ }
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- nverts= efa->v4? 4: 3;
-
- for(i=0; i<nverts; i++) {
- dist= dist_to_line_segment_v2(co, tf->uv[i], tf->uv[(i+1)%nverts]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ nextluv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
- if(dist < mindist) {
- hit->tf= tf;
- hit->efa= efa;
- hit->edge= i;
- mindist= dist;
+ dist= dist_to_line_segment_v2(co, luv->uv, nextluv->uv);
- hit->vert= (*(&efa->v1 + i))->tmp.l;
- hit->vert2= (*(&efa->v1 + ((i+1)%nverts)))->tmp.l;
- }
+ if(dist < mindist) {
+ hit->tf= tf;
+ hit->efa= efa;
+
+ hit->l = l;
+ hit->nextl = l->next;
+ hit->luv = luv;
+ hit->nextluv = nextluv;
+ hit->lindex = i;
+ hit->vert1 = BM_GetIndex(hit->l->v);
+ hit->vert2 = BM_GetIndex(hit->l->next->v);
+
+ mindist = dist;
}
+
+ i++;
}
}
}
-static void find_nearest_uv_face(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit)
+static void find_nearest_uv_face(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit)
{
- MTFace *tf;
- EditFace *efa;
+ MTexPoly *tf;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
float mindist, dist, cent[2];
- int i, nverts;
mindist= 1e10f;
memset(hit, 0, sizeof(*hit));
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- nverts= efa->v4? 4: 3;
- cent[0]= cent[1]= 0.0f;
+ /*this will fill in hit.vert1 and hit.vert2*/
+ find_nearest_uv_edge(scene, ima, em, co, hit);
+ hit->l = hit->nextl = NULL;
+ hit->luv = hit->nextluv = NULL;
- for(i=0; i<nverts; i++) {
- cent[0] += tf->uv[i][0];
- cent[1] += tf->uv[i][1];
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ cent[0]= cent[1]= 0.0f;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- cent[0] /= nverts;
- cent[1] /= nverts;
- dist= fabs(co[0]- cent[0]) + fabs(co[1]- cent[1]);
+ cent[0] += luv->uv[0];
+ cent[1] += luv->uv[1];
+ }
- if(dist < mindist) {
- hit->tf= tf;
- hit->efa= efa;
- mindist= dist;
- }
+ cent[0] /= efa->len;
+ cent[1] /= efa->len;
+ dist= fabs(co[0]- cent[0]) + fabs(co[1]- cent[1]);
+
+ if(dist < mindist) {
+ hit->tf= tf;
+ hit->efa= efa;
+ mindist= dist;
}
}
}
-static int nearest_uv_between(MTFace *tf, int nverts, int id, float co[2], float uv[2])
+static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int UNUSED(nverts), int id,
+ float co[2], float uv[2])
{
- float m[3], v1[3], v2[3], c1, c2;
- int id1, id2;
+ BMLoop *l;
+ MLoopUV *luv;
+ BMIter iter;
+ float m[3], v1[3], v2[3], c1, c2, *uv1, *uv2, *uv3;
+ int id1, id2, i;
- id1= (id+nverts-1)%nverts;
- id2= (id+nverts+1)%nverts;
+ id1= (id+efa->len-1)%efa->len;
+ id2= (id+efa->len+1)%efa->len;
m[0]= co[0]-uv[0];
m[1]= co[1]-uv[1];
- sub_v2_v2v2(v1, tf->uv[id1], tf->uv[id]);
- sub_v2_v2v2(v2, tf->uv[id2], tf->uv[id]);
+
+ i = 0;
+ BM_ITER(l, &iter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (i == id1)
+ uv1 = luv->uv;
+ else if (i == id)
+ uv2 = luv->uv;
+ else if (i == id2)
+ uv3 = luv->uv;
+
+ i++;
+ }
+
+ sub_v3_v3v3(v1, uv1, uv);
+ sub_v3_v3v3(v2, uv3, uv);
/* m and v2 on same side of v-v1? */
c1= v1[0]*m[1] - v1[1]*m[0];
@@ -579,86 +733,103 @@ static int nearest_uv_between(MTFace *tf, int nverts, int id, float co[2], float
return (c1*c2 >= 0.0f);
}
-static void find_nearest_uv_vert(Scene *scene, Image *ima, EditMesh *em, float co[2], float penalty[2], NearestHit *hit)
+static void find_nearest_uv_vert(Scene *scene, Image *ima, BMEditMesh *em,
+ float co[2], float penalty[2], NearestHit *hit)
{
- EditFace *efa;
- EditVert *eve;
- MTFace *tf;
+ BMFace *efa;
+ BMVert *eve;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float mindist, dist;
- int i, nverts;
+ int i;
+
+ /*this will fill in hit.vert1 and hit.vert2*/
+ find_nearest_uv_edge(scene, ima, em, co, hit);
+ hit->l = hit->nextl = NULL;
+ hit->luv = hit->nextluv = NULL;
mindist= 1e10f;
memset(hit, 0, sizeof(*hit));
- for(i=0, eve=em->verts.first; eve; eve=eve->next, i++)
- eve->tmp.l = i;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- nverts= efa->v4? 4: 3;
+ eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
+ for (i=0; eve; eve=BMIter_Step(&iter), i++) {
+ BM_SetIndex(eve, i);
+ }
- for(i=0; i<nverts; i++) {
- if(penalty && uvedit_uv_selected(scene, efa, tf, i))
- dist= fabsf(co[0]-tf->uv[i][0])+penalty[0] + fabsf(co[1]-tf->uv[i][1]) + penalty[1];
- else
- dist= fabsf(co[0]-tf->uv[i][0]) + fabsf(co[1]-tf->uv[i][1]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- if(dist<=mindist) {
- if(dist==mindist)
- if(!nearest_uv_between(tf, nverts, i, co, tf->uv[i]))
- continue;
+ if(penalty && uvedit_uv_selected(em, scene, l))
+ dist= fabs(co[0]-luv->uv[0])+penalty[0] + fabs(co[1]-luv->uv[1])+penalty[1];
+ else
+ dist= fabs(co[0]-luv->uv[0]) + fabs(co[1]-luv->uv[1]);
- mindist= dist;
+ if(dist<=mindist) {
+ if(dist==mindist)
+ if(!nearest_uv_between(em, efa, efa->len, i, co, luv->uv)) {
+ i++;
+ continue;
+ }
- hit->uv= i;
- hit->tf= tf;
- hit->efa= efa;
+ mindist= dist;
- hit->vert= (*(&efa->v1 + i))->tmp.l;
- }
+ hit->l = l;
+ hit->nextl = l->next;
+ hit->luv = luv;
+ hit->nextluv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
+ hit->tf= tf;
+ hit->efa= efa;
+ hit->lindex = i;
+ hit->vert1 = BM_GetIndex(hit->l->v);
}
+
+ i++;
}
}
}
int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, float co[2], float uv[2])
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float mindist, dist;
- int i, nverts, found= 0;
+ int found= 0;
mindist= 1e10f;
uv[0]= co[0];
uv[1]= co[1];
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- nverts= efa->v4? 4: 3;
-
- for(i=0; i<nverts; i++) {
- if(uvedit_uv_selected(scene, efa, tf, i))
- continue;
-
- dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->uv[i][1]);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ dist= fabs(co[0]-luv->uv[0]) + fabs(co[1]-luv->uv[1]);
- if(dist<=mindist) {
- mindist= dist;
+ if(dist<=mindist) {
+ mindist= dist;
- uv[0]= tf->uv[i][0];
- uv[1]= tf->uv[i][1];
- found= 1;
- }
+ uv[0]= luv->uv[0];
+ uv[1]= luv->uv[1];
+ found= 1;
}
}
}
- BKE_mesh_end_editmesh(obedit->data, em);
return found;
}
@@ -680,26 +851,28 @@ static void uv_vertex_loop_flag(UvMapVert *first)
first->flag= 1;
}
-static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, EditFace *efa, int a)
+static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, BMFace *efa, int a)
{
UvMapVert *iterv, *first;
-
- first= EM_get_uv_map_vert(vmap, (*(&efa->v1 + a))->tmp.l);
+ BMLoop *l;
+
+ l = BMIter_AtIndex(NULL, BM_LOOPS_OF_FACE, efa, a);
+ first= EDBM_get_uv_map_vert(vmap, BM_GetIndex(l->v));
for(iterv=first; iterv; iterv=iterv->next) {
if(iterv->separate)
first= iterv;
- if(iterv->f == efa->tmp.l)
+ if(iterv->f == BM_GetIndex(efa))
return first;
}
return NULL;
}
-static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface)
+static int uv_edge_tag_faces(BMEditMesh *em, UvMapVert *first1, UvMapVert *first2, int *totface)
{
UvMapVert *iterv1, *iterv2;
- EditFace *efa;
+ BMFace *efa;
int tot = 0;
/* count number of faces this edge has */
@@ -713,8 +886,8 @@ static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface)
if(iterv1->f == iterv2->f) {
/* if face already tagged, don't do this edge */
- efa= EM_get_face_for_index(iterv1->f);
- if(efa->f1)
+ efa= EDBM_get_face_for_index(em, iterv1->f);
+ if(BMO_TestFlag(em->bm, efa, EFA_F1_FLAG))
return 0;
tot++;
@@ -738,8 +911,8 @@ static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface)
break;
if(iterv1->f == iterv2->f) {
- efa= EM_get_face_for_index(iterv1->f);
- efa->f1= 1;
+ efa= EDBM_get_face_for_index(em, iterv1->f);
+ BMO_SetFlag(em->bm, efa, EFA_F1_FLAG);
break;
}
}
@@ -748,41 +921,47 @@ static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface)
return 1;
}
-static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *hit, float limit[2], int extend)
+static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit *hit, float limit[2], int extend)
{
- EditVert *eve;
- EditFace *efa;
- MTFace *tf;
+ BMVert *eve;
+ BMFace *efa;
+ BMIter iter, liter;
+ BMLoop *l;
+ MTexPoly *tf;
UvVertMap *vmap;
UvMapVert *iterv1, *iterv2;
int a, count, looking, nverts, starttotf, select;
/* setup */
- EM_init_index_arrays(em, 0, 0, 1);
- vmap= EM_make_uv_vert_map(em, 0, 0, limit);
+ EDBM_init_index_arrays(em, 0, 0, 1);
+ vmap= EDBM_make_uv_vert_map(em, 0, 0, limit);
- for(count=0, eve=em->verts.first; eve; count++, eve= eve->next)
- eve->tmp.l = count;
+ count = 0;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(eve, count);
+ count++;
+ }
- for(count=0, efa= em->faces.first; efa; count++, efa= efa->next) {
+ count = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
if(!extend) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- uvedit_face_deselect(scene, efa, tf);
+ uvedit_face_deselect(scene, em, efa);
}
-
- efa->tmp.l= count;
- efa->f1= 0;
+
+ BMO_ClearFlag(em->bm, efa, EFA_F1_FLAG);
+ BM_SetIndex(efa, count);
+ count++;
}
-
+
/* set flags for first face and verts */
- nverts= (hit->efa->v4)? 4: 3;
- iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge);
- iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts);
+ nverts= hit->efa->len;
+ iterv1= uv_vertex_map_get(vmap, hit->efa, hit->lindex);
+ iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->lindex+1)%nverts);
uv_vertex_loop_flag(iterv1);
uv_vertex_loop_flag(iterv2);
starttotf= 0;
- uv_edge_tag_faces(iterv1, iterv2, &starttotf);
+ uv_edge_tag_faces(em, iterv1, iterv2, &starttotf);
/* sorry, first edge isnt even ok */
if(iterv1->flag==0 && iterv2->flag==0) looking= 0;
@@ -793,21 +972,25 @@ static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *h
looking= 0;
/* find correct valence edges which are not tagged yet, but connect to tagged one */
- for(efa= em->faces.first; efa; efa=efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(!efa->f1 && uvedit_face_visible(scene, ima, efa, tf)) {
- nverts= (efa->v4)? 4: 3;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+
+ if(!BMO_TestFlag(em->bm, efa, EFA_F1_FLAG) && uvedit_face_visible(scene, ima, efa, tf)) {
+ nverts= efa->len;
for(a=0; a<nverts; a++) {
/* check face not hidden and not tagged */
iterv1= uv_vertex_map_get(vmap, efa, a);
iterv2= uv_vertex_map_get(vmap, efa, (a+1)%nverts);
+
+ if (!iterv1 || !iterv2)
+ continue;
/* check if vertex is tagged and has right valence */
if(iterv1->flag || iterv2->flag) {
- if(uv_edge_tag_faces(iterv1, iterv2, &starttotf)) {
+ if(uv_edge_tag_faces(em, iterv1, iterv2, &starttotf)) {
looking= 1;
- efa->f1= 1;
+ BMO_SetFlag(em->bm, efa, EFA_F1_FLAG);
uv_vertex_loop_flag(iterv1);
uv_vertex_loop_flag(iterv2);
@@ -820,16 +1003,14 @@ static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *h
}
/* do the actual select/deselect */
- nverts= (hit->efa->v4)? 4: 3;
- iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge);
- iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts);
+ nverts= hit->efa->len;
+ iterv1= uv_vertex_map_get(vmap, hit->efa, hit->lindex);
+ iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->lindex+1)%nverts);
iterv1->flag= 1;
iterv2->flag= 1;
if(extend) {
- tf= CustomData_em_get(&em->fdata, hit->efa->data, CD_MTFACE);
-
- if(uvedit_uv_selected(scene, hit->efa, tf, hit->edge))
+ if(uvedit_uv_selected(em, scene, hit->l) && uvedit_uv_selected(em, scene, hit->l))
select= 0;
else
select= 1;
@@ -837,83 +1018,109 @@ static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *h
else
select= 1;
- for(efa= em->faces.first; efa; efa=efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- nverts= (efa->v4)? 4: 3;
- for(a=0; a<nverts; a++) {
+ a = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
iterv1= uv_vertex_map_get(vmap, efa, a);
if(iterv1->flag) {
- if(select) uvedit_uv_select(scene, efa, tf, a);
- else uvedit_uv_deselect(scene, efa, tf, a);
+ if(select) uvedit_uv_select(em, scene, l);
+ else uvedit_uv_deselect(em, scene, l);
}
+
+ a++;
}
}
/* cleanup */
- EM_free_uv_vert_map(vmap);
- EM_free_index_arrays();
+ EDBM_free_uv_vert_map(vmap);
+ EDBM_free_index_arrays(em);
return (select)? 1: -1;
}
/*********************** linked select ***********************/
-static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2], NearestHit *hit, int extend)
+static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, float limit[2], NearestHit *hit, int extend)
{
- EditFace *efa;
- MTFace *tf;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
UvVertMap *vmap;
UvMapVert *vlist, *iterv, *startv;
int i, nverts, stacksize= 0, *stack;
unsigned int a;
char *flag;
- EM_init_index_arrays(em, 0, 0, 1); /* we can use this too */
- vmap= EM_make_uv_vert_map(em, 1, 0, limit);
+ EDBM_init_index_arrays(em, 0, 0, 1); /* we can use this too */
+ vmap= EDBM_make_uv_vert_map(em, 1, 1, limit);
+
if(vmap == NULL)
return;
- stack= MEM_mallocN(sizeof(*stack) * em->totface, "UvLinkStack");
- flag= MEM_callocN(sizeof(*flag) * em->totface, "UvLinkFlag");
+ stack= MEM_mallocN(sizeof(*stack)*(em->bm->totface+1), "UvLinkStack");
+ flag= MEM_callocN(sizeof(*flag)*em->bm->totface, "UvLinkFlag");
if(!hit) {
- for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3);
- if(tf->flag & select_flag) {
- stack[stacksize]= a;
- stacksize++;
- flag[a]= 1;
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ stack[stacksize]= a;
+ stacksize++;
+ flag[a]= 1;
+
+ break;
+ }
}
}
}
+ a++;
}
else {
- for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
if(efa == hit->efa) {
stack[stacksize]= a;
stacksize++;
flag[a]= 1;
break;
}
+
+ a++;
}
}
while(stacksize > 0) {
+ int j;
+
stacksize--;
a= stack[stacksize];
+
+ j = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(j==a)
+ break;
+
+ j++;
+ }
- efa = EM_get_face_for_index(a);
+ nverts= efa->len;
- nverts= efa->v4? 4: 3;
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
- for(i=0; i<nverts; i++) {
/* make_uv_vert_map_EM sets verts tmp.l to the indices */
- vlist= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l);
+ vlist= EDBM_get_uv_map_vert(vmap, BM_GetIndex(l->v));
startv= vlist;
@@ -933,50 +1140,86 @@ static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2]
stacksize++;
}
}
+
+ i++;
}
}
- if(!extend) {
- for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(flag[a])
- tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
- else
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ if(!extend) {
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (flag[a])
+ luv->flag |= MLOOPUV_VERTSEL;
+ else
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ }
+ a++;
}
}
else {
- for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
- if(flag[a]) {
- const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3);
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if((tf->flag & select_flag))
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!flag[a]) {
+ a++;
+ continue;
+ }
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (luv->flag & MLOOPUV_VERTSEL)
break;
}
+
+ if (l)
+ break;
+
+ a++;
}
if(efa) {
- for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
- if(flag[a]) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!flag[a]) {
+ a++;
+ continue;
}
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ }
+
+ a++;
}
}
else {
- for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
- if(flag[a]) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ a = 0;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!flag[a]) {
+ a++;
+ continue;
}
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+
+ a++;
}
}
}
MEM_freeN(stack);
MEM_freeN(flag);
- EM_free_uv_vert_map(vmap);
- EM_free_index_arrays();
+ EDBM_free_uv_vert_map(vmap);
+ EDBM_free_index_arrays(em);
}
/* ******************** align operator **************** */
@@ -987,32 +1230,34 @@ static void weld_align_uv(bContext *C, int tool)
Scene *scene;
Object *obedit;
Image *ima;
- EditMesh *em;
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float cent[2], min[2], max[2];
scene= CTX_data_scene(C);
obedit= CTX_data_edit_object(C);
- em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ em= ((Mesh*)obedit->data)->edit_btmesh;
ima= CTX_data_edit_image(C);
sima= CTX_wm_space_image(C);
INIT_MINMAX2(min, max);
if(tool == 'a') {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0))
- DO_MINMAX2(tf->uv[0], min, max)
- if(uvedit_uv_selected(scene, efa, tf, 1))
- DO_MINMAX2(tf->uv[1], min, max)
- if(uvedit_uv_selected(scene, efa, tf, 2))
- DO_MINMAX2(tf->uv[2], min, max)
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
- DO_MINMAX2(tf->uv[3], min, max)
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ DO_MINMAX2(luv->uv, min, max)
+ }
}
}
@@ -1022,37 +1267,39 @@ static void weld_align_uv(bContext *C, int tool)
uvedit_center(scene, ima, obedit, cent, 0);
if(tool == 'x' || tool == 'w') {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0))
- tf->uv[0][0]= cent[0];
- if(uvedit_uv_selected(scene, efa, tf, 1))
- tf->uv[1][0]= cent[0];
- if(uvedit_uv_selected(scene, efa, tf, 2))
- tf->uv[2][0]= cent[0];
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
- tf->uv[3][0]= cent[0];
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->uv[0] = cent[0];
+ }
+
}
}
}
if(tool == 'y' || tool == 'w') {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0))
- tf->uv[0][1]= cent[1];
- if(uvedit_uv_selected(scene, efa, tf, 1))
- tf->uv[1][1]= cent[1];
- if(uvedit_uv_selected(scene, efa, tf, 2))
- tf->uv[2][1]= cent[1];
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
- tf->uv[3][1]= cent[1];
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->uv[1] = cent[1];
+ }
+
}
}
}
+#if 0 // BMESH_TODO
+
if(tool == 's' || tool == 't' || tool == 'u') {
/* pass 1&2 variables */
int i, j;
@@ -1181,11 +1428,11 @@ static void weld_align_uv(bContext *C, int tool)
}
}
+#endif
+
uvedit_live_unwrap_update(sima, scene, obedit);
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
}
static int align_exec(bContext *C, wmOperator *op)
@@ -1252,40 +1499,43 @@ typedef struct UVVertAverage {
static int stitch_exec(bContext *C, wmOperator *op)
{
- SpaceImage *sima;
Scene *scene;
Object *obedit;
- EditMesh *em;
- EditFace *efa;
- EditVert *eve;
+ BMEditMesh *em;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ BMVert *eve;
Image *ima;
- MTFace *tf;
+ SpaceImage *sima= CTX_wm_space_image(C);
+ MTexPoly *tf;
+ MLoopUV *luv;
scene= CTX_data_scene(C);
obedit= CTX_data_edit_object(C);
- em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ em= ((Mesh*)obedit->data)->edit_btmesh;
ima= CTX_data_edit_image(C);
sima= CTX_wm_space_image(C);
if(RNA_boolean_get(op->ptr, "use_limit")) {
UvVertMap *vmap;
UvMapVert *vlist, *iterv;
- float newuv[2], limit[2];
+ float newuv[2], limit[2], pixels;
int a, vtot;
- limit[0]= RNA_float_get(op->ptr, "limit");
- limit[1]= limit[0];
+ pixels= RNA_float_get(op->ptr, "limit");
+ uvedit_pixel_to_float(sima, limit, pixels);
- EM_init_index_arrays(em, 0, 0, 1);
- vmap= EM_make_uv_vert_map(em, 1, 0, limit);
+ EDBM_init_index_arrays(em, 0, 0, 1);
+ vmap= EDBM_make_uv_vert_map(em, 1, 0, limit);
if(vmap == NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
-
- for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) {
- vlist= EM_get_uv_map_vert(vmap, a);
+
+ a = 0;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ vlist= EDBM_get_uv_map_vert(vmap, a);
while(vlist) {
newuv[0]= 0; newuv[1]= 0;
@@ -1295,12 +1545,15 @@ static int stitch_exec(bContext *C, wmOperator *op)
if((iterv != vlist) && iterv->separate)
break;
- efa = EM_get_face_for_index(iterv->f);
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ efa = EDBM_get_face_for_index(em, iterv->f);
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) {
- newuv[0] += tf->uv[iterv->tfindex][0];
- newuv[1] += tf->uv[iterv->tfindex][1];
+ l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ newuv[0] += luv->uv[0];
+ newuv[1] += luv->uv[1];
vtot++;
}
}
@@ -1312,95 +1565,72 @@ static int stitch_exec(bContext *C, wmOperator *op)
if((iterv != vlist) && iterv->separate)
break;
- efa = EM_get_face_for_index(iterv->f);
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ efa = EDBM_get_face_for_index(em, iterv->f);
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+
+ l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) {
- tf->uv[iterv->tfindex][0]= newuv[0];
- tf->uv[iterv->tfindex][1]= newuv[1];
+ luv->uv[0] = newuv[0];
+ luv->uv[1] = newuv[1];
+ vtot++;
}
}
}
vlist= iterv;
}
+
+ a++;
}
- EM_free_uv_vert_map(vmap);
- EM_free_index_arrays();
+ EDBM_free_uv_vert_map(vmap);
+ EDBM_free_index_arrays(em);
}
else {
UVVertAverage *uv_average, *uvav;
int count;
// index and count verts
- for(count=0, eve=em->verts.first; eve; count++, eve= eve->next)
- eve->tmp.l = count;
+ count=0;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(eve, count);
+ count++;
+ }
uv_average= MEM_callocN(sizeof(UVVertAverage)*count, "Stitch");
// gather uv averages per vert
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0)) {
- uvav = uv_average + efa->v1->tmp.l;
- uvav->count++;
- uvav->uv[0] += tf->uv[0][0];
- uvav->uv[1] += tf->uv[0][1];
- }
-
- if(uvedit_uv_selected(scene, efa, tf, 1)) {
- uvav = uv_average + efa->v2->tmp.l;
- uvav->count++;
- uvav->uv[0] += tf->uv[1][0];
- uvav->uv[1] += tf->uv[1][1];
- }
-
- if(uvedit_uv_selected(scene, efa, tf, 2)) {
- uvav = uv_average + efa->v3->tmp.l;
- uvav->count++;
- uvav->uv[0] += tf->uv[2][0];
- uvav->uv[1] += tf->uv[2][1];
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if(uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ uvav = uv_average + BM_GetIndex(l->v);
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
- uvav = uv_average + efa->v4->tmp.l;
uvav->count++;
- uvav->uv[0] += tf->uv[3][0];
- uvav->uv[1] += tf->uv[3][1];
+ uvav->uv[0] += luv->uv[0];
+ uvav->uv[1] += luv->uv[1];
}
}
}
// apply uv welding
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(uvedit_uv_selected(scene, efa, tf, 0)) {
- uvav = uv_average + efa->v1->tmp.l;
- tf->uv[0][0] = uvav->uv[0]/uvav->count;
- tf->uv[0][1] = uvav->uv[1]/uvav->count;
- }
-
- if(uvedit_uv_selected(scene, efa, tf, 1)) {
- uvav = uv_average + efa->v2->tmp.l;
- tf->uv[1][0] = uvav->uv[0]/uvav->count;
- tf->uv[1][1] = uvav->uv[1]/uvav->count;
- }
-
- if(uvedit_uv_selected(scene, efa, tf, 2)) {
- uvav = uv_average + efa->v3->tmp.l;
- tf->uv[2][0] = uvav->uv[0]/uvav->count;
- tf->uv[2][1] = uvav->uv[1]/uvav->count;
- }
-
- if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
- uvav = uv_average + efa->v4->tmp.l;
- tf->uv[3][0] = uvav->uv[0]/uvav->count;
- tf->uv[3][1] = uvav->uv[1]/uvav->count;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if(uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ uvav = uv_average + BM_GetIndex(l->v);
+ luv->uv[0] = uvav->uv[0]/uvav->count;
+ luv->uv[1] = uvav->uv[1]/uvav->count;
}
}
}
@@ -1412,7 +1642,6 @@ static int stitch_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1430,7 +1659,7 @@ static void UV_OT_stitch(wmOperatorType *ot)
/* properties */
RNA_def_boolean(ot->srna, "use_limit", 1, "Use Limit", "Stitch UVs within a specified limit distance");
- RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, FLT_MAX, "Limit", "Limit distance in normalized coordinates", -FLT_MAX, FLT_MAX);
+ RNA_def_float(ot->srna, "limit", 20.0, 0.0f, FLT_MAX, "Limit", "Limit distance in image pixels", -FLT_MAX, FLT_MAX);
}
/* ******************** (de)select all operator **************** */
@@ -1440,44 +1669,51 @@ static int select_all_exec(bContext *C, wmOperator *op)
Scene *scene;
ToolSettings *ts;
Object *obedit;
- EditMesh *em;
- EditFace *efa;
+ BMEditMesh *em;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
Image *ima;
- MTFace *tf;
+ MTexPoly *tf;
+ MLoopUV *luv;
int action = RNA_enum_get(op->ptr, "action");
scene= CTX_data_scene(C);
ts= CTX_data_tool_settings(C);
obedit= CTX_data_edit_object(C);
- em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ em= ((Mesh*)obedit->data)->edit_btmesh;
ima= CTX_data_edit_image(C);
if(ts->uv_flag & UV_SYNC_SELECTION) {
+
switch (action) {
case SEL_TOGGLE:
- EM_toggle_select_all(em);
+ EDBM_toggle_select_all(((Mesh*)obedit->data)->edit_btmesh);
break;
case SEL_SELECT:
- EM_select_all(em);
+ EDBM_set_flag_all(em, BM_SELECT);
break;
case SEL_DESELECT:
- EM_deselect_all(em);
+ EDBM_clear_flag_all(em, BM_SELECT);
break;
case SEL_INVERT:
- EM_select_swap(em);
+ EDBM_select_swap(em);
break;
}
}
else {
-
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
- for(efa= em->faces.first; efa; efa= efa->next) {
- const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3);
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(tf->flag & select_flag) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (luv->flag & MLOOPUV_VERTSEL) {
action = SEL_DESELECT;
break;
}
@@ -1485,21 +1721,25 @@ static int select_all_exec(bContext *C, wmOperator *op)
}
}
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
switch (action) {
case SEL_SELECT:
- tf->flag |= select_flag;
+ luv->flag |= MLOOPUV_VERTSEL;
break;
case SEL_DESELECT:
- tf->flag &= ~select_flag;
+ luv->flag &= ~MLOOPUV_VERTSEL;
break;
case SEL_INVERT:
- tf->flag ^= select_flag;
+ luv->flag ^= MLOOPUV_VERTSEL;
break;
}
}
@@ -1508,7 +1748,6 @@ static int select_all_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1529,7 +1768,7 @@ static void UV_OT_select_all(wmOperatorType *ot)
/* ******************** mouse select operator **************** */
-static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky)
+static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky, int hitlen)
{
int i;
@@ -1538,7 +1777,7 @@ static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], floa
if(sticky == SI_STICKY_DISABLE)
return 0;
- for(i=0; i<4; i++) {
+ for(i=0; i<hitlen; i++) {
if(hitv[i] == v) {
if(sticky == SI_STICKY_LOC) {
if(fabsf(hituv[i][0]-uv[0]) < limit[0] && fabsf(hituv[i][1]-uv[1]) < limit[1])
@@ -1559,13 +1798,19 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
NearestHit hit;
- int a, i, select = 1, selectmode, sticky, sync, hitv[4], nvert;
- int flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
- float limit[2], *hituv[4], penalty[2];
+ int a, i, select = 1, selectmode, sticky, sync, *hitv=NULL, nvert;
+ BLI_array_declare(hitv);
+ int flush = 0, hitlen=0; /* 0 == dont flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
+ float limit[2], **hituv = NULL;
+ BLI_array_declare(hituv);
+ float penalty[2];
/* notice 'limit' is the same no matter the zoom level, since this is like
* remove doubles and could annoying if it joined points when zoomed out.
@@ -1592,7 +1837,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
else {
sync= 0;
selectmode= ts->uv_selectmode;
- sticky= (sima)? sima->sticky: 1;
+ sticky= sima->sticky;
}
/* find nearest element */
@@ -1600,76 +1845,100 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
/* find edge */
find_nearest_uv_edge(scene, ima, em, co, &hit);
if(hit.efa == NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
+ BLI_array_free(hitv);
+ BLI_array_free(hituv);
return OPERATOR_CANCELLED;
}
+
+ hitlen = 0;
}
else if(selectmode == UV_SELECT_VERTEX) {
/* find vertex */
find_nearest_uv_vert(scene, ima, em, co, penalty, &hit);
if(hit.efa == NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
+ BLI_array_free(hitv);
+ BLI_array_free(hituv);
return OPERATOR_CANCELLED;
}
/* mark 1 vertex as being hit */
- for(i=0; i<4; i++)
+ for(i=0; i<hit.efa->len; i++) {
+ BLI_array_growone(hitv);
+ BLI_array_growone(hituv);
hitv[i]= 0xFFFFFFFF;
+ }
- hitv[hit.uv]= hit.vert;
- hituv[hit.uv]= hit.tf->uv[hit.uv];
+ hitv[hit.lindex]= hit.vert1;
+ hituv[hit.lindex]= hit.luv->uv;
+
+ hitlen = hit.efa->len;
}
else if(selectmode == UV_SELECT_EDGE) {
/* find edge */
find_nearest_uv_edge(scene, ima, em, co, &hit);
if(hit.efa == NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
+ BLI_array_free(hitv);
+ BLI_array_free(hituv);
return OPERATOR_CANCELLED;
}
/* mark 2 edge vertices as being hit */
- for(i=0; i<4; i++)
+ for(i=0; i<hit.efa->len; i++) {
+ BLI_array_growone(hitv);
+ BLI_array_growone(hituv);
hitv[i]= 0xFFFFFFFF;
+ }
+
+ nvert= hit.efa->len;
- nvert= (hit.efa->v4)? 4: 3;
+ hitv[hit.lindex]= hit.vert1;
+ hitv[(hit.lindex+1)%nvert]= hit.vert2;
+ hituv[hit.lindex]= hit.luv->uv;
+ hituv[(hit.lindex+1)%nvert]= hit.nextluv->uv;
- hitv[hit.edge]= hit.vert;
- hitv[(hit.edge+1)%nvert]= hit.vert2;
- hituv[hit.edge]= hit.tf->uv[hit.edge];
- hituv[(hit.edge+1)%nvert]= hit.tf->uv[(hit.edge+1)%nvert];
+ hitlen = hit.efa->len;
}
else if(selectmode == UV_SELECT_FACE) {
/* find face */
find_nearest_uv_face(scene, ima, em, co, &hit);
if(hit.efa == NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
+ BLI_array_free(hitv);
+ BLI_array_free(hituv);
return OPERATOR_CANCELLED;
}
/* make active */
- EM_set_actFace(em, hit.efa);
+ BM_set_actFace(em->bm, hit.efa);
/* mark all face vertices as being hit */
- for(i=0; i<4; i++)
- hituv[i]= hit.tf->uv[i];
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, hit.efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- hitv[0]= hit.efa->v1->tmp.l;
- hitv[1]= hit.efa->v2->tmp.l;
- hitv[2]= hit.efa->v3->tmp.l;
+ BLI_array_growone(hitv);
+ BLI_array_growone(hituv);
+ hituv[i]= luv->uv;
+ hitv[i] = BM_GetIndex(l->v);
+ i++;
+ }
- if(hit.efa->v4) hitv[3]= hit.efa->v4->tmp.l;
- else hitv[3]= 0xFFFFFFFF;
+ hitlen = hit.efa->len;
}
else if(selectmode == UV_SELECT_ISLAND) {
find_nearest_uv_vert(scene, ima, em, co, NULL, &hit);
if(hit.efa==NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
+ BLI_array_free(hitv);
+ BLI_array_free(hituv);
return OPERATOR_CANCELLED;
}
+
+ hitlen = 0;
}
else {
- BKE_mesh_end_editmesh(obedit->data, em);
+ hitlen = 0;
+ BLI_array_free(hitv);
+ BLI_array_free(hituv);
return OPERATOR_CANCELLED;
}
@@ -1683,36 +1952,36 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
else if(extend) {
if(selectmode == UV_SELECT_VERTEX) {
/* (de)select uv vertex */
- if(uvedit_uv_selected(scene, hit.efa, hit.tf, hit.uv)) {
- uvedit_uv_deselect(scene, hit.efa, hit.tf, hit.uv);
+ if(uvedit_uv_selected(em, scene, hit.l)) {
+ uvedit_uv_deselect(em, scene, hit.l);
select= 0;
}
else {
- uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv);
+ uvedit_uv_select(em, scene, hit.l);
select= 1;
}
flush = 1;
}
else if(selectmode == UV_SELECT_EDGE) {
/* (de)select edge */
- if(uvedit_edge_selected(scene, hit.efa, hit.tf, hit.edge)) {
- uvedit_edge_deselect(scene, hit.efa, hit.tf, hit.edge);
+ if(uvedit_edge_selected(em, scene, hit.l)) {
+ uvedit_edge_deselect(em, scene, hit.l);
select= 0;
}
else {
- uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge);
+ uvedit_edge_select(em, scene, hit.l);
select= 1;
}
flush = 1;
}
else if(selectmode == UV_SELECT_FACE) {
/* (de)select face */
- if(uvedit_face_selected(scene, hit.efa, hit.tf)) {
- uvedit_face_deselect(scene, hit.efa, hit.tf);
+ if(uvedit_face_selected(scene, em, hit.efa)) {
+ uvedit_face_deselect(scene, em, hit.efa);
select= 0;
}
else {
- uvedit_face_select(scene, hit.efa, hit.tf);
+ uvedit_face_select(scene, em, hit.efa);
select= 1;
}
flush = -1;
@@ -1720,109 +1989,102 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
/* (de)select sticky uv nodes */
if(sticky != SI_STICKY_DISABLE) {
- EditVert *ev;
-
- for(a=0, ev=em->verts.first; ev; ev = ev->next, a++)
- ev->tmp.l = a;
+ BMVert *ev;
+ a = 0;
+ BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(ev, a);
+ a++;
+ }
+
/* deselect */
if(select==0) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
- uvedit_uv_deselect(scene, efa, tf, 0);
- if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
- uvedit_uv_deselect(scene, efa, tf, 1);
- if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
- uvedit_uv_deselect(scene, efa, tf, 2);
- if(efa->v4)
- if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
- uvedit_uv_deselect(scene, efa, tf, 3);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if(sticky_select(limit, hitv, BM_GetIndex(l->v), hituv, luv->uv, sticky, hitlen))
+ uvedit_uv_deselect(em, scene, l);
}
}
flush = -1;
}
/* select */
else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
- uvedit_uv_select(scene, efa, tf, 0);
- if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
- uvedit_uv_select(scene, efa, tf, 1);
- if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
- uvedit_uv_select(scene, efa, tf, 2);
- if(efa->v4)
- if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
- uvedit_uv_select(scene, efa, tf, 3);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if(sticky_select(limit, hitv, BM_GetIndex(l->v), hituv, luv->uv, sticky, hitlen))
+ uvedit_uv_select(em, scene, l);
}
}
-
+
flush = 1;
}
}
}
else {
/* deselect all */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- uvedit_face_deselect(scene, efa, tf);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ uvedit_face_deselect(scene, em, efa);
}
if(selectmode == UV_SELECT_VERTEX) {
/* select vertex */
- uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv);
+ uvedit_uv_select(em, scene, hit.l);
flush= 1;
}
else if(selectmode == UV_SELECT_EDGE) {
/* select edge */
- uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge);
+ uvedit_edge_select(em, scene, hit.l);
flush= 1;
}
else if(selectmode == UV_SELECT_FACE) {
/* select face */
- uvedit_face_select(scene, hit.efa, hit.tf);
+ uvedit_face_select(scene, em, hit.efa);
}
/* select sticky uvs */
if(sticky != SI_STICKY_DISABLE) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tf)) {
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
if(sticky == SI_STICKY_DISABLE) continue;
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
- uvedit_uv_select(scene, efa, tf, 0);
- if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
- uvedit_uv_select(scene, efa, tf, 1);
- if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
- uvedit_uv_select(scene, efa, tf, 2);
- if(efa->v4)
- if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
- uvedit_uv_select(scene, efa, tf, 3);
+ if(sticky_select(limit, hitv, BM_GetIndex(l->v), hituv, luv->uv, sticky, hitlen))
+ uvedit_uv_select(em, scene, l);
flush= 1;
}
}
}
}
-
+
if(sync) {
/* flush for mesh selection */
if(ts->selectmode != SCE_SELECT_FACE) {
- if(flush==1) EM_select_flush(em);
- else if(flush==-1) EM_deselect_flush(em);
+ if(flush==1) EDBM_select_flush(em, ts->selectmode);
+ //else if(flush==-1) EDBM_deselect_flush(em); <-- I think this takes care of itself. . .
}
}
-
+
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
-
- BKE_mesh_end_editmesh(obedit->data, em);
+
+ BLI_array_free(hitv);
+ BLI_array_free(hituv);
+
return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED;
}
@@ -1923,7 +2185,7 @@ static int select_linked_internal(bContext *C, wmOperator *op, wmEvent *event, i
ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
float limit[2];
int extend;
@@ -1931,7 +2193,6 @@ static int select_linked_internal(bContext *C, wmOperator *op, wmEvent *event, i
if(ts->uv_flag & UV_SYNC_SELECTION) {
BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled");
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
@@ -1962,7 +2223,6 @@ static int select_linked_internal(bContext *C, wmOperator *op, wmEvent *event, i
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -2027,31 +2287,45 @@ static int unlink_selection_exec(bContext *C, wmOperator *op)
ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
if(ts->uv_flag & UV_SYNC_SELECTION) {
BKE_report(op->reports, RPT_ERROR, "Can't unlink selection when sync selection is enabled");
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ int desel = 0;
- if(uvedit_face_visible(scene, ima, efa, tf)) {
- const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3);
- if(~tf->flag & select_flag)
- tf->flag &= ~select_flag;
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (!(luv->flag & MLOOPUV_VERTSEL)) {
+ desel = 1;
+ break;
+ }
+ }
+
+ if (desel) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ }
}
}
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -2086,78 +2360,77 @@ static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Obje
* selection (so for sticky modes, vertex or location based). */
ToolSettings *ts= CTX_data_tool_settings(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
- int nverts, i;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ /* MTexPoly *tf; */
if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) {
/* Tag all verts as untouched, then touch the ones that have a face center
- * in the loop and select all MTFace UV's that use a touched vert. */
- EditVert *eve;
+ * in the loop and select all MLoopUV's that use a touched vert. */
+ BMVert *eve;
- for(eve= em->verts.first; eve; eve= eve->next)
- eve->tmp.l = 0;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL)
+ BM_SetIndex(eve, 0);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->tmp.l) {
- if(efa->v4)
- efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= efa->v4->tmp.l=1;
- else
- efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= 1;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(BM_GetIndex(efa)) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ BM_SetIndex(l->v, 1);
+ }
}
}
/* now select tagged verts */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- nverts= efa->v4? 4: 3;
- for(i=0; i<nverts; i++) {
- if((*(&efa->v1 + i))->tmp.l) {
- if(select)
- uvedit_uv_select(scene, efa, tf, i);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (BM_GetIndex(l->v)) {
+ if (select)
+ uvedit_uv_select(em, scene, l);
else
- uvedit_uv_deselect(scene, efa, tf, i);
+ uvedit_uv_deselect(em, scene, l);
}
}
}
}
else if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) {
- EditFace *efa_vlist;
- MTFace *tf_vlist;
+ BMFace *efa_vlist;
+ MTexPoly *tf_vlist;
UvMapVert *start_vlist=NULL, *vlist_iter;
struct UvVertMap *vmap;
float limit[2];
unsigned int efa_index;
- //EditVert *eve; /* removed vert counting for now */
+ //BMVert *eve; /* removed vert counting for now */
//int a;
uvedit_pixel_to_float(sima, limit, 0.05);
- EM_init_index_arrays(em, 0, 0, 1);
- vmap= EM_make_uv_vert_map(em, 0, 0, limit);
+ EDBM_init_index_arrays(em, 0, 0, 1);
+ vmap= EDBM_make_uv_vert_map(em, 0, 0, limit);
/* verts are numbered above in make_uv_vert_map_EM, make sure this stays true! */
/*for(a=0, eve= em->verts.first; eve; a++, eve= eve->next)
eve->tmp.l = a; */
if(vmap == NULL) {
- BKE_mesh_end_editmesh(obedit->data, em);
return;
}
- for(efa_index=0, efa= em->faces.first; efa; efa_index++, efa= efa->next) {
- if(efa->tmp.l) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- nverts= efa->v4? 4: 3;
-
- for(i=0; i<nverts; i++) {
+ efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for (efa_index=0; efa; efa=BMIter_Step(&iter), efa_index++) {
+ if(BM_GetIndex(efa)) {
+ /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
if(select)
- uvedit_uv_select(scene, efa, tf, i);
+ uvedit_uv_select(em, scene, l);
else
- uvedit_uv_deselect(scene, efa, tf, i);
+ uvedit_uv_deselect(em, scene, l);
- vlist_iter= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l);
+ vlist_iter= EDBM_get_uv_map_vert(vmap, BM_GetIndex(l->v));
while (vlist_iter) {
if(vlist_iter->separate)
@@ -2176,35 +2449,33 @@ static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Obje
break;
if(efa_index != vlist_iter->f) {
- efa_vlist = EM_get_face_for_index(vlist_iter->f);
- tf_vlist = CustomData_em_get(&em->fdata, efa_vlist->data, CD_MTFACE);
+ efa_vlist = EDBM_get_face_for_index(em, vlist_iter->f);
+ tf_vlist = CustomData_bmesh_get(&em->bm->pdata, efa_vlist->head.data, CD_MTEXPOLY);
if(select)
- uvedit_uv_select(scene, efa_vlist, tf_vlist, vlist_iter->tfindex);
+ uvedit_uv_select(em, scene, BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex));
else
- uvedit_uv_deselect(scene, efa_vlist, tf_vlist, vlist_iter->tfindex);
+ uvedit_uv_deselect(em, scene, BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex));
}
vlist_iter = vlist_iter->next;
}
}
}
}
- EM_free_index_arrays();
- EM_free_uv_vert_map(vmap);
+ EDBM_free_index_arrays(em);
+ EDBM_free_uv_vert_map(vmap);
}
else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->tmp.l) {
- tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(BM_GetIndex(efa)) {
if(select)
- uvedit_face_select(scene, efa, tf);
+ uvedit_face_select(scene, em, efa);
else
- uvedit_face_deselect(scene, efa, tf);
+ uvedit_face_deselect(scene, em, efa);
}
}
}
- BKE_mesh_end_editmesh(obedit->data, em);
}
static int border_select_exec(bContext *C, wmOperator *op)
@@ -2215,9 +2486,12 @@ static int border_select_exec(bContext *C, wmOperator *op)
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
ARegion *ar= CTX_wm_region(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tface;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
rcti rect;
rctf rectf;
int change, pinned, select, faces;
@@ -2247,14 +2521,16 @@ static int border_select_exec(bContext *C, wmOperator *op)
change= 0;
- for(efa= em->faces.first; efa; efa= efa->next) {
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
/* assume not touched */
- efa->tmp.l = 0;
- tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tface)) {
- uv_center(tface->uv, cent, efa->v4 != NULL);
+ BM_SetIndex(efa, 0);
+
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(uvedit_face_visible(scene, ima, efa, tf)) {
+ poly_uv_center(em, efa, cent);
if(BLI_in_rctf(&rectf, cent[0], cent[1])) {
- efa->tmp.l = change = 1;
+ BM_SetIndex(efa, 1);
+ change = 1;
}
}
}
@@ -2266,51 +2542,26 @@ static int border_select_exec(bContext *C, wmOperator *op)
else {
/* other selection modes */
change= 1;
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tf))
+ continue;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tface)) {
if(!pinned || (ts->uv_flag & UV_SYNC_SELECTION) ) {
+
/* UV_SYNC_SELECTION - can't do pinned selection */
- if(BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
- if(select) uvedit_uv_select(scene, efa, tface, 0);
- else uvedit_uv_deselect(scene, efa, tface, 0);
- }
- if(BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
- if(select) uvedit_uv_select(scene, efa, tface, 1);
- else uvedit_uv_deselect(scene, efa, tface, 1);
- }
- if(BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
- if(select) uvedit_uv_select(scene, efa, tface, 2);
- else uvedit_uv_deselect(scene, efa, tface, 2);
- }
- if(efa->v4 && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
- if(select) uvedit_uv_select(scene, efa, tface, 3);
- else uvedit_uv_deselect(scene, efa, tface, 3);
- }
- }
- else if(pinned) {
- if((tface->unwrap & TF_PIN1) &&
- BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
-
- if(select) uvedit_uv_select(scene, efa, tface, 0);
- else uvedit_uv_deselect(scene, efa, tface, 0);
- }
- if((tface->unwrap & TF_PIN2) &&
- BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
-
- if(select) uvedit_uv_select(scene, efa, tface, 1);
- else uvedit_uv_deselect(scene, efa, tface, 1);
- }
- if((tface->unwrap & TF_PIN3) &&
- BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
-
- if(select) uvedit_uv_select(scene, efa, tface, 2);
- else uvedit_uv_deselect(scene, efa, tface, 2);
+ if(BLI_in_rctf(&rectf, luv->uv[0], luv->uv[1])) {
+ if(select) uvedit_uv_select(em, scene, l);
+ else uvedit_uv_deselect(em, scene, l);
}
- if((efa->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
- if(select) uvedit_uv_select(scene, efa, tface, 3);
- else uvedit_uv_deselect(scene, efa, tface, 3);
+ } else if(pinned) {
+ if ((luv->flag & MLOOPUV_PINNED) &&
+ BLI_in_rctf(&rectf, luv->uv[0], luv->uv[1])) {
+ if(select) uvedit_uv_select(em, scene, l);
+ else uvedit_uv_deselect(em, scene, l);
}
}
}
@@ -2319,20 +2570,20 @@ static int border_select_exec(bContext *C, wmOperator *op)
if(change) {
/* make sure newly selected vert selection is updated*/
+#if 0 //ok, I think the BM_Select API handles all of this?
if(ts->uv_flag & UV_SYNC_SELECTION) {
if(ts->selectmode != SCE_SELECT_FACE) {
if(select) EM_select_flush(em);
else EM_deselect_flush(em);
}
}
+#endif
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
+
return OPERATOR_CANCELLED;
}
@@ -2361,20 +2612,22 @@ static void UV_OT_select_border(wmOperatorType *ot)
/* ******************** circle select operator **************** */
-static void select_uv_inside_ellipse(Scene *scene, int select, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, int select_index)
+static void select_uv_inside_ellipse(BMEditMesh *em, SpaceImage *UNUSED(sima), Scene *scene, int select,
+ float *offset, float *ell, BMLoop *l, MLoopUV *luv)
{
/* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
float x, y, r2, *uv;
- uv= tface->uv[index];
+
+ uv= luv->uv;
x= (uv[0] - offset[0])*ell[0];
y= (uv[1] - offset[1])*ell[1];
r2 = x*x + y*y;
if(r2 < 1.0f) {
- if(select) uvedit_uv_select(scene, efa, tface, select_index);
- else uvedit_uv_deselect(scene, efa, tface, select_index);
+ if(select) uvedit_uv_select(em, scene, l);
+ else uvedit_uv_deselect(em, scene, l);
}
}
@@ -2383,10 +2636,12 @@ static int circle_select_exec(bContext *C, wmOperator *op)
SpaceImage *sima= CTX_wm_space_image(C);
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
ARegion *ar= CTX_wm_region(C);
- EditFace *efa;
- MTFace *tface;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
int x, y, radius, width, height, select;
float zoomx, zoomy, offset[2], ellipse[2];
int gesture_mode= RNA_int_get(op->ptr, "gesture_mode");
@@ -2408,21 +2663,19 @@ static int circle_select_exec(bContext *C, wmOperator *op)
UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]);
/* do selection */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- select_uv_inside_ellipse(scene, select, efa, tface, 0, offset, ellipse, 0);
- select_uv_inside_ellipse(scene, select, efa, tface, 1, offset, ellipse, 1);
- select_uv_inside_ellipse(scene, select, efa, tface, 2, offset, ellipse, 2);
- if(efa->v4)
- select_uv_inside_ellipse(scene, select, efa, tface, 3, offset, ellipse, 3);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ select_uv_inside_ellipse(em, sima, scene, select, offset, ellipse, l, luv);
+ }
}
+#if 0 //I think the BM_Select api stuff handles all this as necassary?
if(select) EM_select_flush(em);
else EM_deselect_flush(em);
-
+#endif
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -2522,97 +2775,88 @@ static void UV_OT_snap_cursor(wmOperatorType *ot)
static int snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, SpaceImage *sima)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tface;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tface;
+ MLoopUV *luv;
short change= 0;
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tface)) {
- if(uvedit_uv_selected(scene, efa, tface, 0)) VECCOPY2D(tface->uv[0], sima->cursor);
- if(uvedit_uv_selected(scene, efa, tface, 1)) VECCOPY2D(tface->uv[1], sima->cursor);
- if(uvedit_uv_selected(scene, efa, tface, 2)) VECCOPY2D(tface->uv[2], sima->cursor);
- if(efa->v4)
- if(uvedit_uv_selected(scene, efa, tface, 3)) VECCOPY2D(tface->uv[3], sima->cursor);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface))
+ continue;
- change= 1;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if(uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ VECCOPY2D(luv->uv, sima->cursor);
+ change= 1;
+ }
}
}
- BKE_mesh_end_editmesh(obedit->data, em);
return change;
}
static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- EditVert *eve;
- MTFace *tface;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ BMVert *eve;
+ MTexPoly *tface;
+ MLoopUV *luv;
short change = 0;
int count = 0;
float *coords;
short *usercount, users;
/* set all verts to -1 : an unused index*/
- for(eve= em->verts.first; eve; eve= eve->next)
- eve->tmp.l=-1;
+ BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL)
+ BM_SetIndex(eve, -1);
/* index every vert that has a selected UV using it, but only once so as to
* get unique indices and to count how much to malloc */
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tface)) {
- if(uvedit_uv_selected(scene, efa, tface, 0) && efa->v1->tmp.l==-1) efa->v1->tmp.l= count++;
- if(uvedit_uv_selected(scene, efa, tface, 1) && efa->v2->tmp.l==-1) efa->v2->tmp.l= count++;
- if(uvedit_uv_selected(scene, efa, tface, 2) && efa->v3->tmp.l==-1) efa->v3->tmp.l= count++;
- if(efa->v4)
- if(uvedit_uv_selected(scene, efa, tface, 3) && efa->v4->tmp.l==-1) efa->v4->tmp.l= count++;
-
- change = 1;
-
- /* optional speedup */
- efa->tmp.p = tface;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface)) {
+ BM_SetIndex(efa, 0);
+ continue;
+ } else {
+ BM_SetIndex(efa, 1);
+ }
+
+ change = 1;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l) && BM_GetIndex(l->v) == -1) {
+ BM_SetIndex(l->v, count);
+ count++;
+ }
}
- else
- efa->tmp.p = NULL;
}
coords = MEM_callocN(sizeof(float)*count*2, "snap to adjacent coords");
usercount = MEM_callocN(sizeof(short)*count, "snap to adjacent counts");
/* add all UV coords from visible, unselected UV coords as well as counting them to average later */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if((tface=(MTFace *)efa->tmp.p)) {
- /* is this an unselected UV we can snap to? */
- if(efa->v1->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 0))) {
- coords[efa->v1->tmp.l*2] += tface->uv[0][0];
- coords[(efa->v1->tmp.l*2)+1] += tface->uv[0][1];
- usercount[efa->v1->tmp.l]++;
- change = 1;
- }
- if(efa->v2->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 1))) {
- coords[efa->v2->tmp.l*2] += tface->uv[1][0];
- coords[(efa->v2->tmp.l*2)+1] += tface->uv[1][1];
- usercount[efa->v2->tmp.l]++;
- change = 1;
- }
- if(efa->v3->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 2))) {
- coords[efa->v3->tmp.l*2] += tface->uv[2][0];
- coords[(efa->v3->tmp.l*2)+1] += tface->uv[2][1];
- usercount[efa->v3->tmp.l]++;
- change = 1;
- }
-
- if(efa->v4) {
- if(efa->v4->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 3))) {
- coords[efa->v4->tmp.l*2] += tface->uv[3][0];
- coords[(efa->v4->tmp.l*2)+1] += tface->uv[3][1];
- usercount[efa->v4->tmp.l]++;
- change = 1;
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
+
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (BM_GetIndex(l->v) >= 0 &&
+ (!uvedit_uv_selected(em, scene, l))) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ coords[BM_GetIndex(l->v)*2] += luv->uv[0];
+ coords[BM_GetIndex(l->v)*2+1] += luv->uv[1];
+ change = 1;
}
}
}
@@ -2621,46 +2865,24 @@ static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe
if(!change) {
MEM_freeN(coords);
MEM_freeN(usercount);
- BKE_mesh_end_editmesh(obedit->data, em);
return change;
}
/* copy the averaged unselected UVs back to the selected UVs */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if((tface=(MTFace *)efa->tmp.p)) {
-
- if( uvedit_uv_selected(scene, efa, tface, 0) &&
- efa->v1->tmp.l >= 0 &&
- (users = usercount[efa->v1->tmp.l])
- ) {
- tface->uv[0][0] = coords[efa->v1->tmp.l*2] / users;
- tface->uv[0][1] = coords[(efa->v1->tmp.l*2)+1] / users;
- }
-
- if( uvedit_uv_selected(scene, efa, tface, 1) &&
- efa->v2->tmp.l >= 0 &&
- (users = usercount[efa->v2->tmp.l])
- ) {
- tface->uv[1][0] = coords[efa->v2->tmp.l*2] / users;
- tface->uv[1][1] = coords[(efa->v2->tmp.l*2)+1] / users;
- }
-
- if( uvedit_uv_selected(scene, efa, tface, 2) &&
- efa->v3->tmp.l >= 0 &&
- (users = usercount[efa->v3->tmp.l])
- ) {
- tface->uv[2][0] = coords[efa->v3->tmp.l*2] / users;
- tface->uv[2][1] = coords[(efa->v3->tmp.l*2)+1] / users;
- }
-
- if(efa->v4) {
- if( uvedit_uv_selected(scene, efa, tface, 3) &&
- efa->v4->tmp.l >= 0 &&
- (users = usercount[efa->v4->tmp.l])
- ) {
- tface->uv[3][0] = coords[efa->v4->tmp.l*2] / users;
- tface->uv[3][1] = coords[(efa->v4->tmp.l*2)+1] / users;
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_GetIndex(efa))
+ continue;
+
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l) && BM_GetIndex(l->v) >= 0
+ && (users = usercount[BM_GetIndex(l->v)])) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->uv[0] = coords[BM_GetIndex(l->v)*2];
+ luv->uv[1] = coords[BM_GetIndex(l->v)*2+1];
}
}
}
@@ -2668,43 +2890,41 @@ static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe
MEM_freeN(coords);
MEM_freeN(usercount);
- BKE_mesh_end_editmesh(obedit->data, em);
return change;
}
static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- Image *ima;
- EditFace *efa;
- MTFace *tface;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ Image *ima= sima->image;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tface;
+ MLoopUV *luv;
int width= 0, height= 0;
float w, h;
short change = 0;
- if(!sima)
- return 0;
-
- ima= sima->image;
-
ED_space_image_size(sima, &width, &height);
w = (float)width;
h = (float)height;
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(uvedit_face_visible(scene, ima, efa, tface)) {
- if(uvedit_uv_selected(scene, efa, tface, 0)) snap_uv_to_pixel(tface->uv[0], w, h);
- if(uvedit_uv_selected(scene, efa, tface, 1)) snap_uv_to_pixel(tface->uv[1], w, h);
- if(uvedit_uv_selected(scene, efa, tface, 2)) snap_uv_to_pixel(tface->uv[2], w, h);
- if(efa->v4)
- if(uvedit_uv_selected(scene, efa, tface, 3)) snap_uv_to_pixel(tface->uv[3], w, h);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface))
+ continue;
- change = 1;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l)) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ snap_uv_to_pixel(luv->uv, w, h);
+ }
}
+
+ change = 1;
}
- BKE_mesh_end_editmesh(obedit->data, em);
return change;
}
@@ -2767,35 +2987,34 @@ static int pin_exec(bContext *C, wmOperator *op)
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tface;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tface;
+ MLoopUV *luv;
int clear= RNA_boolean_get(op->ptr, "clear");
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface))
+ continue;
- if(uvedit_face_visible(scene, ima, efa, tface)) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
if(!clear) {
- if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap |= TF_PIN1;
- if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap |= TF_PIN2;
- if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap |= TF_PIN3;
- if(efa->v4)
- if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap |= TF_PIN4;
- }
- else {
- if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap &= ~TF_PIN1;
- if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap &= ~TF_PIN2;
- if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap &= ~TF_PIN3;
- if(efa->v4)
- if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap &= ~TF_PIN4;
+ if (uvedit_uv_selected(em, scene, l))
+ luv->flag |= MLOOPUV_PINNED;
+ } else {
+ if (uvedit_uv_selected(em, scene, l))
+ luv->flag &= ~MLOOPUV_PINNED;
}
}
}
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -2822,26 +3041,28 @@ static int select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
Image *ima= CTX_data_edit_image(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tface;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(uvedit_face_visible(scene, ima, efa, tface)) {
- if(tface->unwrap & TF_PIN1) uvedit_uv_select(scene, efa, tface, 0);
- if(tface->unwrap & TF_PIN2) uvedit_uv_select(scene, efa, tface, 1);
- if(tface->unwrap & TF_PIN3) uvedit_uv_select(scene, efa, tface, 2);
- if(efa->v4) {
- if(tface->unwrap & TF_PIN4) uvedit_uv_select(scene, efa, tface, 3);
- }
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tface;
+ MLoopUV *luv;
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if(!uvedit_face_visible(scene, ima, efa, tface))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (luv->flag & MLOOPUV_PINNED)
+ uvedit_uv_select(em, scene, l);
}
}
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -2865,122 +3086,75 @@ static int hide_exec(bContext *C, wmOperator *op)
SpaceImage *sima= CTX_wm_space_image(C);
ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ Scene *scene = CTX_data_scene(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
int swap= RNA_boolean_get(op->ptr, "unselected");
int facemode= sima ? sima->flag & SI_SELACTFACE : 0;
if(ts->uv_flag & UV_SYNC_SELECTION) {
- EM_hide_mesh(em, swap);
+ EDBM_hide_mesh(em, swap);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
- if(swap) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- if(facemode) {
- /* Pretend face mode */
- if(( (efa->v4==NULL &&
- ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) ||
- ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) ) == 0) {
-
- if(em->selectmode == SCE_SELECT_FACE) {
- efa->f &= ~SELECT;
- /* must re-select after */
- efa->e1->f &= ~SELECT;
- efa->e2->f &= ~SELECT;
- efa->e3->f &= ~SELECT;
- if(efa->e4) efa->e4->f &= ~SELECT;
- }
- else
- EM_select_face(efa, 0);
- }
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
- }
- else if(em->selectmode == SCE_SELECT_FACE) {
- const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3);
- if((tf->flag & select_flag)==0) {
- EM_select_face(efa, 0);
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
- }
- }
- else {
- /* EM_deselect_flush will deselect the face */
- if((tf->flag & TF_SEL1)==0) efa->v1->f &= ~SELECT;
- if((tf->flag & TF_SEL2)==0) efa->v2->f &= ~SELECT;
- if((tf->flag & TF_SEL3)==0) efa->v3->f &= ~SELECT;
- if((efa->v4) && (tf->flag & TF_SEL4)==0) efa->v4->f &= ~SELECT;
-
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
- }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ int hide = 0;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ hide = 1;
+ break;
}
}
- }
- else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(facemode) {
- if( (efa->v4==NULL &&
- ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) ||
- ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) ) {
-
- if(em->selectmode == SCE_SELECT_FACE) {
- efa->f &= ~SELECT;
- /* must re-select after */
- efa->e1->f &= ~SELECT;
- efa->e2->f &= ~SELECT;
- efa->e3->f &= ~SELECT;
- if(efa->e4) efa->e4->f &= ~SELECT;
- }
- else
- EM_select_face(efa, 0);
- }
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ if (swap)
+ hide = !hide;
+
+ if (hide) {
+ if (facemode) {
+ /*check that every UV is selected*/
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (!(luv->flag & MLOOPUV_VERTSEL))
+ break;
}
- else if(em->selectmode == SCE_SELECT_FACE) {
- const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3);
- if(tf->flag & select_flag)
- EM_select_face(efa, 0);
-
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+
+ if (!luv) {
+ BM_Select(em->bm, efa, 0);
+ uvedit_face_deselect(scene, em, efa);
+ }
+ } else if(em->selectmode == SCE_SELECT_FACE) {
+ /*check if a UV is selected*/
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ BM_Select(em->bm, efa, 0);
+ }
+ luv->flag &= ~MLOOPUV_VERTSEL;
}
- else {
- /* EM_deselect_flush will deselect the face */
- if(tf->flag & TF_SEL1) efa->v1->f &= ~SELECT;
- if(tf->flag & TF_SEL2) efa->v2->f &= ~SELECT;
- if(tf->flag & TF_SEL3) efa->v3->f &= ~SELECT;
- if((efa->v4) && tf->flag & TF_SEL4) efa->v4->f &= ~SELECT;
-
- tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
+ } else {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (luv->flag & MLOOPUV_VERTSEL) {
+ BM_Select(em->bm, l->v, 0);
+ luv->flag &= ~MLOOPUV_VERTSEL;
+ }
}
}
}
}
- /*deselects too many but ok for now*/
- if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX))
- EM_deselect_flush(em);
-
- if(em->selectmode==SCE_SELECT_FACE) {
- /* de-selected all edges from faces that were de-selected.
- * now make sure all faces that are selected also have selected edges */
- for(efa= em->faces.first; efa; efa= efa->next)
- if(efa->f & SELECT)
- EM_select_face(efa, 1);
- }
- EM_validate_selections(em);
+ EDBM_validate_selections(em);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -3007,114 +3181,102 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
SpaceImage *sima= CTX_wm_space_image(C);
ToolSettings *ts= CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ /*Scene *scene = CTX_data_scene(C);*/ /*UNUSED*/
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMVert *v;
+ BMIter iter, liter;
+ MLoopUV *luv;
int facemode= sima ? sima->flag & SI_SELACTFACE : 0;
int stickymode= sima ? (sima->sticky != SI_STICKY_DISABLE) : 1;
+ BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(v, BM_TestHFlag(v, BM_SELECT));
+ }
+
/* call the mesh function if we are in mesh sync sel */
if(ts->uv_flag & UV_SYNC_SELECTION) {
- EM_reveal_mesh(em);
+ EDBM_reveal_mesh(em);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
-
if(facemode) {
if(em->selectmode == SCE_SELECT_FACE) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(!(efa->h) && !(efa->f & SELECT)) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- EM_select_face(efa, 1);
- tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN) && !BM_TestHFlag(efa, BM_SELECT)) {
+ BM_Select(em->bm, efa, 1);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
}
}
}
else {
/* enable adjacent faces to have disconnected UV selections if sticky is disabled */
if(!stickymode) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(!(efa->h) && !(efa->f & SELECT)) {
- /* All verts must be unselected for the face to be selected in the UV view */
- if((efa->v1->f&SELECT)==0 && (efa->v2->f&SELECT)==0 && (efa->v3->f&SELECT)==0 && (efa->v4==NULL || (efa->v4->f&SELECT)==0)) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
- /* Cant use EM_select_face here because it unselects the verts
- * and we cant tell if the face was totally unselected or not */
- /*EM_select_face(efa, 1);
- *
- * See Loop with EM_select_face() below... */
- efa->f |= SELECT;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN) && !BM_TestHFlag(efa, BM_SELECT)) {
+ int totsel=0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ totsel += BM_TestHFlag(l->v, BM_SELECT);
+ }
+
+ if (!totsel) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+
+ BM_Select(em->bm, efa, 1);
}
}
}
- }
- else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(!(efa->h) && !(efa->f & SELECT)) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if((efa->v1->f & SELECT)==0) {tf->flag |= TF_SEL1;}
- if((efa->v2->f & SELECT)==0) {tf->flag |= TF_SEL2;}
- if((efa->v3->f & SELECT)==0) {tf->flag |= TF_SEL3;}
- if((efa->v4 && (efa->v4->f & SELECT)==0)) {tf->flag |= TF_SEL4;}
-
- efa->f |= SELECT;
+ } else {
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN) && !BM_TestHFlag(efa, BM_SELECT)) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (BM_TestHFlag(l->v, BM_SELECT)==0) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+ }
+
+ BM_Select(em->bm, efa, 1);
}
}
}
-
- /* Select all edges and verts now */
- for(efa= em->faces.first; efa; efa= efa->next)
- /* we only selected the face flags, and didnt changes edges or verts, fix this now */
- if(!(efa->h) && (efa->f & SELECT))
- EM_select_face(efa, 1);
-
- EM_select_flush(em);
}
- }
- else if(em->selectmode == SCE_SELECT_FACE) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(!(efa->h) && !(efa->f & SELECT)) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- efa->f |= SELECT;
- tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
+ } else if(em->selectmode == SCE_SELECT_FACE) {
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN) && !BM_TestHFlag(efa, BM_SELECT)) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+
+ BM_Select(em->bm, efa, 1);
}
}
-
- /* Select all edges and verts now */
- for(efa= em->faces.first; efa; efa= efa->next)
- /* we only selected the face flags, and didnt changes edges or verts, fix this now */
- if(!(efa->h) && (efa->f & SELECT))
- EM_select_face(efa, 1);
- }
- else {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(!(efa->h) && !(efa->f & SELECT)) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if((efa->v1->f & SELECT)==0) {tf->flag |= TF_SEL1;}
- if((efa->v2->f & SELECT)==0) {tf->flag |= TF_SEL2;}
- if((efa->v3->f & SELECT)==0) {tf->flag |= TF_SEL3;}
- if((efa->v4 && (efa->v4->f & SELECT)==0)) {tf->flag |= TF_SEL4;}
-
- efa->f |= SELECT;
+ } else {
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_HIDDEN) && !BM_TestHFlag(efa, BM_SELECT)) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (BM_TestHFlag(l->v, BM_SELECT)==0) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->flag |= MLOOPUV_VERTSEL;
+ }
+ }
+
+ BM_Select(em->bm, efa, 1);
}
}
-
- /* Select all edges and verts now */
- for(efa= em->faces.first; efa; efa= efa->next)
- /* we only selected the face flags, and didnt changes edges or verts, fix this now */
- if(!(efa->h) && (efa->f & SELECT))
- EM_select_face(efa, 1);
}
-
+
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 1b117a15516..09446fc5eab 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -731,8 +731,10 @@ static PEdge *p_edge_lookup(PHandle *handle, PHashKey *vkeys)
return NULL;
}
-static PBool p_face_exists(PHandle *handle, PHashKey *vkeys, int i1, int i2, int i3)
+int p_face_exists(ParamHandle *phandle, ParamKey *pvkeys, int i1, int i2, int i3)
{
+ PHandle *handle = (PHandle*)phandle;
+ PHashKey *vkeys = (PHashKey*)pvkeys;
PHashKey key = PHASH_edge(vkeys[i1], vkeys[i2]);
PEdge *e = (PEdge*)phash_lookup(handle->hash_edges, key);
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h b/source/blender/editors/uvedit/uvedit_parametrizer.h
index e8dac7346ac..df2fbfa193e 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.h
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.h
@@ -33,6 +33,8 @@ ParamHandle *param_construct_begin(void);
void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy);
+int p_face_exists(ParamHandle *handle, ParamKey *vkeys, int i1, int i2, int i3);
+
void param_face_add(ParamHandle *handle,
ParamKey key,
int nverts,
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 29a9ae84cd5..84eb418ea41 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -41,17 +41,27 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
#include "BLI_editVert.h"
#include "BLI_uvproject.h"
#include "BLI_utildefines.h"
+#include "BLI_rand.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_depsgraph.h"
#include "BKE_image.h"
#include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
+
+#include "BLI_math.h"
+#include "BLI_edgehash.h"
+#include "BLI_editVert.h"
+#include "BLI_scanfill.h"
+#include "BLI_array.h"
+#include "BLI_uvproject.h"
#include "PIL_time.h"
@@ -73,9 +83,9 @@
static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMIter iter;
Image *ima;
bScreen *sc;
ScrArea *sa;
@@ -83,15 +93,15 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
SpaceImage *sima;
if(ED_uvedit_test(obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return 1;
}
- if(em && em->faces.first)
- EM_add_data_layer(em, &em->fdata, CD_MTFACE, NULL);
-
+ if(em && em->bm->totface && !CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) {
+ BM_add_data_layer(em->bm, &em->bm->pdata, CD_MTEXPOLY);
+ BM_add_data_layer(em->bm, &em->bm->ldata, CD_MLOOPUV);
+ }
+
if(!ED_uvedit_test(obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return 0;
}
@@ -121,70 +131,71 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
ED_uvedit_assign_image(scene, obedit, ima, NULL);
/* select new UV's */
- for(efa=em->faces.first; efa; efa=efa->next) {
- tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- uvedit_face_select(scene, efa, tf);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ uvedit_face_select(scene, em, efa);
}
- BKE_mesh_end_editmesh(obedit->data, em);
return 1;
}
/****************** Parametrizer Conversion ***************/
-static int uvedit_have_selection(Scene *scene, EditMesh *em, short implicit)
+static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit)
{
- EditFace *efa;
- MTFace *tf;
-
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+
/* verify if we have any selected uv's before unwrapping,
so we can cancel the operator early */
- for(efa= em->faces.first; efa; efa= efa->next) {
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
- if(efa->h)
+ if(BM_TestHFlag(efa, BM_HIDDEN))
continue;
}
- else if((efa->h) || ((efa->f & SELECT)==0))
+ else if(BM_TestHFlag(efa, BM_HIDDEN) || !BM_TestHFlag(efa, BM_SELECT))
continue;
-
- tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(!tf)
- return 1; /* default selected if doesn't exists */
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (!luv)
+ return 1;
+
+ if (uvedit_uv_selected(em, scene, l))
+ break;
+ }
- if(implicit &&
- !( uvedit_uv_selected(scene, efa, tf, 0) ||
- uvedit_uv_selected(scene, efa, tf, 1) ||
- uvedit_uv_selected(scene, efa, tf, 2) ||
- (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) )
- ) {
+ if (implicit && !l)
continue;
- }
-
+
return 1;
}
return 0;
}
-static ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit,
- short fill, short sel, short correct_aspect)
+static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em,
+ short implicit, short fill, short sel,
+ short correct_aspect)
{
ParamHandle *handle;
- EditFace *efa;
- EditEdge *eed;
- EditVert *ev;
- MTFace *tf;
+ BMFace *efa;
+ BMLoop *l;
+ BMEdge *eed;
+ BMVert *ev;
+ BMIter iter, liter;
+ MTexPoly *tf;
int a;
handle = param_construct_begin();
if(correct_aspect) {
- efa = EM_get_actFace(em, 1);
+ efa = BM_get_actFace(em->bm, 1);
if(efa) {
+ MTexPoly *tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
float aspx, aspy;
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
@@ -194,71 +205,112 @@ static ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short imp
}
/* we need the vert indices */
- for(ev= em->verts.first, a=0; ev; ev= ev->next, a++)
- ev->tmp.l = a;
+ a = 0;
+ BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+ BM_SetIndex(ev, a);
+ a++;
+ }
- for(efa= em->faces.first; efa; efa= efa->next) {
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ EditVert *v, *lastv, *firstv;
+ EditFace *sefa;
ParamKey key, vkeys[4];
ParamBool pin[4], select[4];
+ BMLoop *ls[3];
+ MLoopUV *luvs[3];
float *co[4];
float *uv[4];
- int nverts;
-
- if((efa->h) || (sel && (efa->f & SELECT)==0))
- continue;
+ int lsel;
- tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- if(implicit &&
- !( uvedit_uv_selected(scene, efa, tf, 0) ||
- uvedit_uv_selected(scene, efa, tf, 1) ||
- uvedit_uv_selected(scene, efa, tf, 2) ||
- (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) )
- ) {
+ if((BM_TestHFlag(efa, BM_HIDDEN)) || (sel && BM_TestHFlag(efa, BM_SELECT)==0))
continue;
+
+ tf= (MTexPoly *)CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ lsel = 0;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ if (uvedit_uv_selected(em, scene, l)) {
+ lsel = 1;
+ break;
+ }
}
+ if (implicit && !lsel)
+ continue;
+
key = (ParamKey)efa;
- vkeys[0] = (ParamKey)efa->v1->tmp.l;
- vkeys[1] = (ParamKey)efa->v2->tmp.l;
- vkeys[2] = (ParamKey)efa->v3->tmp.l;
-
- co[0] = efa->v1->co;
- co[1] = efa->v2->co;
- co[2] = efa->v3->co;
-
- uv[0] = tf->uv[0];
- uv[1] = tf->uv[1];
- uv[2] = tf->uv[2];
-
- pin[0] = ((tf->unwrap & TF_PIN1) != 0);
- pin[1] = ((tf->unwrap & TF_PIN2) != 0);
- pin[2] = ((tf->unwrap & TF_PIN3) != 0);
-
- select[0] = ((uvedit_uv_selected(scene, efa, tf, 0)) != 0);
- select[1] = ((uvedit_uv_selected(scene, efa, tf, 1)) != 0);
- select[2] = ((uvedit_uv_selected(scene, efa, tf, 2)) != 0);
-
- if(efa->v4) {
- vkeys[3] = (ParamKey)efa->v4->tmp.l;
- co[3] = efa->v4->co;
- uv[3] = tf->uv[3];
- pin[3] = ((tf->unwrap & TF_PIN4) != 0);
- select[3] = (uvedit_uv_selected(scene, efa, tf, 3) != 0);
- nverts = 4;
+
+ /*scanfill time!*/
+ BLI_begin_edgefill();
+
+ firstv = lastv = NULL;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ int i;
+
+ v = BLI_addfillvert(l->v->co);
+
+ /*add small random offset*/
+ for (i=0; i<3; i++) {
+ v->co[i] += (BLI_drand()-0.5f)*FLT_EPSILON*50;
+ }
+
+ v->tmp.p = l;
+
+ if (lastv) {
+ BLI_addfilledge(lastv, v);
+ }
+
+ lastv = v;
+ if (!firstv)
+ firstv = v;
+ }
+
+ BLI_addfilledge(firstv, v);
+
+ /*mode 2 enables faster handling of tri/quads*/
+ BLI_edgefill(2);
+ for (sefa = fillfacebase.first; sefa; sefa=sefa->next) {
+ ls[0] = sefa->v1->tmp.p;
+ ls[1] = sefa->v2->tmp.p;
+ ls[2] = sefa->v3->tmp.p;
+
+ luvs[0] = CustomData_bmesh_get(&em->bm->ldata, ls[0]->head.data, CD_MLOOPUV);
+ luvs[1] = CustomData_bmesh_get(&em->bm->ldata, ls[1]->head.data, CD_MLOOPUV);
+ luvs[2] = CustomData_bmesh_get(&em->bm->ldata, ls[2]->head.data, CD_MLOOPUV);
+
+ vkeys[0] = (ParamKey)BM_GetIndex(ls[0]->v);
+ vkeys[1] = (ParamKey)BM_GetIndex(ls[1]->v);
+ vkeys[2] = (ParamKey)BM_GetIndex(ls[2]->v);
+
+ co[0] = ls[0]->v->co;
+ co[1] = ls[1]->v->co;
+ co[2] = ls[2]->v->co;
+
+ uv[0] = luvs[0]->uv;
+ uv[1] = luvs[1]->uv;
+ uv[2] = luvs[2]->uv;
+
+ pin[0] = (luvs[0]->flag & MLOOPUV_PINNED) != 0;
+ pin[1] = (luvs[1]->flag & MLOOPUV_PINNED) != 0;
+ pin[2] = (luvs[2]->flag & MLOOPUV_PINNED) != 0;
+
+ select[0] = uvedit_uv_selected(em, scene, ls[0]) != 0;
+ select[1] = uvedit_uv_selected(em, scene, ls[1]) != 0;
+ select[2] = uvedit_uv_selected(em, scene, ls[2]) != 0;
+
+ if (!p_face_exists(handle,vkeys,0,1,2))
+ param_face_add(handle, key, 3, vkeys, co, uv, pin, select);
}
- else
- nverts = 3;
- param_face_add(handle, key, nverts, vkeys, co, uv, pin, select);
+ BLI_end_edgefill();
}
if(!implicit) {
- for(eed= em->edges.first; eed; eed= eed->next) {
- if(eed->seam) {
+ BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+ if(BM_TestHFlag(eed, BM_SEAM)) {
ParamKey vkeys[2];
- vkeys[0] = (ParamKey)eed->v1->tmp.l;
- vkeys[1] = (ParamKey)eed->v2->tmp.l;
+ vkeys[0] = (ParamKey)BM_GetIndex(eed->v1);
+ vkeys[1] = (ParamKey)BM_GetIndex(eed->v2);
param_edge_set_seam(handle, vkeys);
}
}
@@ -274,7 +326,7 @@ static ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short imp
typedef struct MinStretch {
Scene *scene;
Object *obedit;
- EditMesh *em;
+ BMEditMesh *em;
ParamHandle *handle;
float blend;
double lasttime;
@@ -286,13 +338,12 @@ static int minimize_stretch_init(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
MinStretch *ms;
int fill_holes= RNA_boolean_get(op->ptr, "fill_holes");
short implicit= 1;
if(!uvedit_have_selection(scene, em, implicit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return 0;
}
@@ -332,7 +383,7 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, int interact
param_flush(ms->handle);
if(sa) {
- sprintf(str, "Minimize Stretch. Blend %.2f", ms->blend);
+ sprintf(str, "Minimize Stretch. Blend %.2f.", ms->blend);
ED_area_headerprint(sa, str);
}
@@ -473,12 +524,9 @@ void UV_OT_minimize_stretch(wmOperatorType *ot)
ot->poll= ED_operator_uvedit;
/* properties */
- RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes",
- "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry");
- RNA_def_float_factor(ot->srna, "blend", 0.0f, 0.0f, 1.0f, "Blend",
- "Blend factor between stretch minimized and original", 0.0f, 1.0f);
- RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations",
- "Number of iterations to run, 0 is unlimited when run interactively", 0, 100);
+ RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry");
+ RNA_def_float_factor(ot->srna, "blend", 0.0f, 0.0f, 1.0f, "Blend", "Blend factor between stretch minimized and original", 0.0f, 1.0f);
+ RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations", "Number of iterations to run, 0 is unlimited when run interactively", 0, 100);
}
/* ******************** Pack Islands operator **************** */
@@ -487,12 +535,11 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
ParamHandle *handle;
short implicit= 1;
if(!uvedit_have_selection(scene, em, implicit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
@@ -511,7 +558,6 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -527,8 +573,7 @@ void UV_OT_pack_islands(wmOperatorType *ot)
ot->poll= ED_operator_uvedit;
/* properties */
- RNA_def_float_factor(ot->srna, "margin", 0.0f, 0.0f, 1.0f, "Margin",
- "Space between islands", 0.0f, 1.0f);
+ RNA_def_float_factor(ot->srna, "margin", 0.0f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
}
/* ******************** Average Islands Scale operator **************** */
@@ -537,12 +582,11 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
ParamHandle *handle;
short implicit= 1;
if(!uvedit_have_selection(scene, em, implicit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
@@ -554,7 +598,6 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -576,19 +619,17 @@ static ParamHandle *liveHandle = NULL;
void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
short abf = scene->toolsettings->unwrapper == 0;
short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
if(!ED_uvedit_test(obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return;
}
liveHandle = construct_param_handle(scene, em, 0, fillholes, 0, 1);
param_lscm_begin(liveHandle, PARAM_TRUE, abf);
- BKE_mesh_end_editmesh(obedit->data, em);
}
void ED_uvedit_live_unwrap_re_solve(void)
@@ -619,9 +660,12 @@ void ED_uvedit_live_unwrap_end(short cancel)
#define POLAR_ZX 0
#define POLAR_ZY 1
-static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, Object *ob, EditMesh *em)
+static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result,
+ Object *ob, BMEditMesh *em)
{
- EditFace *efa;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
float min[3], max[3], *cursx;
int around= (v3d)? v3d->around: V3D_CENTER;
@@ -631,13 +675,12 @@ static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, Ob
case V3D_CENTER: /* bounding box center */
min[0]= min[1]= min[2]= 1e20f;
max[0]= max[1]= max[2]= -1e20f;
-
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- DO_MINMAX(efa->v1->co, min, max);
- DO_MINMAX(efa->v2->co, min, max);
- DO_MINMAX(efa->v3->co, min, max);
- if(efa->v4) DO_MINMAX(efa->v4->co, min, max);
+
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if(BM_TestHFlag(efa, BM_SELECT)) {
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ DO_MINMAX(l->v->co, min, max);
+ }
}
}
mid_v3_v3v3(result, min, max);
@@ -712,7 +755,7 @@ static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float
/* context checks are messy here, making it work in both 3d view and uv editor */
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
View3D *v3d= CTX_wm_view3d(C);
RegionView3D *rv3d= CTX_wm_region_view3d(C);
/* common operator properties */
@@ -739,7 +782,6 @@ static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float
else
uv_map_rotation_matrix(rotmat, rv3d, obedit, upangledeg, sideangledeg, radius);
- BKE_mesh_end_editmesh(obedit->data, em);
}
static void uv_transform_properties(wmOperatorType *ot, int radius)
@@ -765,14 +807,17 @@ static void uv_transform_properties(wmOperatorType *ot, int radius)
"Radius of the sphere or cylinder", 0.0001f, 100.0f);
}
-static void correct_uv_aspect(EditMesh *em)
+static void correct_uv_aspect(BMEditMesh *em)
{
- EditFace *efa= EM_get_actFace(em, 1);
- MTFace *tf;
+ BMFace *efa= BM_get_actFace(em->bm, 1);
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float scale, aspx= 1.0f, aspy=1.0f;
if(efa) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
}
@@ -782,30 +827,28 @@ static void correct_uv_aspect(EditMesh *em)
if(aspx > aspy) {
scale= aspy/aspx;
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- tf->uv[0][0]= ((tf->uv[0][0]-0.5f)*scale)+0.5f;
- tf->uv[1][0]= ((tf->uv[1][0]-0.5f)*scale)+0.5f;
- tf->uv[2][0]= ((tf->uv[2][0]-0.5f)*scale)+0.5f;
- if(efa->v4)
- tf->uv[3][0]= ((tf->uv[3][0]-0.5f)*scale)+0.5f;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if (!BM_TestHFlag(efa, BM_SELECT) || BM_TestHFlag(efa, BM_HIDDEN))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->uv[0] = ((luv->uv[0]-0.5)*scale)+0.5;
}
}
}
else {
scale= aspx/aspy;
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- tf->uv[0][1]= ((tf->uv[0][1]-0.5f)*scale)+0.5f;
- tf->uv[1][1]= ((tf->uv[1][1]-0.5f)*scale)+0.5f;
- tf->uv[2][1]= ((tf->uv[2][1]-0.5f)*scale)+0.5f;
- if(efa->v4)
- tf->uv[3][1]= ((tf->uv[3][1]-0.5f)*scale)+0.5f;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if (!BM_TestHFlag(efa, BM_SELECT)||BM_TestHFlag(efa, BM_HIDDEN))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv->uv[1] = ((luv->uv[1]-0.5)*scale)+0.5;
}
}
}
@@ -823,12 +866,13 @@ static void uv_map_clip_correct_properties(wmOperatorType *ot)
"Scale UV coordinates to bounds after unwrapping");
}
-static void uv_map_clip_correct(EditMesh *em, wmOperator *op)
+static void uv_map_clip_correct(BMEditMesh *em, wmOperator *op)
{
- EditFace *efa;
- MTFace *tf;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
float dx, dy, min[2], max[2];
- int b, nverts;
int correct_aspect= RNA_boolean_get(op->ptr, "correct_aspect");
int clip_to_bounds= RNA_boolean_get(op->ptr, "clip_to_bounds");
int scale_to_bounds= RNA_boolean_get(op->ptr, "scale_to_bounds");
@@ -840,16 +884,13 @@ static void uv_map_clip_correct(EditMesh *em, wmOperator *op)
if(scale_to_bounds) {
INIT_MINMAX2(min, max);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- DO_MINMAX2(tf->uv[0], min, max);
- DO_MINMAX2(tf->uv[1], min, max);
- DO_MINMAX2(tf->uv[2], min, max);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
- if(efa->v4)
- DO_MINMAX2(tf->uv[3], min, max);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ DO_MINMAX2(luv->uv, min, max);
}
}
@@ -862,31 +903,28 @@ static void uv_map_clip_correct(EditMesh *em, wmOperator *op)
if(dy > 0.0f)
dy= 1.0f/dy;
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- nverts= (efa->v4)? 4: 3;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
- for(b=0; b<nverts; b++) {
- tf->uv[b][0]= (tf->uv[b][0]-min[0])*dx;
- tf->uv[b][1]= (tf->uv[b][1]-min[1])*dy;
- }
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ luv->uv[0] = (luv->uv[0]-min[0])*dx;
+ luv->uv[1] = (luv->uv[1]-min[1])*dy;
}
}
}
else if(clip_to_bounds) {
/* clipping and wrapping */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- nverts= (efa->v4)? 4: 3;
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
- for(b=0; b<nverts; b++) {
- CLAMP(tf->uv[b][0], 0.0f, 1.0f);
- CLAMP(tf->uv[b][1], 0.0f, 1.0f);
- }
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ CLAMP(luv->uv[0], 0.0f, 1.0f);
+ CLAMP(luv->uv[1], 0.0f, 1.0f);
}
}
}
@@ -897,7 +935,7 @@ static void uv_map_clip_correct(EditMesh *em, wmOperator *op)
/* assumes UV layer is checked, doesn't run update funcs */
void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
{
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
ParamHandle *handle;
const short fill_holes= scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
@@ -915,26 +953,21 @@ void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
param_flush(handle);
param_delete(handle);
-
- BKE_mesh_end_editmesh(obedit->data, em);
}
static int unwrap_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
int method = RNA_enum_get(op->ptr, "method");
int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
int correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
short implicit= 0;
if(!uvedit_have_selection(scene, em, implicit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
- return 0;
+ return OPERATOR_CANCELLED;
}
-
- BKE_mesh_end_editmesh(obedit->data, em);
/* add uvs if they don't exist yet */
if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
@@ -991,17 +1024,18 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
Camera *camera= NULL;
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- ARegion *ar= CTX_wm_region(C);
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ ARegion *ar = CTX_wm_region(C);
View3D *v3d= CTX_wm_view3d(C);
- RegionView3D *rv3d= ar->regiondata;
- EditFace *efa;
- MTFace *tf;
+ RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
float rotmat[4][4];
/* add uvs if they don't exist yet */
if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
@@ -1011,17 +1045,15 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
}
if(RNA_boolean_get(op->ptr, "orthographic")) {
- uv_map_rotation_matrix(rotmat, ar->regiondata, obedit, 90.0f, 0.0f, 1.0f);
+ uv_map_rotation_matrix(rotmat, rv3d, obedit, 90.0f, 0.0f, 1.0f);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- project_from_view_ortho(tf->uv[0], efa->v1->co, rotmat);
- project_from_view_ortho(tf->uv[1], efa->v2->co, rotmat);
- project_from_view_ortho(tf->uv[2], efa->v3->co, rotmat);
- if(efa->v4)
- project_from_view_ortho(tf->uv[3], efa->v4->co, rotmat);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ project_from_view_ortho(luv->uv, l->v->co, rotmat);
}
}
}
@@ -1029,15 +1061,13 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
struct UvCameraInfo *uci= project_camera_info(v3d->camera, obedit->obmat, scene->r.xsch, scene->r.ysch);
if(uci) {
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- project_from_camera(tf->uv[0], efa->v1->co, uci);
- project_from_camera(tf->uv[1], efa->v2->co, uci);
- project_from_camera(tf->uv[2], efa->v3->co, uci);
- if(efa->v4)
- project_from_camera(tf->uv[3], efa->v4->co, uci);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ project_from_camera(luv->uv, l->v->co, uci);
}
}
@@ -1047,15 +1077,13 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
else {
copy_m4_m4(rotmat, obedit->obmat);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
- project_from_view(tf->uv[0], efa->v1->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
- project_from_view(tf->uv[1], efa->v2->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
- project_from_view(tf->uv[2], efa->v3->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
- if(efa->v4)
- project_from_view(tf->uv[3], efa->v4->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ project_from_view(luv->uv, l->v->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
}
}
}
@@ -1065,7 +1093,6 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1101,38 +1128,74 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MLoopUV *luv;
+ BLI_array_declare(uvs);
+ float **uvs = NULL;
+ int i;
/* add uvs if they don't exist yet */
if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
+
+ BLI_array_empty(uvs);
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ BLI_array_growone(uvs);
- tf->uv[0][0]= 0.0f;
- tf->uv[0][1]= 0.0f;
-
- tf->uv[1][0]= 1.0f;
- tf->uv[1][1]= 0.0f;
+ uvs[i++] = luv->uv;
+ }
+
+ if (i == 3) {
+ uvs[0][0] = 0.0;
+ uvs[0][1] = 0.0;
- tf->uv[2][0]= 1.0f;
- tf->uv[2][1]= 1.0f;
+ uvs[1][0] = 1.0;
+ uvs[1][1] = 0.0;
+
+ uvs[2][0] = 1.0;
+ uvs[2][1] = 1.0;
+ } else if (i == 4) {
+ uvs[0][0] = 0.0;
+ uvs[0][1] = 0.0;
- tf->uv[3][0]= 0.0f;
- tf->uv[3][1]= 1.0f;
+ uvs[1][0] = 1.0;
+ uvs[1][1] = 0.0;
+
+ uvs[2][0] = 1.0;
+ uvs[2][1] = 1.0;
+
+ uvs[3][0] = 0.0;
+ uvs[3][1] = 1.0;
+ /*make sure we ignore 2-sided faces*/
+ } else if (i > 2) {
+ float fac = 0.0f, dfac = 1.0f / (float)efa->len;
+
+ dfac *= M_PI*2;
+
+ for (i=0; i<efa->len; i++) {
+ uvs[i][0] = sin(fac);
+ uvs[i][1] = cos(fac);
+
+ fac += dfac;
+ }
}
}
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ BLI_array_free(uvs);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1164,55 +1227,71 @@ static void uv_sphere_project(float target[2], float source[3], float center[3],
target[0] -= 1.0f;
}
-static void uv_map_mirror(EditFace *efa, MTFace *tf)
+static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *UNUSED(tf))
{
+ BMLoop *l;
+ BMIter liter;
+ MLoopUV *luv;
+ BLI_array_declare(uvs);
+ float **uvs = NULL;
float dx;
- int nverts, i, mi;
+ int i, mi;
- nverts= (efa->v4)? 4: 3;
+ i = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ BLI_array_growone(uvs);
+
+ uvs[i] = luv->uv;
+ i++;
+ }
mi = 0;
- for(i=1; i<nverts; i++)
- if(tf->uv[i][0] > tf->uv[mi][0])
+ for(i=1; i<efa->len; i++)
+ if(uvs[i][0] > uvs[mi][0])
mi = i;
- for(i=0; i<nverts; i++) {
+ for(i=0; i<efa->len; i++) {
if(i != mi) {
- dx = tf->uv[mi][0] - tf->uv[i][0];
- if(dx > 0.5f) tf->uv[i][0] += 1.0f;
+ dx = uvs[mi][0] - uvs[i][0];
+ if(dx > 0.5f) uvs[i][0] += 1.0f;
}
}
+
+ BLI_array_free(uvs);
}
static int sphere_project_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float center[3], rotmat[4][4];
/* add uvs if they don't exist yet */
if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
uv_map_transform(C, op, center, rotmat);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
- uv_sphere_project(tf->uv[0], efa->v1->co, center, rotmat);
- uv_sphere_project(tf->uv[1], efa->v2->co, center, rotmat);
- uv_sphere_project(tf->uv[2], efa->v3->co, center, rotmat);
- if(efa->v4)
- uv_sphere_project(tf->uv[3], efa->v4->co, center, rotmat);
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- uv_map_mirror(efa, tf);
+ uv_sphere_project(luv->uv, l->v->co, center, rotmat);
}
+
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ uv_map_mirror(em, efa, tf);
}
uv_map_clip_correct(em, op);
@@ -1220,7 +1299,6 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1260,31 +1338,33 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float center[3], rotmat[4][4];
/* add uvs if they don't exist yet */
if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
uv_map_transform(C, op, center, rotmat);
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
- uv_cylinder_project(tf->uv[0], efa->v1->co, center, rotmat);
- uv_cylinder_project(tf->uv[1], efa->v2->co, center, rotmat);
- uv_cylinder_project(tf->uv[2], efa->v3->co, center, rotmat);
- if(efa->v4)
- uv_cylinder_project(tf->uv[3], efa->v4->co, center, rotmat);
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
+
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- uv_map_mirror(efa, tf);
+ uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
}
+
+ uv_map_mirror(em, efa, tf);
}
uv_map_clip_correct(em, op);
@@ -1292,7 +1372,6 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1318,15 +1397,17 @@ static int cube_project_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
- EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
- EditFace *efa;
- MTFace *tf;
+ BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ MTexPoly *tf;
+ MLoopUV *luv;
float no[3], cube_size, *loc, dx, dy;
int cox, coy;
/* add uvs if they don't exist yet */
if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_CANCELLED;
}
@@ -1336,41 +1417,40 @@ static int cube_project_exec(bContext *C, wmOperator *op)
/* choose x,y,z axis for projection depending on the largest normal
* component, but clusters all together around the center of map. */
- for(efa= em->faces.first; efa; efa= efa->next) {
- if(efa->f & SELECT) {
- tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
- normal_tri_v3( no,efa->v1->co, efa->v2->co, efa->v3->co);
-
- no[0]= fabs(no[0]);
- no[1]= fabs(no[1]);
- no[2]= fabs(no[2]);
-
- cox=0; coy= 1;
- if(no[2]>=no[0] && no[2]>=no[1]);
- else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2;
- else { cox= 1; coy= 2; }
+ BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+ int first=1;
+
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ if (!BM_TestHFlag(efa, BM_SELECT))
+ continue;
+
+ VECCOPY(no, efa->no);
+
+ no[0]= fabs(no[0]);
+ no[1]= fabs(no[1]);
+ no[2]= fabs(no[2]);
+
+ cox=0; coy= 1;
+ if(no[2]>=no[0] && no[2]>=no[1]);
+ else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2;
+ else { cox= 1; coy= 2; }
+
+ dx = dy = 0;
+ BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+ luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ luv->uv[0] = 0.5f+0.5f*cube_size*(loc[cox] + l->v->co[cox]);
+ luv->uv[1] = 0.5f+0.5f*cube_size*(loc[coy] + l->v->co[coy]);
- tf->uv[0][0]= 0.5f+0.5f*cube_size*(loc[cox] + efa->v1->co[cox]);
- tf->uv[0][1]= 0.5f+0.5f*cube_size*(loc[coy] + efa->v1->co[coy]);
- dx = floor(tf->uv[0][0]);
- dy = floor(tf->uv[0][1]);
- tf->uv[0][0] -= dx;
- tf->uv[0][1] -= dy;
- tf->uv[1][0]= 0.5f+0.5f*cube_size*(loc[cox] + efa->v2->co[cox]);
- tf->uv[1][1]= 0.5f+0.5f*cube_size*(loc[coy] + efa->v2->co[coy]);
- tf->uv[1][0] -= dx;
- tf->uv[1][1] -= dy;
- tf->uv[2][0]= 0.5f+0.5f*cube_size*(loc[cox] + efa->v3->co[cox]);
- tf->uv[2][1]= 0.5f+0.5f*cube_size*(loc[coy] + efa->v3->co[coy]);
- tf->uv[2][0] -= dx;
- tf->uv[2][1] -= dy;
-
- if(efa->v4) {
- tf->uv[3][0]= 0.5f+0.5f*cube_size*(loc[cox] + efa->v4->co[cox]);
- tf->uv[3][1]= 0.5f+0.5f*cube_size*(loc[coy] + efa->v4->co[coy]);
- tf->uv[3][0] -= dx;
- tf->uv[3][1] -= dy;
+ if (first) {
+ dx = floor(luv->uv[0]);
+ dy = floor(luv->uv[1]);
+ first = 0;
}
+
+
+ luv->uv[0] -= dx;
+ luv->uv[1] -= dy;
}
}
@@ -1379,7 +1459,6 @@ static int cube_project_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
- BKE_mesh_end_editmesh(obedit->data, em);
return OPERATOR_FINISHED;
}
@@ -1395,7 +1474,6 @@ void UV_OT_cube_project(wmOperatorType *ot)
ot->poll= ED_operator_uvmap;
/* properties */
- RNA_def_float(ot->srna, "cube_size", 1.0f, 0.0f, FLT_MAX, "Cube Size",
- "Size of the cube to project on", 0.001f, 100.0f);
+ RNA_def_float(ot->srna, "cube_size", 1.0f, 0.0f, FLT_MAX, "Cube Size", "Size of the cube to project on", 0.001f, 100.0f);
uv_map_clip_correct_properties(ot);
}
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index d833fb5eb04..0e877b2c2b9 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -398,8 +398,8 @@ GPUDrawObject *GPU_drawobject_new( DerivedMesh *dm )
int points_per_mat[MAX_MATERIALS];
int i, curmat, curpoint, totface;
- mface = dm->getFaceArray(dm);
- totface= dm->getNumFaces(dm);
+ mface = dm->getTessFaceArray(dm);
+ totface= dm->getNumTessFaces(dm);
/* get the number of points used by each material, treating
each quad as two triangles */
@@ -576,9 +576,9 @@ static void GPU_buffer_copy_vertex(DerivedMesh *dm, float *varray, int *index, i
int i, j, start, totface;
mvert = dm->getVertArray(dm);
- f = dm->getFaceArray(dm);
+ f = dm->getTessFaceArray(dm);
- totface= dm->getNumFaces(dm);
+ totface= dm->getNumTessFaces(dm);
for(i = 0; i < totface; i++, f++) {
start = index[mat_orig_to_new[f->mat_nr]];
@@ -613,11 +613,11 @@ static void GPU_buffer_copy_normal(DerivedMesh *dm, float *varray, int *index, i
int start;
float f_no[3];
- float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
+ float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
MVert *mvert = dm->getVertArray(dm);
- MFace *f = dm->getFaceArray(dm);
+ MFace *f = dm->getTessFaceArray(dm);
- totface= dm->getNumFaces(dm);
+ totface= dm->getNumTessFaces(dm);
for(i = 0; i < totface; i++, f++) {
const int smoothnormal = (f->flag & ME_SMOOTH);
@@ -678,9 +678,9 @@ static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int *
if(!(mtface = DM_get_face_data_layer(dm, CD_MTFACE)))
return;
- f = dm->getFaceArray(dm);
+ f = dm->getTessFaceArray(dm);
- totface = dm->getNumFaces(dm);
+ totface = dm->getNumTessFaces(dm);
for(i = 0; i < totface; i++, f++) {
start = index[mat_orig_to_new[f->mat_nr]];
@@ -706,9 +706,9 @@ static void GPU_buffer_copy_color3(DerivedMesh *dm, float *varray_, int *index,
int i, totface;
unsigned char *varray = (unsigned char *)varray_;
unsigned char *mcol = (unsigned char *)user;
- MFace *f = dm->getFaceArray(dm);
+ MFace *f = dm->getTessFaceArray(dm);
- totface= dm->getNumFaces(dm);
+ totface= dm->getNumTessFaces(dm);
for(i=0; i < totface; i++, f++) {
int start = index[mat_orig_to_new[f->mat_nr]];
@@ -741,9 +741,9 @@ static void GPU_buffer_copy_mcol(DerivedMesh *dm, float *varray_, int *index, in
int i, totface;
unsigned char *varray = (unsigned char *)varray_;
unsigned char *mcol = (unsigned char *)user;
- MFace *f = dm->getFaceArray(dm);
+ MFace *f = dm->getTessFaceArray(dm);
- totface= dm->getNumFaces(dm);
+ totface= dm->getNumTessFaces(dm);
for(i=0; i < totface; i++, f++) {
int start = index[mat_orig_to_new[f->mat_nr]];
@@ -788,7 +788,7 @@ static void GPU_buffer_copy_uvedge(DerivedMesh *dm, float *varray, int *UNUSED(i
for(i = 0; i < dm->numFaceData; i++, tf++) {
MFace mf;
- dm->getFace(dm,i,&mf);
+ dm->getTessFace(dm,i,&mf);
copy_v2_v2(&varray[j],tf->uv[0]);
copy_v2_v2(&varray[j+2],tf->uv[1]);
diff --git a/source/blender/ikplugin/CMakeLists.txt b/source/blender/ikplugin/CMakeLists.txt
index 87b0c6c671a..bde6f78df8b 100644
--- a/source/blender/ikplugin/CMakeLists.txt
+++ b/source/blender/ikplugin/CMakeLists.txt
@@ -49,7 +49,7 @@ set(SRC
if(WITH_IK_ITASC)
add_definitions(-DWITH_IK_ITASC)
list(APPEND INC
- ../../../extern/Eigen3
+ ../../../extern/Eigen2
../../../intern/itasc
)
list(APPEND SRC
@@ -57,8 +57,4 @@ if(WITH_IK_ITASC)
)
endif()
-if(WIN32)
- add_definitions(-DEIGEN_DONT_ALIGN_STATICALLY)
-endif()
-
blender_add_lib(bf_ikplugin "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/ikplugin/SConscript b/source/blender/ikplugin/SConscript
index 4cff3399fdc..f60c42f8dc9 100644
--- a/source/blender/ikplugin/SConscript
+++ b/source/blender/ikplugin/SConscript
@@ -4,11 +4,8 @@ defs = []
sources = env.Glob('intern/*.c') + env.Glob('intern/*.cpp')
incs = '#/intern/guardedalloc #/intern/iksolver/extern ../makesdna ../blenlib'
-incs += ' ../blenkernel ../include ../ikplugin #/intern/itasc #/extern/Eigen3'
+incs += ' ../blenkernel ../include ../ikplugin #/intern/itasc #/extern/Eigen2'
defs.append('WITH_IK_ITASC')
-if env['PLATFORM'] == 'win32':
- defs.append('EIGEN_DONT_ALIGN_STATICALLY')
-
env.BlenderLib ( 'bf_ikplugin', sources, Split(incs), defs, libtype=['core','player'], priority=[180, 190] )
diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt
index a03d6ce280d..35c54482f9f 100644
--- a/source/blender/imbuf/CMakeLists.txt
+++ b/source/blender/imbuf/CMakeLists.txt
@@ -23,6 +23,11 @@
#
# ***** END GPL LICENSE BLOCK *****
+if(WITH_CODEC_FFMPEG)
+ # FFMPEG gives warnigns which are hard to avoid across multiple versions.
+ remove_strict_flags()
+endif()
+
set(INC
.
../avi
@@ -56,7 +61,6 @@ set(SRC
intern/md5.c
intern/metadata.c
intern/module.c
- intern/moviecache.c
intern/png.c
intern/readimage.c
intern/rectop.c
@@ -70,7 +74,6 @@ set(SRC
IMB_imbuf.h
IMB_imbuf_types.h
- IMB_moviecache.h
IMB_thumbs.h
intern/IMB_allocimbuf.h
intern/IMB_anim.h
@@ -155,12 +158,6 @@ if(WITH_CODEC_FFMPEG)
${FFMPEG_INCLUDE_DIRS}
)
add_definitions(-DWITH_FFMPEG)
-
- remove_strict_flags_file(
- intern/indexer.c
- intern/util.c
- intern/anim_movie.c
- )
endif()
if(WITH_IMAGE_DDS)
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 5f03ca9ba28..e57130c7c35 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -137,6 +137,19 @@ struct ImBuf * IMB_makeSingleUser(struct ImBuf *ibuf);
*
* @attention Defined in allocimbuf.c
*/
+void IMB_cache_limiter_insert(struct ImBuf *i);
+void IMB_cache_limiter_unmanage(struct ImBuf *i);
+void IMB_cache_limiter_touch(struct ImBuf *i);
+void IMB_cache_limiter_ref(struct ImBuf *i);
+void IMB_cache_limiter_unref(struct ImBuf *i);
+int IMB_cache_limiter_get_refcount(struct ImBuf *i);
+
+void IMB_free_cache_limiter(void);
+
+/**
+ *
+ * @attention Defined in allocimbuf.c
+ */
struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1);
/**
diff --git a/source/blender/imbuf/IMB_moviecache.h b/source/blender/imbuf/IMB_moviecache.h
deleted file mode 100644
index 309c6ee550e..00000000000
--- a/source/blender/imbuf/IMB_moviecache.h
+++ /dev/null
@@ -1,56 +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 *****
- */
-
-#ifndef IMB_MOVIECACHE_H
-#define IMB_MOVIECACHE_H
-
-/** \file IMB_moviecache.h
- * \ingroup imbuf
- * \author Sergey Sharybin
- */
-
-#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
-
-/* Cache system for movie data - now supports stoting ImBufs only
- Supposed to provide unified cache system for movie clips, sequencer and
- other movie-related areas */
-
-struct ImBuf;
-struct MovieCache;
-
-typedef void (*MovieCacheGetKeyDataFP) (void *userkey, int *framenr, int *proxy, int *render_flags);
-
-void IMB_moviecache_init(void);
-void IMB_moviecache_destruct(void);
-
-struct MovieCache *IMB_moviecache_create(int keysize, GHashHashFP hashfp, GHashCmpFP cmpfp, MovieCacheGetKeyDataFP getdatafp);
-void IMB_moviecache_put(struct MovieCache *cache, void *userkey, struct ImBuf *ibuf);
-struct ImBuf* IMB_moviecache_get(struct MovieCache *cache, void *userkey);
-void IMB_moviecache_free(struct MovieCache *cache);
-void IMB_moviecache_get_cache_segments(struct MovieCache *cache, int proxy, int render_flags, int *totseg_r, int **points_r);
-
-#endif
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index 1d82c862dbd..077d907dda0 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -164,9 +164,8 @@ void IMB_freeImBuf(ImBuf *ibuf)
IMB_freezbufImBuf(ibuf);
IMB_freezbuffloatImBuf(ibuf);
freeencodedbufferImBuf(ibuf);
+ IMB_cache_limiter_unmanage(ibuf);
IMB_metadata_free(ibuf);
- if (ibuf->dds_data.data != NULL)
- free(ibuf->dds_data.data);
MEM_freeN(ibuf);
}
}
@@ -468,7 +467,60 @@ static MEM_CacheLimiterC **get_imbuf_cache_limiter(void)
static MEM_CacheLimiterC *c = NULL;
if(!c)
- c = new_MEM_CacheLimiter(imbuf_cache_destructor, NULL);
+ c = new_MEM_CacheLimiter(imbuf_cache_destructor);
return &c;
}
+
+void IMB_free_cache_limiter(void)
+{
+ delete_MEM_CacheLimiter(*get_imbuf_cache_limiter());
+ *get_imbuf_cache_limiter() = NULL;
+}
+
+void IMB_cache_limiter_insert(ImBuf *i)
+{
+ if(!i->c_handle) {
+ i->c_handle = MEM_CacheLimiter_insert(
+ *get_imbuf_cache_limiter(), i);
+ MEM_CacheLimiter_ref(i->c_handle);
+ MEM_CacheLimiter_enforce_limits(
+ *get_imbuf_cache_limiter());
+ MEM_CacheLimiter_unref(i->c_handle);
+ }
+}
+
+void IMB_cache_limiter_unmanage(ImBuf *i)
+{
+ if(i->c_handle) {
+ MEM_CacheLimiter_unmanage(i->c_handle);
+ i->c_handle = NULL;
+ }
+}
+
+void IMB_cache_limiter_touch(ImBuf *i)
+{
+ if(i->c_handle)
+ MEM_CacheLimiter_touch(i->c_handle);
+}
+
+void IMB_cache_limiter_ref(ImBuf *i)
+{
+ if(i->c_handle)
+ MEM_CacheLimiter_ref(i->c_handle);
+}
+
+void IMB_cache_limiter_unref(ImBuf *i)
+{
+ if(i->c_handle)
+ MEM_CacheLimiter_unref(i->c_handle);
+}
+
+int IMB_cache_limiter_get_refcount(ImBuf *i)
+{
+ if(i->c_handle)
+ return MEM_CacheLimiter_get_refcount(i->c_handle);
+
+ return 0;
+}
+
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 3a94c79f48d..242d7dcb700 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -452,7 +452,7 @@ static int round_up(int x, int mod)
static struct proxy_output_ctx * alloc_proxy_output_ffmpeg(
struct anim * anim,
AVStream * st, int proxy_size, int width, int height,
- int UNUSED(quality))
+ int quality)
{
struct proxy_output_ctx * rv = MEM_callocN(
sizeof(struct proxy_output_ctx), "alloc_proxy_output");
diff --git a/source/blender/imbuf/intern/module.c b/source/blender/imbuf/intern/module.c
index 55a29333620..f787a6c777e 100644
--- a/source/blender/imbuf/intern/module.c
+++ b/source/blender/imbuf/intern/module.c
@@ -37,6 +37,7 @@ void IMB_init(void)
void IMB_exit(void)
{
+ IMB_free_cache_limiter();
imb_tile_cache_exit();
imb_filetypes_exit();
}
diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c
deleted file mode 100644
index 7492b6aec44..00000000000
--- a/source/blender/imbuf/intern/moviecache.c
+++ /dev/null
@@ -1,382 +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,
- * Peter Schlaile
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/moviecache.c
- * \ingroup bke
- */
-
-#include <stdlib.h> /* for qsort */
-#include <memory.h>
-
-#include "MEM_guardedalloc.h"
-#include "MEM_CacheLimiterC-Api.h"
-
-#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
-#include "BLI_mempool.h"
-
-#include "IMB_moviecache.h"
-
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-
-static MEM_CacheLimiterC *limitor= NULL;
-
-typedef struct MovieCache {
- GHash *hash;
- GHashHashFP hashfp;
- GHashCmpFP cmpfp;
- MovieCacheGetKeyDataFP getdatafp;
-
- struct BLI_mempool *keys_pool;
- struct BLI_mempool *items_pool;
- struct BLI_mempool *userkeys_pool;
-
- int keysize;
- unsigned long curtime;
-
- int totseg, *points, proxy, render_flags; /* for visual statistics optimization */
- int pad;
-} MovieCache;
-
-typedef struct MovieCacheKey {
- MovieCache *cache_owner;
- void *userkey;
-} MovieCacheKey;
-
-typedef struct MovieCacheItem {
- MovieCache *cache_owner;
- ImBuf *ibuf;
- MEM_CacheLimiterHandleC * c_handle;
- unsigned long last_access;
-} MovieCacheItem;
-
-static unsigned int moviecache_hashhash(const void *keyv)
-{
- MovieCacheKey *key= (MovieCacheKey*)keyv;
-
- return key->cache_owner->hashfp(key->userkey);
-}
-
-static int moviecache_hashcmp(const void *av, const void *bv)
-{
- const MovieCacheKey *a= (MovieCacheKey*)av;
- const MovieCacheKey *b= (MovieCacheKey*)bv;
-
- return a->cache_owner->cmpfp(a->userkey, b->userkey);
-}
-
-static void moviecache_keyfree(void *val)
-{
- MovieCacheKey *key= (MovieCacheKey*)val;
-
- BLI_mempool_free(key->cache_owner->keys_pool, key);
-}
-
-static void moviecache_valfree(void *val)
-{
- MovieCacheItem *item= (MovieCacheItem*)val;
-
- if (item->ibuf) {
- MEM_CacheLimiter_unmanage(item->c_handle);
- IMB_freeImBuf(item->ibuf);
- }
-
- BLI_mempool_free(item->cache_owner->items_pool, item);
-}
-
-static void check_unused_keys(MovieCache *cache)
-{
- GHashIterator *iter;
-
- iter= BLI_ghashIterator_new(cache->hash);
- while(!BLI_ghashIterator_isDone(iter)) {
- MovieCacheKey *key= BLI_ghashIterator_getKey(iter);
- MovieCacheItem *item= BLI_ghashIterator_getValue(iter);
-
- BLI_ghashIterator_step(iter);
-
- if(!item->ibuf)
- BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree);
- }
-
- BLI_ghashIterator_free(iter);
-}
-
-static int compare_int(const void *av, const void *bv)
-{
- const int *a= (int *)av;
- const int *b= (int *)bv;
- return *a-*b;
-}
-
-static void IMB_moviecache_destructor(void *p)
-{
- MovieCacheItem *item= (MovieCacheItem *) p;
-
- if (item && item->ibuf) {
- IMB_freeImBuf(item->ibuf);
-
- item->ibuf= NULL;
- item->c_handle= NULL;
- }
-}
-
-/* approximate size of ImBuf in memory */
-static intptr_t IMB_get_size_in_memory(ImBuf *ibuf)
-{
- int a;
- intptr_t size= 0, channel_size= 0;
-
- size+= sizeof(ImBuf);
-
- if(ibuf->rect)
- channel_size+= sizeof(char);
-
- if(ibuf->rect_float)
- channel_size+= sizeof(float);
-
- size+= channel_size*ibuf->x*ibuf->y*ibuf->channels;
-
- if(ibuf->miptot) {
- for(a= 0; a<ibuf->miptot; a++) {
- if(ibuf->mipmap[a])
- size+= IMB_get_size_in_memory(ibuf->mipmap[a]);
- }
- }
-
- if(ibuf->tiles) {
- size+= sizeof(unsigned int)*ibuf->ytiles*ibuf->xtiles;
- }
-
- return size;
-}
-
-static intptr_t get_item_size (void *p)
-{
- intptr_t size= sizeof(MovieCacheItem);
- MovieCacheItem *item= (MovieCacheItem *) p;
-
- if(item->ibuf)
- size+= IMB_get_size_in_memory(item->ibuf);
-
- return size;
-}
-
-void IMB_moviecache_init(void)
-{
- limitor= new_MEM_CacheLimiter(IMB_moviecache_destructor, get_item_size);
-}
-
-void IMB_moviecache_destruct(void)
-{
- if(limitor)
- delete_MEM_CacheLimiter(limitor);
-}
-
-struct MovieCache *IMB_moviecache_create(int keysize, GHashHashFP hashfp, GHashCmpFP cmpfp,
- MovieCacheGetKeyDataFP getdatafp)
-{
- MovieCache *cache;
-
- cache= MEM_callocN(sizeof(MovieCache), "MovieCache");
- cache->keys_pool= BLI_mempool_create(sizeof(MovieCacheKey), 64, 64, 0);
- cache->items_pool= BLI_mempool_create(sizeof(MovieCacheItem), 64, 64, 0);
- cache->userkeys_pool= BLI_mempool_create(keysize, 64, 64, 0);
- cache->hash= BLI_ghash_new(moviecache_hashhash, moviecache_hashcmp, "MovieClip ImBuf cache hash");
-
- cache->keysize= keysize;
- cache->hashfp= hashfp;
- cache->cmpfp= cmpfp;
- cache->getdatafp= getdatafp;
- cache->proxy= -1;
-
- return cache;
-}
-
-void IMB_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf)
-{
- MovieCacheKey *key;
- MovieCacheItem *item;
-
- if(!limitor)
- IMB_moviecache_init();
-
- IMB_refImBuf(ibuf);
-
- key= BLI_mempool_alloc(cache->keys_pool);
- key->cache_owner= cache;
- key->userkey= BLI_mempool_alloc(cache->userkeys_pool);;
- memcpy(key->userkey, userkey, cache->keysize);
-
- item= BLI_mempool_alloc(cache->items_pool);
- item->ibuf= ibuf;
- item->cache_owner= cache;
- item->last_access= cache->curtime++;
- item->c_handle= NULL;
-
- BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree);
- BLI_ghash_insert(cache->hash, key, item);
-
- item->c_handle= MEM_CacheLimiter_insert(limitor, item);
-
- MEM_CacheLimiter_ref(item->c_handle);
- MEM_CacheLimiter_enforce_limits(limitor);
- MEM_CacheLimiter_unref(item->c_handle);
-
- /* cache limiter can't remove unused keys which points to destoryed values */
- check_unused_keys(cache);
-
- if(cache->points) {
- MEM_freeN(cache->points);
- cache->points= NULL;
- }
-}
-
-ImBuf* IMB_moviecache_get(MovieCache *cache, void *userkey)
-{
- MovieCacheKey key;
- MovieCacheItem *item;
-
- key.cache_owner= cache;
- key.userkey= userkey;
- item= (MovieCacheItem*)BLI_ghash_lookup(cache->hash, &key);
-
- if(item) {
- item->last_access= cache->curtime++;
-
- if(item->ibuf) {
- MEM_CacheLimiter_touch(item->c_handle);
- IMB_refImBuf(item->ibuf);
-
- return item->ibuf;
- }
- }
-
- return NULL;
-}
-
-void IMB_moviecache_free(MovieCache *cache)
-{
- BLI_ghash_free(cache->hash, moviecache_keyfree, moviecache_valfree);
-
- BLI_mempool_destroy(cache->keys_pool);
- BLI_mempool_destroy(cache->items_pool);
- BLI_mempool_destroy(cache->userkeys_pool);
-
- if(cache->points)
- MEM_freeN(cache->points);
-
- MEM_freeN(cache);
-}
-
-/* get segments of cached frames. useful for debugging cache policies */
-void IMB_moviecache_get_cache_segments(MovieCache *cache, int proxy, int render_flags, int *totseg_r, int **points_r)
-{
- *totseg_r= 0;
- *points_r= NULL;
-
- if(!cache->getdatafp)
- return;
-
- if(cache->proxy!=proxy || cache->render_flags!=render_flags) {
- if(cache->points)
- MEM_freeN(cache->points);
-
- cache->points= NULL;
- }
-
- if(cache->points) {
- *totseg_r= cache->totseg;
- *points_r= cache->points;
- } else {
- int totframe= BLI_ghash_size(cache->hash);
- int *frames= MEM_callocN(totframe*sizeof(int), "movieclip cache frames");
- int a, totseg= 0;
- GHashIterator *iter;
-
- iter= BLI_ghashIterator_new(cache->hash);
- a= 0;
- while(!BLI_ghashIterator_isDone(iter)) {
- MovieCacheKey *key= BLI_ghashIterator_getKey(iter);
- MovieCacheItem *item= BLI_ghashIterator_getValue(iter);
- int framenr, curproxy, curflags;
-
- if(item->ibuf) {
- cache->getdatafp(key->userkey, &framenr, &curproxy, &curflags);
-
- if(curproxy==proxy && curflags==render_flags)
- frames[a++]= framenr;
- }
-
- BLI_ghashIterator_step(iter);
- }
-
- BLI_ghashIterator_free(iter);
-
- qsort(frames, totframe, sizeof(int), compare_int);
-
- /* count */
- for(a= 0; a<totframe; a++) {
- if(a && frames[a]-frames[a-1]!=1)
- totseg++;
-
- if(a==totframe-1)
- totseg++;
- }
-
- if(totseg) {
- int b, *points;
-
- points= MEM_callocN(2*sizeof(int)*totseg, "movieclip cache segments");
-
- /* fill */
- for(a= 0, b= 0; a<totframe; a++) {
- if(a==0)
- points[b++]= frames[a];
-
- if(a && frames[a]-frames[a-1]!=1) {
- points[b++]= frames[a-1];
- points[b++]= frames[a];
- }
-
- if(a==totframe-1)
- points[b++]= frames[a];
- }
-
- *totseg_r= totseg;
- *points_r= points;
-
- cache->totseg= totseg;
- cache->points= points;
- cache->proxy= proxy;
- cache->render_flags= render_flags;
- }
-
- MEM_freeN(frames);
- }
-}
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index d2c7d49e5f9..560870a2d30 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -116,13 +116,7 @@ typedef struct Library {
ID *idblock;
struct FileData *filedata;
char name[240]; /* path name used for reading, can be relative and edited in the outliner */
- char filepath[240]; /* absolute filepath, this is only for convenience,
- * 'name' is the real path used on file read but in
- * some cases its useful to access the absolute one,
- * This is set on file read.
- * Use BKE_library_filepath_set() rather than
- * setting 'name' directly and it will be kepk in
- * sync - campbell */
+ char filepath[240]; /* temp. absolute filepath, only used while reading */
int tot, pad; /* tot, idblock and filedata are only fo read and write */
struct Library *parent; /* set for indirectly linked libs, used in the outliner and while reading */
} Library;
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index d98e5200d21..b5666a4dc37 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -45,7 +45,7 @@ typedef struct CustomDataLayer {
int active_rnd; /* number of the layer to render*/
int active_clone; /* number of the layer to render*/
int active_mask; /* number of the layer to render*/
- char pad[4];
+ int uid; /*shape keyblock unique id reference*/
char name[32]; /* layer name */
void *data; /* layer data */
} CustomDataLayer;
@@ -59,6 +59,7 @@ typedef struct CustomDataExternal {
* layers, each with a data type (e.g. MTFace, MDeformVert, etc.). */
typedef struct CustomData {
CustomDataLayer *layers; /* CustomDataLayers, ordered by type */
+ int typemap[100]; /* maps types to indices of first layer of that type */
int totlayer, maxlayer; /* number of layers, size of layers array */
int totsize, pad; /* in editmode, total size of all data layers */
void *pool; /* Bmesh: Memory pool for allocation of blocks */
@@ -87,11 +88,18 @@ typedef struct CustomData {
#define CD_TANGENT 18
#define CD_MDISPS 19
#define CD_WEIGHT_MCOL 20 /* for displaying weightpaint colors */
-#define CD_ID_MCOL 21
-#define CD_TEXTURE_MCOL 22
+#define CD_MPOLY 21
+#define CD_MLOOP 22
#define CD_CLOTH_ORCO 23
-#define CD_RECAST 24
-#define CD_NUMTYPES 25
+#define CD_ID_MCOL 24
+#define CD_TEXTURE_MCOL 25
+#define CD_SHAPE_KEYINDEX 26
+#define CD_SHAPEKEY 27
+#define CD_BWEIGHT 28
+#define CD_CREASE 29
+#define CD_WEIGHT_MLOOPCOL 30
+#define CD_RECAST 31
+#define CD_NUMTYPES 32
/* Bits for CustomDataMask */
#define CD_MASK_MVERT (1 << CD_MVERT)
@@ -115,9 +123,19 @@ typedef struct CustomData {
#define CD_MASK_TANGENT (1 << CD_TANGENT)
#define CD_MASK_MDISPS (1 << CD_MDISPS)
#define CD_MASK_WEIGHT_MCOL (1 << CD_WEIGHT_MCOL)
+#define CD_MASK_MPOLY (1 << CD_MPOLY)
+#define CD_MASK_MLOOP (1 << CD_MLOOP)
+#define CD_MASK_WEIGHT_MLOOPCOL (1 << CD_WEIGHT_MLOOPCOL)
+#define CD_MASK_SHAPE_KEYINDEX (1 << CD_SHAPE_KEYINDEX)
+#define CD_MASK_SHAPEKEY (1 << CD_SHAPEKEY)
#define CD_MASK_CLOTH_ORCO (1 << CD_CLOTH_ORCO)
#define CD_MASK_RECAST (1 << CD_RECAST)
+/* derivedmesh wants CustomDataMask for weightpaint too, is not customdata though */
+#define CD_MASK_WEIGHTPAINT (1 << CD_WEIGHTPAINT)
+#define CD_MASK_BWEIGHT (1 << CD_BWEIGHT)
+#define CD_MASK_CREASE (1 << CD_CREASE)
+
/* CustomData.flag */
/* indicates layer should not be copied by CustomData_from_template or
diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h
index 105aa4280ef..f8b48a2c60f 100644
--- a/source/blender/makesdna/DNA_key_types.h
+++ b/source/blender/makesdna/DNA_key_types.h
@@ -52,6 +52,8 @@ typedef struct KeyBlock {
float slidermin;
float slidermax;
+
+ int uid, pad3;
} KeyBlock;
@@ -71,6 +73,9 @@ typedef struct Key {
short type, totkey;
short slurph, flag;
+
+ /*can never be 0, this is used for detecting old data*/
+ int uidgen, pad; /*current free uid for keyblocks*/
} Key;
/* **************** KEY ********************* */
@@ -91,6 +96,6 @@ typedef struct Key {
#define KEYBLOCK_MUTE (1<<0)
#define KEYBLOCK_SEL (1<<1)
#define KEYBLOCK_LOCKED (1<<2)
-
+#define KEYBLOCK_MISSING (1<<3) /*temporary flag*/
#endif
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index ece6c84b0e8..c38e8d02954 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -46,6 +46,11 @@ struct MCol;
struct MSticky;
struct Mesh;
struct OcInfo;
+struct MPoly;
+struct MTexPoly;
+struct MLoop;
+struct MLoopUV;
+struct MLoopCol;
struct Multires;
struct PartialVisibility;
struct EditMesh;
@@ -60,23 +65,35 @@ typedef struct Mesh {
struct Ipo *ipo; // XXX depreceated... old animation system
struct Key *key;
struct Material **mat;
-
- struct MFace *mface; /* array of mesh object mode faces */
- struct MTFace *mtface; /* store face UV's and texture here */
+
+ /*new face structures*/
+ struct MPoly *mpoly;
+ struct MTexPoly *mtpoly;
+ struct MLoop *mloop;
+ struct MLoopUV *mloopuv;
+ struct MLoopCol *mloopcol;
+
+ /*mface stores the tesselation (triangulation) of the mesh,
+ real faces are now stored in nface.*/
+ struct MFace *mface; /* array of mesh object mode faces for tesselation */
+ struct MTFace *mtface; /* store tesselation face UV's and texture here */
struct TFace *tface; /* depecrated, use mtface */
struct MVert *mvert; /* array of verts */
struct MEdge *medge; /* array of edges */
struct MDeformVert *dvert; /* deformgroup vertices */
- struct MCol *mcol; /* array of colors, this must be the number of faces * 4 */
+
+ /* array of colors for the tesselated faces, must be number of tesselated
+ faces * 4 in length */
+ struct MCol *mcol;
struct MSticky *msticky;
struct Mesh *texcomesh;
struct MSelect *mselect;
- struct EditMesh *edit_mesh; /* not saved in file! */
+ struct BMEditMesh *edit_btmesh; /* not saved in file! */
- struct CustomData vdata, edata, fdata;
+ struct CustomData vdata, edata, fdata, pdata, ldata;
- int totvert, totedge, totface, totselect;
+ int totvert, totedge, totface, totpoly, totloop, totselect;
/* the last selected vertex/edge/face are used for the active face however
* this means the active face must always be selected, this is to keep track
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index be7b985412f..0430dbed48d 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -37,6 +37,7 @@
struct Bone;
struct Image;
+/*tesselation face, see MLoop/MPoly for the real face data*/
typedef struct MFace {
unsigned int v1, v2, v3, v4;
short mat_nr;
@@ -66,13 +67,29 @@ typedef struct MVert {
char flag, bweight;
} MVert;
-/* at the moment alpha is abused for vertex painting
+/* tesselation vertex color data.
+ * at the moment alpha is abused for vertex painting
* and not used for transperency, note that red and blue are swapped */
typedef struct MCol {
char a, r, g, b;
} MCol;
-/*bmesh custom data stuff*/
+/*new face structure, replaces MFace, which is now
+ only used for storing tesselations.*/
+typedef struct MPoly {
+ /*offset into loop array and number of loops in the face*/
+ int loopstart, totloop;
+ short mat_nr;
+ short flag;
+} MPoly;
+
+/*the e here is because we want to move away from
+ relying on edge hashes.*/
+typedef struct MLoop {
+ int v; /*vertex index*/
+ int e; /*edge index*/
+} MLoop;
+
typedef struct MTexPoly{
struct Image *tpage;
char flag, transp;
@@ -81,12 +98,19 @@ typedef struct MTexPoly{
typedef struct MLoopUV{
float uv[2];
+ int flag;
}MLoopUV;
+/*mloopuv->flag*/
+#define MLOOPUV_EDGESEL 1
+#define MLOOPUV_VERTSEL 2
+#define MLOOPUV_PINNED 4
+
+/* at the moment alpha is abused for vertex painting
+ * and not used for transperency, note that red and blue are swapped */
typedef struct MLoopCol{
char a, r, g, b;
- int pad; /*waste!*/
-}MLoopCol;
+} MLoopCol;
typedef struct MSticky {
float co[2];
@@ -97,6 +121,7 @@ typedef struct MSelect {
int type;
} MSelect;
+/*tesselation uv face data*/
typedef struct MTFace {
float uv[4][2];
struct Image *tpage;
@@ -223,10 +248,12 @@ typedef struct MRecast{
/* flag (mface) */
#define ME_SMOOTH 1
#define ME_FACE_SEL 2
- /* flag ME_HIDE==16 is used here too */
+/* flag ME_HIDE==16 is used here too */
+#define ME_DRAW_ACT 4
+
/* mselect->type */
-#define ME_VSEl 0
-#define ME_ESEl 1
+#define ME_VSEL 0
+#define ME_ESEL 1
#define ME_FSEL 2
/* mtface->flag */
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 7991a903bbb..a2a288d1f82 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -74,6 +74,9 @@ typedef enum ModifierType {
eModifierType_WeightVGProximity,
eModifierType_EmptySlot, /* keep so DynamicPaint keep loading, can re-use later */
eModifierType_DynamicPaint, /* reserve slot */
+
+ /* BMESH ONLY - keeps getting bumped by new modifiers in trunk */
+ eModifierType_NgonInterp,
NUM_MODIFIER_TYPES
} ModifierType;
@@ -678,6 +681,7 @@ typedef struct ShrinkwrapModifierData {
#define MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS (1<<2)
#define MOD_SHRINKWRAP_PROJECT_OVER_NORMAL 0 /* projection over normal is used if no axis is selected */
+
typedef struct SimpleDeformModifierData {
ModifierData modifier;
@@ -749,9 +753,13 @@ typedef struct ScrewModifierData {
#define MOD_SCREW_OBJECT_OFFSET (1<<2)
// #define MOD_SCREW_OBJECT_ANGLE (1<<4)
-typedef struct WarpModifierData {
+typedef struct NgonInterpModifierData {
ModifierData modifier;
+ int resolution, pad0;
+} NgonInterpModifierData;
+typedef struct WarpModifierData {
+ ModifierData modifier;
/* keep in sync with MappingInfoModifierData */
struct Tex *texture;
struct Object *map_object;
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 19eff756ce1..ca6c5daef9f 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -134,7 +134,7 @@ typedef struct Object {
/* materials */
struct Material **mat; /* material slots */
- char *matbits; /* 1 if material linked to object */
+ char *matbits; /* a boolean field, with each byte 1 if corrusponding material is linked to object */
int totcol; /* copy of mesh or curve or meta */
int actcol; /* currently selected material in the UI */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index a3934618582..8e8197b473d 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -394,7 +394,7 @@ typedef struct UserDef {
struct ColorBand coba_weight; /* from texture.h */
float sculpt_paint_overlay_col[3];
- int pad3;
+ int loopcut_finish_on_release;
char author[80]; /* author name for file formats supporting it */
} UserDef;
diff --git a/source/blender/makesdna/DNA_vec_types.h b/source/blender/makesdna/DNA_vec_types.h
index 75ac69cb379..9e7e9ffad3f 100644
--- a/source/blender/makesdna/DNA_vec_types.h
+++ b/source/blender/makesdna/DNA_vec_types.h
@@ -59,11 +59,11 @@ typedef struct vec2d {
typedef struct vec3i {
int x, y, z;
} vec3i;
-
+*/
typedef struct vec3f {
float x, y, z;
} vec3f;
-
+/*
typedef struct vec3d {
double x, y, z;
} vec3d;
diff --git a/source/blender/makesdna/intern/SConscript b/source/blender/makesdna/intern/SConscript
index 8185676cbfc..a819d827788 100644
--- a/source/blender/makesdna/intern/SConscript
+++ b/source/blender/makesdna/intern/SConscript
@@ -18,7 +18,7 @@ dna = env.Clone()
makesdna_tool.Append(CCFLAGS = '-DBASE_HEADER="\\"source/blender/makesdna/\\"" ')
makesdna_tool.Append (CPPPATH = ['#/intern/guardedalloc',
- '../../makesdna', '../../blenloader'])
+ '../../makesdna', '../../blenloader', '../../bmesh'])
if env['OURPLATFORM'] == 'linuxcross':
USE_WINE = True # when cross compiling on linux 64bit this is useful
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index 2186a067c10..49f012a4b4d 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -42,6 +42,7 @@
#include "MEM_guardedalloc.h" // for MEM_freeN MEM_mallocN MEM_callocN
#ifdef WITH_DNA_GHASH
+# include "BLI_utildefines.h"
# include "BLI_ghash.h"
#endif
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index cf593555bc7..395af024a20 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -303,6 +303,8 @@ extern StructRNA RNA_MeshColorLayer;
extern StructRNA RNA_MeshDeformModifier;
extern StructRNA RNA_MeshEdge;
extern StructRNA RNA_MeshFace;
+extern StructRNA RNA_MeshPolygon;
+extern StructRNA RNA_MeshLoop;
extern StructRNA RNA_MeshFloatProperty;
extern StructRNA RNA_MeshFloatPropertyLayer;
extern StructRNA RNA_MeshIntProperty;
diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript
index da186a57c8b..f0e841abdae 100644
--- a/source/blender/makesrna/SConscript
+++ b/source/blender/makesrna/SConscript
@@ -8,7 +8,7 @@ objs += o
incs = '#/intern/guardedalloc #/intern/memutil #/intern/audaspace/intern ../blenkernel ../blenlib ../makesdna intern .'
incs += ' ../windowmanager ../editors/include ../gpu ../imbuf ../ikplugin ../blenfont ../blenloader'
-incs += ' ../render/extern/include'
+incs += ' ../render/extern/include ../bmesh'
incs += ' ../nodes'
incs += ' #/extern/glew/include'
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 59b251317dc..33753bacc94 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -230,6 +230,7 @@ blender_include_dirs(
../../blenkernel
../../blenloader
../../blenlib
+ ../../bmesh
../../blenfont
../../gpu
../../imbuf
diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript
index d710dd06a17..e9153b63193 100644
--- a/source/blender/makesrna/intern/SConscript
+++ b/source/blender/makesrna/intern/SConscript
@@ -32,7 +32,7 @@ defs = []
incs = '#/intern/guardedalloc ../../blenlib ../../blenkernel ../../blenloader'
incs += ' ../../imbuf ../../makesdna ../../makesrna ../../ikplugin'
incs += ' ../../windowmanager ../../editors/include ../../blenfont'
-incs += ' ../../render/extern/include'
+incs += ' ../../render/extern/include ../../bmesh'
incs += ' #/intern/audaspace/intern '
incs += ' #/extern/glew/include '
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 194c3e8d18e..c1f3c644e0b 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -326,12 +326,6 @@ int rna_IDMaterials_assign_int(PointerRNA *ptr, int key, const PointerRNA *assig
}
}
-void rna_Library_filepath_set(PointerRNA *ptr, const char *value)
-{
- Library *lib= (Library*)ptr->data;
- BKE_library_filepath_set(lib, value);
-}
-
#else
static void rna_def_ID_properties(BlenderRNA *brna)
@@ -527,7 +521,7 @@ static void rna_def_library(BlenderRNA *brna)
prop= RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
RNA_def_property_string_sdna(prop, NULL, "name");
RNA_def_property_ui_text(prop, "File Path", "Path to the library .blend file");
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Library_filepath_set");
+ /* TODO - lib->filename isnt updated, however the outliner also skips this, probably only needed on read. */
prop= RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Library");
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index c651dca4b31..08a71e0cd4f 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -621,7 +621,7 @@ static void rna_FKeyframe_points_remove(FCurve *fcu, ReportList *reports, BezTri
static void rna_fcurve_range(FCurve *fcu, float range[2])
{
- calc_fcurve_range(fcu, range, range+1, FALSE, FALSE);
+ calc_fcurve_range(fcu, range, range+1, FALSE);
}
#else
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 93cdfb6069b..eeee2b3df68 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -1,4 +1,4 @@
-/*
+/**
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -8,7 +8,7 @@
*
* 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
+ * 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
@@ -20,6 +20,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/*note: the original vertex color stuff is now just used for
+ getting info on the layers themselves, accessing the data is
+ done through the (not yet written) mpoly interfaces.*/
+
/** \file blender/makesrna/intern/rna_mesh.c
* \ingroup RNA
*/
@@ -28,6 +32,7 @@
#include <stdlib.h>
#include "RNA_define.h"
+#include "RNA_types.h"
#include "rna_internal.h"
@@ -52,14 +57,14 @@
#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
-
+#include "BKE_tessmesh.h"
#include "ED_mesh.h" /* XXX Bad level call */
#include "WM_api.h"
#include "WM_types.h"
-static void rna_Mesh_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Mesh_update_data(Main *bmain, Scene *scene, PointerRNA *ptr)
{
ID *id= ptr->id.data;
@@ -70,7 +75,7 @@ static void rna_Mesh_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin
}
}
-static void rna_Mesh_update_select(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Mesh_update_select(Main *bmain, Scene *scene, PointerRNA *ptr)
{
ID *id= ptr->id.data;
/* cheating way for importers to avoid slow updates */
@@ -79,7 +84,7 @@ static void rna_Mesh_update_select(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
}
}
-void rna_Mesh_update_draw(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+void rna_Mesh_update_draw(Main *bmain, Scene *scene, PointerRNA *ptr)
{
ID *id= ptr->id.data;
/* cheating way for importers to avoid slow updates */
@@ -158,14 +163,21 @@ static void rna_MEdge_crease_set(PointerRNA *ptr, float value)
medge->crease= (char)(CLAMPIS(value*255.0f, 0, 255));
}
+static void rna_MeshPolygon_normal_get(PointerRNA *ptr, float *values)
+{
+ Mesh *me= (Mesh*)ptr->id.data;
+ MPoly *mp= (MPoly*)ptr->data;
+
+ mesh_calc_poly_normal(mp, me->mloop+mp->loopstart, me->mvert, values);
+}
+
static void rna_MeshFace_normal_get(PointerRNA *ptr, float *values)
{
Mesh *me= (Mesh*)ptr->id.data;
MFace *mface= (MFace*)ptr->data;
-
+
if(mface->v4)
- normal_quad_v3(values,me->mvert[mface->v1].co, me->mvert[mface->v2].co,
- me->mvert[mface->v3].co, me->mvert[mface->v4].co);
+ normal_quad_v3( values,me->mvert[mface->v1].co, me->mvert[mface->v2].co, me->mvert[mface->v3].co, me->mvert[mface->v4].co);
else
normal_tri_v3( values,me->mvert[mface->v1].co, me->mvert[mface->v2].co, me->mvert[mface->v3].co);
}
@@ -254,55 +266,12 @@ static void rna_MeshColor_color4_set(PointerRNA *ptr, const float *values)
(&mcol[3].r)[0]= (char)(CLAMPIS(values[2]*255.0f, 0, 255));
}
-static void rna_Mesh_texspace_set(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- Mesh *me= (Mesh*)ptr->data;
-
- if (me->texflag & AUTOSPACE)
- tex_space_mesh(me);
-}
-
-
static int rna_Mesh_texspace_editable(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
return (me->texflag & AUTOSPACE)? 0: PROP_EDITABLE;
}
-static void rna_Mesh_texspace_loc_get(PointerRNA *ptr, float *values)
-{
- Mesh *me= (Mesh *)ptr->data;
-
- if (!me->bb)
- tex_space_mesh(me);
-
- copy_v3_v3(values, me->loc);
-}
-
-static void rna_Mesh_texspace_loc_set(PointerRNA *ptr, const float *values)
-{
- Mesh *me= (Mesh *)ptr->data;
-
- copy_v3_v3(me->loc, values);
-}
-
-static void rna_Mesh_texspace_size_get(PointerRNA *ptr, float *values)
-{
- Mesh *me= (Mesh *)ptr->data;
-
- if (!me->bb)
- tex_space_mesh(me);
-
- copy_v3_v3(values, me->size);
-}
-
-static void rna_Mesh_texspace_size_set(PointerRNA *ptr, const float *values)
-{
- Mesh *me= (Mesh *)ptr->data;
-
- copy_v3_v3(me->size, values);
-}
-
static void rna_MeshVertex_groups_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
@@ -325,15 +294,20 @@ static void rna_MeshFace_material_index_range(PointerRNA *ptr, int *min, int *ma
*max= MAX2(0, *max);
}
-static CustomData *rna_mesh_fdata(Mesh *me)
+static CustomData *rna_mesh_pdata(Mesh *me)
{
- return (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
+ return (me->edit_btmesh)? &me->edit_btmesh->bm->pdata: &me->pdata;
+}
+
+static CustomData *rna_mesh_ldata(Mesh *me)
+{
+ return (me->edit_btmesh)? &me->edit_btmesh->bm->ldata: &me->ldata;
}
static int rna_CustomDataLayer_length(PointerRNA *ptr, int type)
{
Mesh *me= (Mesh*)ptr->id.data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
CustomDataLayer *layer;
int i, length= 0;
@@ -347,17 +321,17 @@ static int rna_CustomDataLayer_length(PointerRNA *ptr, int type)
static int rna_CustomDataLayer_active_get(PointerRNA *ptr, int type, int render)
{
Mesh *me= (Mesh*)ptr->id.data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
int n= ((CustomDataLayer*)ptr->data) - fdata->layers;
if(render) return (n == CustomData_get_render_layer_index(fdata, type));
else return (n == CustomData_get_active_layer_index(fdata, type));
}
-static int rna_CustomDataLayer_clone_get(PointerRNA *ptr, int type, int UNUSED(render))
+static int rna_CustomDataLayer_clone_get(PointerRNA *ptr, int type, int render)
{
Mesh *me= (Mesh*)ptr->id.data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
int n= ((CustomDataLayer*)ptr->data) - fdata->layers;
return (n == CustomData_get_clone_layer_index(fdata, type));
@@ -366,7 +340,7 @@ static int rna_CustomDataLayer_clone_get(PointerRNA *ptr, int type, int UNUSED(r
static void rna_CustomDataLayer_active_set(PointerRNA *ptr, int value, int type, int render)
{
Mesh *me= (Mesh*)ptr->id.data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
int n= ((CustomDataLayer*)ptr->data) - fdata->layers;
if(value == 0)
@@ -376,10 +350,10 @@ static void rna_CustomDataLayer_active_set(PointerRNA *ptr, int value, int type,
else CustomData_set_layer_active_index(fdata, type, n);
}
-static void rna_CustomDataLayer_clone_set(PointerRNA *ptr, int value, int type, int UNUSED(render))
+static void rna_CustomDataLayer_clone_set(PointerRNA *ptr, int value, int type, int render)
{
Mesh *me= (Mesh*)ptr->id.data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
int n= ((CustomDataLayer*)ptr->data) - fdata->layers;
if(value == 0)
@@ -388,29 +362,29 @@ static void rna_CustomDataLayer_clone_set(PointerRNA *ptr, int value, int type,
CustomData_set_layer_clone_index(fdata, type, n);
}
-static int rna_uv_texture_check(CollectionPropertyIterator *UNUSED(iter), void *data)
+static int rna_uv_texture_check(CollectionPropertyIterator *iter, void *data)
{
CustomDataLayer *layer= (CustomDataLayer*)data;
- return (layer->type != CD_MTFACE);
+ return (layer->type != CD_MTEXPOLY);
}
static void rna_Mesh_uv_textures_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, 0, rna_uv_texture_check);
}
static int rna_Mesh_uv_textures_length(PointerRNA *ptr)
{
- return rna_CustomDataLayer_length(ptr, CD_MTFACE);
+ return rna_CustomDataLayer_length(ptr, CD_MTEXPOLY);
}
static PointerRNA rna_Mesh_active_uv_texture_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
- int index= CustomData_get_active_layer_index(fdata, CD_MTFACE);
+ CustomData *fdata= rna_mesh_pdata(me);
+ int index= CustomData_get_active_layer_index(fdata, CD_MTEXPOLY);
CustomDataLayer *cdl= (index == -1)? NULL: &fdata->layers[index];
return rna_pointer_inherit_refine(ptr, &RNA_MeshTextureFaceLayer, cdl);
@@ -418,34 +392,42 @@ static PointerRNA rna_Mesh_active_uv_texture_get(PointerRNA *ptr)
static PointerRNA rna_Mesh_uv_texture_clone_get(PointerRNA *ptr)
{
+ PointerRNA pnull = {{0}};
+#if 0
Mesh *me= (Mesh*)ptr->data;
CustomData *fdata= rna_mesh_fdata(me);
int index= CustomData_get_clone_layer_index(fdata, CD_MTFACE);
CustomDataLayer *cdl= (index == -1)? NULL: &fdata->layers[index];
return rna_pointer_inherit_refine(ptr, &RNA_MeshTextureFaceLayer, cdl);
+#endif
+ return pnull;
}
static PointerRNA rna_Mesh_uv_texture_stencil_get(PointerRNA *ptr)
{
+ PointerRNA pnull = {{0}};
+#if 0
Mesh *me= (Mesh*)ptr->data;
CustomData *fdata= rna_mesh_fdata(me);
int index= CustomData_get_stencil_layer_index(fdata, CD_MTFACE);
CustomDataLayer *cdl= (index == -1)? NULL: &fdata->layers[index];
return rna_pointer_inherit_refine(ptr, &RNA_MeshTextureFaceLayer, cdl);
+#endif
+ return pnull;
}
static void rna_Mesh_active_uv_texture_set(PointerRNA *ptr, PointerRNA value)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
CustomDataLayer *cdl;
int a;
for(cdl=fdata->layers, a=0; a<fdata->totlayer; cdl++, a++) {
if(value.data == cdl) {
- CustomData_set_layer_active_index(fdata, CD_MTFACE, a);
+ CustomData_set_layer_active_index(fdata, CD_MTEXPOLY, a);
mesh_update_customdata_pointers(me);
return;
}
@@ -454,6 +436,7 @@ static void rna_Mesh_active_uv_texture_set(PointerRNA *ptr, PointerRNA value)
static void rna_Mesh_uv_texture_clone_set(PointerRNA *ptr, PointerRNA value)
{
+#if 0
Mesh *me= (Mesh*)ptr->data;
CustomData *fdata= rna_mesh_fdata(me);
CustomDataLayer *cdl;
@@ -465,10 +448,13 @@ static void rna_Mesh_uv_texture_clone_set(PointerRNA *ptr, PointerRNA value)
return;
}
}
+#endif
+ return;
}
static void rna_Mesh_uv_texture_stencil_set(PointerRNA *ptr, PointerRNA value)
{
+#if 0
Mesh *me= (Mesh*)ptr->data;
CustomData *fdata= rna_mesh_fdata(me);
CustomDataLayer *cdl;
@@ -480,146 +466,85 @@ static void rna_Mesh_uv_texture_stencil_set(PointerRNA *ptr, PointerRNA value)
return;
}
}
+#endif
+ return;
}
static int rna_Mesh_active_uv_texture_index_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
- return CustomData_get_active_layer(fdata, CD_MTFACE);
+ CustomData *fdata= rna_mesh_pdata(me);
+ return CustomData_get_active_layer(fdata, CD_MTEXPOLY);
}
static int rna_Mesh_uv_texture_clone_index_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
- return CustomData_get_clone_layer(fdata, CD_MTFACE);
+ CustomData *fdata= rna_mesh_pdata(me);
+ return CustomData_get_clone_layer(fdata, CD_MTEXPOLY);
}
static int rna_Mesh_uv_texture_stencil_index_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
- return CustomData_get_stencil_layer(fdata, CD_MTFACE);
+ CustomData *fdata= rna_mesh_pdata(me);
+ return CustomData_get_stencil_layer(fdata, CD_MTEXPOLY);
}
static void rna_Mesh_active_uv_texture_index_set(PointerRNA *ptr, int value)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
- CustomData_set_layer_active(fdata, CD_MTFACE, value);
+ CustomData_set_layer_active(fdata, CD_MTEXPOLY, value);
mesh_update_customdata_pointers(me);
}
static void rna_Mesh_uv_texture_clone_index_set(PointerRNA *ptr, int value)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
- CustomData_set_layer_clone(fdata, CD_MTFACE, value);
+ CustomData_set_layer_clone(fdata, CD_MTEXPOLY, value);
}
static void rna_Mesh_uv_texture_stencil_index_set(PointerRNA *ptr, int value)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
- CustomData_set_layer_stencil(fdata, CD_MTFACE, value);
+ CustomData_set_layer_stencil(fdata, CD_MTEXPOLY, value);
}
static void rna_Mesh_active_uv_texture_index_range(PointerRNA *ptr, int *min, int *max)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *pdata= rna_mesh_pdata(me);
*min= 0;
- *max= CustomData_number_of_layers(fdata, CD_MTFACE)-1;
+ *max= CustomData_number_of_layers(pdata, CD_MTEXPOLY)-1;
*max= MAX2(0, *max);
}
-static PointerRNA rna_Mesh_active_mtface_get(PointerRNA *ptr)
-{
- Mesh *me= (Mesh*)ptr->data;
- EditMesh *em= BKE_mesh_get_editmesh(me);
- MTFace *tf;
-
- if (em && EM_texFaceCheck(em))
- {
- tf = EM_get_active_mtface(em, NULL, NULL, 1);
-
- return rna_pointer_inherit_refine(ptr, &RNA_MeshTextureFace, tf);
- }
-
- return rna_pointer_inherit_refine(ptr, &RNA_MeshTextureFace, NULL);
-}
-
static void rna_MeshTextureFace_uv1_get(PointerRNA *ptr, float *values)
{
- MTFace *mtface= (MTFace*)ptr->data;
+ MLoopUV *mloopuv= (MLoopUV*)ptr->data;
- values[0]= mtface->uv[0][0];
- values[1]= mtface->uv[0][1];
+ values[0]= mloopuv->uv[0];
+ values[1]= mloopuv->uv[1];
}
static void rna_MeshTextureFace_uv1_set(PointerRNA *ptr, const float *values)
{
- MTFace *mtface= (MTFace*)ptr->data;
-
- mtface->uv[0][0]= values[0];
- mtface->uv[0][1]= values[1];
-}
-
-static void rna_MeshTextureFace_uv2_get(PointerRNA *ptr, float *values)
-{
- MTFace *mtface= (MTFace*)ptr->data;
-
- values[0]= mtface->uv[1][0];
- values[1]= mtface->uv[1][1];
-}
-
-static void rna_MeshTextureFace_uv2_set(PointerRNA *ptr, const float *values)
-{
- MTFace *mtface= (MTFace*)ptr->data;
-
- mtface->uv[1][0]= values[0];
- mtface->uv[1][1]= values[1];
-}
-
-static void rna_MeshTextureFace_uv3_get(PointerRNA *ptr, float *values)
-{
- MTFace *mtface= (MTFace*)ptr->data;
-
- values[0]= mtface->uv[2][0];
- values[1]= mtface->uv[2][1];
-}
-
-static void rna_MeshTextureFace_uv3_set(PointerRNA *ptr, const float *values)
-{
- MTFace *mtface= (MTFace*)ptr->data;
-
- mtface->uv[2][0]= values[0];
- mtface->uv[2][1]= values[1];
-}
-
-static void rna_MeshTextureFace_uv4_get(PointerRNA *ptr, float *values)
-{
- MTFace *mtface= (MTFace*)ptr->data;
-
- values[0]= mtface->uv[3][0];
- values[1]= mtface->uv[3][1];
-}
-
-static void rna_MeshTextureFace_uv4_set(PointerRNA *ptr, const float *values)
-{
- MTFace *mtface= (MTFace*)ptr->data;
-
- mtface->uv[3][0]= values[0];
- mtface->uv[3][1]= values[1];
+ MLoopUV *mloopuv= (MLoopUV*)ptr->data;
+
+ mloopuv->uv[0] = values[0];
+ mloopuv->uv[1] = values[1];
}
static int rna_CustomDataData_numverts(PointerRNA *ptr, int type)
{
+ /*BMESH_TODO
Mesh *me= (Mesh*)ptr->id.data;
CustomData *fdata= rna_mesh_fdata(me);
CustomDataLayer *cdl;
@@ -633,53 +558,53 @@ static int rna_CustomDataData_numverts(PointerRNA *ptr, int type)
}
}
+ return 0;*/
return 0;
}
static int rna_MeshTextureFace_uv_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
{
- length[0]= rna_CustomDataData_numverts(ptr, CD_MTFACE);
- length[1]= 2;
- return length[0]*length[1];
+ //return rna_CustomDataData_numverts(ptr, CD_MTFACE) * 2;
+ return 0; //BMESH_TODO
}
static void rna_MeshTextureFace_uv_get(PointerRNA *ptr, float *values)
{
- MTFace *mtface= (MTFace*)ptr->data;
- int totvert= rna_CustomDataData_numverts(ptr, CD_MTFACE);
+ //MTFace *mtface= (MTFace*)ptr->data;
+ //int totvert= rna_CustomDataData_numverts(ptr, CD_MTFACE);
- memcpy(values, mtface->uv, totvert * 2 * sizeof(float));
+ //memcpy(values, mtface->uv, totvert * 2 * sizeof(float));
}
static void rna_MeshTextureFace_uv_set(PointerRNA *ptr, const float *values)
{
- MTFace *mtface= (MTFace*)ptr->data;
- int totvert= rna_CustomDataData_numverts(ptr, CD_MTFACE);
+ //MTFace *mtface= (MTFace*)ptr->data;
+ //int totvert= rna_CustomDataData_numverts(ptr, CD_MTFACE);
- memcpy(mtface->uv, values, totvert * 2 * sizeof(float));
+ //memcpy(mtface->uv, values, totvert * 2 * sizeof(float));
}
static void rna_MeshTextureFaceLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
CustomDataLayer *layer= (CustomDataLayer*)ptr->data;
- rna_iterator_array_begin(iter, layer->data, sizeof(MTFace), (me->edit_mesh)? 0: me->totface, 0, NULL);
+ rna_iterator_array_begin(iter, layer->data, sizeof(MTexPoly), me->totpoly, 0, NULL);
}
static int rna_MeshTextureFaceLayer_data_length(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
- return (me->edit_mesh)? 0: me->totface;
+ return me->totpoly;
}
static int rna_MeshTextureFaceLayer_active_render_get(PointerRNA *ptr)
{
- return rna_CustomDataLayer_active_get(ptr, CD_MTFACE, 1);
+ return rna_CustomDataLayer_active_get(ptr, CD_MTEXPOLY, 1);
}
static int rna_MeshTextureFaceLayer_active_get(PointerRNA *ptr)
{
- return rna_CustomDataLayer_active_get(ptr, CD_MTFACE, 0);
+ return rna_CustomDataLayer_active_get(ptr, CD_MTEXPOLY, 0);
}
static int rna_MeshTextureFaceLayer_clone_get(PointerRNA *ptr)
@@ -689,12 +614,12 @@ static int rna_MeshTextureFaceLayer_clone_get(PointerRNA *ptr)
static void rna_MeshTextureFaceLayer_active_render_set(PointerRNA *ptr, int value)
{
- rna_CustomDataLayer_active_set(ptr, value, CD_MTFACE, 1);
+ rna_CustomDataLayer_active_set(ptr, value, CD_MTEXPOLY, 1);
}
static void rna_MeshTextureFaceLayer_active_set(PointerRNA *ptr, int value)
{
- rna_CustomDataLayer_active_set(ptr, value, CD_MTFACE, 0);
+ rna_CustomDataLayer_active_set(ptr, value, CD_MTEXPOLY, 0);
}
static void rna_MeshTextureFaceLayer_clone_set(PointerRNA *ptr, int value)
@@ -705,36 +630,36 @@ static void rna_MeshTextureFaceLayer_clone_set(PointerRNA *ptr, int value)
static void rna_MeshTextureFaceLayer_name_set(PointerRNA *ptr, const char *value)
{
Mesh *me= (Mesh*)ptr->id.data;
- CustomData *fdata= rna_mesh_fdata(me);
+ /* CustomData *fdata= rna_mesh_pdata(me); */ /* UNUSED */
CustomDataLayer *cdl= (CustomDataLayer*)ptr->data;
BLI_strncpy_utf8(cdl->name, value, sizeof(cdl->name));
- CustomData_set_layer_unique_name(fdata, cdl - fdata->layers);
+ CustomData_set_layer_unique_name(&me->pdata, cdl - rna_mesh_pdata(me)->layers);
}
-static int rna_vertex_color_check(CollectionPropertyIterator *UNUSED(iter), void *data)
+static int rna_vertex_color_check(CollectionPropertyIterator *iter, void *data)
{
CustomDataLayer *layer= (CustomDataLayer*)data;
- return (layer->type != CD_MCOL);
+ return (layer->type != CD_MLOOPCOL);
}
static void rna_Mesh_vertex_colors_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
- rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, 0, rna_vertex_color_check);
+ CustomData *ldata= rna_mesh_ldata(me);
+ rna_iterator_array_begin(iter, (void*)ldata->layers, sizeof(CustomDataLayer), ldata->totlayer, 0, rna_vertex_color_check);
}
static int rna_Mesh_vertex_colors_length(PointerRNA *ptr)
{
- return rna_CustomDataLayer_length(ptr, CD_MCOL);
+ return rna_CustomDataLayer_length(ptr, CD_MLOOPCOL);
}
static PointerRNA rna_Mesh_active_vertex_color_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
- int index= CustomData_get_active_layer_index(fdata, CD_MCOL);
- CustomDataLayer *cdl= (index == -1)? NULL: &fdata->layers[index];
+ CustomData *ldata= rna_mesh_ldata(me);
+ int index= CustomData_get_active_layer_index(ldata, CD_MLOOPCOL);
+ CustomDataLayer *cdl= (index == -1)? NULL: &ldata->layers[index];
return rna_pointer_inherit_refine(ptr, &RNA_MeshColorLayer, cdl);
}
@@ -742,42 +667,47 @@ static PointerRNA rna_Mesh_active_vertex_color_get(PointerRNA *ptr)
static void rna_Mesh_active_vertex_color_set(PointerRNA *ptr, PointerRNA value)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *ldata= rna_mesh_ldata(me);
CustomDataLayer *cdl;
- int a;
+ int a, b;
+
+ b = 0;
+ for(cdl=ldata->layers, a=0; a<ldata->totlayer; cdl++, a++) {
+ if (cdl->type == CD_MLOOPCOL)
+ b++;
- for(cdl=fdata->layers, a=0; a<fdata->totlayer; cdl++, a++) {
if(value.data == cdl) {
- CustomData_set_layer_active_index(fdata, CD_MCOL, a);
- mesh_update_customdata_pointers(me);
- return;
+ CustomData_set_layer_active_index(ldata, CD_MLOOPCOL, a);
+ break;
}
}
+
+ mesh_update_customdata_pointers(me);
}
static int rna_Mesh_active_vertex_color_index_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
- return CustomData_get_active_layer(fdata, CD_MCOL);
+ CustomData *ldata= rna_mesh_ldata(me);
+ return CustomData_get_active_layer(ldata, CD_MLOOPCOL);
}
static void rna_Mesh_active_vertex_color_index_set(PointerRNA *ptr, int value)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *ldata= rna_mesh_ldata(me);
- CustomData_set_layer_active(fdata, CD_MCOL, value);
+ CustomData_set_layer_active(ldata, CD_MLOOPCOL, value);
mesh_update_customdata_pointers(me);
}
static void rna_Mesh_active_vertex_color_index_range(PointerRNA *ptr, int *min, int *max)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *ldata= rna_mesh_ldata(me);
*min= 0;
- *max= CustomData_number_of_layers(fdata, CD_MCOL)-1;
+ *max= CustomData_number_of_layers(ldata, CD_MLOOPCOL)-1;
*max= MAX2(0, *max);
}
@@ -785,58 +715,58 @@ static void rna_MeshColorLayer_data_begin(CollectionPropertyIterator *iter, Poin
{
Mesh *me= (Mesh*)ptr->id.data;
CustomDataLayer *layer= (CustomDataLayer*)ptr->data;
- rna_iterator_array_begin(iter, layer->data, sizeof(MCol)*4, (me->edit_mesh)? 0: me->totface, 0, NULL);
+ rna_iterator_array_begin(iter, layer->data, sizeof(CD_MLOOPCOL), me->totloop, 0, NULL);
}
static int rna_MeshColorLayer_data_length(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
- return (me->edit_mesh)? 0: me->totface;
+ return me->totloop;
}
static int rna_MeshColorLayer_active_render_get(PointerRNA *ptr)
{
- return rna_CustomDataLayer_active_get(ptr, CD_MCOL, 1);
+ return rna_CustomDataLayer_active_get(ptr, CD_MLOOPCOL, 1);
}
static int rna_MeshColorLayer_active_get(PointerRNA *ptr)
{
- return rna_CustomDataLayer_active_get(ptr, CD_MCOL, 0);
+ return rna_CustomDataLayer_active_get(ptr, CD_MLOOPCOL, 0);
}
static void rna_MeshColorLayer_active_render_set(PointerRNA *ptr, int value)
{
- rna_CustomDataLayer_active_set(ptr, value, CD_MCOL, 1);
+ rna_CustomDataLayer_active_set(ptr, value, CD_MLOOPCOL, 1);
}
static void rna_MeshColorLayer_active_set(PointerRNA *ptr, int value)
{
- rna_CustomDataLayer_active_set(ptr, value, CD_MCOL, 0);
+ rna_CustomDataLayer_active_set(ptr, value, CD_MLOOPCOL, 0);
}
static void rna_MeshColorLayer_name_set(PointerRNA *ptr, const char *value)
{
Mesh *me= (Mesh*)ptr->id.data;
- CustomData *fdata= rna_mesh_fdata(me);
+ /* CustomData *fdata= rna_mesh_pdata(me); */ /* UNUSED */
CustomDataLayer *cdl= (CustomDataLayer*)ptr->data;
BLI_strncpy_utf8(cdl->name, value, sizeof(cdl->name));
- CustomData_set_layer_unique_name(fdata, cdl - fdata->layers);
+ CustomData_set_layer_unique_name(&me->ldata, cdl - rna_mesh_ldata(me)->layers);
}
static void rna_MeshFloatPropertyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
CustomDataLayer *layer= (CustomDataLayer*)ptr->data;
- rna_iterator_array_begin(iter, layer->data, sizeof(MFloatProperty), (me->edit_mesh)? 0: me->totface, 0, NULL);
+ rna_iterator_array_begin(iter, layer->data, sizeof(MFloatProperty), me->totface, 0, NULL);
}
static int rna_MeshFloatPropertyLayer_data_length(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
- return (me->edit_mesh)? 0: me->totface;
+ return me->totface;
}
-static int rna_float_layer_check(CollectionPropertyIterator *UNUSED(iter), void *data)
+static int rna_float_layer_check(CollectionPropertyIterator *iter, void *data)
{
CustomDataLayer *layer= (CustomDataLayer*)data;
return (layer->type != CD_PROP_FLT);
@@ -845,7 +775,7 @@ static int rna_float_layer_check(CollectionPropertyIterator *UNUSED(iter), void
static void rna_Mesh_float_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, 0, rna_float_layer_check);
}
@@ -854,7 +784,7 @@ static int rna_Mesh_float_layers_length(PointerRNA *ptr)
return rna_CustomDataLayer_length(ptr, CD_PROP_FLT);
}
-static int rna_int_layer_check(CollectionPropertyIterator *UNUSED(iter), void *data)
+static int rna_int_layer_check(CollectionPropertyIterator *iter, void *data)
{
CustomDataLayer *layer= (CustomDataLayer*)data;
return (layer->type != CD_PROP_INT);
@@ -864,19 +794,19 @@ static void rna_MeshIntPropertyLayer_data_begin(CollectionPropertyIterator *iter
{
Mesh *me= (Mesh*)ptr->id.data;
CustomDataLayer *layer= (CustomDataLayer*)ptr->data;
- rna_iterator_array_begin(iter, layer->data, sizeof(MIntProperty), (me->edit_mesh)? 0: me->totface, 0, NULL);
+ rna_iterator_array_begin(iter, layer->data, sizeof(MIntProperty), me->totface, 0, NULL);
}
static int rna_MeshIntPropertyLayer_data_length(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
- return (me->edit_mesh)? 0: me->totface;
+ return me->totface;
}
static void rna_Mesh_int_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, 0, rna_int_layer_check);
}
@@ -885,7 +815,7 @@ static int rna_Mesh_int_layers_length(PointerRNA *ptr)
return rna_CustomDataLayer_length(ptr, CD_PROP_INT);
}
-static int rna_string_layer_check(CollectionPropertyIterator *UNUSED(iter), void *data)
+static int rna_string_layer_check(CollectionPropertyIterator *iter, void *data)
{
CustomDataLayer *layer= (CustomDataLayer*)data;
return (layer->type != CD_PROP_STR);
@@ -895,19 +825,19 @@ static void rna_MeshStringPropertyLayer_data_begin(CollectionPropertyIterator *i
{
Mesh *me= (Mesh*)ptr->id.data;
CustomDataLayer *layer= (CustomDataLayer*)ptr->data;
- rna_iterator_array_begin(iter, layer->data, sizeof(MStringProperty), (me->edit_mesh)? 0: me->totface, 0, NULL);
+ rna_iterator_array_begin(iter, layer->data, sizeof(MStringProperty), me->totface, 0, NULL);
}
static int rna_MeshStringPropertyLayer_data_length(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
- return (me->edit_mesh)? 0: me->totface;
+ return me->totface;
}
static void rna_Mesh_string_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, 0, rna_string_layer_check);
}
@@ -918,7 +848,7 @@ static int rna_Mesh_string_layers_length(PointerRNA *ptr)
static void rna_TextureFace_image_set(PointerRNA *ptr, PointerRNA value)
{
- MTFace *tf= (MTFace*)ptr->data;
+ MTexPoly *tf= (MTexPoly*)ptr->data;
ID *id= value.data;
if(id) {
@@ -971,6 +901,37 @@ static void rna_MeshFace_verts_set(PointerRNA *ptr, const int *values)
memcpy(&face->v1, values, (face->v4 ? 4 : 3) * sizeof(int));
}
+/* poly.vertices - this is faked loop access for convenience */
+static int rna_MeshPoly_vertices_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ MPoly *mp= (MPoly*)ptr->data;
+ /* note, raw access uses dummy item, this _could_ crash, watch out for this, mface uses it but it cant work here */
+ return (length[0]= mp->totloop);
+}
+
+static void rna_MeshPoly_vertices_get(PointerRNA *ptr, int *values)
+{
+ Mesh *me= (Mesh*)ptr->id.data;
+ MPoly *mp= (MPoly*)ptr->data;
+ MLoop *ml= &me->mloop[mp->loopstart];
+ unsigned int i;
+ for(i= mp->totloop; i > 0; i--, values++, ml++) {
+ *values = ml->v;
+ }
+}
+
+static void rna_MeshPoly_vertices_set(PointerRNA *ptr, const int *values)
+{
+ Mesh *me= (Mesh*)ptr->id.data;
+ MPoly *mp= (MPoly*)ptr->data;
+ MLoop *ml= &me->mloop[mp->loopstart];
+ unsigned int i;
+ for(i= mp->totloop; i > 0; i--, values++, ml++) {
+ ml->v = *values;
+ }
+}
+
+
static int rna_MeshVertex_index_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
@@ -992,6 +953,13 @@ static int rna_MeshFace_index_get(PointerRNA *ptr)
return (int)(face - me->mface);
}
+static int rna_MeshPolygon_index_get(PointerRNA *ptr)
+{
+ Mesh *me= (Mesh*)ptr->id.data;
+ MPoly *mpoly= (MPoly*)ptr->data;
+ return (int)(mpoly - me->mpoly);
+}
+
/* path construction */
static char *rna_VertexGroupElement_path(PointerRNA *ptr)
@@ -1001,33 +969,19 @@ static char *rna_VertexGroupElement_path(PointerRNA *ptr)
MDeformVert *dvert;
int a, b;
- /* sanity check: make sure that mesh pointer is valid */
- if (me == NULL)
- return NULL;
- else if (GS(me->id.name) != ID_ME) {
- /* if object pointer, try to resolve the object's data to mesh pointer */
- if (GS(me->id.name) == ID_OB) {
- Object *ob = (Object *)me;
-
- if (ob->type == OB_MESH)
- me = (Mesh *)ob->data;
- else
- return NULL; /* nothing can be done */
- }
- else
- return NULL; /* nothing can be done */
- }
-
- for(a=0, dvert=me->dvert; a<me->totvert; a++, dvert++) {
- for(b=0; b<dvert->totweight; b++) {
+ for(a=0, dvert=me->dvert; a<me->totvert; a++, dvert++)
+ for(b=0; b<dvert->totweight; b++)
if(dw == &dvert->dw[b])
- return BLI_sprintfN("vertices[%d].groups[%d]", a, b);
- }
- }
+ return BLI_sprintfN("verts[%d].groups[%d]", a, b);
return NULL;
}
+static char *rna_MeshPolygon_path(PointerRNA *ptr)
+{
+ return BLI_sprintfN("polygons[%d]", (int)((MPoly*)ptr->data - ((Mesh*)ptr->id.data)->mpoly));
+}
+
static char *rna_MeshFace_path(PointerRNA *ptr)
{
return BLI_sprintfN("faces[%d]", (int)((MFace*)ptr->data - ((Mesh*)ptr->id.data)->mface));
@@ -1038,6 +992,12 @@ static char *rna_MeshEdge_path(PointerRNA *ptr)
return BLI_sprintfN("edges[%d]", (int)((MEdge*)ptr->data - ((Mesh*)ptr->id.data)->medge));
}
+static char *rna_MeshLoop_path(PointerRNA *ptr)
+{
+ return BLI_sprintfN("loops[%d]", (int)((MLoop*)ptr->data - ((Mesh*)ptr->id.data)->mloop));
+}
+
+
static char *rna_MeshVertex_path(PointerRNA *ptr)
{
return BLI_sprintfN("vertices[%d]", (int)((MVert*)ptr->data - ((Mesh*)ptr->id.data)->mvert));
@@ -1051,7 +1011,7 @@ static char *rna_MeshTextureFaceLayer_path(PointerRNA *ptr)
static char *rna_CustomDataData_path(PointerRNA *ptr, char *collection, int type)
{
Mesh *me= (Mesh*)ptr->id.data;
- CustomData *fdata= rna_mesh_fdata(me);
+ CustomData *fdata= rna_mesh_pdata(me);
CustomDataLayer *cdl;
int a, b;
@@ -1068,7 +1028,7 @@ static char *rna_CustomDataData_path(PointerRNA *ptr, char *collection, int type
static char *rna_MeshTextureFace_path(PointerRNA *ptr)
{
- return rna_CustomDataData_path(ptr, "uv_textures", CD_MTFACE);
+ return rna_CustomDataData_path(ptr, "uv_textures", CD_MTEXPOLY);
}
static char *rna_MeshColorLayer_path(PointerRNA *ptr)
@@ -1078,7 +1038,7 @@ static char *rna_MeshColorLayer_path(PointerRNA *ptr)
static char *rna_MeshColor_path(PointerRNA *ptr)
{
- return rna_CustomDataData_path(ptr, "vertex_colors", CD_MCOL);
+ return rna_CustomDataData_path(ptr, "vertex_colors", CD_MLOOPCOL);
}
static char *rna_MeshSticky_path(PointerRNA *ptr)
@@ -1119,43 +1079,43 @@ static char *rna_MeshStringProperty_path(PointerRNA *ptr)
static int rna_Mesh_tot_vert_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
- return me->edit_mesh ? me->edit_mesh->totvertsel : 0;
+ return me->edit_btmesh ? me->edit_btmesh->bm->totvertsel : 0;
}
static int rna_Mesh_tot_edge_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
- return me->edit_mesh ? me->edit_mesh->totedgesel: 0;
+ return me->edit_btmesh ? me->edit_btmesh->bm->totedgesel: 0;
}
static int rna_Mesh_tot_face_get(PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
- return me->edit_mesh ? me->edit_mesh->totfacesel : 0;
+ return me->edit_btmesh ? me->edit_btmesh->bm->totfacesel : 0;
}
static CustomDataLayer *rna_Mesh_vertex_color_new(struct Mesh *me, struct bContext *C, const char *name)
{
- CustomData *fdata;
+ CustomData *ldata;
CustomDataLayer *cdl= NULL;
int index;
if(ED_mesh_color_add(C, NULL, NULL, me, name, FALSE)) {
- fdata= rna_mesh_fdata(me);
- index= CustomData_get_named_layer_index(fdata, CD_MCOL, name);
- cdl= (index == -1)? NULL: &fdata->layers[index];
+ ldata= rna_mesh_ldata(me);
+ index= CustomData_get_named_layer_index(ldata, CD_MLOOPCOL, name);
+ cdl= (index == -1)? NULL: &ldata->layers[index];
}
return cdl;
}
static CustomDataLayer *rna_Mesh_uv_texture_new(struct Mesh *me, struct bContext *C, const char *name)
{
- CustomData *fdata;
+ CustomData *pdata;
CustomDataLayer *cdl= NULL;
int index;
if(ED_mesh_uv_texture_add(C, me, name, FALSE)) {
- fdata= rna_mesh_fdata(me);
- index= CustomData_get_named_layer_index(fdata, CD_MTFACE, name);
- cdl= (index == -1)? NULL: &fdata->layers[index];
+ pdata= rna_mesh_pdata(me);
+ index= CustomData_get_named_layer_index(pdata, CD_MTEXPOLY, name);
+ cdl= (index == -1)? NULL: &pdata->layers[index];
}
return cdl;
}
@@ -1225,8 +1185,7 @@ static void rna_def_mvert(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop= RNA_def_property(srna, "groups", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_funcs(prop, "rna_MeshVertex_groups_begin", "rna_iterator_array_next",
- "rna_iterator_array_end", "rna_iterator_array_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_collection_funcs(prop, "rna_MeshVertex_groups_begin", "rna_iterator_array_next", "rna_iterator_array_end", "rna_iterator_array_get", NULL, NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "VertexGroupElement");
RNA_def_property_ui_text(prop, "Groups", "Weights for the vertex groups this vertex is member of");
@@ -1348,12 +1307,12 @@ static void rna_def_mface(BlenderRNA *brna)
RNA_def_property_range(prop, -1.0f, 1.0f);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_float_funcs(prop, "rna_MeshFace_normal_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Face normal", "Local space unit length normal vector for this face");
+ RNA_def_property_ui_text(prop, "face normal", "local space unit length normal vector for this face");
prop= RNA_def_property(srna, "area", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_float_funcs(prop, "rna_MeshFace_area_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Face area", "Read only area of the face");
+ RNA_def_property_ui_text(prop, "face area", "read only area of the face");
prop= RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -1361,11 +1320,104 @@ static void rna_def_mface(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Index", "Index number of the vertex");
}
-static void rna_def_mtface(BlenderRNA *brna)
+
+static void rna_def_mloop(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
- const int uv_dim[]= {4, 2};
+
+ srna= RNA_def_struct(brna, "MeshLoop", NULL);
+ RNA_def_struct_sdna(srna, "MLoop");
+ RNA_def_struct_ui_text(srna, "Mesh Loop", "Loop in a Mesh datablock");
+ RNA_def_struct_path_func(srna, "rna_MeshLoop_path");
+ RNA_def_struct_ui_icon(srna, ICON_EDGESEL);
+
+ prop= RNA_def_property(srna, "vertex_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "v");
+ RNA_def_property_ui_text(prop, "Vertex", "Vertex index");
+
+ prop= RNA_def_property(srna, "edge_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "e");
+ RNA_def_property_ui_text(prop, "Edge", "Edge index");
+}
+
+static void rna_def_mpolygon(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna= RNA_def_struct(brna, "MeshPolygon", NULL);
+ RNA_def_struct_sdna(srna, "MPoly");
+ RNA_def_struct_ui_text(srna, "Mesh Polygon", "Polygon in a Mesh datablock");
+ RNA_def_struct_path_func(srna, "rna_MeshPolygon_path");
+ RNA_def_struct_ui_icon(srna, ICON_FACESEL);
+
+ /* faked, actually access to loop vertex values, dont this way because manually setting up vertex/edge per loop is very low level
+ * instead we setup poly sizes, assign indicies, then calc edges automatic when creating meshes from rna/py */
+ prop= RNA_def_property(srna, "vertices", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_array(prop, 3); // eek, this is still used in some cases but infact we dont want to use it at all here.
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_MeshPoly_vertices_get_length");
+ RNA_def_property_int_funcs(prop, "rna_MeshPoly_vertices_get", "rna_MeshPoly_vertices_set", NULL);
+ RNA_def_property_ui_text(prop, "Vertices", "Vertex indices");
+
+ /* these are both very low level access */
+ prop= RNA_def_property(srna, "loop_start", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "loopstart");
+ RNA_def_property_ui_text(prop, "Loop Start", "");
+ /* also low level */
+ prop= RNA_def_property(srna, "loop_total", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "totloop");
+ RNA_def_property_ui_text(prop, "Loop Total", "");
+
+ prop= RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "mat_nr");
+ RNA_def_property_ui_text(prop, "Material Index", "");
+ RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshFace_material_index_range");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
+ prop= RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_FACE_SEL);
+ RNA_def_property_ui_text(prop, "Select", "");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
+
+ prop= RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_HIDE);
+ RNA_def_property_ui_text(prop, "Hide", "");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
+
+ prop= RNA_def_property(srna, "use_smooth", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_SMOOTH);
+ RNA_def_property_ui_text(prop, "Smooth", "");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
+ prop= RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, -1.0f, 1.0f);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_float_funcs(prop, "rna_MeshPolygon_normal_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "face normal", "local space unit length normal vector for this polygon");
+
+#if 0 /* BMESH_TODO */
+ prop= RNA_def_property(srna, "area", PROP_FLOAT, PROP_UNSIGNED);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_float_funcs(prop, "rna_MeshPolygon_area_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "face area", "read only area of the face");
+#endif
+
+ prop= RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_int_funcs(prop, "rna_MeshPolygon_index_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Index", "Index number of the vertex");
+}
+
+static void rna_def_mtexpoly(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+#if 0 /* BMESH_TODO: needed later when do another todo */
+ int uv_dim[]= {4, 2};
+#endif
srna= RNA_def_struct(brna, "MeshTextureFaceLayer", NULL);
RNA_def_struct_ui_text(srna, "Mesh Texture Face Layer", "Layer of texture faces in a Mesh datablock");
@@ -1386,8 +1438,7 @@ static void rna_def_mtface(BlenderRNA *brna)
prop= RNA_def_property(srna, "active_render", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "active_rnd", 0);
- RNA_def_property_boolean_funcs(prop, "rna_MeshTextureFaceLayer_active_render_get",
- "rna_MeshTextureFaceLayer_active_render_set");
+ RNA_def_property_boolean_funcs(prop, "rna_MeshTextureFaceLayer_active_render_get", "rna_MeshTextureFaceLayer_active_render_set");
RNA_def_property_ui_text(prop, "Active Render", "Set the layer as active for rendering");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
@@ -1400,12 +1451,10 @@ static void rna_def_mtface(BlenderRNA *brna)
prop= RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshTextureFace");
RNA_def_property_ui_text(prop, "Data", "");
- RNA_def_property_collection_funcs(prop, "rna_MeshTextureFaceLayer_data_begin", "rna_iterator_array_next",
- "rna_iterator_array_end", "rna_iterator_array_get",
- "rna_MeshTextureFaceLayer_data_length", NULL, NULL, NULL);
+ RNA_def_property_collection_funcs(prop, "rna_MeshTextureFaceLayer_data_begin", "rna_iterator_array_next", "rna_iterator_array_end", "rna_iterator_array_get", "rna_MeshTextureFaceLayer_data_length", NULL, NULL, NULL);
srna= RNA_def_struct(brna, "MeshTextureFace", NULL);
- RNA_def_struct_sdna(srna, "MTFace");
+ RNA_def_struct_sdna(srna, "MTexPoly");
RNA_def_struct_ui_text(srna, "Mesh Texture Face", "UV mapping, texturing and game engine data for a face");
RNA_def_struct_path_func(srna, "rna_MeshTextureFace_path");
RNA_def_struct_ui_icon(srna, ICON_FACESEL_HLT);
@@ -1423,36 +1472,13 @@ static void rna_def_mtface(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "UV Selected", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
+#if 0 /*BMESH_TODO*/
prop= RNA_def_property(srna, "pin_uv", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "unwrap", TF_PIN1);
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "UV Pinned", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
- prop= RNA_def_property(srna, "uv1", PROP_FLOAT, PROP_XYZ);
- RNA_def_property_array(prop, 2);
- RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv1_get", "rna_MeshTextureFace_uv1_set", NULL);
- RNA_def_property_ui_text(prop, "UV 1", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop= RNA_def_property(srna, "uv2", PROP_FLOAT, PROP_XYZ);
- RNA_def_property_array(prop, 2);
- RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv2_get", "rna_MeshTextureFace_uv2_set", NULL);
- RNA_def_property_ui_text(prop, "UV 2", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop= RNA_def_property(srna, "uv3", PROP_FLOAT, PROP_XYZ);
- RNA_def_property_array(prop, 2);
- RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv3_get", "rna_MeshTextureFace_uv3_set", NULL);
- RNA_def_property_ui_text(prop, "UV 3", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop= RNA_def_property(srna, "uv4", PROP_FLOAT, PROP_XYZ);
- RNA_def_property_array(prop, 2);
- RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv4_get", "rna_MeshTextureFace_uv4_set", NULL);
- RNA_def_property_ui_text(prop, "UV 4", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
prop= RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE);
RNA_def_property_multi_array(prop, 2, uv_dim);
RNA_def_property_flag(prop, PROP_DYNAMIC);
@@ -1465,7 +1491,7 @@ static void rna_def_mtface(BlenderRNA *brna)
RNA_def_property_multi_array(prop, 2, uv_dim);
RNA_def_property_float_sdna(prop, NULL, "uv");
RNA_def_property_ui_text(prop, "UV", "Fixed size UV coordinates array");
-
+#endif
}
static void rna_def_msticky(BlenderRNA *brna)
@@ -1483,7 +1509,7 @@ static void rna_def_msticky(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
-static void rna_def_mcol(BlenderRNA *brna)
+static void rna_def_mloopcol(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
@@ -1514,41 +1540,13 @@ static void rna_def_mcol(BlenderRNA *brna)
prop= RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshColor");
RNA_def_property_ui_text(prop, "Data", "");
- RNA_def_property_collection_funcs(prop, "rna_MeshColorLayer_data_begin", "rna_iterator_array_next",
- "rna_iterator_array_end", "rna_iterator_array_get",
- "rna_MeshColorLayer_data_length", NULL, NULL, NULL);
+ RNA_def_property_collection_funcs(prop, "rna_MeshColorLayer_data_begin", "rna_iterator_array_next", "rna_iterator_array_end", "rna_iterator_array_get", "rna_MeshColorLayer_data_length", NULL, NULL, NULL);
srna= RNA_def_struct(brna, "MeshColor", NULL);
RNA_def_struct_sdna(srna, "MCol");
RNA_def_struct_ui_text(srna, "Mesh Vertex Color", "Vertex colors for a face in a Mesh");
RNA_def_struct_path_func(srna, "rna_MeshColor_path");
- prop= RNA_def_property(srna, "color1", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_float_funcs(prop, "rna_MeshColor_color1_get", "rna_MeshColor_color1_set", NULL);
- RNA_def_property_ui_text(prop, "Color 1", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop= RNA_def_property(srna, "color2", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_float_funcs(prop, "rna_MeshColor_color2_get", "rna_MeshColor_color2_set", NULL);
- RNA_def_property_ui_text(prop, "Color 2", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop= RNA_def_property(srna, "color3", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_float_funcs(prop, "rna_MeshColor_color3_get", "rna_MeshColor_color3_set", NULL);
- RNA_def_property_ui_text(prop, "Color 3", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop= RNA_def_property(srna, "color4", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_float_funcs(prop, "rna_MeshColor_color4_get", "rna_MeshColor_color4_set", NULL);
- RNA_def_property_ui_text(prop, "Color 4", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
@@ -1571,9 +1569,7 @@ static void rna_def_mproperties(BlenderRNA *brna)
prop= RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshFloatProperty");
RNA_def_property_ui_text(prop, "Data", "");
- RNA_def_property_collection_funcs(prop, "rna_MeshFloatPropertyLayer_data_begin", "rna_iterator_array_next",
- "rna_iterator_array_end", "rna_iterator_array_get",
- "rna_MeshFloatPropertyLayer_data_length", NULL, NULL, NULL);
+ RNA_def_property_collection_funcs(prop, "rna_MeshFloatPropertyLayer_data_begin", "rna_iterator_array_next", "rna_iterator_array_end", "rna_iterator_array_get", "rna_MeshFloatPropertyLayer_data_length", NULL, NULL, NULL);
srna= RNA_def_struct(brna, "MeshFloatProperty", NULL);
RNA_def_struct_sdna(srna, "MFloatProperty");
@@ -1599,9 +1595,7 @@ static void rna_def_mproperties(BlenderRNA *brna)
prop= RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshIntProperty");
RNA_def_property_ui_text(prop, "Data", "");
- RNA_def_property_collection_funcs(prop, "rna_MeshIntPropertyLayer_data_begin", "rna_iterator_array_next",
- "rna_iterator_array_end", "rna_iterator_array_get",
- "rna_MeshIntPropertyLayer_data_length", NULL, NULL, NULL);
+ RNA_def_property_collection_funcs(prop, "rna_MeshIntPropertyLayer_data_begin", "rna_iterator_array_next", "rna_iterator_array_end", "rna_iterator_array_get", "rna_MeshIntPropertyLayer_data_length", NULL, NULL, NULL);
srna= RNA_def_struct(brna, "MeshIntProperty", NULL);
RNA_def_struct_sdna(srna, "MIntProperty");
@@ -1627,9 +1621,7 @@ static void rna_def_mproperties(BlenderRNA *brna)
prop= RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshStringProperty");
RNA_def_property_ui_text(prop, "Data", "");
- RNA_def_property_collection_funcs(prop, "rna_MeshStringPropertyLayer_data_begin", "rna_iterator_array_next",
- "rna_iterator_array_end", "rna_iterator_array_get",
- "rna_MeshStringPropertyLayer_data_length", NULL, NULL, NULL);
+ RNA_def_property_collection_funcs(prop, "rna_MeshStringPropertyLayer_data_begin", "rna_iterator_array_next", "rna_iterator_array_end", "rna_iterator_array_get", "rna_MeshStringPropertyLayer_data_length", NULL, NULL, NULL);
srna= RNA_def_struct(brna, "MeshStringProperty", NULL);
RNA_def_struct_sdna(srna, "MStringProperty");
@@ -1642,6 +1634,45 @@ static void rna_def_mproperties(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
+void rna_def_texmat_common(StructRNA *srna, const char *texspace_editable)
+{
+ PropertyRNA *prop;
+
+ /* texture space */
+ prop= RNA_def_property(srna, "auto_texspace", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "texflag", AUTOSPACE);
+ RNA_def_property_ui_text(prop, "Auto Texture Space", "Adjusts active object's texture space automatically when transforming object");
+
+ prop= RNA_def_property(srna, "texspace_loc", PROP_FLOAT, PROP_TRANSLATION);
+ RNA_def_property_float_sdna(prop, NULL, "loc");
+ RNA_def_property_ui_text(prop, "Texure Space Location", "Texture space location");
+ RNA_def_property_editable_func(prop, texspace_editable);
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+
+ prop= RNA_def_property(srna, "texspace_size", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "size");
+ RNA_def_property_ui_text(prop, "Texture Space Size", "Texture space size");
+ RNA_def_property_editable_func(prop, texspace_editable);
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+
+ /* not supported yet
+ prop= RNA_def_property(srna, "texspace_rot", PROP_FLOAT, PROP_EULER);
+ RNA_def_property_float(prop, NULL, "rot");
+ RNA_def_property_ui_text(prop, "Texture Space Rotation", "Texture space rotation");
+ RNA_def_property_editable_func(prop, texspace_editable);
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");*/
+
+ /* materials */
+ prop= RNA_def_property(srna, "materials", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "mat", "totcol");
+ RNA_def_property_struct_type(prop, "Material");
+ RNA_def_property_ui_text(prop, "Materials", "");
+ RNA_def_property_srna(prop, "IDMaterials"); /* see rna_ID.c */
+ RNA_def_property_collection_funcs(prop, 0, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
+}
+
+
+/* scene.objects */
/* mesh.vertices */
static void rna_def_mesh_vertices(BlenderRNA *brna, PropertyRNA *cprop)
{
@@ -1687,7 +1718,7 @@ static void rna_def_mesh_faces(BlenderRNA *brna, PropertyRNA *cprop)
PropertyRNA *prop;
FunctionRNA *func;
- /*PropertyRNA *parm;*/
+ PropertyRNA *parm;
RNA_def_property_srna(cprop, "MeshFaces");
srna= RNA_def_struct(brna, "MeshFaces", NULL);
@@ -1698,17 +1729,64 @@ static void rna_def_mesh_faces(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_int_sdna(prop, NULL, "act_face");
RNA_def_property_ui_text(prop, "Active Face", "The active face for this mesh");
- prop= RNA_def_property(srna, "active_tface", PROP_POINTER, PROP_UNSIGNED);
- RNA_def_property_struct_type(prop, "MeshTextureFace");
- RNA_def_property_pointer_funcs(prop, "rna_Mesh_active_mtface_get", NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Active Texture Face", "Active Texture Face");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
func= RNA_def_function(srna, "add", "ED_mesh_faces_add");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- RNA_def_int(func, "count", 0, 0, INT_MAX, "Count", "Number of vertices to add", 0, INT_MAX);
+ parm= RNA_def_int(func, "count", 0, 0, INT_MAX, "Count", "Number of vertices to add", 0, INT_MAX);
+}
+
+/* mesh.loops */
+static void rna_def_mesh_loops(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ /*PropertyRNA *prop;*/
+
+ FunctionRNA *func;
+ /*PropertyRNA *parm;*/
+
+ RNA_def_property_srna(cprop, "MeshLoops");
+ srna= RNA_def_struct(brna, "MeshLoops", NULL);
+ RNA_def_struct_sdna(srna, "Mesh");
+ RNA_def_struct_ui_text(srna, "Mesh Loops", "Collection of mesh loops");
+
+#if 0 // BMESH_TODO
+ prop= RNA_def_property(srna, "active", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "act_face");
+ RNA_def_property_ui_text(prop, "Active Polygon", "The active polygon for this mesh");
+#endif
+
+ func= RNA_def_function(srna, "add", "ED_mesh_loops_add");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_int(func, "count", 0, 0, INT_MAX, "Count", "Number of loops to add", 0, INT_MAX);
+}
+
+/* mesh.polygons */
+static void rna_def_mesh_polygons(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+// PropertyRNA *prop;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "MeshPolygons");
+ srna= RNA_def_struct(brna, "MeshPolygons", NULL);
+ RNA_def_struct_sdna(srna, "Mesh");
+ RNA_def_struct_ui_text(srna, "Mesh Polygons", "Collection of mesh polygons");
+
+#if 0 // BMESH_TODO
+ prop= RNA_def_property(srna, "active", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "act_face");
+ RNA_def_property_ui_text(prop, "Active Polygon", "The active polygon for this mesh");
+#endif
+
+ func= RNA_def_function(srna, "add", "ED_mesh_polys_add");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm= RNA_def_int(func, "count", 0, 0, INT_MAX, "Count", "Number of polygons to add", 0, INT_MAX);
}
+
/* mesh.vertex_colors */
static void rna_def_vertex_colors(BlenderRNA *brna, PropertyRNA *cprop)
{
@@ -1786,8 +1864,7 @@ static void rna_def_uv_textures(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop= RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop, "rna_Mesh_active_uv_texture_index_get",
- "rna_Mesh_active_uv_texture_index_set", "rna_Mesh_active_uv_texture_index_range");
+ RNA_def_property_int_funcs(prop, "rna_Mesh_active_uv_texture_index_get", "rna_Mesh_active_uv_texture_index_set", "rna_Mesh_active_uv_texture_index_range");
RNA_def_property_ui_text(prop, "Active UV Texture Index", "Active UV texture index");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
@@ -1819,6 +1896,18 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Faces", "Faces of the mesh");
rna_def_mesh_faces(brna, prop);
+ prop= RNA_def_property(srna, "loops", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "mloop", "totloop");
+ RNA_def_property_struct_type(prop, "MeshLoop");
+ RNA_def_property_ui_text(prop, "Loops", "Loops of the mesh");
+ rna_def_mesh_loops(brna, prop);
+
+ prop= RNA_def_property(srna, "polygons", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "mpoly", "totpoly");
+ RNA_def_property_struct_type(prop, "MeshPolygon");
+ RNA_def_property_ui_text(prop, "Polygons", "Polygons of the mesh");
+ rna_def_mesh_polygons(brna, prop);
+
prop= RNA_def_property(srna, "sticky", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "msticky", "totvert");
RNA_def_property_struct_type(prop, "MeshSticky");
@@ -1828,11 +1917,11 @@ static void rna_def_mesh(BlenderRNA *brna)
prop= RNA_def_property(srna, "texture_mesh", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "texcomesh");
RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK);
- RNA_def_property_ui_text(prop, "Texture Mesh", "Use another mesh for texture indices (vertex indices must be aligned)");
+ RNA_def_property_ui_text(prop, "Texture Mesh", "Use another mesh for texture indicies (vertex indicies must be aligned)");
/* UV textures */
prop= RNA_def_property(srna, "uv_textures", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
+ RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_uv_textures_begin", NULL, NULL, NULL,
"rna_Mesh_uv_textures_length", NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "MeshTextureFaceLayer");
@@ -1846,8 +1935,7 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Clone UV Texture", "UV texture to be used as cloning source");
prop= RNA_def_property(srna, "uv_texture_clone_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop, "rna_Mesh_uv_texture_clone_index_get",
- "rna_Mesh_uv_texture_clone_index_set", "rna_Mesh_active_uv_texture_index_range");
+ RNA_def_property_int_funcs(prop, "rna_Mesh_uv_texture_clone_index_get", "rna_Mesh_uv_texture_clone_index_set", "rna_Mesh_active_uv_texture_index_range");
RNA_def_property_ui_text(prop, "Clone UV Texture Index", "Clone UV texture index");
prop= RNA_def_property(srna, "uv_texture_stencil", PROP_POINTER, PROP_UNSIGNED);
@@ -1863,7 +1951,7 @@ static void rna_def_mesh(BlenderRNA *brna)
/* Vertex colors */
prop= RNA_def_property(srna, "vertex_colors", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
+ RNA_def_property_collection_sdna(prop, NULL, "ldata.layers", "ldata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_vertex_colors_begin", NULL, NULL, NULL,
"rna_Mesh_vertex_colors_length", NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "MeshColorLayer");
@@ -1871,21 +1959,21 @@ static void rna_def_mesh(BlenderRNA *brna)
rna_def_vertex_colors(brna, prop);
prop= RNA_def_property(srna, "layers_float", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
+ RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_float_layers_begin", NULL, NULL, NULL,
"rna_Mesh_float_layers_length", NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "MeshFloatPropertyLayer");
RNA_def_property_ui_text(prop, "Float Property Layers", "");
prop= RNA_def_property(srna, "layers_int", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
+ RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_int_layers_begin", NULL, NULL, NULL,
"rna_Mesh_int_layers_length", NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "MeshIntPropertyLayer");
RNA_def_property_ui_text(prop, "Int Property Layers", "");
prop= RNA_def_property(srna, "layers_string", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
+ RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
RNA_def_property_collection_funcs(prop, "rna_Mesh_string_layers_begin", NULL, NULL, NULL,
"rna_Mesh_string_layers_length", NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "MeshStringPropertyLayer");
@@ -1893,9 +1981,7 @@ static void rna_def_mesh(BlenderRNA *brna)
prop= RNA_def_property(srna, "use_auto_smooth", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_AUTOSMOOTH);
- RNA_def_property_ui_text(prop, "Auto Smooth",
- "Treat all set-smoothed faces with angles less than the "
- "specified angle as 'smooth' during render");
+ RNA_def_property_ui_text(prop, "Auto Smooth", "Treats all set-smoothed faces with angles less than the specified angle as 'smooth' during render");
#if 1 /* expose as radians */
prop= RNA_def_property(srna, "auto_smooth_angle", PROP_FLOAT, PROP_ANGLE);
@@ -1906,8 +1992,7 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "smoothresh");
RNA_def_property_range(prop, 1, 80);
#endif
- RNA_def_property_ui_text(prop, "Auto Smooth Angle",
- "Maximum angle between face normals that 'Auto Smooth' will operate on");
+ RNA_def_property_ui_text(prop, "Auto Smooth Angle", "Defines maximum angle between face normals that 'Auto Smooth' will operate on");
prop= RNA_def_property(srna, "show_double_sided", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_TWOSIDED);
@@ -1926,23 +2011,15 @@ static void rna_def_mesh(BlenderRNA *brna)
/* texture space */
prop= RNA_def_property(srna, "use_auto_texspace", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "texflag", AUTOSPACE);
- RNA_def_property_ui_text(prop, "Auto Texture Space",
- "Adjust active object's texture space automatically when transforming object");
- RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Mesh_texspace_set");
+ RNA_def_property_ui_text(prop, "Auto Texture Space", "Adjusts active object's texture space automatically when transforming object");
- prop= RNA_def_property(srna, "texspace_location", PROP_FLOAT, PROP_TRANSLATION);
+ /*prop= RNA_def_property(srna, "texspace_location", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Texture Space Location", "Texture space location");
RNA_def_property_editable_func(prop, "rna_Mesh_texspace_editable");
RNA_def_property_float_funcs(prop, "rna_Mesh_texspace_loc_get", "rna_Mesh_texspace_loc_set", NULL);
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
-
- prop= RNA_def_property(srna, "texspace_size", PROP_FLOAT, PROP_XYZ);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Texture Space Size", "Texture space size");
- RNA_def_property_editable_func(prop, "rna_Mesh_texspace_editable");
- RNA_def_property_float_funcs(prop, "rna_Mesh_texspace_size_get", "rna_Mesh_texspace_size_set", NULL);
- RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+ */
/* not supported yet
prop= RNA_def_property(srna, "texspace_rot", PROP_FLOAT, PROP_EULER);
@@ -1950,79 +2027,67 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Texture Space Rotation", "Texture space rotation");
RNA_def_property_editable_func(prop, texspace_editable);
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");*/
-
- /* materials */
- prop= RNA_def_property(srna, "materials", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "mat", "totcol");
- RNA_def_property_struct_type(prop, "Material");
- RNA_def_property_ui_text(prop, "Materials", "");
- RNA_def_property_srna(prop, "IDMaterials"); /* see rna_ID.c */
- RNA_def_property_collection_funcs(prop, 0, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
/* Mesh Draw Options for Edit Mode*/
prop= RNA_def_property(srna, "show_edges", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWEDGES);
- RNA_def_property_ui_text(prop, "Draw Edges", "Display selected edges using highlights in the 3D view and UV editor");
+ RNA_def_property_ui_text(prop, "Draw Edges", "Displays selected edges using hilights in the 3D view and UV editor");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
prop= RNA_def_property(srna, "show_all_edges", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_ALLEDGES);
- RNA_def_property_ui_text(prop, "All Edges", "Display all edges for wireframe in all view modes in the 3D view");
+ RNA_def_property_ui_text(prop, "All Edges", "Displays all edges for wireframe in all view modes in the 3D view");
RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL);
prop= RNA_def_property(srna, "show_faces", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWFACES);
- RNA_def_property_ui_text(prop, "Draw Faces", "Display all faces as shades in the 3D view and UV editor");
+ RNA_def_property_ui_text(prop, "Draw Faces", "Displays all faces as shades in the 3D view and UV editor");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
prop= RNA_def_property(srna, "show_normal_face", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWNORMALS);
- RNA_def_property_ui_text(prop, "Draw Normals", "Display face normals as lines");
+ RNA_def_property_ui_text(prop, "Draw Normals", "Displays face normals as lines");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
prop= RNA_def_property(srna, "show_normal_vertex", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAW_VNORMALS);
- RNA_def_property_ui_text(prop, "Draw Vertex Normals", "Display vertex normals as lines");
+ RNA_def_property_ui_text(prop, "Draw Vertex Normals", "Displays vertex normals as lines");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
prop= RNA_def_property(srna, "show_edge_crease", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWCREASES);
- RNA_def_property_ui_text(prop, "Draw Creases", "Display creases created for subsurf weighting");
+ RNA_def_property_ui_text(prop, "Draw Creases", "Displays creases created for subsurf weighting");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
prop= RNA_def_property(srna, "show_edge_bevel_weight", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWBWEIGHTS);
- RNA_def_property_ui_text(prop, "Draw Bevel Weights", "Display weights created for the Bevel modifier");
+ RNA_def_property_ui_text(prop, "Draw Bevel Weights", "Displays weights created for the Bevel modifier");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
prop= RNA_def_property(srna, "show_edge_seams", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWSEAMS);
- RNA_def_property_ui_text(prop, "Draw Seams", "Display UV unwrapping seams");
+ RNA_def_property_ui_text(prop, "Draw Seams", "Displays UV unwrapping seams");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
prop= RNA_def_property(srna, "show_edge_sharp", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWSHARP);
- RNA_def_property_ui_text(prop, "Draw Sharp", "Display sharp edges, used with the EdgeSplit modifier");
+ RNA_def_property_ui_text(prop, "Draw Sharp", "Displays sharp edges, used with the EdgeSplit modifier");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
prop= RNA_def_property(srna, "show_extra_edge_length", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWEXTRA_EDGELEN);
- RNA_def_property_ui_text(prop, "Edge Length",
- "Display selected edge lengths, using global values when set in the transform panel");
+ RNA_def_property_ui_text(prop, "Edge Length", "Displays selected edge lengths, Using global values when set in the transform panel");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
prop= RNA_def_property(srna, "show_extra_face_angle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWEXTRA_FACEANG);
- RNA_def_property_ui_text(prop, "Faces Angles",
- "Display the angles between the selected edges in degrees, using "
- "global values when set in the transform panel");
+ RNA_def_property_ui_text(prop, "Face Angles", "Displays the angles in the selected edges in degrees, Using global values when set in the transform panel");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
prop= RNA_def_property(srna, "show_extra_face_area", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWEXTRA_FACEAREA);
- RNA_def_property_ui_text(prop, "Face Area",
- "Display the area of selected faces, using global values when set in the transform panel");
+ RNA_def_property_ui_text(prop, "Face Area", "Displays the area of selected faces, Using global values when set in the transform panel");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
/* editflag */
@@ -2042,8 +2107,7 @@ static void rna_def_mesh(BlenderRNA *brna)
prop= RNA_def_property(srna, "use_mirror_topology", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "editflag", ME_EDIT_MIRROR_TOPO);
- RNA_def_property_ui_text(prop, "Topology Mirror",
- "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
+ RNA_def_property_ui_text(prop, "Topology Mirror", "Use topology based mirroring. For when both sides of mesh have matching, unique topology");
prop= RNA_def_property(srna, "use_paint_mask", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "editflag", ME_EDIT_PAINT_MASK);
@@ -2076,6 +2140,7 @@ static void rna_def_mesh(BlenderRNA *brna)
/* pointers */
rna_def_animdata_common(srna);
+ rna_def_texmat_common(srna, "rna_Mesh_texspace_editable");
RNA_api_mesh(srna);
}
@@ -2087,9 +2152,11 @@ void RNA_def_mesh(BlenderRNA *brna)
rna_def_mvert_group(brna);
rna_def_medge(brna);
rna_def_mface(brna);
- rna_def_mtface(brna);
+ rna_def_mloop(brna);
+ rna_def_mpolygon(brna);
+ rna_def_mtexpoly(brna);
rna_def_msticky(brna);
- rna_def_mcol(brna);
+ rna_def_mloopcol(brna);
rna_def_mproperties(brna);
}
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index 0a93c9b05c5..9bee359bbf5 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -40,7 +40,15 @@
#include "ED_mesh.h"
#ifdef RNA_RUNTIME
-
+const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, bContext *C, struct Mesh *mesh2)
+{
+ const char *ret = mesh_cmp(mesh, mesh2, FLT_EPSILON*60);
+
+ if (!ret)
+ ret = "Same";
+
+ return ret;
+}
#else
@@ -61,6 +69,13 @@ void RNA_api_mesh(StructRNA *srna)
RNA_def_boolean(func, "calc_edges", 0, "Calculate Edges", "Force recalculation of edges");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ func= RNA_def_function(srna, "unit_test_compare", "rna_Mesh_unit_test_compare");
+ parm= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to compare to");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ /* return value */
+ parm= RNA_def_string(func, "result", "nothing", 64, "Return value", "String description of result of comparison");
+ RNA_def_function_return(func, parm);
+
func= RNA_def_function(srna, "validate", "BKE_mesh_validate");
RNA_def_function_ui_description(func, "validate geometry, return True when the mesh has had "
"invalid geometry corrected/removed");
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 5eb317ede3e..30895a865c7 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -94,6 +94,7 @@ EnumPropertyItem modifier_type_items[] ={
{eModifierType_Smoke, "SMOKE", ICON_MOD_SMOKE, "Smoke", ""},
{eModifierType_Softbody, "SOFT_BODY", ICON_MOD_SOFT, "Soft Body", ""},
{eModifierType_Surface, "SURFACE", ICON_MOD_PHYSICS, "Surface", ""},
+ {eModifierType_NgonInterp, "NGONINTERP", ICON_MOD_LATTICE, "Precision UV Interpolation", ""},
{0, NULL, 0, NULL, NULL}};
#ifdef RNA_RUNTIME
@@ -178,6 +179,8 @@ static StructRNA* rna_Modifier_refine(struct PointerRNA *ptr)
return &RNA_MultiresModifier;
case eModifierType_Surface:
return &RNA_SurfaceModifier;
+ case eModifierType_NgonInterp:
+ return &RNA_NgonInterpModifier;
case eModifierType_Smoke:
return &RNA_SmokeModifier;
case eModifierType_Solidify:
@@ -479,7 +482,7 @@ static int rna_MultiresModifier_external_get(PointerRNA *ptr)
Object *ob= (Object*)ptr->id.data;
Mesh *me= ob->data;
- return CustomData_external_test(&me->fdata, CD_MDISPS);
+ return CustomData_external_test(&me->ldata, CD_MDISPS);
}
static void rna_MultiresModifier_filepath_get(PointerRNA *ptr, char *value)
@@ -2780,6 +2783,25 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna)
rna_def_modifier_weightvg_mask(brna, srna);
}
+
+
+static void rna_def_modifier_ngoninterp(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna= RNA_def_struct(brna, "NgonInterpModifier", "Modifier");
+ RNA_def_struct_ui_text(srna, "Precision UV Modifier", "Precision UV interpolation");
+ RNA_def_struct_sdna(srna, "NgonInterpModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_SCREW);
+
+ prop= RNA_def_property(srna, "resolution", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_range(prop, 1, 10000);
+ RNA_def_property_ui_range(prop, 1, 100, 1, 0);
+ RNA_def_property_ui_text(prop, "Resolution", "Size of interpolation grids");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+}
void RNA_def_modifier(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2880,6 +2902,7 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_weightvgedit(brna);
rna_def_modifier_weightvgmix(brna);
rna_def_modifier_weightvgproximity(brna);
+ rna_def_modifier_ngoninterp(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index f0ba435954b..b7886571988 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -46,6 +46,7 @@
#include "DNA_scene_types.h"
#include "DNA_meta_types.h"
+#include "BKE_tessmesh.h"
#include "BKE_group.h" /* needed for object_in_group() */
#include "BLO_sys_types.h" /* needed for intptr_t used in ED_mesh.h */
@@ -227,8 +228,8 @@ void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr)
/* exit/enter editmode to get new shape */
switch(ob->type) {
case OB_MESH:
- load_editMesh(scene, ob);
- make_editMesh(scene, ob);
+ EDBM_LoadEditBMesh(scene, ob);
+ EDBM_MakeEditBMesh(scene->toolsettings, scene, ob);
break;
case OB_CURVE:
case OB_SURF:
@@ -606,8 +607,8 @@ static void rna_Object_active_material_index_set(PointerRNA *ptr, int value)
if(ob->type==OB_MESH) {
Mesh *me= ob->data;
- if(me->edit_mesh)
- me->edit_mesh->mat_nr= value;
+ if(me->edit_btmesh)
+ me->edit_btmesh->mat_nr= value;
}
}
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 0acff2a5790..042cf748669 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -158,7 +158,7 @@ static Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int
dm = mesh_create_derived_view( sce, ob, mask );
tmpmesh = add_mesh( "Mesh" );
- DM_to_mesh( dm, tmpmesh );
+ DM_to_mesh( dm, tmpmesh, ob );
dm->release( dm );
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index fc3e7d96be7..6d9713b659e 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -39,6 +39,8 @@
#include "DNA_userdef_types.h"
#include "BLI_math.h"
+#include "BKE_tessmesh.h"
+
/* Include for Bake Options */
#include "RE_pipeline.h"
@@ -885,9 +887,9 @@ static void rna_Scene_editmesh_select_mode_set(PointerRNA *ptr, const int *value
if(scene->basact) {
Mesh *me= get_mesh(scene->basact->object);
- if(me && me->edit_mesh && me->edit_mesh->selectmode != flag) {
- me->edit_mesh->selectmode= flag;
- EM_selectmode_set(me->edit_mesh);
+ if(me && me->edit_btmesh && me->edit_btmesh->selectmode != flag) {
+ me->edit_btmesh->selectmode= flag;
+ EDBM_selectmode_set(me->edit_btmesh);
}
}
}
@@ -899,7 +901,7 @@ static void rna_Scene_editmesh_select_mode_update(Main *UNUSED(bmain), Scene *sc
if(scene->basact) {
me= get_mesh(scene->basact->object);
- if(me && me->edit_mesh==NULL)
+ if(me && me->edit_btmesh==NULL)
me= NULL;
}
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 659346974fa..1322d1d239b 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -334,7 +334,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_return(func, parm);
func= RNA_def_function(srna, "template_preview", "uiTemplatePreview");
- RNA_def_function_ui_description(func, "Item. A preview window for materials, textures, lamps, etc.");
+ RNA_def_function_ui_description(func, "Item. A preview window for materials, textures, lamps, etc");
parm= RNA_def_pointer(func, "id", "ID", "", "ID datablock");
RNA_def_property_flag(parm, PROP_REQUIRED);
RNA_def_boolean(func, "show_buttons", 1, "", "Show preview buttons?");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 898ee2b2623..fbb8218bc85 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -2539,7 +2539,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
/*{25, "NEPALI", 0, "Nepali (नेपाली)", "ne_NP"},*/
/* using the utf8 flipped form of Persian (فارسی) */
{26, "PERSIAN", 0, "Persian (ﯽﺳﺭﺎﻓ)", "fa_PE"},
- {27, "INDONESIAN", 0, "Indonesian (Bahasa indonesia)", "id_ID"},
{0, NULL, 0, NULL, NULL}};
srna= RNA_def_struct(brna, "UserPreferencesSystem", NULL);
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index 7e06ef1d017..f31565dd48e 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -33,6 +33,7 @@ set(INC
../blenloader
../makesdna
../makesrna
+ ../bmesh
../render/extern/include
../../../intern/elbeem/extern
../../../intern/guardedalloc
@@ -40,7 +41,7 @@ set(INC
set(INC_SYS
${ZLIB_INCLUDE_DIRS}
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
@@ -65,6 +66,7 @@ set(SRC
intern/MOD_meshdeform.c
intern/MOD_mirror.c
intern/MOD_multires.c
+ intern/MOD_ngoninterp.c
intern/MOD_none.c
intern/MOD_particleinstance.c
intern/MOD_particlesystem.c
diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h
index 1feee9ccf8a..48830e05bcd 100644
--- a/source/blender/modifiers/MOD_modifiertypes.h
+++ b/source/blender/modifiers/MOD_modifiertypes.h
@@ -74,6 +74,7 @@ extern ModifierTypeInfo modifierType_NavMesh;
extern ModifierTypeInfo modifierType_WeightVGEdit;
extern ModifierTypeInfo modifierType_WeightVGMix;
extern ModifierTypeInfo modifierType_WeightVGProximity;
+extern ModifierTypeInfo modifierType_NgonInterp;
/* MOD_util.c */
void modifier_type_init(ModifierTypeInfo *types[]);
diff --git a/source/blender/modifiers/SConscript b/source/blender/modifiers/SConscript
index 77a2d577fb5..c1f2ca63f6b 100644
--- a/source/blender/modifiers/SConscript
+++ b/source/blender/modifiers/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('intern/*.c')
incs = '. ./intern'
incs += ' #/intern/guardedalloc #/intern/decimation/extern #/intern/bsp/extern #/intern/elbeem/extern #/extern/glew/include'
-incs += ' ../render/extern/include ../blenloader'
+incs += ' ../render/extern/include ../blenloader ../bmesh'
incs += ' ../include ../blenlib ../makesdna ../makesrna ../blenkernel ../blenkernel/intern'
incs += ' ../gpu'
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 95e16f3bea4..b089fead356 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -136,13 +136,13 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct EditMesh *editData,
+ ModifierData *md, Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
ArmatureModifierData *amd = (ArmatureModifierData*) md;
DerivedMesh *dm = derivedData;
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+ if(!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data, 0);
modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
@@ -159,14 +159,14 @@ static void deformVertsEM(
}
static void deformMatricesEM(
- ModifierData *md, Object *ob, struct EditMesh *editData,
+ ModifierData *md, Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3],
float (*defMats)[3][3], int numVerts)
{
ArmatureModifierData *amd = (ArmatureModifierData*) md;
DerivedMesh *dm = derivedData;
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+ if(!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data, 0);
armature_deform_verts(amd->object, ob, dm, vertexCos, defMats, numVerts,
amd->deformflag, NULL, amd->defgrp_name);
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index f56eda674c5..5b94885f4af 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -28,17 +28,12 @@
*
*/
-/** \file blender/modifiers/intern/MOD_array.c
- * \ingroup modifiers
- */
-
-
/* Array modifier: duplicates the object multiple times along an axis */
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_math.h"
#include "BLI_ghash.h"
#include "BLI_edgehash.h"
@@ -51,10 +46,13 @@
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
+#include "BKE_tessmesh.h"
#include "depsgraph_private.h"
-#include "MOD_util.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
static void initData(ModifierData *md)
{
@@ -107,8 +105,8 @@ static void foreachObjectLink(
walk(userData, ob, &amd->offset_ob);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Scene *UNUSED(scene), Object *UNUSED(ob), DagNode *obNode)
+static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
+ Object *UNUSED(ob), DagNode *obNode)
{
ArrayModifierData *amd = (ArrayModifierData*) md;
@@ -157,28 +155,116 @@ static float vertarray_size(MVert *mvert, int numVerts, int axis)
return max_co - min_co;
}
-/* XXX This function fixes bad merging code, in some cases removing vertices creates indices > maxvert */
-
-static int test_index_face_maxvert(MFace *mface, CustomData *fdata, int mfindex, int nr, int maxvert)
+/* finds the best possible flipped name. For renaming; check for unique names afterwards */
+/* if strip_number: removes number extensions */
+void vertgroup_flip_name (char *name, int strip_number)
{
- if(mface->v1 >= maxvert) {
- // printf("bad index in array\n");
- mface->v1= maxvert - 1;
+ int len;
+ char prefix[128]={""}; /* The part before the facing */
+ char suffix[128]={""}; /* The part after the facing */
+ char replace[128]={""}; /* The replacement string */
+ char number[128]={""}; /* The number extension string */
+ char *index=NULL;
+
+ len= strlen(name);
+ if(len<3) return; // we don't do names like .R or .L
+
+ /* We first check the case with a .### extension, let's find the last period */
+ if(isdigit(name[len-1])) {
+ index= strrchr(name, '.'); // last occurrance
+ if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever!
+ if(strip_number==0)
+ strcpy(number, index);
+ *index= 0;
+ len= strlen(name);
+ }
}
- if(mface->v2 >= maxvert) {
- // printf("bad index in array\n");
- mface->v2= maxvert - 1;
+
+ strcpy (prefix, name);
+
+#define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_')
+
+ /* first case; separator . - _ with extensions r R l L */
+ if( IS_SEPARATOR(name[len-2]) ) {
+ switch(name[len-1]) {
+ case 'l':
+ prefix[len-1]= 0;
+ strcpy(replace, "r");
+ break;
+ case 'r':
+ prefix[len-1]= 0;
+ strcpy(replace, "l");
+ break;
+ case 'L':
+ prefix[len-1]= 0;
+ strcpy(replace, "R");
+ break;
+ case 'R':
+ prefix[len-1]= 0;
+ strcpy(replace, "L");
+ break;
+ }
}
- if(mface->v3 >= maxvert) {
- // printf("bad index in array\n");
- mface->v3= maxvert - 1;
+ /* case; beginning with r R l L , with separator after it */
+ else if( IS_SEPARATOR(name[1]) ) {
+ switch(name[0]) {
+ case 'l':
+ strcpy(replace, "r");
+ strcpy(suffix, name+1);
+ prefix[0]= 0;
+ break;
+ case 'r':
+ strcpy(replace, "l");
+ strcpy(suffix, name+1);
+ prefix[0]= 0;
+ break;
+ case 'L':
+ strcpy(replace, "R");
+ strcpy(suffix, name+1);
+ prefix[0]= 0;
+ break;
+ case 'R':
+ strcpy(replace, "L");
+ strcpy(suffix, name+1);
+ prefix[0]= 0;
+ break;
+ }
}
- if(mface->v4 >= maxvert) {
- // printf("bad index in array\n");
- mface->v4= maxvert - 1;
+ else if(len > 5) {
+ /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
+ index = BLI_strcasestr(prefix, "right");
+ if (index==prefix || index==prefix+len-5) {
+ if(index[0]=='r')
+ strcpy (replace, "left");
+ else {
+ if(index[1]=='I')
+ strcpy (replace, "LEFT");
+ else
+ strcpy (replace, "Left");
+ }
+ *index= 0;
+ strcpy (suffix, index+5);
+ }
+ else {
+ index = BLI_strcasestr(prefix, "left");
+ if (index==prefix || index==prefix+len-4) {
+ if(index[0]=='l')
+ strcpy (replace, "right");
+ else {
+ if(index[1]=='E')
+ strcpy (replace, "RIGHT");
+ else
+ strcpy (replace, "Right");
+ }
+ *index= 0;
+ strcpy (suffix, index+4);
+ }
+ }
}
-
- return test_index_face(mface, fdata, mfindex, nr);
+
+#undef IS_SEPARATOR
+
+ sprintf (name, "%s%s%s%s", prefix, replace, suffix, number);
}
typedef struct IndexMapEntry {
@@ -220,45 +306,34 @@ static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
}
static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
- struct Scene *scene, Object *ob, DerivedMesh *dm,
- int initFlags)
+ Scene *scene, Object *ob, DerivedMesh *dm,
+ int UNUSED(initFlags))
{
- int i, j;
+ DerivedMesh *cddm = dm; //copying shouldn't be necassary here, as all modifiers return CDDM's
+ BMEditMesh *em = CDDM_To_BMesh(ob, cddm, NULL);
+ BMOperator op, oldop, weldop;
+ int i, j, indexLen;
/* offset matrix */
float offset[4][4];
- float final_offset[4][4];
- float tmp_mat[4][4];
float length = amd->length;
- int count = amd->count;
- int numVerts, numEdges, numFaces;
- int maxVerts, maxEdges, maxFaces;
- int finalVerts, finalEdges, finalFaces;
- DerivedMesh *result, *start_cap = NULL, *end_cap = NULL;
- MVert *mvert, *src_mvert;
- MEdge *medge;
- MFace *mface;
-
- IndexMapEntry *indexMap;
-
- EdgeHash *edges;
+ int count = amd->count, maxVerts;
+ int *indexMap = NULL;
+ DerivedMesh *start_cap = NULL, *end_cap = NULL;
+ MVert *src_mvert;
/* need to avoid infinite recursion here */
if(amd->start_cap && amd->start_cap != ob)
- start_cap = amd->start_cap->derivedFinal;
+ start_cap = mesh_get_derived_final(scene, amd->start_cap, CD_MASK_MESH);
if(amd->end_cap && amd->end_cap != ob)
- end_cap = amd->end_cap->derivedFinal;
+ end_cap = mesh_get_derived_final(scene, amd->end_cap, CD_MASK_MESH);
unit_m4(offset);
- indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm),
- "indexmap");
-
- src_mvert = dm->getVertArray(dm);
-
- maxVerts = dm->getNumVerts(dm);
+ src_mvert = cddm->getVertArray(dm);
+ maxVerts = cddm->getNumVerts(dm);
if(amd->offset_type & MOD_ARR_OFF_CONST)
- add_v3_v3(offset[3], amd->offset);
+ add_v3_v3v3(offset[3], offset[3], amd->offset);
if(amd->offset_type & MOD_ARR_OFF_RELATIVE) {
for(j = 0; j < 3; j++)
offset[3][j] += amd->scale[j] * vertarray_size(src_mvert,
@@ -276,7 +351,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
mul_serie_m4(result_mat, offset,
obinv, amd->offset_ob->obmat,
- NULL, NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL);
copy_m4_m4(offset, result_mat);
}
@@ -285,10 +360,10 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
if(cu) {
float tmp_mat[3][3];
float scale;
-
+
object_to_mat3(amd->curve_ob, tmp_mat);
scale = mat3_to_scale(tmp_mat);
-
+
if(!cu->path) {
cu->flag |= CU_PATH; // needed for path & bevlist
makeDispListCurveTypes(scene, amd->curve_ob, 0);
@@ -301,8 +376,9 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
/* calculate the maximum number of copies which will fit within the
prescribed length */
if(amd->fit_type == MOD_ARR_FITLENGTH
- || amd->fit_type == MOD_ARR_FITCURVE) {
- float dist = sqrt(dot_v3v3(offset[3], offset[3]));
+ || amd->fit_type == MOD_ARR_FITCURVE)
+ {
+ float dist = sqrt(INPR(offset[3], offset[3]));
if(dist > 1e-6f)
/* this gives length = first copy start to last copy end
@@ -316,484 +392,118 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
if(count < 1)
count = 1;
- /* allocate memory for count duplicates (including original) plus
- * start and end caps
- */
- finalVerts = dm->getNumVerts(dm) * count;
- finalEdges = dm->getNumEdges(dm) * count;
- finalFaces = dm->getNumFaces(dm) * count;
- if(start_cap) {
- finalVerts += start_cap->getNumVerts(start_cap);
- finalEdges += start_cap->getNumEdges(start_cap);
- finalFaces += start_cap->getNumFaces(start_cap);
- }
- if(end_cap) {
- finalVerts += end_cap->getNumVerts(end_cap);
- finalEdges += end_cap->getNumEdges(end_cap);
- finalFaces += end_cap->getNumFaces(end_cap);
- }
- result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces);
-
- /* calculate the offset matrix of the final copy (for merging) */
- unit_m4(final_offset);
+ BMO_Init_Op(&weldop, "weldverts");
+ BMO_InitOpf(em->bm, &op, "dupe geom=%avef");
+ oldop = op;
+ for (j=0; j < count - 1; j++) {
+ BMVert *v, *v2;
+ BMOpSlot *s1;
+ BMOpSlot *s2;
- for(j=0; j < count - 1; j++) {
- mul_m4_m4m4(tmp_mat, final_offset, offset);
- copy_m4_m4(final_offset, tmp_mat);
- }
+ BMO_InitOpf(em->bm, &op, "dupe geom=%s", &oldop, j==0 ? "geom" : "newout");
+ BMO_Exec_Op(em->bm, &op);
- numVerts = numEdges = numFaces = 0;
- mvert = CDDM_get_verts(result);
+ s1 = BMO_GetSlot(&op, "geom");
+ s2 = BMO_GetSlot(&op, "newout");
- for (i = 0; i < maxVerts; i++) {
- indexMap[i].merge = -1; /* default to no merge */
- indexMap[i].merge_final = 0; /* default to no merge */
- }
+ BMO_CallOpf(em->bm, "transform mat=%m4 verts=%s", offset, &op, "newout");
- for (i = 0; i < maxVerts; i++) {
- MVert *inMV;
- MVert *mv = &mvert[numVerts];
- MVert *mv2;
- float co[3];
+ #define _E(s, i) ((BMVert**)(s)->data.buf)[i]
- inMV = &src_mvert[i];
+ /*calculate merge mapping*/
+ if (j == 0) {
+ BMOperator findop;
+ BMOIter oiter;
+ BMVert *v, *v2;
+ BMHeader *h;
- DM_copy_vert_data(dm, result, i, numVerts, 1);
- *mv = *inMV;
- numVerts++;
+ BMO_InitOpf(em->bm, &findop,
+ "finddoubles verts=%av dist=%f keepverts=%s",
+ amd->merge_dist, &op, "geom");
- indexMap[i].new = numVerts - 1;
-
- copy_v3_v3(co, mv->co);
-
- /* Attempts to merge verts from one duplicate with verts from the
- * next duplicate which are closer than amd->merge_dist.
- * Only the first such vert pair is merged.
- * If verts are merged in the first duplicate pair, they are merged
- * in all pairs.
- */
- if((count > 1) && (amd->flags & MOD_ARR_MERGE)) {
- float tmp_co[3];
- mul_v3_m4v3(tmp_co, offset, mv->co);
-
- for(j = 0; j < maxVerts; j++) {
- /* if vertex already merged, don't use it */
- if( indexMap[j].merge != -1 ) continue;
-
- inMV = &src_mvert[j];
- /* if this vert is within merge limit, merge */
- if(compare_len_v3v3(tmp_co, inMV->co, amd->merge_dist)) {
- indexMap[i].merge = j;
-
- /* test for merging with final copy of merge target */
- if(amd->flags & MOD_ARR_MERGEFINAL) {
- copy_v3_v3(tmp_co, inMV->co);
- inMV = &src_mvert[i];
- mul_m4_v3(final_offset, tmp_co);
- if(compare_len_v3v3(tmp_co, inMV->co, amd->merge_dist))
- indexMap[i].merge_final = 1;
- }
- break;
- }
+ i = 0;
+ BMO_ITER(h, &oiter, em->bm, &op, "geom", BM_ALL) {
+ BM_SetIndex(h, i);
+ i++;
}
- }
-
- /* if no merging, generate copies of this vert */
- if(indexMap[i].merge < 0) {
- for(j=0; j < count - 1; j++) {
- mv2 = &mvert[numVerts];
-
- DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1);
- *mv2 = *mv;
- numVerts++;
- mul_m4_v3(offset, co);
- copy_v3_v3(mv2->co, co);
+ BMO_ITER(h, &oiter, em->bm, &op, "newout", BM_ALL) {
+ BM_SetIndex(h, i);
+ i++;
}
- } else if(indexMap[i].merge != i && indexMap[i].merge_final) {
- /* if this vert is not merging with itself, and it is merging
- * with the final copy of its merge target, remove the first copy
- */
- numVerts--;
- DM_free_vert_data(result, numVerts, 1);
- }
- }
-
- /* make a hashtable so we can avoid duplicate edges from merging */
- edges = BLI_edgehash_new();
- maxEdges = dm->getNumEdges(dm);
- medge = CDDM_get_edges(result);
- for(i = 0; i < maxEdges; i++) {
- MEdge inMED;
- MEdge med;
- MEdge *med2;
- int vert1, vert2;
+ BMO_Exec_Op(em->bm, &findop);
- dm->getEdge(dm, i, &inMED);
-
- med = inMED;
- med.v1 = indexMap[inMED.v1].new;
- med.v2 = indexMap[inMED.v2].new;
-
- /* if vertices are to be merged with the final copies of their
- * merge targets, calculate that final copy
- */
- if(indexMap[inMED.v1].merge_final) {
- med.v1 = calc_mapping(indexMap, indexMap[inMED.v1].merge,
- count - 1);
- }
- if(indexMap[inMED.v2].merge_final) {
- med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge,
- count - 1);
- }
-
- if(med.v1 == med.v2) continue;
-
- /* XXX Unfortunately the calc_mapping returns sometimes numVerts... leads to bad crashes */
- if(med.v1 >= numVerts)
- med.v1= numVerts-1;
- if(med.v2 >= numVerts)
- med.v2= numVerts-1;
-
- if (initFlags) {
- med.flag |= ME_EDGEDRAW | ME_EDGERENDER;
- }
-
- if(!BLI_edgehash_haskey(edges, med.v1, med.v2)) {
- DM_copy_edge_data(dm, result, i, numEdges, 1);
- medge[numEdges] = med;
- numEdges++;
-
- BLI_edgehash_insert(edges, med.v1, med.v2, NULL);
- }
+ indexLen = i;
+ indexMap = MEM_callocN(sizeof(int)*indexLen, "indexMap");
- for(j = 1; j < count; j++)
- {
- vert1 = calc_mapping(indexMap, inMED.v1, j);
- vert2 = calc_mapping(indexMap, inMED.v2, j);
+ /*element type argument doesn't do anything here*/
+ BMO_ITER(v, &oiter, em->bm, &findop, "targetmapout", 0) {
+ v2 = BMO_IterMapValp(&oiter);
- /* edge could collapse to single point after mapping */
- if(vert1 == vert2) continue;
-
- /* XXX Unfortunately the calc_mapping returns sometimes numVerts... leads to bad crashes */
- if(vert1 >= numVerts)
- vert1= numVerts-1;
- if(vert2 >= numVerts)
- vert2= numVerts-1;
-
- /* avoid duplicate edges */
- if(!BLI_edgehash_haskey(edges, vert1, vert2)) {
- med2 = &medge[numEdges];
-
- DM_copy_edge_data(dm, result, i, numEdges, 1);
- *med2 = med;
- numEdges++;
-
- med2->v1 = vert1;
- med2->v2 = vert2;
-
- BLI_edgehash_insert(edges, med2->v1, med2->v2, NULL);
+ indexMap[BM_GetIndex(v)] = BM_GetIndex(v2)+1;
}
- }
- }
- maxFaces = dm->getNumFaces(dm);
- mface = CDDM_get_faces(result);
- for (i=0; i < maxFaces; i++) {
- MFace inMF;
- MFace *mf = &mface[numFaces];
-
- dm->getFace(dm, i, &inMF);
-
- DM_copy_face_data(dm, result, i, numFaces, 1);
- *mf = inMF;
-
- mf->v1 = indexMap[inMF.v1].new;
- mf->v2 = indexMap[inMF.v2].new;
- mf->v3 = indexMap[inMF.v3].new;
- if(inMF.v4)
- mf->v4 = indexMap[inMF.v4].new;
-
- /* if vertices are to be merged with the final copies of their
- * merge targets, calculate that final copy
- */
- if(indexMap[inMF.v1].merge_final)
- mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-1);
- if(indexMap[inMF.v2].merge_final)
- mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-1);
- if(indexMap[inMF.v3].merge_final)
- mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-1);
- if(inMF.v4 && indexMap[inMF.v4].merge_final)
- mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-1);
-
- if(test_index_face_maxvert(mf, &result->faceData, numFaces, inMF.v4?4:3, numVerts) < 3)
- continue;
-
- numFaces++;
-
- /* if the face has fewer than 3 vertices, don't create it */
- if(mf->v3 == 0 || (mf->v1 && (mf->v1 == mf->v3 || mf->v1 == mf->v4))) {
- numFaces--;
- DM_free_face_data(result, numFaces, 1);
+ BMO_Finish_Op(em->bm, &findop);
}
- for(j = 1; j < count; j++)
- {
- MFace *mf2 = &mface[numFaces];
-
- DM_copy_face_data(dm, result, i, numFaces, 1);
- *mf2 = *mf;
+ /*generate merge mappping using index map. we do this by using the
+ operator slots as lookup arrays.*/
+ #define E(i) (i) < s1->len ? _E(s1, i) : _E(s2, (i)-s1->len)
- mf2->v1 = calc_mapping(indexMap, inMF.v1, j);
- mf2->v2 = calc_mapping(indexMap, inMF.v2, j);
- mf2->v3 = calc_mapping(indexMap, inMF.v3, j);
- if (inMF.v4)
- mf2->v4 = calc_mapping(indexMap, inMF.v4, j);
+ for (i=0; i<indexLen; i++) {
+ if (!indexMap[i]) continue;
- numFaces++;
+ v = E(i);
+ v2 = E(indexMap[i]-1);
- /* if the face has fewer than 3 vertices, don't create it */
- if(test_index_face_maxvert(mf2, &result->faceData, numFaces-1, inMF.v4?4:3, numVerts) < 3) {
- numFaces--;
- DM_free_face_data(result, numFaces, 1);
- }
- }
- }
-
- /* add start and end caps */
- if(start_cap) {
- float startoffset[4][4];
- MVert *cap_mvert;
- MEdge *cap_medge;
- MFace *cap_mface;
- int *origindex;
- int *vert_map;
- int capVerts, capEdges, capFaces;
-
- capVerts = start_cap->getNumVerts(start_cap);
- capEdges = start_cap->getNumEdges(start_cap);
- capFaces = start_cap->getNumFaces(start_cap);
- cap_mvert = start_cap->getVertArray(start_cap);
- cap_medge = start_cap->getEdgeArray(start_cap);
- cap_mface = start_cap->getFaceArray(start_cap);
-
- invert_m4_m4(startoffset, offset);
-
- vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
- "arrayModifier_doArray vert_map");
-
- origindex = result->getVertDataArray(result, CD_ORIGINDEX);
- for(i = 0; i < capVerts; i++) {
- MVert *mv = &cap_mvert[i];
- short merged = 0;
-
- if(amd->flags & MOD_ARR_MERGE) {
- float tmp_co[3];
- MVert *in_mv;
- int j;
-
- copy_v3_v3(tmp_co, mv->co);
- mul_m4_v3(startoffset, tmp_co);
-
- for(j = 0; j < maxVerts; j++) {
- in_mv = &src_mvert[j];
- /* if this vert is within merge limit, merge */
- if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) {
- vert_map[i] = calc_mapping(indexMap, j, 0);
- merged = 1;
- break;
- }
- }
- }
-
- if(!merged) {
- DM_copy_vert_data(start_cap, result, i, numVerts, 1);
- mvert[numVerts] = *mv;
- mul_m4_v3(startoffset, mvert[numVerts].co);
- origindex[numVerts] = ORIGINDEX_NONE;
-
- vert_map[i] = numVerts;
-
- numVerts++;
- }
+ BMO_Insert_MapPointer(em->bm, &weldop, "targetmap", v, v2);
}
- origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
- for(i = 0; i < capEdges; i++) {
- int v1, v2;
-
- v1 = vert_map[cap_medge[i].v1];
- v2 = vert_map[cap_medge[i].v2];
- if(!BLI_edgehash_haskey(edges, v1, v2)) {
- DM_copy_edge_data(start_cap, result, i, numEdges, 1);
- medge[numEdges] = cap_medge[i];
- medge[numEdges].v1 = v1;
- medge[numEdges].v2 = v2;
- origindex[numEdges] = ORIGINDEX_NONE;
+ #undef E
+ #undef _E
- numEdges++;
- }
- }
- origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
- for(i = 0; i < capFaces; i++) {
- DM_copy_face_data(start_cap, result, i, numFaces, 1);
- mface[numFaces] = cap_mface[i];
- mface[numFaces].v1 = vert_map[mface[numFaces].v1];
- mface[numFaces].v2 = vert_map[mface[numFaces].v2];
- mface[numFaces].v3 = vert_map[mface[numFaces].v3];
- if(mface[numFaces].v4) {
- mface[numFaces].v4 = vert_map[mface[numFaces].v4];
-
- test_index_face_maxvert(&mface[numFaces], &result->faceData,
- numFaces, 4, numVerts);
- }
- else
- {
- test_index_face(&mface[numFaces], &result->faceData,
- numFaces, 3);
- }
-
- origindex[numFaces] = ORIGINDEX_NONE;
-
- numFaces++;
- }
-
- MEM_freeN(vert_map);
- start_cap->release(start_cap);
+ BMO_Finish_Op(em->bm, &oldop);
+ oldop = op;
}
- if(end_cap) {
- float endoffset[4][4];
- MVert *cap_mvert;
- MEdge *cap_medge;
- MFace *cap_mface;
- int *origindex;
- int *vert_map;
- int capVerts, capEdges, capFaces;
-
- capVerts = end_cap->getNumVerts(end_cap);
- capEdges = end_cap->getNumEdges(end_cap);
- capFaces = end_cap->getNumFaces(end_cap);
- cap_mvert = end_cap->getVertArray(end_cap);
- cap_medge = end_cap->getEdgeArray(end_cap);
- cap_mface = end_cap->getFaceArray(end_cap);
-
- mul_m4_m4m4(endoffset, final_offset, offset);
-
- vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
- "arrayModifier_doArray vert_map");
-
- origindex = result->getVertDataArray(result, CD_ORIGINDEX);
- for(i = 0; i < capVerts; i++) {
- MVert *mv = &cap_mvert[i];
- short merged = 0;
-
- if(amd->flags & MOD_ARR_MERGE) {
- float tmp_co[3];
- MVert *in_mv;
- int j;
-
- copy_v3_v3(tmp_co, mv->co);
- mul_m4_v3(offset, tmp_co);
-
- for(j = 0; j < maxVerts; j++) {
- in_mv = &src_mvert[j];
- /* if this vert is within merge limit, merge */
- if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) {
- vert_map[i] = calc_mapping(indexMap, j, count - 1);
- merged = 1;
- break;
- }
- }
- }
-
- if(!merged) {
- DM_copy_vert_data(end_cap, result, i, numVerts, 1);
- mvert[numVerts] = *mv;
- mul_m4_v3(endoffset, mvert[numVerts].co);
- origindex[numVerts] = ORIGINDEX_NONE;
-
- vert_map[i] = numVerts;
-
- numVerts++;
- }
- }
- origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
- for(i = 0; i < capEdges; i++) {
- int v1, v2;
-
- v1 = vert_map[cap_medge[i].v1];
- v2 = vert_map[cap_medge[i].v2];
+ if (j > 0) BMO_Finish_Op(em->bm, &op);
- if(!BLI_edgehash_haskey(edges, v1, v2)) {
- DM_copy_edge_data(end_cap, result, i, numEdges, 1);
- medge[numEdges] = cap_medge[i];
- medge[numEdges].v1 = v1;
- medge[numEdges].v2 = v2;
- origindex[numEdges] = ORIGINDEX_NONE;
-
- numEdges++;
- }
- }
- origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
- for(i = 0; i < capFaces; i++) {
- DM_copy_face_data(end_cap, result, i, numFaces, 1);
- mface[numFaces] = cap_mface[i];
- mface[numFaces].v1 = vert_map[mface[numFaces].v1];
- mface[numFaces].v2 = vert_map[mface[numFaces].v2];
- mface[numFaces].v3 = vert_map[mface[numFaces].v3];
- if(mface[numFaces].v4) {
- mface[numFaces].v4 = vert_map[mface[numFaces].v4];
-
- test_index_face(&mface[numFaces], &result->faceData,
- numFaces, 4);
- }
- else
- {
- test_index_face(&mface[numFaces], &result->faceData,
- numFaces, 3);
- }
- origindex[numFaces] = ORIGINDEX_NONE;
+ if (amd->flags & MOD_ARR_MERGE)
+ BMO_Exec_Op(em->bm, &weldop);
- numFaces++;
- }
+ BMO_Finish_Op(em->bm, &weldop);
- MEM_freeN(vert_map);
- end_cap->release(end_cap);
- }
+ BMEdit_RecalcTesselation(em);
+ cddm = CDDM_from_BMEditMesh(em, NULL, 0);
- BLI_edgehash_free(edges, NULL);
+ BMEdit_Free(em);
+ MEM_freeN(em);
MEM_freeN(indexMap);
- CDDM_lower_num_verts(result, numVerts);
- CDDM_lower_num_edges(result, numEdges);
- CDDM_lower_num_faces(result, numFaces);
-
- return result;
+ return cddm;
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *dm,
- int UNUSED(useRenderParams),
- int UNUSED(isFinalCalc))
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int UNUSED(useRenderParams), int UNUSED(isFinalCalc))
{
DerivedMesh *result;
ArrayModifierData *amd = (ArrayModifierData*) md;
- result = arrayModifier_doArray(amd, md->scene, ob, dm, 0);
+ result = arrayModifier_doArray(amd, md->scene, ob, derivedData, 0);
- if(result != dm)
- CDDM_calc_normals(result);
+ //if(result != derivedData)
+ // CDDM_calc_normals(result);
return result;
}
-static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
- struct EditMesh *UNUSED(editData),
- DerivedMesh *dm)
+static DerivedMesh *applyModifierEM(
+ ModifierData *md, Object *ob, struct BMEditMesh *UNUSED(editData),
+ DerivedMesh *derivedData)
{
- return applyModifier(md, ob, dm, 0, 1);
+ return applyModifier(md, ob, derivedData, 0, 1);
}
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index c746b10755e..1ae79825d48 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -90,6 +90,10 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
int UNUSED(useRenderParams),
int UNUSED(isFinalCalc))
{
+#if 1 /*BMESH_TODO*/
+ (void)md;
+ return CDDM_copy(derivedData, 0);
+#else
DerivedMesh *result;
BME_Mesh *bm;
@@ -112,12 +116,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
BME_free_mesh(bm);
CDDM_calc_normals(result);
-
- return result;
+#endif
}
static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
- EditMesh *UNUSED(editData),
+ struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData)
{
return applyModifier(md, ob, derivedData, 0, 1);
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 1828781690b..3b13f1b21c0 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -97,12 +97,12 @@ static DerivedMesh *get_quick_derivedMesh(DerivedMesh *derivedData, DerivedMesh
if(derivedData->getNumFaces(derivedData) == 0 || dm->getNumFaces(dm) == 0) {
switch(operation) {
case eBooleanModifierOp_Intersect:
- result = CDDM_new(0, 0, 0);
+ result = CDDM_new(0, 0, 0, 0, 0);
break;
case eBooleanModifierOp_Union:
if(derivedData->getNumFaces(derivedData)) result = derivedData;
- else result = CDDM_copy(dm);
+ else result = CDDM_copy(dm, FALSE);
break;
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.c b/source/blender/modifiers/intern/MOD_boolean_util.c
index 843501133c5..d83fa0f6c2d 100644
--- a/source/blender/modifiers/intern/MOD_boolean_util.c
+++ b/source/blender/modifiers/intern/MOD_boolean_util.c
@@ -173,14 +173,14 @@ static int FaceIt_Done(CSG_IteratorPtr it)
{
// assume CSG_IteratorPtr is of the correct type.
FaceIt * iterator = (FaceIt *)it;
- return(iterator->pos >= iterator->dm->getNumFaces(iterator->dm));
+ return(iterator->pos >= iterator->dm->getNumTessFaces(iterator->dm));
}
static void FaceIt_Fill(CSG_IteratorPtr it, CSG_IFace *face)
{
// assume CSG_IteratorPtr is of the correct type.
FaceIt *face_it = (FaceIt *)it;
- MFace *mfaces = face_it->dm->getFaceArray(face_it->dm);
+ MFace *mfaces = face_it->dm->getTessFaceArray(face_it->dm);
MFace *mface = &mfaces[face_it->pos];
/* reverse face vertices if necessary */
@@ -254,7 +254,7 @@ static void FaceIt_Construct(
output->Fill = FaceIt_Fill;
output->Done = FaceIt_Done;
output->Reset = FaceIt_Reset;
- output->num_elements = it->dm->getNumFaces(it->dm);
+ output->num_elements = it->dm->getNumTessFaces(it->dm);
output->it = it;
}
@@ -304,8 +304,8 @@ static void InterpCSGFace(
MFace *mface, *orig_mface;
int j;
- mface = CDDM_get_face(dm, index);
- orig_mface = orig_dm->getFaceArray(orig_dm) + orig_index;
+ mface = CDDM_get_tessface(dm, index);
+ orig_mface = orig_dm->getTessFaceArray(orig_dm) + orig_index;
// get the vertex coordinates from the original mesh
orig_co[0] = (orig_dm->getVertArray(orig_dm) + orig_mface->v1)->co;
@@ -346,14 +346,14 @@ static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
DerivedMesh *dm2,
Object *ob2)
{
- DerivedMesh *result, *orig_dm;
+ DerivedMesh *result, *orig_dm, *dm;
GHash *material_hash = NULL;
Mesh *me1= (Mesh*)ob1->data;
Mesh *me2= (Mesh*)ob2->data;
int i;
// create a new DerivedMesh
- result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements);
+ result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements, 0, 0);
CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
CD_DEFAULT, face_it->num_elements);
CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
@@ -393,16 +393,16 @@ static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
face_it->Step(face_it->it);
// find the original mesh and data
- orig_ob = (csgface.orig_face < dm1->getNumFaces(dm1))? ob1: ob2;
- orig_dm = (csgface.orig_face < dm1->getNumFaces(dm1))? dm1: dm2;
+ orig_ob = (csgface.orig_face < dm1->getNumTessFaces(dm1))? ob1: ob2;
+ orig_dm = (csgface.orig_face < dm1->getNumTessFaces(dm1))? dm1: dm2;
orig_me = (orig_ob == ob1)? me1: me2;
- orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - dm1->getNumFaces(dm1);
+ orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - dm1->getNumTessFaces(dm1);
// copy all face layers, including mface
CustomData_copy_data(&orig_dm->faceData, &result->faceData, orig_index, i, 1);
// set mface
- mface = CDDM_get_face(result, i);
+ mface = CDDM_get_tessface(result, i);
mface->v1 = csgface.vertex_index[0];
mface->v2 = csgface.vertex_index[1];
mface->v3 = csgface.vertex_index[2];
@@ -433,9 +433,13 @@ static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
BLI_ghash_free(material_hash, NULL, NULL);
CDDM_calc_edges(result);
- CDDM_calc_normals(result);
- return result;
+ dm = CDDM_copy(result, 1); /*builds ngon faces from tess (mface) faces*/
+ CDDM_calc_normals(dm);
+ result->needsFree = 1;
+ result->release(result);
+
+ return dm;
}
static void BuildMeshDescriptors(
@@ -468,7 +472,7 @@ static DerivedMesh *NewBooleanDerivedMesh_intern(
DerivedMesh *result = NULL;
if (dm == NULL || dm_select == NULL) return 0;
- if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select)) return 0;
+ if (!dm->getNumTessFaces(dm) || !dm_select->getNumTessFaces(dm_select)) return 0;
// we map the final object back into ob's local coordinate space. For this
// we need to compute the inverse transform from global to ob (inv_mat),
@@ -500,7 +504,7 @@ static DerivedMesh *NewBooleanDerivedMesh_intern(
}
BuildMeshDescriptors(dm_select, ob_select, 0, &fd_1, &vd_1);
- BuildMeshDescriptors(dm, ob, dm_select->getNumFaces(dm_select) , &fd_2, &vd_2);
+ BuildMeshDescriptors(dm, ob, dm_select->getNumTessFaces(dm_select) , &fd_2, &vd_2);
bool_op = CSG_NewBooleanFunction();
@@ -554,7 +558,7 @@ int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type)
/* put some checks in for nice user feedback */
if (dm == NULL || dm_select == NULL) return 0;
- if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select))
+ if (!dm->getNumTessFaces(dm) || !dm_select->getNumTessFaces(dm_select))
{
MEM_freeN(mat);
return -1;
@@ -571,7 +575,7 @@ int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type)
ob_new= AddNewBlenderMesh(scene, base_select);
me_new= ob_new->data;
- DM_to_mesh(result, me_new);
+ DM_to_mesh(result, me_new, ob_new);
result->release(result);
dm->release(dm);
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index 10c2f6019ed..87989b541f5 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -83,10 +83,12 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DerivedMesh *dm = derivedData;
DerivedMesh *result;
BuildModifierData *bmd = (BuildModifierData*) md;
- int i;
- int numFaces, numEdges;
+ int i, j, k;
+ int numFaces, numEdges, numLoops = 0;
int *vertMap, *edgeMap, *faceMap;
float frac;
+ MPoly *mpolys, *mpolyd;
+ MLoop *mld, *mloops, *mls, *mloopd;
GHashIterator *hashIter;
/* maps vert indices in old mesh to indices in new mesh */
GHash *vertHash = BLI_ghash_new(BLI_ghashutil_inthash,
@@ -94,11 +96,18 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* maps edge indices in new mesh to indices in old mesh */
GHash *edgeHash = BLI_ghash_new(BLI_ghashutil_inthash,
BLI_ghashutil_intcmp, "build ed apply gh");
+ GHash *edgeHash2 = BLI_ghash_new(BLI_ghashutil_inthash,
+ BLI_ghashutil_intcmp, "build ed apply gh");
const int maxVerts= dm->getNumVerts(dm);
const int maxEdges= dm->getNumEdges(dm);
const int maxFaces= dm->getNumFaces(dm);
-
+
+ if (!CDDM_Check(dm)) {
+ result = CDDM_copy(dm, 0);
+ dm = result;
+ }
+
vertMap = MEM_callocN(sizeof(*vertMap) * maxVerts, "build modifier vertMap");
for(i = 0; i < maxVerts; ++i) vertMap[i] = i;
edgeMap = MEM_callocN(sizeof(*edgeMap) * maxEdges, "build modifier edgeMap");
@@ -119,6 +128,10 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* if there's at least one face, build based on faces */
if(numFaces) {
+ MPoly *mpoly, *mp;
+ MLoop *ml, *mloop;
+ MEdge *medge;
+
if(bmd->randomize)
BLI_array_randomize(faceMap, sizeof(*faceMap),
maxFaces, bmd->seed);
@@ -126,37 +139,40 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* get the set of all vert indices that will be in the final mesh,
* mapped to the new indices
*/
+ mpoly = CDDM_get_polys(dm);
+ mloop = CDDM_get_loops(dm);
for(i = 0; i < numFaces; ++i) {
- MFace mf;
- dm->getFace(dm, faceMap[i], &mf);
-
- if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v1),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
- if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v2),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
- if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v3),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
- if(mf.v4 && !BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v4),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ mp = mpoly + faceMap[i];
+ ml = mloop + mp->loopstart;
+
+ for (j=0; j<mp->totloop; j++, ml++) {
+ if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml->v)))
+ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(ml->v),
+ SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ }
+
+ numLoops += mp->totloop;
}
/* get the set of edges that will be in the new mesh (i.e. all edges
* that have both verts in the new mesh)
*/
+ medge = CDDM_get_edges(dm);
for(i = 0; i < maxEdges; ++i) {
- MEdge me;
- dm->getEdge(dm, i, &me);
-
- if(BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1))
- && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
- BLI_ghash_insert(edgeHash,
- SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)), SET_INT_IN_POINTER(i));
+ MEdge *me = medge + i;
+
+ if(BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1))
+ && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2)))
+ {
+ j = BLI_ghash_size(edgeHash);
+
+ BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(j), SET_INT_IN_POINTER(i));
+ BLI_ghash_insert(edgeHash2, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(j));
+ }
}
} else if(numEdges) {
+ MEdge *medge, *me;
+
if(bmd->randomize)
BLI_array_randomize(edgeMap, sizeof(*edgeMap),
maxEdges, bmd->seed);
@@ -164,26 +180,27 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* get the set of all vert indices that will be in the final mesh,
* mapped to the new indices
*/
+ medge = CDDM_get_edges(dm);
for(i = 0; i < numEdges; ++i) {
- MEdge me;
- dm->getEdge(dm, edgeMap[i], &me);
+ me = medge + edgeMap[i];
- if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v1),
+ if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1)))
+ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me->v1),
SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
- if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v2),
+ if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2)))
+ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me->v2),
SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
}
/* get the set of edges that will be in the new mesh
*/
for(i = 0; i < numEdges; ++i) {
- MEdge me;
- dm->getEdge(dm, edgeMap[i], &me);
-
- BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)),
+ j = BLI_ghash_size(edgeHash);
+
+ BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(j),
SET_INT_IN_POINTER(edgeMap[i]));
+ BLI_ghash_insert(edgeHash2, SET_INT_IN_POINTER(edgeMap[i]),
+ SET_INT_IN_POINTER(j));
}
} else {
int numVerts = dm->getNumVerts(dm) * frac;
@@ -203,7 +220,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
* the mesh
*/
result = CDDM_from_template(dm, BLI_ghash_size(vertHash),
- BLI_ghash_size(edgeHash), numFaces);
+ BLI_ghash_size(edgeHash), 0, numLoops, numFaces);
/* copy the vertices across */
for( hashIter = BLI_ghashIterator_new(vertHash);
@@ -239,38 +256,48 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
*dest = source;
}
+ mpolys = CDDM_get_polys(dm);
+ mpolyd = CDDM_get_polys(result);
+ mloops = CDDM_get_loops(dm);
+ mloopd = mld = CDDM_get_loops(result);
+
/* copy the faces across, remapping indices */
+ k = 0;
for(i = 0; i < numFaces; ++i) {
- MFace source;
- MFace *dest;
- int orig_v4;
-
- dm->getFace(dm, faceMap[i], &source);
- dest = CDDM_get_face(result, i);
-
- orig_v4 = source.v4;
-
- source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
- source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
- source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3)));
- if(source.v4)
- source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
+ MPoly *source;
+ MPoly *dest;
+ source = mpolys + faceMap[i];
+ dest = mpolyd + i;
DM_copy_face_data(dm, result, faceMap[i], i, 1);
- *dest = source;
- test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3));
+ *dest = *source;
+ dest->loopstart = k;
+
+ DM_copy_loop_data(dm, result, source->loopstart, dest->loopstart, dest->totloop);
+
+ mls = mloops + source->loopstart;
+ for (j=0; j<source->totloop; j++, k++, mls++, mld++) {
+ mld->v = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(mls->v)));
+ mld->e = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash2, SET_INT_IN_POINTER(mls->e)));
+ }
}
CDDM_calc_normals(result);
BLI_ghash_free(vertHash, NULL, NULL);
BLI_ghash_free(edgeHash, NULL, NULL);
+ BLI_ghash_free(edgeHash2, NULL, NULL);
MEM_freeN(vertMap);
MEM_freeN(edgeMap);
MEM_freeN(faceMap);
+ if (dm != derivedData) {
+ dm->needsFree = 1;
+ dm->release(dm);
+ }
+
return result;
}
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index c91cabd4a37..10b0aebbe39 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -590,7 +590,7 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct EditMesh *editData,
+ ModifierData *md, Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = get_dm(ob, editData, derivedData, NULL, 0);
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index 0cd3481c899..99d608351d8 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -117,7 +117,7 @@ static void deformVerts(ModifierData *md, Object *ob,
MVert *tempVert = NULL;
/* if possible use/create DerivedMesh */
- if(derivedData) dm = CDDM_copy(derivedData);
+ if(derivedData) dm = CDDM_copy(derivedData, 0);
else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob);
if(!ob->pd)
@@ -166,8 +166,8 @@ static void deformVerts(ModifierData *md, Object *ob,
collmd->numverts = numverts;
- collmd->mfaces = dm->dupFaceArray(dm);
- collmd->numfaces = dm->getNumFaces(dm);
+ collmd->mfaces = dm->dupTessFaceArray(dm);
+ collmd->numfaces = dm->getNumTessFaces(dm);
// create bounding box hierarchy
collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft);
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index bdf67c25e74..da676325cd9 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -124,12 +124,12 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct EditMesh *editData,
+ ModifierData *md, Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+ if(!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data, 0);
deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c
index aba68dc9edc..f533e205fe6 100644
--- a/source/blender/modifiers/intern/MOD_decimate.c
+++ b/source/blender/modifiers/intern/MOD_decimate.c
@@ -82,9 +82,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
int a, numTris;
mvert = dm->getVertArray(dm);
- mface = dm->getFaceArray(dm);
+ mface = dm->getTessFaceArray(dm);
totvert = dm->getNumVerts(dm);
- totface = dm->getNumFaces(dm);
+ totface = dm->getNumTessFaces(dm);
numTris = 0;
for (a=0; a<totface; a++) {
@@ -96,7 +96,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
if(numTris<3) {
modifier_setError(md,
"Modifier requires more than 3 input faces (triangles).");
- goto exit;
+ dm = CDDM_copy(dm, 0);
+ return dm;
}
lod.vertex_buffer= MEM_mallocN(3*sizeof(float)*totvert, "vertices");
@@ -140,11 +141,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
}
if(lod.vertex_num>2) {
- result = CDDM_new(lod.vertex_num, 0, lod.face_num);
+ result = CDDM_new(lod.vertex_num, 0, lod.face_num, 0, 0);
dmd->faceCount = lod.face_num;
}
else
- result = CDDM_new(lod.vertex_num, 0, 0);
+ result = CDDM_new(lod.vertex_num, 0, 0, 0, 0);
mvert = CDDM_get_verts(result);
for(a=0; a<lod.vertex_num; a++) {
@@ -155,7 +156,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
}
if(lod.vertex_num>2) {
- mface = CDDM_get_faces(result);
+ mface = CDDM_get_tessfaces(result);
for(a=0; a<lod.face_num; a++) {
MFace *mf = &mface[a];
int *tri = &lod.triangle_index_buffer[a*3];
@@ -167,7 +168,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
}
CDDM_calc_edges(result);
- CDDM_calc_normals(result);
}
else
modifier_setError(md, "Out of memory.");
@@ -181,8 +181,12 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
MEM_freeN(lod.vertex_normal_buffer);
MEM_freeN(lod.triangle_index_buffer);
-exit:
- return result;
+ dm = CDDM_copy(result, 1); /*builds ngon faces from tess (mface) faces*/
+ CDDM_calc_normals(dm);
+ result->needsFree = 1;
+ result->release(result);
+
+ return dm;
}
#else // WITH_MOD_DECIMATE
static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob),
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index a7a25fbb00e..5bb8f0aefbf 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -188,7 +188,8 @@ static void displaceModifier_do(
tex_co = MEM_callocN(sizeof(*tex_co) * numVerts,
"displaceModifier_do tex_co");
get_texture_coords((MappingInfoModifierData *)dmd, ob, dm, vertexCos, tex_co, numVerts);
-
+
+
for(i = 0; i < numVerts; ++i) {
TexResult texres;
float delta = 0, strength = dmd->strength;
@@ -251,7 +252,7 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct EditMesh *editData,
+ ModifierData *md, Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm= get_cddm(ob, editData, derivedData, vertexCos);
diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c
index 939ce123613..4b78592ffa6 100644
--- a/source/blender/modifiers/intern/MOD_edgesplit.c
+++ b/source/blender/modifiers/intern/MOD_edgesplit.c
@@ -36,32 +36,93 @@
/* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
* or edge angle (can be used to achieve autosmoothing) */
-#include <assert.h>
-
#include "DNA_meshdata_types.h"
+#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_memarena.h"
#include "BLI_edgehash.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
+#include "BLI_array.h"
+#include "BLI_smallhash.h"
#include "BLI_linklist.h"
-
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
+#include "BKE_tessmesh.h"
+#include "BKE_mesh.h"
#include "MEM_guardedalloc.h"
-#include "MOD_util.h"
+/* EdgeSplit */
+/* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
+ * or edge angle (can be used to achieve autosmoothing)
+*/
+
+#define EDGE_MARK 1
+
+static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Object *ob)
+{
+ BMesh *bm;
+ BMEditMesh *em;
+ DerivedMesh *cddm;
+ BMIter iter, liter;
+ BMFace *f;
+ BMLoop *l;
+ BMEdge *e;
+ /* int allocsize[] = {512, 512, 2048, 512}; */ /* UNUSED */
+ float threshold = cos((emd->split_angle + 0.00001) * M_PI / 180.0);
+
+ if (!CDDM_Check(dm)) {
+ cddm = CDDM_copy(dm, 0);
+ } else cddm = dm;
+
+ em = CDDM_To_BMesh(ob, dm, NULL);
+ bm = em->bm;
-#if 0
-#define EDGESPLIT_DEBUG_3
-#define EDGESPLIT_DEBUG_2
-#define EDGESPLIT_DEBUG_1
-#define EDGESPLIT_DEBUG_0
-#endif
+ BM_Compute_Normals(bm);
+ BMO_push(bm, NULL);
+
+ if (emd->flags & MOD_EDGESPLIT_FROMANGLE) {
+ BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+ BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+ float edge_angle_cos;
+
+ if (l->radial_next == l)
+ continue;
+
+ edge_angle_cos = INPR(f->no, l->radial_next->f->no);
+ if (edge_angle_cos < threshold) {
+ BMO_SetFlag(bm, l->e, EDGE_MARK);
+ }
+ }
+ }
+ }
+
+ if (emd->flags & MOD_EDGESPLIT_FROMFLAG) {
+ BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+ if (BM_TestHFlag(e, BM_SHARP))
+ BMO_SetFlag(bm, e, EDGE_MARK);
+ }
+ }
+
+ BMO_CallOpf(bm, "edgesplit edges=%fe", EDGE_MARK);
+
+ BMO_pop(bm);
+ BMEdit_RecalcTesselation(em);
+
+ if (cddm != dm) {
+ cddm->needsFree = 1;
+ cddm->release(cddm);
+ }
+
+ cddm = CDDM_from_BMEditMesh(em, NULL, 1);
+ BMEdit_Free(em);
+ MEM_freeN(em);
+
+ return cddm;
+}
static void initData(ModifierData *md)
{
@@ -82,1192 +143,23 @@ static void copyData(ModifierData *md, ModifierData *target)
temd->flags = emd->flags;
}
-/* Mesh data for edgesplit operation */
-typedef struct SmoothVert {
- LinkNode *faces; /* all faces which use this vert */
- int oldIndex; /* the index of the original DerivedMesh vert */
- int newIndex; /* the index of the new DerivedMesh vert */
-} SmoothVert;
-
-#define SMOOTHEDGE_NUM_VERTS 2
-
-typedef struct SmoothEdge {
- SmoothVert *verts[SMOOTHEDGE_NUM_VERTS]; /* the verts used by this edge */
- LinkNode *faces; /* all faces which use this edge */
- int oldIndex; /* the index of the original DerivedMesh edge */
- int newIndex; /* the index of the new DerivedMesh edge */
- short flag; /* the flags from the original DerivedMesh edge */
-} SmoothEdge;
-
-#define SMOOTHFACE_MAX_EDGES 4
-
-typedef struct SmoothFace {
- SmoothEdge *edges[SMOOTHFACE_MAX_EDGES]; /* nonexistent edges == NULL */
- int flip[SMOOTHFACE_MAX_EDGES]; /* 1 = flip edge dir, 0 = don't flip */
- float normal[3]; /* the normal of this face */
- int oldIndex; /* the index of the original DerivedMesh face */
- int newIndex; /* the index of the new DerivedMesh face */
-} SmoothFace;
-
-typedef struct SmoothMesh {
- SmoothVert *verts;
- SmoothEdge *edges;
- SmoothFace *faces;
- int num_verts, num_edges, num_faces;
- int max_verts, max_edges, max_faces;
- DerivedMesh *dm;
- float threshold; /* the cosine of the smoothing angle */
- int flags;
- MemArena *arena;
- ListBase propagatestack, reusestack;
-} SmoothMesh;
-
-static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
-{
- SmoothVert *copy = &mesh->verts[mesh->num_verts];
-
- assert(vert != NULL);
-
- if(mesh->num_verts >= mesh->max_verts) {
- printf("Attempted to add a SmoothMesh vert beyond end of array\n");
- return NULL;
- }
-
- *copy = *vert;
- copy->faces = NULL;
- copy->newIndex = mesh->num_verts;
- ++mesh->num_verts;
-
-#ifdef EDGESPLIT_DEBUG_2
- printf("copied vert %4d to vert %4d\n", vert->newIndex, copy->newIndex);
-#endif
- return copy;
-}
-
-static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
-{
- SmoothEdge *copy = &mesh->edges[mesh->num_edges];
-
- if(mesh->num_edges >= mesh->max_edges) {
- printf("Attempted to add a SmoothMesh edge beyond end of array\n");
- return NULL;
- }
-
- *copy = *edge;
- copy->faces = NULL;
- copy->newIndex = mesh->num_edges;
- ++mesh->num_edges;
-
-#ifdef EDGESPLIT_DEBUG_2
- printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
-#endif
- return copy;
-}
-
-static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
-{
- int i;
- for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
- if(edge->verts[i] == vert) return 1;
-
- return 0;
-}
-
-static SmoothMesh *smoothmesh_new(int num_verts, int num_edges, int num_faces,
- int max_verts, int max_edges, int max_faces)
-{
- SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh");
- mesh->verts = MEM_callocN(sizeof(*mesh->verts) * max_verts,
- "SmoothMesh.verts");
- mesh->edges = MEM_callocN(sizeof(*mesh->edges) * max_edges,
- "SmoothMesh.edges");
- mesh->faces = MEM_callocN(sizeof(*mesh->faces) * max_faces,
- "SmoothMesh.faces");
-
- mesh->num_verts = num_verts;
- mesh->num_edges = num_edges;
- mesh->num_faces = num_faces;
-
- mesh->max_verts = max_verts;
- mesh->max_edges = max_edges;
- mesh->max_faces = max_faces;
-
- return mesh;
-}
-
-static void smoothmesh_free(SmoothMesh *mesh)
-{
- int i;
-
- for(i = 0; i < mesh->num_verts; ++i)
- BLI_linklist_free(mesh->verts[i].faces, NULL);
-
- for(i = 0; i < mesh->num_edges; ++i)
- BLI_linklist_free(mesh->edges[i].faces, NULL);
-
- if(mesh->arena)
- BLI_memarena_free(mesh->arena);
-
- MEM_freeN(mesh->verts);
- MEM_freeN(mesh->edges);
- MEM_freeN(mesh->faces);
- MEM_freeN(mesh);
-}
-
-static void smoothmesh_resize_verts(SmoothMesh *mesh, int max_verts)
-{
- int i;
- SmoothVert *tmp;
-
- if(max_verts <= mesh->max_verts) return;
-
- tmp = MEM_callocN(sizeof(*tmp) * max_verts, "SmoothMesh.verts");
-
- memcpy(tmp, mesh->verts, sizeof(*tmp) * mesh->num_verts);
-
- /* remap vert pointers in edges */
- for(i = 0; i < mesh->num_edges; ++i) {
- int j;
- SmoothEdge *edge = &mesh->edges[i];
-
- for(j = 0; j < SMOOTHEDGE_NUM_VERTS; ++j)
- /* pointer arithmetic to get vert array index */
- edge->verts[j] = &tmp[edge->verts[j] - mesh->verts];
- }
-
- MEM_freeN(mesh->verts);
- mesh->verts = tmp;
- mesh->max_verts = max_verts;
-}
-
-static void smoothmesh_resize_edges(SmoothMesh *mesh, int max_edges)
-{
- int i;
- SmoothEdge *tmp;
-
- if(max_edges <= mesh->max_edges) return;
-
- tmp = MEM_callocN(sizeof(*tmp) * max_edges, "SmoothMesh.edges");
-
- memcpy(tmp, mesh->edges, sizeof(*tmp) * mesh->num_edges);
-
- /* remap edge pointers in faces */
- for(i = 0; i < mesh->num_faces; ++i) {
- int j;
- SmoothFace *face = &mesh->faces[i];
-
- for(j = 0; j < SMOOTHFACE_MAX_EDGES; ++j)
- if(face->edges[j])
- /* pointer arithmetic to get edge array index */
- face->edges[j] = &tmp[face->edges[j] - mesh->edges];
- }
-
- MEM_freeN(mesh->edges);
- mesh->edges = tmp;
- mesh->max_edges = max_edges;
-}
-
-#ifdef EDGESPLIT_DEBUG_0
-static void smoothmesh_print(SmoothMesh *mesh)
-{
- int i, j;
- DerivedMesh *dm = mesh->dm;
-
- printf("--- SmoothMesh ---\n");
- printf("--- Vertices ---\n");
- for(i = 0; i < mesh->num_verts; i++) {
- SmoothVert *vert = &mesh->verts[i];
- LinkNode *node;
- MVert mv;
-
- dm->getVert(dm, vert->oldIndex, &mv);
-
- printf("%3d: ind={%3d, %3d}, pos={% 5.1f, % 5.1f, % 5.1f}",
- i, vert->oldIndex, vert->newIndex,
- mv.co[0], mv.co[1], mv.co[2]);
- printf(", faces={");
- for(node = vert->faces; node != NULL; node = node->next) {
- printf(" %d", ((SmoothFace *)node->link)->newIndex);
- }
- printf("}\n");
- }
-
- printf("\n--- Edges ---\n");
- for(i = 0; i < mesh->num_edges; i++) {
- SmoothEdge *edge = &mesh->edges[i];
- LinkNode *node;
-
- printf("%4d: indices={%4d, %4d}, verts={%4d, %4d}",
- i,
- edge->oldIndex, edge->newIndex,
- edge->verts[0]->newIndex, edge->verts[1]->newIndex);
- if(edge->verts[0] == edge->verts[1]) printf(" <- DUPLICATE VERTEX");
- printf(", faces={");
- for(node = edge->faces; node != NULL; node = node->next) {
- printf(" %d", ((SmoothFace *)node->link)->newIndex);
- }
- printf("}\n");
- }
-
- printf("\n--- Faces ---\n");
- for(i = 0; i < mesh->num_faces; i++) {
- SmoothFace *face = &mesh->faces[i];
-
- printf("%4d: indices={%4d, %4d}, edges={", i,
- face->oldIndex, face->newIndex);
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- if(face->flip[j])
- printf(" -%-2d", face->edges[j]->newIndex);
- else
- printf(" %-2d", face->edges[j]->newIndex);
- }
- printf("}, verts={");
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- printf(" %d", face->edges[j]->verts[face->flip[j]]->newIndex);
- }
- printf("}\n");
- }
-}
-#endif
-
-static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
-{
- SmoothMesh *mesh;
- EdgeHash *edges = BLI_edgehash_new();
- int i;
- int totvert, totedge, totface;
-
- totvert = dm->getNumVerts(dm);
- totedge = dm->getNumEdges(dm);
- totface = dm->getNumFaces(dm);
-
- mesh = smoothmesh_new(totvert, totedge, totface,
- totvert, totedge, totface);
-
- mesh->dm = dm;
-
- for(i = 0; i < totvert; i++) {
- SmoothVert *vert = &mesh->verts[i];
-
- vert->oldIndex = vert->newIndex = i;
- }
-
- for(i = 0; i < totedge; i++) {
- SmoothEdge *edge = &mesh->edges[i];
- MEdge med;
-
- dm->getEdge(dm, i, &med);
- edge->verts[0] = &mesh->verts[med.v1];
- edge->verts[1] = &mesh->verts[med.v2];
- edge->oldIndex = edge->newIndex = i;
- edge->flag = med.flag;
-
- BLI_edgehash_insert(edges, med.v1, med.v2, edge);
- }
-
- for(i = 0; i < totface; i++) {
- SmoothFace *face = &mesh->faces[i];
- MFace mf;
- MVert v1, v2, v3;
- int j;
-
- dm->getFace(dm, i, &mf);
-
- dm->getVert(dm, mf.v1, &v1);
- dm->getVert(dm, mf.v2, &v2);
- dm->getVert(dm, mf.v3, &v3);
- face->edges[0] = BLI_edgehash_lookup(edges, mf.v1, mf.v2);
- if(face->edges[0]->verts[1]->oldIndex == mf.v1) face->flip[0] = 1;
- face->edges[1] = BLI_edgehash_lookup(edges, mf.v2, mf.v3);
- if(face->edges[1]->verts[1]->oldIndex == mf.v2) face->flip[1] = 1;
- if(mf.v4) {
- MVert v4;
- dm->getVert(dm, mf.v4, &v4);
- face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v4);
- if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
- face->edges[3] = BLI_edgehash_lookup(edges, mf.v4, mf.v1);
- if(face->edges[3]->verts[1]->oldIndex == mf.v4) face->flip[3] = 1;
- normal_quad_v3( face->normal,v1.co, v2.co, v3.co, v4.co);
- } else {
- face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v1);
- if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
- face->edges[3] = NULL;
- normal_tri_v3( face->normal,v1.co, v2.co, v3.co);
- }
-
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- SmoothEdge *edge = face->edges[j];
- BLI_linklist_prepend(&edge->faces, face);
- BLI_linklist_prepend(&edge->verts[face->flip[j]]->faces, face);
- }
-
- face->oldIndex = face->newIndex = i;
- }
-
- BLI_edgehash_free(edges, NULL);
-
- return mesh;
-}
-
-static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
-{
- DerivedMesh *result = CDDM_from_template(mesh->dm,
- mesh->num_verts,
- mesh->num_edges,
- mesh->num_faces);
- MVert *new_verts = CDDM_get_verts(result);
- MEdge *new_edges = CDDM_get_edges(result);
- MFace *new_faces = CDDM_get_faces(result);
- int i;
-
- for(i = 0; i < mesh->num_verts; ++i) {
- SmoothVert *vert = &mesh->verts[i];
- MVert *newMV = &new_verts[vert->newIndex];
-
- DM_copy_vert_data(mesh->dm, result,
- vert->oldIndex, vert->newIndex, 1);
- mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV);
- }
-
- for(i = 0; i < mesh->num_edges; ++i) {
- SmoothEdge *edge = &mesh->edges[i];
- MEdge *newME = &new_edges[edge->newIndex];
-
- DM_copy_edge_data(mesh->dm, result,
- edge->oldIndex, edge->newIndex, 1);
- mesh->dm->getEdge(mesh->dm, edge->oldIndex, newME);
- newME->v1 = edge->verts[0]->newIndex;
- newME->v2 = edge->verts[1]->newIndex;
- }
-
- for(i = 0; i < mesh->num_faces; ++i) {
- SmoothFace *face = &mesh->faces[i];
- MFace *newMF = &new_faces[face->newIndex];
-
- DM_copy_face_data(mesh->dm, result,
- face->oldIndex, face->newIndex, 1);
- mesh->dm->getFace(mesh->dm, face->oldIndex, newMF);
-
- newMF->v1 = face->edges[0]->verts[face->flip[0]]->newIndex;
- newMF->v2 = face->edges[1]->verts[face->flip[1]]->newIndex;
- newMF->v3 = face->edges[2]->verts[face->flip[2]]->newIndex;
-
- if(face->edges[3]) {
- newMF->v4 = face->edges[3]->verts[face->flip[3]]->newIndex;
- } else {
- newMF->v4 = 0;
- }
- }
-
- return result;
-}
-
-/* returns the other vert in the given edge
- */
-static SmoothVert *other_vert(SmoothEdge *edge, SmoothVert *vert)
-{
- if(edge->verts[0] == vert) return edge->verts[1];
- else return edge->verts[0];
-}
-
-/* returns the other edge in the given face that uses the given vert
- * returns NULL if no other edge in the given face uses the given vert
- * (this should never happen)
- */
-static SmoothEdge *other_edge(SmoothFace *face, SmoothVert *vert,
- SmoothEdge *edge)
-{
- int i,j;
- for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
- SmoothEdge *tmp_edge = face->edges[i];
- if(tmp_edge == edge) continue;
-
- for(j = 0; j < SMOOTHEDGE_NUM_VERTS; j++)
- if(tmp_edge->verts[j] == vert) return tmp_edge;
- }
-
- /* if we get to here, something's wrong (there should always be 2 edges
- * which use the same vert in a face)
- */
- return NULL;
-}
-
-/* returns a face attached to the given edge which is not the given face.
- * returns NULL if no other faces use this edge.
- */
-static SmoothFace *other_face(SmoothEdge *edge, SmoothFace *face)
-{
- LinkNode *node;
-
- for(node = edge->faces; node != NULL; node = node->next)
- if(node->link != face) return node->link;
-
- return NULL;
-}
-
-#if 0
-/* copies source list to target, overwriting target (target is not freed)
- * nodes in the copy will be in the same order as in source
- */
-static void linklist_copy(LinkNode **target, LinkNode *source)
-{
- LinkNode *node = NULL;
- *target = NULL;
-
- for(; source; source = source->next) {
- if(node) {
- node->next = MEM_mallocN(sizeof(*node->next), "nlink_copy");
- node = node->next;
- } else {
- node = *target = MEM_mallocN(sizeof(**target), "nlink_copy");
- }
- node->link = source->link;
- node->next = NULL;
- }
-}
-#endif
-
-/* appends source to target if it's not already in target */
-static void linklist_append_unique(LinkNode **target, void *source)
-{
- LinkNode *node;
- LinkNode *prev = NULL;
-
- /* check if source value is already in the list */
- for(node = *target; node; prev = node, node = node->next)
- if(node->link == source) return;
-
- node = MEM_mallocN(sizeof(*node), "nlink");
- node->next = NULL;
- node->link = source;
-
- if(prev) prev->next = node;
- else *target = node;
-}
-
-/* appends elements of source which aren't already in target to target */
-static void linklist_append_list_unique(LinkNode **target, LinkNode *source)
-{
- for(; source; source = source->next)
- linklist_append_unique(target, source->link);
-}
-
-#if 0 /* this is no longer used, it should possibly be removed */
-/* prepends prepend to list - doesn't copy nodes, just joins the lists */
-static void linklist_prepend_linklist(LinkNode **list, LinkNode *prepend)
-{
- if(prepend) {
- LinkNode *node = prepend;
- while(node->next) node = node->next;
-
- node->next = *list;
- *list = prepend;
- }
-}
-#endif
-
-/* returns 1 if the linked list contains the given pointer, 0 otherwise
- */
-static int linklist_contains(LinkNode *list, void *ptr)
-{
- LinkNode *node;
-
- for(node = list; node; node = node->next)
- if(node->link == ptr) return 1;
-
- return 0;
-}
-
-/* returns 1 if the first linked list is a subset of the second (comparing
- * pointer values), 0 if not
- */
-static int linklist_subset(LinkNode *list1, LinkNode *list2)
-{
- for(; list1; list1 = list1->next)
- if(!linklist_contains(list2, list1->link))
- return 0;
-
- return 1;
-}
-
-#if 0
-/* empties the linked list
- * frees pointers with freefunc if freefunc is not NULL
- */
-static void linklist_empty(LinkNode **list, LinkNodeFreeFP freefunc)
-{
- BLI_linklist_free(*list, freefunc);
- *list = NULL;
-}
-#endif
-
-/* removes the first instance of value from the linked list
- * frees the pointer with freefunc if freefunc is not NULL
- */
-static void linklist_remove_first(LinkNode **list, void *value,
- LinkNodeFreeFP freefunc)
-{
- LinkNode *node = *list;
- LinkNode *prev = NULL;
-
- while(node && node->link != value) {
- prev = node;
- node = node->next;
- }
-
- if(node) {
- if(prev)
- prev->next = node->next;
- else
- *list = node->next;
-
- if(freefunc)
- freefunc(node->link);
-
- MEM_freeN(node);
- }
-}
-
-/* removes all elements in source from target */
-static void linklist_remove_list(LinkNode **target, LinkNode *source,
- LinkNodeFreeFP freefunc)
-{
- for(; source; source = source->next)
- linklist_remove_first(target, source->link, freefunc);
-}
-
-#ifdef EDGESPLIT_DEBUG_0
-static void print_ptr(void *ptr)
-{
- printf("%p\n", ptr);
-}
-
-static void print_edge(void *ptr)
-{
- SmoothEdge *edge = ptr;
- printf(" %4d", edge->newIndex);
-}
-
-static void print_face(void *ptr)
-{
- SmoothFace *face = ptr;
- printf(" %4d", face->newIndex);
-}
-#endif
-
-typedef struct ReplaceData {
- void *find;
- void *replace;
-} ReplaceData;
-
-static void edge_replace_vert(void *ptr, void *userdata)
-{
- SmoothEdge *edge = ptr;
- SmoothVert *find = ((ReplaceData *)userdata)->find;
- SmoothVert *replace = ((ReplaceData *)userdata)->replace;
- int i;
-
-#ifdef EDGESPLIT_DEBUG_3
- printf("replacing vert %4d with %4d in edge %4d",
- find->newIndex, replace->newIndex, edge->newIndex);
- printf(": {%4d, %4d}", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
-#endif
-
- for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++) {
- if(edge->verts[i] == find) {
- linklist_append_list_unique(&replace->faces, edge->faces);
- linklist_remove_list(&find->faces, edge->faces, NULL);
-
- edge->verts[i] = replace;
- }
- }
-
-#ifdef EDGESPLIT_DEBUG_3
- printf(" -> {%4d, %4d}\n", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
-#endif
-}
-
-static void face_replace_vert(void *ptr, void *userdata)
-{
- SmoothFace *face = ptr;
- int i;
-
- for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++)
- edge_replace_vert(face->edges[i], userdata);
-}
-
-static void face_replace_edge(void *ptr, void *userdata)
-{
- SmoothFace *face = ptr;
- SmoothEdge *find = ((ReplaceData *)userdata)->find;
- SmoothEdge *replace = ((ReplaceData *)userdata)->replace;
- int i;
-
-#ifdef EDGESPLIT_DEBUG_3
- printf("replacing edge %4d with %4d in face %4d",
- find->newIndex, replace->newIndex, face->newIndex);
- if(face->edges[3])
- printf(": {%2d %2d %2d %2d}",
- face->edges[0]->newIndex, face->edges[1]->newIndex,
- face->edges[2]->newIndex, face->edges[3]->newIndex);
- else
- printf(": {%2d %2d %2d}",
- face->edges[0]->newIndex, face->edges[1]->newIndex,
- face->edges[2]->newIndex);
-#endif
-
- for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
- if(face->edges[i] == find) {
- linklist_remove_first(&face->edges[i]->faces, face, NULL);
- BLI_linklist_prepend(&replace->faces, face);
- face->edges[i] = replace;
- }
- }
-
-#ifdef EDGESPLIT_DEBUG_3
- if(face->edges[3])
- printf(" -> {%2d %2d %2d %2d}\n",
- face->edges[0]->newIndex, face->edges[1]->newIndex,
- face->edges[2]->newIndex, face->edges[3]->newIndex);
- else
- printf(" -> {%2d %2d %2d}\n",
- face->edges[0]->newIndex, face->edges[1]->newIndex,
- face->edges[2]->newIndex);
-#endif
-}
-
-static int edge_is_loose(SmoothEdge *edge)
-{
- return !(edge->faces && edge->faces->next);
-}
-
-static int edge_is_sharp(SmoothEdge *edge)
-{
-#ifdef EDGESPLIT_DEBUG_1
- printf("edge %d: ", edge->newIndex);
-#endif
- if(edge->flag & ME_SHARP) {
- /* edge can only be sharp if it has at least 2 faces */
- if(!edge_is_loose(edge)) {
-#ifdef EDGESPLIT_DEBUG_1
- printf("sharp\n");
-#endif
- return 1;
- } else {
- /* edge is loose, so it can't be sharp */
- edge->flag &= ~ME_SHARP;
- }
- }
-
-#ifdef EDGESPLIT_DEBUG_1
- printf("not sharp\n");
-#endif
- return 0;
-}
-
-/* finds another sharp edge which uses vert, by traversing faces around the
- * vert until it does one of the following:
- * - hits a loose edge (the edge is returned)
- * - hits a sharp edge (the edge is returned)
- * - returns to the start edge (NULL is returned)
- */
-static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge, LinkNode **visited_faces)
-{
- SmoothFace *face = NULL;
- SmoothEdge *edge2 = NULL;
- /* holds the edges we've seen so we can avoid looping indefinitely */
- LinkNode *visited_edges = NULL;
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== START === find_other_sharp_edge(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
-
- /* get a face on which to start */
- if(edge->faces) face = edge->faces->link;
- else return NULL;
-
- /* record this edge as visited */
- BLI_linklist_prepend(&visited_edges, edge);
-
- /* get the next edge */
- edge2 = other_edge(face, vert, edge);
-
- /* record this face as visited */
- if(visited_faces)
- BLI_linklist_prepend(visited_faces, face);
-
- /* search until we hit a loose edge or a sharp edge or an edge we've
- * seen before
- */
- while(face && !edge_is_sharp(edge2)
- && !linklist_contains(visited_edges, edge2)) {
-#ifdef EDGESPLIT_DEBUG_3
- printf("current face %4d; current edge %4d\n", face->newIndex,
- edge2->newIndex);
-#endif
- /* get the next face */
- face = other_face(edge2, face);
-
- /* if face == NULL, edge2 is a loose edge */
- if(face) {
- /* record this face as visited */
- if(visited_faces)
- BLI_linklist_prepend(visited_faces, face);
-
- /* record this edge as visited */
- BLI_linklist_prepend(&visited_edges, edge2);
-
- /* get the next edge */
- edge2 = other_edge(face, vert, edge2);
-#ifdef EDGESPLIT_DEBUG_3
- printf("next face %4d; next edge %4d\n",
- face->newIndex, edge2->newIndex);
- } else {
- printf("loose edge: %4d\n", edge2->newIndex);
-#endif
- }
- }
-
- /* either we came back to the start edge or we found a sharp/loose edge */
- if(linklist_contains(visited_edges, edge2))
- /* we came back to the start edge */
- edge2 = NULL;
-
- BLI_linklist_free(visited_edges, NULL);
-
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), "
- "returning edge %d\n",
- edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1);
-#endif
- return edge2;
-}
-
-static void split_single_vert(SmoothVert *vert, SmoothFace *face,
- SmoothMesh *mesh)
-{
- SmoothVert *copy_vert;
- ReplaceData repdata;
-
- copy_vert = smoothvert_copy(vert, mesh);
-
- if(copy_vert == NULL) {
- /* bug [#26316], this prevents a segfault
- * but this still needs fixing */
- return;
- }
-
- repdata.find = vert;
- repdata.replace = copy_vert;
- face_replace_vert(face, &repdata);
-}
-
-typedef struct PropagateEdge {
- struct PropagateEdge *next, *prev;
- SmoothEdge *edge;
- SmoothVert *vert;
-} PropagateEdge;
-
-static void push_propagate_stack(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
-{
- PropagateEdge *pedge = mesh->reusestack.first;
-
- if(pedge) {
- BLI_remlink(&mesh->reusestack, pedge);
- }
- else {
- if(!mesh->arena) {
- mesh->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "edgesplit arena");
- BLI_memarena_use_calloc(mesh->arena);
- }
-
- pedge = BLI_memarena_alloc(mesh->arena, sizeof(PropagateEdge));
- }
-
- pedge->edge = edge;
- pedge->vert = vert;
- BLI_addhead(&mesh->propagatestack, pedge);
-}
-
-static void pop_propagate_stack(SmoothEdge **edge, SmoothVert **vert, SmoothMesh *mesh)
-{
- PropagateEdge *pedge = mesh->propagatestack.first;
-
- if(pedge) {
- *edge = pedge->edge;
- *vert = pedge->vert;
- BLI_remlink(&mesh->propagatestack, pedge);
- BLI_addhead(&mesh->reusestack, pedge);
- }
- else {
- *edge = NULL;
- *vert = NULL;
- }
-}
-
-static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh);
-
-static void propagate_split(SmoothEdge *edge, SmoothVert *vert,
- SmoothMesh *mesh)
-{
- SmoothEdge *edge2;
- LinkNode *visited_faces = NULL;
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== START === propagate_split(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
-
- edge2 = find_other_sharp_edge(vert, edge, &visited_faces);
-
- if(!edge2) {
- /* didn't find a sharp or loose edge, so we've hit a dead end */
- } else if(!edge_is_loose(edge2)) {
- /* edge2 is not loose, so it must be sharp */
- if(edge_is_loose(edge)) {
- /* edge is loose, so we can split edge2 at this vert */
- split_edge(edge2, vert, mesh);
- } else if(edge_is_sharp(edge)) {
- /* both edges are sharp, so we can split the pair at vert */
- split_edge(edge, vert, mesh);
- } else {
- /* edge is not sharp, so try to split edge2 at its other vert */
- split_edge(edge2, other_vert(edge2, vert), mesh);
- }
- } else { /* edge2 is loose */
- if(edge_is_loose(edge)) {
- SmoothVert *vert2;
- ReplaceData repdata;
-
- /* can't split edge, what should we do with vert? */
- if(linklist_subset(vert->faces, visited_faces)) {
- /* vert has only one fan of faces attached; don't split it */
- } else {
- /* vert has more than one fan of faces attached; split it */
- vert2 = smoothvert_copy(vert, mesh);
-
- /* fails in rare cases, see [#26993] */
- if(vert2) {
- /* replace vert with its copy in visited_faces */
- repdata.find = vert;
- repdata.replace = vert2;
- BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
- }
- }
- } else {
- /* edge is not loose, so it must be sharp; split it */
- split_edge(edge, vert, mesh);
- }
- }
-
- BLI_linklist_free(visited_faces, NULL);
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== END === propagate_split(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
-}
-
-static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
-{
- SmoothEdge *edge2;
- SmoothVert *vert2;
- ReplaceData repdata;
- /* the list of faces traversed while looking for a sharp edge */
- LinkNode *visited_faces = NULL;
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== START === split_edge(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
-
- edge2 = find_other_sharp_edge(vert, edge, &visited_faces);
-
- if(!edge2) {
- /* didn't find a sharp or loose edge, so try the other vert */
- vert2 = other_vert(edge, vert);
- push_propagate_stack(edge, vert2, mesh);
- } else if(!edge_is_loose(edge2)) {
- /* edge2 is not loose, so it must be sharp */
- SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
- SmoothEdge *copy_edge2 = smoothedge_copy(edge2, mesh);
- SmoothVert *vert2;
-
- /* replace edge with its copy in visited_faces */
- repdata.find = edge;
- repdata.replace = copy_edge;
- BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
- /* replace edge2 with its copy in visited_faces */
- repdata.find = edge2;
- repdata.replace = copy_edge2;
- BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
- vert2 = smoothvert_copy(vert, mesh);
-
- /* replace vert with its copy in visited_faces (must be done after
- * edge replacement so edges have correct vertices)
- */
- repdata.find = vert;
- repdata.replace = vert2;
- BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
-
- /* all copying and replacing is done; the mesh should be consistent.
- * now propagate the split to the vertices at either end
- */
- push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
- push_propagate_stack(copy_edge2, other_vert(copy_edge2, vert2), mesh);
-
- if(smoothedge_has_vert(edge, vert))
- push_propagate_stack(edge, vert, mesh);
- } else {
- /* edge2 is loose */
- SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
- SmoothVert *vert2;
-
- /* replace edge with its copy in visited_faces */
- repdata.find = edge;
- repdata.replace = copy_edge;
- BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
- vert2 = smoothvert_copy(vert, mesh);
-
- /* replace vert with its copy in visited_faces (must be done after
- * edge replacement so edges have correct vertices)
- */
- repdata.find = vert;
- repdata.replace = vert2;
- BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
-
- /* copying and replacing is done; the mesh should be consistent.
- * now propagate the split to the vertex at the other end
- */
- push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
-
- if(smoothedge_has_vert(edge, vert))
- push_propagate_stack(edge, vert, mesh);
- }
-
- BLI_linklist_free(visited_faces, NULL);
-#ifdef EDGESPLIT_DEBUG_1
- printf("=== END === split_edge(edge = %4d, vert = %4d)\n",
- edge->newIndex, vert->newIndex);
-#endif
-}
-
-static void tag_and_count_extra_edges(SmoothMesh *mesh, float split_angle,
- int flags, int *extra_edges)
-{
- /* if normal1 dot normal2 < threshold, angle is greater, so split */
- /* FIXME not sure if this always works */
- /* 0.00001 added for floating-point rounding */
- float threshold = cos((split_angle + 0.00001f) * (float)M_PI / 180.0f);
- int i;
-
- *extra_edges = 0;
-
- /* loop through edges, counting potential new ones */
- for(i = 0; i < mesh->num_edges; i++) {
- SmoothEdge *edge = &mesh->edges[i];
- int sharp = 0;
-
- /* treat all non-manifold edges (3 or more faces) as sharp */
- if(edge->faces && edge->faces->next && edge->faces->next->next) {
- LinkNode *node;
-
- /* this edge is sharp */
- sharp = 1;
-
- /* add an extra edge for every face beyond the first */
- *extra_edges += 2;
- for(node = edge->faces->next->next->next; node; node = node->next)
- (*extra_edges)++;
- } else if((flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))
- && !edge_is_loose(edge)) {
- /* (the edge can only be sharp if we're checking angle or flag,
- * and it has at least 2 faces) */
-
- /* if we're checking the sharp flag and it's set, good */
- if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP)) {
- /* this edge is sharp */
- sharp = 1;
-
- (*extra_edges)++;
- } else if(flags & MOD_EDGESPLIT_FROMANGLE) {
- /* we know the edge has 2 faces, so check the angle */
- SmoothFace *face1 = edge->faces->link;
- SmoothFace *face2 = edge->faces->next->link;
- float edge_angle_cos = dot_v3v3(face1->normal,
- face2->normal);
-
- if(edge_angle_cos < threshold) {
- /* this edge is sharp */
- sharp = 1;
-
- (*extra_edges)++;
- }
- }
- }
-
- /* set/clear sharp flag appropriately */
- if(sharp) edge->flag |= ME_SHARP;
- else edge->flag &= ~ME_SHARP;
- }
-}
-
-static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags)
-{
- SmoothVert *vert;
- int i;
- /* if normal1 dot normal2 < threshold, angle is greater, so split */
- /* FIXME not sure if this always works */
- /* 0.00001 added for floating-point rounding */
- mesh->threshold = cosf((split_angle + 0.00001f) * (float)M_PI / 180.0f);
- mesh->flags = flags;
-
- /* loop through edges, splitting sharp ones */
- /* can't use an iterator here, because we'll be adding edges */
- for(i = 0; i < mesh->num_edges; i++) {
- SmoothEdge *edge = &mesh->edges[i];
-
- if(edge_is_sharp(edge)) {
- split_edge(edge, edge->verts[0], mesh);
-
- do {
- pop_propagate_stack(&edge, &vert, mesh);
- if(edge && smoothedge_has_vert(edge, vert))
- propagate_split(edge, vert, mesh);
- } while(edge);
- }
- }
-}
-
-static int count_bridge_verts(SmoothMesh *mesh)
+static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd,
+ Object *ob, DerivedMesh *dm)
{
- int i, j, count = 0;
-
- for(i = 0; i < mesh->num_faces; i++) {
- SmoothFace *face = &mesh->faces[i];
-
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- SmoothEdge *edge = face->edges[j];
- SmoothEdge *next_edge;
- SmoothVert *vert = edge->verts[1 - face->flip[j]];
- int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
-
- /* wrap next around if at last edge */
- if(!face->edges[next]) next = 0;
-
- next_edge = face->edges[next];
-
- /* if there are other faces sharing this vertex but not
- * these edges, the vertex will be split, so count it
- */
- /* vert has to have at least one face (this one), so faces != 0 */
- if(!edge->faces->next && !next_edge->faces->next
- && vert->faces->next) {
- count++;
- }
- }
- }
-
- /* each bridge vert will be counted once per face that uses it,
- * so count is too high, but it's ok for now
- */
- return count;
-}
-
-static void split_bridge_verts(SmoothMesh *mesh)
-{
- int i,j;
-
- for(i = 0; i < mesh->num_faces; i++) {
- SmoothFace *face = &mesh->faces[i];
-
- for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
- SmoothEdge *edge = face->edges[j];
- SmoothEdge *next_edge;
- SmoothVert *vert = edge->verts[1 - face->flip[j]];
- int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
-
- /* wrap next around if at last edge */
- if(!face->edges[next]) next = 0;
-
- next_edge = face->edges[next];
-
- /* if there are other faces sharing this vertex but not
- * these edges, split the vertex
- */
- /* vert has to have at least one face (this one), so faces != 0 */
- if(!edge->faces->next && !next_edge->faces->next
- && vert->faces->next)
- /* FIXME this needs to find all faces that share edges with
- * this one and split off together
- */
- split_single_vert(vert, face, mesh);
- }
- }
-}
-
-static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd, DerivedMesh *dm)
-{
- SmoothMesh *mesh;
- DerivedMesh *result;
- int max_verts, max_edges;
-
if(!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)))
return dm;
- /* 1. make smoothmesh with initial number of elements */
- mesh = smoothmesh_from_derivedmesh(dm);
-
- /* 2. count max number of elements to add */
- tag_and_count_extra_edges(mesh, emd->split_angle, emd->flags, &max_edges);
- max_verts = max_edges * 2 + mesh->max_verts;
- max_verts += count_bridge_verts(mesh);
- max_edges += mesh->max_edges;
-
- /* 3. reallocate smoothmesh arrays & copy elements across */
- /* 4. remap copied elements' pointers to point into the new arrays */
- smoothmesh_resize_verts(mesh, max_verts);
- smoothmesh_resize_edges(mesh, max_edges);
-
-#ifdef EDGESPLIT_DEBUG_1
- printf("********** Pre-split **********\n");
- smoothmesh_print(mesh);
-#endif
-
- split_sharp_edges(mesh, emd->split_angle, emd->flags);
-#ifdef EDGESPLIT_DEBUG_1
- printf("********** Post-edge-split **********\n");
- smoothmesh_print(mesh);
-#endif
-
- split_bridge_verts(mesh);
-
-#ifdef EDGESPLIT_DEBUG_1
- printf("********** Post-vert-split **********\n");
- smoothmesh_print(mesh);
-#endif
-
-#ifdef EDGESPLIT_DEBUG_0
- printf("Edgesplit: Estimated %d verts & %d edges, "
- "found %d verts & %d edges\n", max_verts, max_edges,
- mesh->num_verts, mesh->num_edges);
-#endif
-
- result = CDDM_from_smoothmesh(mesh);
- smoothmesh_free(mesh);
-
- return result;
+ return doEdgeSplit(dm, emd, ob);
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
- DerivedMesh *derivedData,
- int UNUSED(useRenderParams),
- int UNUSED(isFinalCalc))
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int UNUSED(useRenderParams), int UNUSED(isFinalCalc))
{
DerivedMesh *result;
EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
- result = edgesplitModifier_do(emd, derivedData);
+ result = edgesplitModifier_do(emd, ob, derivedData);
if(result != derivedData)
CDDM_calc_normals(result);
@@ -1276,8 +168,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
}
static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
- struct EditMesh *UNUSED(editData),
- DerivedMesh *derivedData)
+ BMEditMesh *UNUSED(editData), DerivedMesh *derivedData)
{
return applyModifier(md, ob, derivedData, 0, 1);
}
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 8dcb6f4b4d9..8c04d7c694e 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -36,11 +36,11 @@
#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
+#include "BLI_utildefines.h"
#include "BLI_kdtree.h"
#include "BLI_rand.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
-#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_deform.h"
@@ -108,8 +108,8 @@ static void createFacepa(ExplodeModifierData *emd,
int i,p,v1,v2,v3,v4=0;
mvert = dm->getVertArray(dm);
- mface = dm->getFaceArray(dm);
- totface= dm->getNumFaces(dm);
+ mface = dm->getTessFaceArray(dm);
+ totface= dm->getNumTessFaces(dm);
totvert= dm->getNumVerts(dm);
totpart= psmd->psys->totpart;
@@ -198,8 +198,8 @@ static const short add_faces[24] = {
static MFace *get_dface(DerivedMesh *dm, DerivedMesh *split, int cur, int i, MFace *mf)
{
- MFace *df = CDDM_get_face(split, cur);
- DM_copy_face_data(dm, split, i, cur, 1);
+ MFace *df = CDDM_get_tessface(split, cur);
+ DM_copy_tessface_data(dm, split, i, cur, 1);
*df = *mf;
return df;
}
@@ -545,12 +545,12 @@ static DerivedMesh * cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
{
DerivedMesh *splitdm;
MFace *mf=NULL,*df1=NULL;
- MFace *mface=dm->getFaceArray(dm);
+ MFace *mface=dm->getTessFaceArray(dm);
MVert *dupve, *mv;
EdgeHash *edgehash;
EdgeHashIterator *ehi;
int totvert=dm->getNumVerts(dm);
- int totface=dm->getNumFaces(dm);
+ int totface=dm->getNumTessFaces(dm);
int *facesplit = MEM_callocN(sizeof(int)*totface,"explode_facesplit");
int *vertpa = MEM_callocN(sizeof(int)*totvert,"explode_vertpa2");
@@ -628,7 +628,7 @@ static DerivedMesh * cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
for(i=0,fs=facesplit; i<totface; i++,fs++)
totfsplit += add_faces[*fs];
- splitdm= CDDM_from_template(dm, totesplit, 0, totface+totfsplit);
+ splitdm= CDDM_from_template(dm, totesplit, 0, totface+totfsplit, 0, 0);
numlayer = CustomData_number_of_layers(&splitdm->faceData, CD_MTFACE);
/* copy new faces & verts (is it really this painful with custom data??) */
@@ -670,7 +670,7 @@ static DerivedMesh * cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
curdupface=0;//=totface;
//curdupin=totesplit;
for(i=0,fs=facesplit; i<totface; i++,fs++){
- mf = dm->getFaceData(dm, i, CD_MFACE);
+ mf = dm->getTessFaceData(dm, i, CD_MFACE);
switch(*fs) {
case 3:
@@ -760,7 +760,7 @@ static DerivedMesh * cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
}
for(i=0; i<curdupface; i++) {
- mf = CDDM_get_face(splitdm, i);
+ mf = CDDM_get_tessface(splitdm, i);
test_index_face(mf, &splitdm->faceData, i, (mf->flag & ME_FACE_SEL ? 4 : 3));
}
@@ -768,8 +768,11 @@ static DerivedMesh * cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
MEM_freeN(facesplit);
MEM_freeN(vertpa);
- return splitdm;
+ dm = CDDM_copy(splitdm, 1); /*builds ngon faces from tess (mface) faces*/
+ splitdm->needsFree = 1;
+ splitdm->release(splitdm);
+ return dm;
}
static DerivedMesh * explodeMesh(ExplodeModifierData *emd,
ParticleSystemModifierData *psmd, Scene *scene, Object *ob,
@@ -792,9 +795,9 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd,
int i, j, v, mindex=0;
MTFace *mtface = NULL, *mtf;
- totface= dm->getNumFaces(dm);
+ totface= dm->getNumTessFaces(dm);
totvert= dm->getNumVerts(dm);
- mface= dm->getFaceArray(dm);
+ mface= dm->getTessFaceArray(dm);
totpart= psmd->psys->totpart;
sim.scene= scene;
@@ -839,7 +842,7 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd,
BLI_edgehashIterator_free(ehi);
/* the final duplicated vertices */
- explode= CDDM_from_template(dm, totdup, 0,totface);
+ explode= CDDM_from_template(dm, totdup, 0,totface, 0, 0);
mtface = CustomData_get_layer_named(&explode->faceData, CD_MTFACE, emd->uvname);
/*dupvert= CDDM_get_verts(explode);*/
@@ -907,8 +910,8 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd,
if(pa->alive==PARS_DEAD && (emd->flag&eExplodeFlag_Dead)==0) continue;
}
- dm->getFace(dm,i,&source);
- mf=CDDM_get_face(explode,i);
+ dm->getTessFace(dm,i,&source);
+ mf=CDDM_get_tessface(explode,i);
orig_v4 = source.v4;
@@ -923,7 +926,7 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd,
if(source.v4)
source.v4 = edgecut_get(vertpahash, source.v4, mindex);
- DM_copy_face_data(dm,explode,i,i,1);
+ DM_copy_tessface_data(dm,explode,i,i,1);
*mf = source;
@@ -947,6 +950,7 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd,
/* finalization */
CDDM_calc_edges(explode);
+ CDDM_tessfaces_to_faces(explode);
CDDM_calc_normals(explode);
if(psmd->psys->lattice){
@@ -988,7 +992,7 @@ static DerivedMesh * applyModifier(ModifierData *md, Object *ob,
if(emd->facepa == NULL
|| psmd->flag&eParticleSystemFlag_Pars
|| emd->flag&eExplodeFlag_CalcFaces
- || MEM_allocN_len(emd->facepa)/sizeof(int) != dm->getNumFaces(dm))
+ || MEM_allocN_len(emd->facepa)/sizeof(int) != dm->getNumTessFaces(dm))
{
if(psmd->flag & eParticleSystemFlag_Pars)
psmd->flag &= ~eParticleSystemFlag_Pars;
diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c
index 0e9b71c3e6d..5d8471e75dc 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim_util.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c
@@ -224,7 +224,7 @@ static DerivedMesh *fluidsim_read_obj(const char *filename)
return NULL;
}
- dm = CDDM_new(numverts, 0, numfaces);
+ dm = CDDM_new(numverts, 0, numfaces, 0, 0);
if(!dm)
{
@@ -280,7 +280,7 @@ static DerivedMesh *fluidsim_read_obj(const char *filename)
}
// read triangles from file
- mf = CDDM_get_faces(dm);
+ mf = CDDM_get_tessfaces(dm);
for(i=numfaces; i>0; i--, mf++)
{
int face[3];
@@ -505,12 +505,12 @@ static DerivedMesh *fluidsim_read_cache(DerivedMesh *orgdm, FluidsimModifierData
}
// assign material + flags to new dm
- mface = orgdm->getFaceArray(orgdm);
+ mface = orgdm->getTessFaceArray(orgdm);
mat_nr = mface[0].mat_nr;
flag = mface[0].flag;
- mface = dm->getFaceArray(dm);
- numfaces = dm->getNumFaces(dm);
+ mface = dm->getTessFaceArray(dm);
+ numfaces = dm->getNumTessFaces(dm);
for(i=0; i<numfaces; i++)
{
mface[i].mat_nr = mat_nr;
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index ad1a636589f..1e356d4557a 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -252,12 +252,12 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct EditMesh *editData,
+ ModifierData *md, Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+ if(!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data, 0);
deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index 9ef5e501aca..8cfde5e3a4c 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -119,12 +119,12 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct EditMesh *editData,
+ ModifierData *md, Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
- if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+ if(!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data, 0);
deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index 4145dafce7b..046eb0e5d03 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -117,7 +117,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* get original number of verts, edges, and faces */
maxVerts= dm->getNumVerts(dm);
maxEdges= dm->getNumEdges(dm);
- maxFaces= dm->getNumFaces(dm);
+ maxFaces= dm->getNumTessFaces(dm);
/* check if we can just return the original mesh
* - must have verts and therefore verts assigned to vgroups to do anything useful
@@ -282,7 +282,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
for (i = 0; i < maxFaces; i++)
{
MFace mf;
- dm->getFace(dm, i, &mf);
+ dm->getTessFace(dm, i, &mf);
/* all verts must be available */
if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)) &&
@@ -299,7 +299,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* now we know the number of verts, edges and faces,
* we can create the new (reduced) mesh
*/
- result = CDDM_from_template(dm, numVerts, numEdges, numFaces);
+ result = CDDM_from_template(dm, numVerts, numEdges, numFaces, 0, 0);
/* using ghash-iterators, map data into new mesh */
@@ -353,8 +353,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
int orig_v4;
- dm->getFace(dm, oldIndex, &source);
- dest = CDDM_get_face(result, newIndex);
+ dm->getTessFace(dm, oldIndex, &source);
+ dest = CDDM_get_tessface(result, newIndex);
orig_v4 = source.v4;
@@ -364,13 +364,16 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (source.v4)
source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
- DM_copy_face_data(dm, result, oldIndex, newIndex, 1);
+ DM_copy_tessface_data(dm, result, oldIndex, newIndex, 1);
*dest = source;
test_index_face(dest, &result->faceData, newIndex, (orig_v4 ? 4 : 3));
}
BLI_ghashIterator_free(hashIter);
+ /* build polys from tess faces, for now */
+ CDDM_tessfaces_to_faces(result);
+
/* recalculate normals */
CDDM_calc_normals(result);
@@ -380,6 +383,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
BLI_ghash_free(faceHash, NULL, NULL);
/* return the new mesh */
+
return result;
}
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index c211efd64b8..966591a3e56 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -32,7 +32,7 @@
* \ingroup modifiers
*/
-
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -45,6 +45,7 @@
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
+#include "BKE_tessmesh.h"
#include "depsgraph_private.h"
@@ -185,7 +186,7 @@ static void meshdeformModifier_do(
{
MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
struct Mesh *me= (mmd->object)? mmd->object->data: NULL;
- struct EditMesh *em = (me)? BKE_mesh_get_editmesh(me): NULL;
+ BMEditMesh *em = me ? me->edit_btmesh : NULL;
DerivedMesh *tmpdm, *cagedm;
MDeformVert *dvert = NULL;
MDeformWeight *dw;
@@ -201,10 +202,9 @@ static void meshdeformModifier_do(
/* get cage derivedmesh */
if(em) {
- tmpdm= editmesh_get_derived_cage_and_final(md->scene, ob, em, &cagedm, 0);
+ tmpdm= editbmesh_get_derived_cage_and_final(md->scene, ob, em, &cagedm, 0);
if(tmpdm)
tmpdm->release(tmpdm);
- BKE_mesh_end_editmesh(me, em);
}
else
cagedm= mmd->object->derivedFinal;
@@ -361,7 +361,7 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(ModifierData *md, Object *ob,
- struct EditMesh *UNUSED(editData),
+ struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts)
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index f551f0f5e7a..2825053050e 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -28,27 +28,26 @@
*
*/
-/** \file blender/modifiers/intern/MOD_mirror.c
- * \ingroup modifiers
- */
-
-
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "MEM_guardedalloc.h"
+
#include "BLI_math.h"
-#include "BLI_utildefines.h"
+#include "BLI_smallhash.h"
+#include "BLI_array.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
+#include "BKE_utildefines.h"
+#include "BKE_tessmesh.h"
-
-#include "MEM_guardedalloc.h"
#include "depsgraph_private.h"
-#include "MOD_util.h"
+/*from MOD_array.c*/
+void vertgroup_flip_name (char *name, int strip_number);
static void initData(ModifierData *md)
{
@@ -76,14 +75,13 @@ static void foreachObjectLink(
void *userData)
{
MirrorModifierData *mmd = (MirrorModifierData*) md;
-
- walk(userData, ob, &mmd->mirror_ob);
+
+ if (mmd->mirror_ob)
+ walk(userData, ob, &mmd->mirror_ob);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
+static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
+ Object *UNUSED(ob), DagNode *obNode)
{
MirrorModifierData *mmd = (MirrorModifierData*) md;
@@ -95,195 +93,193 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
}
}
-static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
+
+/* Mirror */
+#define VERT_NEW 1
+
+DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
Object *ob,
DerivedMesh *dm,
- int initFlags,
+ int UNUSED(initFlags),
int axis)
{
- int i;
- float tolerance = mmd->tolerance;
- DerivedMesh *result;
- int numVerts, numEdges, numFaces;
- int maxVerts = dm->getNumVerts(dm);
- int maxEdges = dm->getNumEdges(dm);
- int maxFaces = dm->getNumFaces(dm);
- int *flip_map= NULL;
- int do_vgroup_mirr= (mmd->flag & MOD_MIR_VGROUP);
- int (*indexMap)[2];
- float mtx[4][4], imtx[4][4];
-
- numVerts = numEdges = numFaces = 0;
-
- indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap");
-
- result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
-
-
- if (do_vgroup_mirr) {
- flip_map= defgroup_flip_map(ob, 0);
- if(flip_map == NULL)
- do_vgroup_mirr= 0;
+ float tolerance_sq;
+ DerivedMesh *cddm, *origdm;
+ bDeformGroup *def, *defb;
+ bDeformGroup **vector_def = NULL;
+ MVert *mv, *ov;
+ MEdge *me;
+ MLoop *ml;
+ MPoly *mp;
+ float mtx[4][4];
+ int i, j, *vtargetmap = NULL;
+ BLI_array_declare(vtargetmap);
+ int vector_size=0, a, b, totshape;
+
+ tolerance_sq = mmd->tolerance * mmd->tolerance;
+
+ origdm = dm;
+ if (!CDDM_Check(dm))
+ dm = CDDM_copy(dm, 0);
+
+ if (mmd->flag & MOD_MIR_VGROUP) {
+ /* calculate the number of deformedGroups */
+ for(vector_size = 0, def = ob->defbase.first; def;
+ def = def->next, vector_size++);
+
+ /* load the deformedGroups for fast access */
+ vector_def =
+ (bDeformGroup **)MEM_mallocN(sizeof(bDeformGroup*) * vector_size,
+ "group_index");
+ for(a = 0, def = ob->defbase.first; def; def = def->next, a++) {
+ vector_def[a] = def;
+ }
}
+ /*mtx is the mirror transformation*/
+ unit_m4(mtx);
+ mtx[axis][axis] = -1.0;
+
if (mmd->mirror_ob) {
- float obinv[4][4];
-
- invert_m4_m4(obinv, mmd->mirror_ob->obmat);
- mul_m4_m4m4(mtx, ob->obmat, obinv);
- invert_m4_m4(imtx, mtx);
+ float tmp[4][4];
+ float itmp[4][4];
+
+ /*tmp is a transform from coords relative to the object's own origin, to
+ coords relative to the mirror object origin*/
+ invert_m4_m4(tmp, mmd->mirror_ob->obmat);
+ mul_m4_m4m4(tmp, ob->obmat, tmp);
+
+ /*itmp is the reverse transform back to origin-relative coordiantes*/
+ invert_m4_m4(itmp, tmp);
+
+ /*combine matrices to get a single matrix that translates coordinates into
+ mirror-object-relative space, does the mirror, and translates back to
+ origin-relative space*/
+ mul_m4_m4m4(mtx, tmp, mtx);
+ mul_m4_m4m4(mtx, mtx, itmp);
}
-
- for(i = 0; i < maxVerts; i++) {
- MVert inMV;
- MVert *mv = CDDM_get_vert(result, numVerts);
- int isShared;
- float co[3];
-
- dm->getVert(dm, i, &inMV);
-
- copy_v3_v3(co, inMV.co);
-
- if (mmd->mirror_ob) {
- mul_m4_v3(mtx, co);
+
+ cddm = CDDM_from_template(dm, dm->numVertData*2, dm->numEdgeData*2, 0, dm->numLoopData*2, dm->numPolyData*2);
+
+ /*copy customdata to original geometry*/
+ CustomData_copy_data(&dm->vertData, &cddm->vertData, 0, 0, dm->numVertData);
+ CustomData_copy_data(&dm->edgeData, &cddm->edgeData, 0, 0, dm->numEdgeData);
+ CustomData_copy_data(&dm->loopData, &cddm->loopData, 0, 0, dm->numLoopData);
+ CustomData_copy_data(&dm->polyData, &cddm->polyData, 0, 0, dm->numPolyData);
+
+ /*copy customdata to new geometry*/
+ CustomData_copy_data(&dm->vertData, &cddm->vertData, 0, dm->numVertData, dm->numVertData);
+ CustomData_copy_data(&dm->edgeData, &cddm->edgeData, 0, dm->numEdgeData, dm->numEdgeData);
+ CustomData_copy_data(&dm->polyData, &cddm->polyData, 0, dm->numPolyData, dm->numPolyData);
+
+ /*mirror vertex coordinates*/
+ ov = CDDM_get_verts(cddm);
+ mv = ov + dm->numVertData;
+ for (i=0; i<dm->numVertData; i++, mv++, ov++) {
+ mul_m4_v3(mtx, mv->co);
+ /*compare location of the original and mirrored vertex, to see if they
+ should be mapped for merging*/
+ if (len_squared_v3v3(ov->co, mv->co) < tolerance_sq) {
+ BLI_array_append(vtargetmap, i+dm->numVertData);
}
-
- if(mmd->flag & MOD_MIR_NO_MERGE)
- isShared = 0;
- else
- isShared = ABS(co[axis])<=tolerance;
-
- /* Because the topology result (# of vertices) must be the same if
- * the mesh data is overridden by vertex cos, have to calc sharedness
- * based on original coordinates. This is why we test before copy.
- */
- DM_copy_vert_data(dm, result, i, numVerts, 1);
- *mv = inMV;
- numVerts++;
-
- indexMap[i][0] = numVerts - 1;
- indexMap[i][1] = !isShared;
- //
- if(isShared ) {
- co[axis] = 0;
- if (mmd->mirror_ob) {
- mul_m4_v3(imtx, co);
- }
- copy_v3_v3(mv->co, co);
-
- mv->flag |= ME_VERT_MERGED;
- } else {
- MVert *mv2 = CDDM_get_vert(result, numVerts);
-
- DM_copy_vert_data(dm, result, i, numVerts, 1);
- *mv2 = *mv;
-
- co[axis] = -co[axis];
- if (mmd->mirror_ob) {
- mul_m4_v3(imtx, co);
- }
- copy_v3_v3(mv2->co, co);
-
- if (do_vgroup_mirr) {
- MDeformVert *dvert= DM_get_vert_data(result, numVerts, CD_MDEFORMVERT);
- if(dvert) {
- defvert_flip(dvert, flip_map);
- }
- }
-
- numVerts++;
+ else {
+ BLI_array_append(vtargetmap, -1);
}
}
-
- for(i = 0; i < maxEdges; i++) {
- MEdge inMED;
- MEdge *med = CDDM_get_edge(result, numEdges);
-
- dm->getEdge(dm, i, &inMED);
-
- DM_copy_edge_data(dm, result, i, numEdges, 1);
- *med = inMED;
- numEdges++;
-
- med->v1 = indexMap[inMED.v1][0];
- med->v2 = indexMap[inMED.v2][0];
- if(initFlags)
- med->flag |= ME_EDGEDRAW | ME_EDGERENDER;
-
- if(indexMap[inMED.v1][1] || indexMap[inMED.v2][1]) {
- MEdge *med2 = CDDM_get_edge(result, numEdges);
-
- DM_copy_edge_data(dm, result, i, numEdges, 1);
- *med2 = *med;
- numEdges++;
-
- med2->v1 += indexMap[inMED.v1][1];
- med2->v2 += indexMap[inMED.v2][1];
+
+ /*handle shape keys*/
+ totshape = CustomData_number_of_layers(&cddm->vertData, CD_SHAPEKEY);
+ for (a=0; a<totshape; a++) {
+ float (*cos)[3] = CustomData_get_layer_n(&cddm->vertData, CD_SHAPEKEY, a);
+ for (i=dm->numVertData; i<cddm->numVertData; i++) {
+ mul_m4_v3(mtx, cos[i]);
}
}
-
- for(i = 0; i < maxFaces; i++) {
- MFace inMF;
- MFace *mf = CDDM_get_face(result, numFaces);
+
+ for (i=0; i<dm->numVertData; i++) {
+ BLI_array_append(vtargetmap, -1);
+ }
+
+ /*adjust mirrored edge vertex indices*/
+ me = CDDM_get_edges(cddm) + dm->numEdgeData;
+ for (i=0; i<dm->numEdgeData; i++, me++) {
+ me->v1 += dm->numVertData;
+ me->v2 += dm->numVertData;
+ }
+
+ /*adjust mirrored poly loopstart indices, and reverse loop order (normals)*/
+ mp = CDDM_get_polys(cddm) + dm->numPolyData;
+ ml = CDDM_get_loops(cddm);
+ for (i=0; i<dm->numPolyData; i++, mp++) {
+ MLoop *ml2;
+ int e;
- dm->getFace(dm, i, &inMF);
+ for (j=0; j<mp->totloop; j++) {
+ CustomData_copy_data(&dm->loopData, &cddm->loopData, mp->loopstart+j,
+ mp->loopstart+dm->numLoopData+mp->totloop-j-1, 1);
+ }
- DM_copy_face_data(dm, result, i, numFaces, 1);
- *mf = inMF;
- numFaces++;
+ ml2 = ml + mp->loopstart + dm->numLoopData;
+ e = ml2[0].e;
+ for (j=0; j<mp->totloop-1; j++) {
+ ml2[j].e = ml2[j+1].e;
+ }
+ ml2[mp->totloop-1].e = e;
- mf->v1 = indexMap[inMF.v1][0];
- mf->v2 = indexMap[inMF.v2][0];
- mf->v3 = indexMap[inMF.v3][0];
- mf->v4 = indexMap[inMF.v4][0];
+ mp->loopstart += dm->numLoopData;
+ }
+
+ /*adjust mirrored loop vertex and edge indices*/
+ ml = CDDM_get_loops(cddm) + dm->numLoopData;
+ for (i=0; i<dm->numLoopData; i++, ml++) {
+ ml->v += dm->numVertData;
+ ml->e += dm->numEdgeData;
+ }
+
+ CDDM_recalc_tesselation(cddm, 1);
+
+ /*handle vgroup stuff*/
+ if ((mmd->flag & MOD_MIR_VGROUP) && CustomData_has_layer(&cddm->vertData, CD_MDEFORMVERT)) {
+ MDeformVert *dvert = CustomData_get_layer(&cddm->vertData, CD_MDEFORMVERT);
- if(indexMap[inMF.v1][1]
- || indexMap[inMF.v2][1]
- || indexMap[inMF.v3][1]
- || (mf->v4 && indexMap[inMF.v4][1])) {
- MFace *mf2 = CDDM_get_face(result, numFaces);
- static int corner_indices[4] = {2, 1, 0, 3};
-
- DM_copy_face_data(dm, result, i, numFaces, 1);
- *mf2 = *mf;
-
- mf2->v1 += indexMap[inMF.v1][1];
- mf2->v2 += indexMap[inMF.v2][1];
- mf2->v3 += indexMap[inMF.v3][1];
- if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1];
-
- /* mirror UVs if enabled */
- if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) {
- MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE);
- if(tf) {
- int j;
- for(j = 0; j < 4; ++j) {
- if(mmd->flag & MOD_MIR_MIRROR_U)
- tf->uv[j][0] = 1.0f - tf->uv[j][0];
- if(mmd->flag & MOD_MIR_MIRROR_V)
- tf->uv[j][1] = 1.0f - tf->uv[j][1];
+ for (i=0; i<dm->numVertData; i++, dvert++) {
+ for(j = 0; j < dvert->totweight; ++j) {
+ char tmpname[32];
+
+ if(dvert->dw[j].def_nr < 0 ||
+ dvert->dw[j].def_nr >= vector_size)
+ continue;
+
+ def = vector_def[dvert->dw[j].def_nr];
+ strcpy(tmpname, def->name);
+ vertgroup_flip_name(tmpname,0);
+
+ for(b = 0, defb = ob->defbase.first; defb;
+ defb = defb->next, b++)
+ {
+ if(!strcmp(defb->name, tmpname))
+ {
+ dvert->dw[j].def_nr = b;
+ break;
}
}
}
-
- /* Flip face normal */
- SWAP(int, mf2->v1, mf2->v3);
- DM_swap_face_data(result, numFaces, corner_indices);
-
- test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
- numFaces++;
}
}
-
- if (flip_map) MEM_freeN(flip_map);
-
- MEM_freeN(indexMap);
-
- CDDM_lower_num_verts(result, numVerts);
- CDDM_lower_num_edges(result, numEdges);
- CDDM_lower_num_faces(result, numFaces);
-
- return result;
+
+ if (!(mmd->flag & MOD_MIR_NO_MERGE))
+ cddm = CDDM_merge_verts(cddm, vtargetmap);
+
+ BLI_array_free(vtargetmap);
+
+ if (vector_def) MEM_freeN(vector_def);
+
+ if (dm != origdm) {
+ dm->needsFree = 1;
+ dm->release(dm);
+ }
+
+ return cddm;
}
static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
@@ -310,10 +306,9 @@ static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
return result;
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
- int UNUSED(useRenderParams),
- int UNUSED(isFinalCalc))
+static DerivedMesh *applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int UNUSED(useRenderParams), int UNUSED(isFinalCalc))
{
DerivedMesh *result;
MirrorModifierData *mmd = (MirrorModifierData*) md;
@@ -326,9 +321,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
return result;
}
-static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
- struct EditMesh *UNUSED(editData),
- DerivedMesh *derivedData)
+static DerivedMesh *applyModifierEM(
+ ModifierData *md, Object *ob, struct BMEditMesh *UNUSED(editData),
+ DerivedMesh *derivedData)
{
return applyModifier(md, ob, derivedData, 0, 1);
}
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index 8bcaf8802b5..51c4a1eae01 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -78,9 +78,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm,
Mesh *me= (Mesh*)ob->data;
if(mmd->totlvl) {
- if(!CustomData_get_layer(&me->fdata, CD_MDISPS)) {
+ if(!CustomData_get_layer(&me->ldata, CD_MDISPS)) {
/* multires always needs a displacement layer */
- CustomData_add_layer(&me->fdata, CD_MDISPS, CD_CALLOC, NULL, me->totface);
+ CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop);
}
}
@@ -90,7 +90,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm,
return dm;
if(useRenderParams || !isFinalCalc) {
- DerivedMesh *cddm= CDDM_copy(result);
+ DerivedMesh *cddm= CDDM_copy(result, 0);
result->release(result);
result= cddm;
}
diff --git a/source/blender/modifiers/intern/MOD_ngoninterp.c b/source/blender/modifiers/intern/MOD_ngoninterp.c
new file mode 100644
index 00000000000..9043834de82
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_ngoninterp.c
@@ -0,0 +1,330 @@
+/*
+* $Id: MOD_mask.c 35213 2011-02-27 06:19:40Z joeedh $
+*
+* ***** 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 by the Blender Foundation.
+* All rights reserved.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+*/
+
+/** \file blender/modifiers/intern/MOD_mask.c
+ * \ingroup modifiers
+ */
+
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_array.h"
+#include "BLI_smallhash.h"
+#include "BLI_edgehash.h"
+#include "BLI_math.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_deform.h"
+
+#include "depsgraph_private.h"
+
+#include "MOD_util.h"
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ NgonInterpModifierData *mmd = (NgonInterpModifierData*) md;
+ NgonInterpModifierData *tmmd = (NgonInterpModifierData*) target;
+
+ tmmd->resolution = mmd->resolution;
+}
+
+static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
+ DerivedMesh *derivedData,
+ int UNUSED(useRenderParams),
+ int UNUSED(isFinalCalc))
+{
+ NgonInterpModifierData *nmd= (NgonInterpModifierData *)md;
+ DerivedMesh *dm= derivedData;
+ DerivedMesh *cddm, *dummy;
+ MFace *mf;
+ MPoly *mpoly;
+ MLoop *mloop;
+ MFace *mface = NULL, *mf2;
+ MVert *mvert = NULL, *omvert;
+ BLI_array_declare(mface);
+ BLI_array_declare(mvert);
+ int *verts=NULL, *loops=NULL;
+ BLI_array_declare(verts);
+ BLI_array_declare(loops);
+ float *w = NULL, (*cos)[3] = NULL;
+ BLI_array_declare(w);
+ BLI_array_declare(cos);
+ int *origv = NULL, *origf = NULL, *of, *ov;
+ BLI_array_declare(origv);
+ BLI_array_declare(origf);
+ DerivedMesh *copy = NULL;
+ int i;
+
+ if (nmd->resolution <= 0)
+ return dm;
+
+ if (!CDDM_Check(dm)) {
+ dm = copy = CDDM_copy(dm, 0);
+ }
+
+ CDDM_recalc_tesselation(dm, 1);
+
+ mf = dm->getTessFaceArray(dm);
+ of = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ mpoly = CDDM_get_polys(dm);
+ mloop = CDDM_get_loops(dm);
+
+ /*eek!*/
+ if (!of)
+ return dm;
+
+ /*create a dummy mesh to compute interpolated loops on*/
+ dummy = CDDM_from_template(dm, 0, 0, 0, 3, 0);
+
+ /*copy original verts here, so indices stay correct*/
+ omvert = dm->getVertArray(dm);
+ ov = dm->getVertDataArray(dm, CD_ORIGINDEX);
+ for (i=0; i<dm->numVertData; i++) {
+ BLI_array_append(mvert, omvert[i]);
+ BLI_array_append(origv, ov ? ov[i] : i);
+ }
+
+ for (i=0; i<dm->numFaceData; i++, mf++, of++) {
+ int x, y, x2;
+ float fac;
+
+ BLI_array_empty(verts);
+
+#define NG_MAKE_VERT(orig)\
+ BLI_array_append(mvert, omvert[orig]);\
+ BLI_array_append(origv, ov ? ov[orig] : orig);\
+ BLI_array_append(verts, BLI_array_count(mvert)-1);
+
+#define NG_MAKE_VERTCO(orig, coord) NG_MAKE_VERT(orig); copy_v3_v3(mvert[BLI_array_count(mvert)-1].co, coord)
+
+ y = 0;
+ fac = 1.0f / (float)(nmd->resolution + 1);
+ for (x=0; x<nmd->resolution+2; x++) {
+ float co1[3], co2[3], co3[3];
+
+ sub_v3_v3v3(co1, omvert[mf->v1].co, omvert[mf->v3].co);
+ sub_v3_v3v3(co2, omvert[mf->v2].co, omvert[mf->v3].co);
+
+ mul_v3_fl(co1, 1.0f - fac*x);
+ mul_v3_fl(co2, 1.0f - fac*x);
+
+ add_v3_v3(co1, omvert[mf->v3].co);
+ add_v3_v3(co2, omvert[mf->v3].co);
+
+ if (x == 0) {
+ BLI_array_append(verts, mf->v1);
+ } else if (x == nmd->resolution+1) {
+ BLI_array_append(verts, mf->v3);
+ } else {
+ NG_MAKE_VERTCO(mf->v1, co1);
+ }
+
+ for (x2=0; x2<(nmd->resolution-x); x2++) {
+ sub_v3_v3v3(co3, co1, co2);
+ mul_v3_fl(co3, 1.0f - (1.0f/(float)(nmd->resolution-x+1))*(x2+1));
+ add_v3_v3(co3, co2);
+
+ NG_MAKE_VERTCO(mf->v2, co3);
+ }
+
+ if (x == 0) {
+ BLI_array_append(verts, mf->v2);
+ } else if (x != nmd->resolution+1) {
+ NG_MAKE_VERTCO(mf->v1, co2);
+ }
+ }
+
+ y = 0;
+ for (x=0; x<BLI_array_count(verts)-2; x++) {
+ int v1, v2, v3;
+
+ if (x2 == nmd->resolution-y+1) {
+ x2 = 0;
+ y++;
+ continue;
+ } else {
+ /*int lindex[3] = {0, 1, 2};*/ /*UNUSED*/
+
+ v1 = verts[x];
+ v2 = verts[x+1];
+ v3 = verts[x+(nmd->resolution-y)+2];
+
+ BLI_array_growone(mface);
+ BLI_array_growone(origf);
+
+ /*make first face*/
+ origf[BLI_array_count(origf)-1] = *of;
+ mf2 = mface + BLI_array_count(mface)-1;
+ *mf2 = *mf;
+
+ mf2->v1 = v1;
+ mf2->v2 = v2;
+ mf2->v3 = v3;
+ mf2->v4 = 0;
+
+ if (x2 != nmd->resolution-y) {
+ /*make second face*/
+ BLI_array_growone(mface);
+ BLI_array_growone(origf);
+
+ origf[BLI_array_count(origf)-1] = *of;
+ mf2 = mface + BLI_array_count(mface)-1;
+ *mf2 = *mf;
+
+ mf2->v1 = verts[x+(nmd->resolution-y)+3];
+ mf2->v2 = v3;
+ mf2->v3 = v2;
+ mf2->v4 = 0;
+ }
+ }
+
+ x2++;
+ }
+ }
+
+ cddm = CDDM_from_template(dm, BLI_array_count(mvert), dm->numEdgeData, BLI_array_count(mface), 0, 0);
+
+ mf2 = mface;
+ for (i=0; i<BLI_array_count(mface); i++, mf2++) {
+ MPoly *mp = mpoly + *of;
+ MLoop *ml;
+ float co[3], cent[3] = {0.0f, 0.0f, 0.0f};
+ int j, lindex[3] = {0, 1, 2};
+
+ BLI_array_empty(w);
+ BLI_array_empty(cos);
+ BLI_array_empty(loops);
+
+ mp = mpoly + origf[i];
+ ml = mloop + mp->loopstart;
+ for (j=0; j<mp->totloop; j++, ml++) {
+ BLI_array_growone(cos);
+ BLI_array_growone(w);
+ BLI_array_append(loops, j+mp->loopstart);
+ copy_v3_v3(cos[j], mvert[ml->v].co);
+ }
+
+ /*scale source face coordinates a bit, so points sitting directly on an
+ edge will work.*/
+ mul_v3_fl(cent, 1.0f/(float)(mp->totloop));
+ for (j=0; j<mp->totloop; j++) {
+ sub_v3_v3(cos[j], cent);
+ mul_v3_fl(cos[j], 1.0f+FLT_EPSILON*1500.0f);
+ add_v3_v3(cos[j], cent);
+ }
+
+ copy_v3_v3(co, (mvert + mf2->v1)->co);
+ interp_weights_poly_v3(w, cos, mp->totloop, co);
+ CustomData_interp(&dm->loopData, &dummy->loopData, loops, w, NULL, mp->totloop, 0);
+
+ copy_v3_v3(co, (mvert + mf2->v2)->co);
+ interp_weights_poly_v3(w, cos, mp->totloop, co);
+ CustomData_interp(&dm->loopData, &dummy->loopData, loops, w, NULL, mp->totloop, 1);
+
+ copy_v3_v3(co, (mvert + mf2->v3)->co);
+ interp_weights_poly_v3(w, cos, mp->totloop, co);
+ CustomData_interp(&dm->loopData, &dummy->loopData, loops, w, NULL, mp->totloop, 2);
+
+ mesh_loops_to_tri_corners(&cddm->faceData, &dummy->loopData, &dm->polyData, lindex, i, origf[i]);
+ }
+
+ CustomData_copy_data(&dm->vertData, &cddm->vertData, 0, 0, dm->numVertData);
+ CustomData_copy_data(&dm->edgeData, &cddm->edgeData, 0, 0, dm->numEdgeData);
+
+ CDDM_set_mface(cddm, mface);
+ CDDM_set_mvert(cddm, mvert);
+
+ /*set origindex pointer*/
+ MEM_freeN(CustomData_get_layer(&cddm->faceData, CD_ORIGINDEX));
+ CustomData_set_layer(&cddm->faceData, CD_MFACE, mface);
+
+ if (CustomData_has_layer(&cddm->vertData, CD_ORIGINDEX))
+ CustomData_set_layer(&cddm->vertData, CD_ORIGINDEX, origv);
+
+ CustomData_set_layer(&cddm->faceData, CD_ORIGINDEX, origf);
+
+ BLI_array_free(cos);
+ BLI_array_free(w);
+
+ dummy->needsFree = 1;
+ dummy->release(dummy);
+
+ /*create polys from mface triangles*/
+ dummy = cddm;
+ cddm = CDDM_copy(cddm, 1);
+ dummy->needsFree = 1;
+ dummy->release(dummy);
+
+ if (copy) {
+ copy->needsFree = 1;
+ copy->release(dm);
+ copy = copy;
+ }
+
+ return cddm;
+}
+
+
+ModifierTypeInfo modifierType_NgonInterp = {
+ /* name */ "NgonInterp",
+ /* structName */ "NgonInterpModifierData",
+ /* structSize */ sizeof(NgonInterpModifierData),
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh|eModifierTypeFlag_SupportsMapping|eModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ 0,
+ /* deformMatrices */ 0,
+ /* deformVertsEM */ 0,
+ /* deformMatricesEM */ 0,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ 0,
+ /* initData */ 0,
+ /* requiredDataMask */ 0,
+ /* freeData */ 0,
+ /* isDisabled */ 0,
+ /* updateDepgraph */ 0,
+ /* dependsOnTime */ 0,
+ /* dependsOnNormals */ 0,
+ /* foreachObjectLink */ 0,
+ /* foreachIDLink */ 0,
+};
+
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index f93e0469686..eae7dcef26d 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -174,7 +174,7 @@ static DerivedMesh * applyModifier(ModifierData *md, Object *ob,
pars=psys->particles;
totvert=dm->getNumVerts(dm);
- totface=dm->getNumFaces(dm);
+ totface=dm->getNumTessFaces(dm);
maxvert=totvert*totpart;
maxface=totface*totpart;
@@ -190,7 +190,7 @@ static DerivedMesh * applyModifier(ModifierData *md, Object *ob,
max_co=max_r[track];
}
- result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface);
+ result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface, 0, 0);
mvert=result->getVertArray(result);
orig_mvert=dm->getVertArray(dm);
@@ -260,8 +260,8 @@ static DerivedMesh * applyModifier(ModifierData *md, Object *ob,
VECADD(mv->co,mv->co,state.co);
}
- mface=result->getFaceArray(result);
- orig_mface=dm->getFaceArray(dm);
+ mface=result->getTessFaceArray(result);
+ orig_mface=dm->getTessFaceArray(dm);
for(i=0; i<maxface; i++){
MFace *inMF;
@@ -312,10 +312,14 @@ static DerivedMesh * applyModifier(ModifierData *md, Object *ob,
if(size)
MEM_freeN(size);
- return result;
+ dm = CDDM_copy(result, 1); /*builds ngon faces from tess (mface) faces*/
+ result->needsFree = 1;
+ result->release(result);
+
+ return dm;
}
static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
- struct EditMesh *UNUSED(editData),
+ struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData)
{
return applyModifier(md, ob, derivedData, 0, 1);
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
index 5ce2437b8ea..4021a8a8114 100644
--- a/source/blender/modifiers/intern/MOD_particlesystem.c
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -164,7 +164,7 @@ static void deformVerts(ModifierData *md, Object *ob,
}
/* make new dm */
- psmd->dm=CDDM_copy(dm);
+ psmd->dm=CDDM_copy(dm, 0);
CDDM_apply_vert_coords(psmd->dm, vertexCos);
CDDM_calc_normals(psmd->dm);
@@ -179,13 +179,13 @@ static void deformVerts(ModifierData *md, Object *ob,
/* report change in mesh structure */
if(psmd->dm->getNumVerts(psmd->dm)!=psmd->totdmvert ||
psmd->dm->getNumEdges(psmd->dm)!=psmd->totdmedge ||
- psmd->dm->getNumFaces(psmd->dm)!=psmd->totdmface){
+ psmd->dm->getNumTessFaces(psmd->dm)!=psmd->totdmface){
psys->recalc |= PSYS_RECALC_RESET;
psmd->totdmvert= psmd->dm->getNumVerts(psmd->dm);
psmd->totdmedge= psmd->dm->getNumEdges(psmd->dm);
- psmd->totdmface= psmd->dm->getNumFaces(psmd->dm);
+ psmd->totdmface= psmd->dm->getNumTessFaces(psmd->dm);
}
if(psys) {
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 5dc233c78b1..3ab80aecfca 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -174,7 +174,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* dont do anything? */
if (!totvert)
- return CDDM_from_template(dm, 0, 0, 0);
+ return CDDM_from_template(dm, 0, 0, 0, 0, 0);
switch(ltmd->axis) {
case 0:
@@ -292,17 +292,17 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
maxFaces = totedge * (step_tot-1);
}
- result= CDDM_from_template(dm, maxVerts, maxEdges, maxFaces);
+ result= CDDM_from_template(dm, maxVerts, maxEdges, maxFaces, 0, 0);
/* copy verts from mesh */
mvert_orig = dm->getVertArray(dm);
medge_orig = dm->getEdgeArray(dm);
mvert_new = result->getVertArray(result);
- mface_new = result->getFaceArray(result);
+ mface_new = result->getTessFaceArray(result);
medge_new = result->getEdgeArray(result);
- origindex= result->getFaceDataArray(result, CD_ORIGINDEX);
+ origindex= result->getTessFaceDataArray(result, CD_ORIGINDEX);
DM_copy_vert_data(dm, result, 0, 0, totvert); /* copy first otherwise this overwrites our own vertex normals */
@@ -823,7 +823,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
med_new->crease= med_new_firstloop->crease;
med_new++;
}
-
+
+ /* BMesh implimentation info - need to calculate polys before recalculating
+ * normals, since normal calc overwrites MFaces from Polys */
+ CDDM_tessfaces_to_faces(result);
+
if((ltmd->flag & MOD_SCREW_NORMAL_CALC) == 0) {
CDDM_calc_normals(result);
}
@@ -862,7 +866,7 @@ static void foreachObjectLink(
static DerivedMesh *applyModifierEM(
ModifierData *md,
Object *ob,
- struct EditMesh *UNUSED(editData),
+ struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData)
{
return applyModifier(md, ob, derivedData, 0, 1);
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
index 9080ca39ebf..8a93a8a6d6f 100644
--- a/source/blender/modifiers/intern/MOD_shapekey.c
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -90,7 +90,7 @@ static void deformMatrices(ModifierData *md, Object *ob, DerivedMesh *derivedDat
}
static void deformVertsEM(ModifierData *md, Object *ob,
- struct EditMesh *UNUSED(editData),
+ struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts)
@@ -102,7 +102,7 @@ static void deformVertsEM(ModifierData *md, Object *ob,
}
static void deformMatricesEM(ModifierData *UNUSED(md), Object *ob,
- struct EditMesh *UNUSED(editData),
+ struct BMEditMesh *UNUSED(editData),
DerivedMesh *UNUSED(derivedData),
float (*vertexCos)[3],
float (*defMats)[3][3],
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index 6c047a81fa5..66213f38d8d 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -128,7 +128,7 @@ static void deformVerts(ModifierData *md, Object *ob,
dm->release(dm);
}
-static void deformVertsEM(ModifierData *md, Object *ob, struct EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
CustomDataMask dataMask = requiredDataMask(ob, md);
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index 4609ee221a4..6b691ad63aa 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -336,7 +336,7 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(ModifierData *md, Object *ob,
- struct EditMesh *editData,
+ struct BMEditMesh *editData,
DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts)
diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c
index edd16c045f6..102d325c7fa 100644
--- a/source/blender/modifiers/intern/MOD_smooth.c
+++ b/source/blender/modifiers/intern/MOD_smooth.c
@@ -232,7 +232,7 @@ static void deformVerts(
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct EditMesh *editData,
+ ModifierData *md, Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm= get_dm(ob, editData, derivedData, NULL, 0);
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index 8d47ad28a86..c9acaf9ff81 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -35,9 +35,11 @@
#include "DNA_meshdata_types.h"
+#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
-#include "BLI_utildefines.h"
+#include "BLI_array.h"
+#include "BLI_smallhash.h"
#include "BLI_string.h"
#include "BKE_cdderivedmesh.h"
@@ -59,7 +61,8 @@ typedef struct EdgeFaceRef {
static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3])
{
int i, numVerts, numEdges, numFaces;
- MFace *mface, *mf;
+ MPoly *mpoly, *mp;
+ MLoop *mloop, *ml;
MVert *mvert, *mv;
float (*face_nors)[3];
@@ -69,9 +72,10 @@ static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3])
numVerts = dm->getNumVerts(dm);
numEdges = dm->getNumEdges(dm);
numFaces = dm->getNumFaces(dm);
- mface = dm->getFaceArray(dm);
+ mpoly = CDDM_get_polys(dm);
mvert = dm->getVertArray(dm);
-
+ mloop = CDDM_get_loops(dm);
+
/* we don't want to overwrite any referenced layers */
/*
@@ -80,14 +84,14 @@ static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3])
cddm->mvert = mv;
*/
- face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+ face_nors = CustomData_get_layer(&dm->polyData, CD_NORMAL);
if(!face_nors) {
calc_face_nors = 1;
- face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, NULL, numFaces);
+ face_nors = CustomData_add_layer(&dm->polyData, CD_NORMAL, CD_CALLOC, NULL, numFaces);
}
mv = mvert;
- mf = mface;
+ mp = mpoly;
{
EdgeHash *edge_hash = BLI_edgehash_new();
@@ -110,27 +114,19 @@ static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3])
edge_ref->f2=i; \
}
- for(i = 0; i < numFaces; i++, mf++) {
+ for(i = 0; i < numFaces; i++, mp++) {
+ int j;
+
f_no = face_nors[i];
+ if(calc_face_nors)
+ mesh_calc_poly_normal(mp, mloop+mp->loopstart, mvert, f_no);
- if(mf->v4) {
- if(calc_face_nors)
- normal_quad_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
-
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v4);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v4, mf->v1);
- } else {
- if(calc_face_nors)
- normal_tri_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
-
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3);
- NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v1);
+ ml = mloop + mp->loopstart;
+ for (j=0; j<mp->totloop; j++) {
+ NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(ml[j].v, ml[(j+1)%mp->totloop].v);
}
}
-
+
for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) {
/* Get the edge vert indices, and edge value (the face indices that use it)*/
BLI_edgehashIterator_getKey(edge_iter, (int*)&ed_v1, (int*)&ed_v2);
@@ -203,32 +199,35 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
int UNUSED(isFinalCalc))
{
int i;
- DerivedMesh *result;
+ DerivedMesh *result, *odm = dm;
const SolidifyModifierData *smd = (SolidifyModifierData*) md;
- MFace *mf, *mface, *orig_mface;
- MEdge *ed, *medge, *orig_medge;
MVert *mv, *mvert, *orig_mvert;
-
+ MEdge *ed, *medge, *orig_medge;
+ MLoop *ml, *mloop, *orig_mloop;
+ MPoly *mp, *mpoly, *orig_mpoly;
const int numVerts = dm->getNumVerts(dm);
const int numEdges = dm->getNumEdges(dm);
const int numFaces = dm->getNumFaces(dm);
-
+ int numLoops=0, newLoops=0, newFaces=0, newEdges=0;
+ int j;
+
/* only use material offsets if we have 2 or more materials */
const short mat_nr_max= ob->totcol > 1 ? ob->totcol - 1 : 0;
const short mat_ofs= mat_nr_max ? smd->mat_ofs : 0;
- const short mat_ofs_rim= mat_nr_max ? smd->mat_ofs_rim : 0;
+ /* const short mat_ofs_rim= mat_nr_max ? smd->mat_ofs_rim : 0; */ /* UNUSED */
/* use for edges */
int *new_vert_arr= NULL;
- int newFaces = 0;
-
+ BLI_array_declare(new_vert_arr);
int *new_edge_arr= NULL;
- int newEdges = 0;
+ BLI_array_declare(new_edge_arr);
+ int *old_vert_arr = MEM_callocN(sizeof(int)*numVerts, "old_vert_arr in solidify");
int *edge_users= NULL;
char *edge_order= NULL;
-
+ int *edge_origIndex;
+
float (*vert_nors)[3]= NULL;
const float ofs_orig= - (((-smd->offset_fac + 1.0f) * 0.5f) * smd->offset);
@@ -242,10 +241,19 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
int defgrp_index;
modifier_get_vgroup(ob, dm, smd->defgrp_name, &dvert, &defgrp_index);
-
- orig_mface = dm->getFaceArray(dm);
- orig_medge = dm->getEdgeArray(dm);
- orig_mvert = dm->getVertArray(dm);
+
+ if (!CDDM_Check(dm)) {
+ DerivedMesh *dm2 = CDDM_copy(dm, 0);
+ dm = dm2;
+ }
+
+ numLoops = dm->numLoopData;
+ newLoops = 0;
+
+ orig_mvert = CDDM_get_verts(dm);
+ orig_medge = CDDM_get_edges(dm);
+ orig_mloop = CDDM_get_loops(dm);
+ orig_mpoly = CDDM_get_polys(dm);
if(smd->flag & MOD_SOLIDIFY_RIM) {
EdgeHash *edgehash = BLI_edgehash_new();
@@ -278,28 +286,20 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
edge_users= MEM_mallocN(sizeof(int) * numEdges, "solid_mod edges");
edge_order= MEM_mallocN(sizeof(char) * numEdges, "solid_mod eorder");
memset(edge_users, INVALID_UNUSED, sizeof(int) * numEdges);
-
- for(i=0, mf=orig_mface; i<numFaces; i++, mf++) {
- if(mf->v4) {
- ADD_EDGE_USER(mf->v1, mf->v2, 0);
- ADD_EDGE_USER(mf->v2, mf->v3, 1);
- ADD_EDGE_USER(mf->v3, mf->v4, 2);
- ADD_EDGE_USER(mf->v4, mf->v1, 3);
- }
- else {
- ADD_EDGE_USER(mf->v1, mf->v2, 0);
- ADD_EDGE_USER(mf->v2, mf->v3, 1);
- ADD_EDGE_USER(mf->v3, mf->v1, 2);
- }
+
+ for (i=0, mp=orig_mpoly; i<numFaces; i++, mp++) {
+ MLoop *ml;
+
+ for (ml=orig_mloop + mp->loopstart, j=0; j<mp->totloop; ml++, j++) {
+ MLoop *ml2 = orig_mloop + mp->loopstart + (j+1)%mp->totloop;
+ ADD_EDGE_USER(ml->v, ml2->v, j);
+ }
}
#undef ADD_EDGE_USER
#undef INVALID_UNUSED
#undef INVALID_PAIR
-
- new_edge_arr= MEM_callocN(sizeof(int) * numEdges, "solid_mod arr");
-
ehi= BLI_edgehashIterator_new(edgehash);
for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
eidx= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
@@ -307,18 +307,17 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
BLI_edgehashIterator_getKey(ehi, &v1, &v2);
orig_mvert[v1].flag |= ME_VERT_TMP_TAG;
orig_mvert[v2].flag |= ME_VERT_TMP_TAG;
- new_edge_arr[newFaces]= eidx;
+ BLI_array_append(new_edge_arr, eidx);
newFaces++;
+ newLoops += 4;
}
}
BLI_edgehashIterator_free(ehi);
-
-
- new_vert_arr= MEM_callocN(sizeof(int) * numVerts, "solid_mod new_varr");
for(i=0, mv=orig_mvert; i<numVerts; i++, mv++) {
if(mv->flag & ME_VERT_TMP_TAG) {
- new_vert_arr[newEdges] = i;
+ old_vert_arr[i] = BLI_array_count(new_vert_arr);
+ BLI_array_append(new_vert_arr, i);
newEdges++;
mv->flag &= ~ME_VERT_TMP_TAG;
@@ -333,14 +332,12 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
dm_calc_normal(dm, vert_nors);
}
- result = CDDM_from_template(dm, numVerts * 2, (numEdges * 2) + newEdges, (numFaces * 2) + newFaces);
+ result = CDDM_from_template(dm, numVerts * 2, (numEdges * 2) + newEdges, 0, (numLoops*2) + newLoops, (numFaces * 2) + newFaces);
- mface = result->getFaceArray(result);
- medge = result->getEdgeArray(result);
- mvert = result->getVertArray(result);
-
- DM_copy_face_data(dm, result, 0, 0, numFaces);
- DM_copy_face_data(dm, result, 0, numFaces, numFaces);
+ mpoly = CDDM_get_polys(result);
+ mloop = CDDM_get_loops(result);
+ medge = CDDM_get_edges(result);
+ mvert = CDDM_get_verts(result);
DM_copy_edge_data(dm, result, 0, 0, numEdges);
DM_copy_edge_data(dm, result, 0, numEdges, numEdges);
@@ -348,30 +345,41 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DM_copy_vert_data(dm, result, 0, 0, numVerts);
DM_copy_vert_data(dm, result, 0, numVerts, numVerts);
- {
- static int corner_indices[4] = {2, 1, 0, 3};
- int is_quad;
-
- for(i=0, mf=mface+numFaces; i<numFaces; i++, mf++) {
- mf->v1 += numVerts;
- mf->v2 += numVerts;
- mf->v3 += numVerts;
- if(mf->v4)
- mf->v4 += numVerts;
-
- /* Flip face normal */
- {
- is_quad = mf->v4;
- SWAP(int, mf->v1, mf->v3);
- DM_swap_face_data(result, i+numFaces, corner_indices);
- test_index_face(mf, &result->faceData, numFaces, is_quad ? 4:3);
- }
+ DM_copy_loop_data(dm, result, 0, 0, numLoops);
+ DM_copy_loop_data(dm, result, 0, numLoops, numLoops);
+
+ DM_copy_face_data(dm, result, 0, 0, numFaces);
+ DM_copy_face_data(dm, result, 0, numFaces, numFaces);
+
+ /*flip normals*/
+ mp = mpoly + numFaces;
+ for (i=0; i<dm->numPolyData; i++, mp++) {
+ MLoop *ml2;
+ int e;
+
+ ml2 = mloop + mp->loopstart + dm->numLoopData;
+ for (j=0; j<mp->totloop; j++) {
+ CustomData_copy_data(&dm->loopData, &result->loopData, mp->loopstart+j,
+ mp->loopstart+(mp->totloop-j-1)+dm->numLoopData, 1);
if(mat_ofs) {
- mf->mat_nr += mat_ofs;
- CLAMP(mf->mat_nr, 0, mat_nr_max);
+ mp->mat_nr += mat_ofs;
+ CLAMP(mp->mat_nr, 0, mat_nr_max);
}
}
+
+ e = ml2[0].e;
+ for (j=0; j<mp->totloop-1; j++) {
+ ml2[j].e = ml2[j+1].e;
+ }
+ ml2[mp->totloop-1].e = e;
+
+ mp->loopstart += dm->numLoopData;
+
+ for (j=0; j<mp->totloop; j++) {
+ ml2[j].e += numEdges;
+ ml2[j].v += numVerts;
+ }
}
for(i=0, ed=medge+numEdges; i<numEdges; i++, ed++) {
@@ -425,12 +433,13 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* same as EM_solidify() in editmesh_lib.c */
float *vert_angles= MEM_callocN(sizeof(float) * numVerts * 2, "mod_solid_pair"); /* 2 in 1 */
float *vert_accum= vert_angles + numVerts;
- float face_angles[4];
+ float *face_angles = NULL;
+ BLI_array_staticdeclare(face_angles, 16);
int j, vidx;
- face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+ face_nors = CustomData_get_layer(&dm->polyData, CD_NORMAL);
if(!face_nors) {
- face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, NULL, dm->numFaceData);
+ face_nors = CustomData_add_layer(&dm->polyData, CD_NORMAL, CD_CALLOC, NULL, dm->numPolyData);
face_nors_calc= 1;
}
@@ -440,32 +449,31 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
normal_short_to_float_v3(vert_nors[i], mv->no);
}
}
-
- for(i=0, mf=mface; i<numFaces; i++, mf++) {
-
+
+ for (i=0, mp=mpoly; i<numFaces; i++, mp++) {
+ mesh_calc_poly_normal(mp, mloop+mp->loopstart, mvert, face_nors[i]);
+
/* just added, calc the normal */
- if(face_nors_calc) {
- if(mf->v4)
- normal_quad_v3(face_nors[i], mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
- else
- normal_tri_v3(face_nors[i] , mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co);
- }
-
- if(mf->v4) {
- angle_quad_v3(face_angles, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
- j= 3;
- }
- else {
- angle_tri_v3(face_angles, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co);
- j= 2;
+ BLI_array_empty(face_angles);
+ for (j=0, ml=mloop+mp->loopstart; j<mp->totloop; j++, ml++) {
+ MLoop *ml2 = mloop + mp->loopstart + (j+1)%mp->totloop; //next
+ MLoop *ml3 = mloop + mp->loopstart + (j+mp->totloop-1)%mp->totloop; //previous
+ float e1[3], e2[3], angle;
+
+ sub_v3_v3v3(e1, mvert[ml2->v].co, mvert[ml->v].co);
+ sub_v3_v3v3(e2, mvert[ml3->v].co, mvert[ml->v].co);
+ angle = M_PI - angle_normalized_v3v3(e1, e2);
+ BLI_array_append(face_angles, angle);
}
-
- do {
- vidx = *(&mf->v1 + j);
+
+ for (j=0, ml=mloop+mp->loopstart; j<mp->totloop; j++, ml++) {
+ vidx = ml->v;
vert_accum[vidx] += face_angles[j];
vert_angles[vidx]+= shell_angle_to_dist(angle_normalized_v3v3(vert_nors[vidx], face_nors[i])) * face_angles[j];
- } while(j--);
+ }
}
+
+ BLI_array_free(face_angles);
/* vertex group support */
if(dvert) {
@@ -543,12 +551,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
const unsigned char crease_outer= smd->crease_outer * 255.0f;
const unsigned char crease_inner= smd->crease_inner * 255.0f;
- const int edge_indices[4][4] = {
- {1, 0, 0, 1},
- {2, 1, 1, 2},
- {3, 2, 2, 3},
- {0, 3, 3, 0}};
-
/* add faces & edges */
origindex= result->getEdgeDataArray(result, CD_ORIGINDEX);
ed= medge + (numEdges * 2);
@@ -564,12 +566,17 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
/* faces */
- mf= mface + (numFaces * 2);
- origindex= result->getFaceDataArray(result, CD_ORIGINDEX);
- for(i=0; i<newFaces; i++, mf++) {
+ edge_origIndex = CustomData_get_layer(&result->edgeData, CD_ORIGINDEX);
+
+ mp= mpoly + (numFaces * 2);
+ origindex= result->getTessFaceDataArray(result, CD_ORIGINDEX);
+ ml = mloop + (numLoops * 2);
+ j = 0;
+ for(i=0; i<newFaces; i++, mp++) {
int eidx= new_edge_arr[i];
int fidx= edge_users[eidx];
- int flip;
+ int flip, k1, k2;
+ MLoop *ml2;
if(fidx >= numFaces) {
fidx -= numFaces;
@@ -583,32 +590,77 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* copy most of the face settings */
DM_copy_face_data(dm, result, fidx, (numFaces * 2) + i, 1);
-
+ mp->loopstart = j+numLoops*2;
+ mp->flag = mpoly[fidx].flag;
+ mp->totloop = 4;
+
+ ml2 = mloop + mpoly[fidx].loopstart;
+ for (k1=0; k1<mpoly[fidx].totloop; k1++, ml2++) {
+ if (ml2->e == eidx)
+ break;
+ }
+
+ if (k1 == mpoly[fidx].totloop) {
+ fprintf(stderr, "%s: solidify bad k1==totloop (bmesh internal error)\n", __func__);
+ }
+
+ if (ed->v2 == mloop[mpoly[fidx].loopstart+k1].v) {
+ k2 = (k1 + mp->totloop - 1)%mp->totloop;
+ SWAP(int, k1, k2);
+ } else if (ed->v1 == mloop[mpoly[fidx].loopstart+k1].v) {
+ k2 = (k1+1)%mp->totloop;
+ } else {
+ fprintf(stderr, "%s: solidify bad edge/vert\n", __func__);
+ k2 = k1;
+ }
+
+ k1 += mpoly[fidx].loopstart;
+ k2 += mpoly[fidx].loopstart;
+
if(flip) {
- DM_swap_face_data(result, (numFaces * 2) + i, edge_indices[edge_order[eidx]]);
-
- mf->v1= ed->v1;
- mf->v2= ed->v2;
- mf->v3= ed->v2 + numVerts;
- mf->v4= ed->v1 + numVerts;
+ CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops*2+j, 1);
+ CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops*2+j+1, 1);
+ CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops*2+j+2, 1);
+ CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops*2+j+3, 1);
+
+ ml[j].v = ed->v1;
+ ml[j++].e = eidx;
+
+ ml[j].v = ed->v2;
+ ml[j++].e = numEdges*2 + old_vert_arr[ed->v2];
+
+ ml[j].v = ed->v2+numVerts;
+ ml[j++].e = eidx+numEdges;
+
+ ml[j].v = ed->v1+numVerts;
+ ml[j++].e = numEdges*2 + old_vert_arr[ed->v1];
}
else {
- DM_swap_face_data(result, (numFaces * 2) + i, edge_indices[edge_order[eidx]]);
-
- mf->v1= ed->v2;
- mf->v2= ed->v1;
- mf->v3= ed->v1 + numVerts;
- mf->v4= ed->v2 + numVerts;
+ CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops*2+j, 1);
+ CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops*2+j+1, 1);
+ CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops*2+j+2, 1);
+ CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops*2+j+3, 1);
+
+ ml[j].v = ed->v1+numVerts;
+ ml[j++].e = eidx+numEdges;
+
+ ml[j].v = ed->v2+numVerts;
+ ml[j++].e = numEdges*2 + old_vert_arr[ed->v2];
+
+ ml[j].v = ed->v2;
+ ml[j++].e = eidx;
+
+ ml[j].v = ed->v1;
+ ml[j++].e = numEdges*2 + old_vert_arr[ed->v1];
}
- /* use the next material index if option enabled */
- if(mat_ofs_rim) {
- mf->mat_nr += mat_ofs_rim;
- CLAMP(mf->mat_nr, 0, mat_nr_max);
+ if (edge_origIndex) {
+ edge_origIndex[ml[j-3].e] = ORIGINDEX_NONE;
+ edge_origIndex[ml[j-1].e] = ORIGINDEX_NONE;
}
if(crease_outer) {
/* crease += crease_outer; without wrapping */
- unsigned char *cr= (unsigned char *)&(ed->crease);
+ unsigned char *cr= (unsigned char *)&(medge[eidx].crease);
int tcr= *cr + crease_outer;
*cr= tcr > 255 ? 255 : tcr;
}
@@ -621,7 +673,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
#ifdef SOLIDIFY_SIDE_NORMALS
- normal_quad_v3(nor, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
+ normal_quad_v3(nor, mvert[ml[j-4].v].co, mvert[ml[j-3].v].co, mvert[ml[j-2].v].co, mvert[ml[j-1].v].co);
add_v3_v3(edge_vert_nos[ed->v1], nor);
add_v3_v3(edge_vert_nos[ed->v2], nor);
@@ -651,17 +703,27 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
MEM_freeN(edge_vert_nos);
#endif
- MEM_freeN(new_vert_arr);
- MEM_freeN(new_edge_arr);
+ BLI_array_free(new_vert_arr);
+ BLI_array_free(new_edge_arr);
MEM_freeN(edge_users);
MEM_freeN(edge_order);
}
+ if (old_vert_arr)
+ MEM_freeN(old_vert_arr);
+
/* must recalculate normals with vgroups since they can displace unevenly [#26888] */
if(dvert) {
CDDM_calc_normals(result);
+ } else {
+ CDDM_recalc_tesselation(result, 1);
}
-
+
+ if (dm != odm) {
+ dm->needsFree = 1;
+ dm->release(dm);
+ }
+
return result;
}
@@ -669,7 +731,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
static DerivedMesh *applyModifierEM(ModifierData *md,
Object *ob,
- struct EditMesh *UNUSED(editData),
+ struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData)
{
return applyModifier(md, ob, derivedData, 0, 1);
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index d42c95a4ce8..7fd2d4c31ca 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -101,7 +101,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
useRenderParams, NULL, isFinalCalc, 0, (ob->flag & OB_MODE_EDIT));
if(useRenderParams || !isFinalCalc) {
- DerivedMesh *cddm= CDDM_copy(result);
+ DerivedMesh *cddm= CDDM_copy(result, 0);
result->release(result);
result= cddm;
}
@@ -110,7 +110,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
static DerivedMesh *applyModifierEM(ModifierData *md, Object *UNUSED(ob),
- struct EditMesh *UNUSED(editData),
+ struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData)
{
SubsurfModifierData *smd = (SubsurfModifierData*) md;
diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c
index 258627e8481..161bdcaf4ac 100644
--- a/source/blender/modifiers/intern/MOD_surface.c
+++ b/source/blender/modifiers/intern/MOD_surface.c
@@ -99,7 +99,7 @@ static void deformVerts(ModifierData *md, Object *ob,
surmd->dm->release(surmd->dm);
/* if possible use/create DerivedMesh */
- if(derivedData) surmd->dm = CDDM_copy(derivedData);
+ if(derivedData) surmd->dm = CDDM_copy(derivedData, 0);
else surmd->dm = get_dm(ob, NULL, NULL, NULL, 0);
if(!ob->pd)
@@ -158,7 +158,7 @@ static void deformVerts(ModifierData *md, Object *ob,
else
surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh");
- if(surmd->dm->getNumFaces(surmd->dm))
+ if(surmd->dm->getNumTessFaces(surmd->dm))
bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
else
bvhtree_from_mesh_edges(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index b7883eea4d8..8d83bbecaac 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -97,11 +97,11 @@ void get_texture_coords(MappingInfoModifierData *dmd, Object *ob,
/* UVs need special handling, since they come from faces */
if(texmapping == MOD_DISP_MAP_UV) {
if(CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
- MFace *mface = dm->getFaceArray(dm);
+ MFace *mface = dm->getTessFaceArray(dm);
MFace *mf;
char *done = MEM_callocN(sizeof(*done) * numVerts,
"get_texture_coords done");
- int numFaces = dm->getNumFaces(dm);
+ int numFaces = dm->getNumTessFaces(dm);
char uvname[32];
MTFace *tf;
@@ -196,7 +196,7 @@ void validate_layer_name(const CustomData *data, int type, char *name, char *out
}
/* returns a cdderivedmesh if dm == NULL or is another type of derivedmesh */
-DerivedMesh *get_cddm(Object *ob, struct EditMesh *em, DerivedMesh *dm, float (*vertexCos)[3])
+DerivedMesh *get_cddm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3])
{
if(dm && dm->type == DM_TYPE_CDDM)
return dm;
@@ -205,7 +205,7 @@ DerivedMesh *get_cddm(Object *ob, struct EditMesh *em, DerivedMesh *dm, float (*
dm= get_dm(ob, em, dm, vertexCos, 0);
}
else {
- dm= CDDM_copy(dm);
+ dm= CDDM_copy(dm, 0);
CDDM_apply_vert_coords(dm, vertexCos);
}
@@ -216,13 +216,13 @@ DerivedMesh *get_cddm(Object *ob, struct EditMesh *em, DerivedMesh *dm, float (*
}
/* returns a derived mesh if dm == NULL, for deforming modifiers that need it */
-DerivedMesh *get_dm(Object *ob, struct EditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], int orco)
+DerivedMesh *get_dm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], int orco)
{
if(dm)
return dm;
if(ob->type==OB_MESH) {
- if(em) dm= CDDM_from_editmesh(em, ob->data);
+ if(em) dm= CDDM_from_BMEditMesh(em, ob->data, 0);
else dm = CDDM_from_mesh((struct Mesh *)(ob->data), ob);
if(vertexCos) {
@@ -296,5 +296,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
INIT_TYPE(WeightVGEdit);
INIT_TYPE(WeightVGMix);
INIT_TYPE(WeightVGProximity);
+ INIT_TYPE(NgonInterp);
#undef INIT_TYPE
}
diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h
index 4de767358e4..82e04468c86 100644
--- a/source/blender/modifiers/intern/MOD_util.h
+++ b/source/blender/modifiers/intern/MOD_util.h
@@ -48,8 +48,8 @@ void get_texture_value(struct Tex *texture, float *tex_co, struct TexResult *tex
void get_texture_coords(struct MappingInfoModifierData *dmd, struct Object *ob, struct DerivedMesh *dm, float (*co)[3], float (*texco)[3], int numVerts);
void modifier_vgroup_cache(struct ModifierData *md, float (*vertexCos)[3]);
void validate_layer_name(const struct CustomData *data, int type, char *name, char *outname);
-struct DerivedMesh *get_cddm(struct Object *ob, struct EditMesh *em, struct DerivedMesh *dm, float (*vertexCos)[3]);
-struct DerivedMesh *get_dm(struct Object *ob, struct EditMesh *em, struct DerivedMesh *dm, float (*vertexCos)[3], int orco);
+struct DerivedMesh *get_cddm(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, float (*vertexCos)[3]);
+struct DerivedMesh *get_dm(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, float (*vertexCos)[3], int orco);
void modifier_get_vgroup(struct Object *ob, struct DerivedMesh *dm, const char *name, struct MDeformVert **dvert, int *defgrp_index);
#endif /* MOD_UTIL_H */
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 36d773ad605..2ddbae28cb6 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -273,8 +273,8 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
for(i = 0, co = coords; i < numVerts; ++i, ++co)
mul_project_m4_v3(projectors[0].projmat, *co);
- mface = dm->getFaceArray(dm);
- numFaces = dm->getNumFaces(dm);
+ mface = dm->getTessFaceArray(dm);
+ numFaces = dm->getNumTessFaces(dm);
/* apply coords as UVs, and apply image if tfaces are new */
for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tface) {
@@ -398,7 +398,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
- struct EditMesh *UNUSED(editData),
+ struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData)
{
return applyModifier(md, ob, derivedData, 0, 1);
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index 8422916e450..d86e746abbc 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -330,7 +330,7 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
}
}
-static void deformVertsEM(ModifierData *md, Object *ob, struct EditMesh *editData,
+static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
@@ -338,7 +338,7 @@ static void deformVertsEM(ModifierData *md, Object *ob, struct EditMesh *editDat
if(use_dm) {
if(!derivedData)
- dm = CDDM_from_editmesh(editData, ob->data);
+ dm = CDDM_from_BMEditMesh(editData, ob->data, 0);
}
deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index 6aac7077447..5d020cc8a03 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -188,11 +188,11 @@ static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob,
/* UVs need special handling, since they come from faces */
if(texmapping == MOD_WAV_MAP_UV) {
if(CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
- MFace *mface = dm->getFaceArray(dm);
+ MFace *mface = dm->getTessFaceArray(dm);
MFace *mf;
char *done = MEM_callocN(sizeof(*done) * numVerts,
"get_texture_coords done");
- int numFaces = dm->getNumFaces(dm);
+ int numFaces = dm->getNumTessFaces(dm);
char uvname[32];
MTFace *tf;
@@ -430,7 +430,7 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct EditMesh *editData,
+ ModifierData *md, Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm= derivedData;
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index 24d80fe847c..a4c0f0ffa70 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -241,7 +241,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
else
ret = dm;
#else
- ret = CDDM_copy(dm);
+ ret = CDDM_copy(dm, 0);
rel_ret = 1;
dvert = ret->getVertDataArray(ret, CD_MDEFORMVERT);
if (dvert == NULL) {
@@ -289,7 +289,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
}
static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
- struct EditMesh *UNUSED(editData),
+ struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData)
{
return applyModifier(md, ob, derivedData, 0, 1);
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index 221deeef1a6..43f503a7624 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -288,7 +288,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
else
ret = dm;
#else
- ret = CDDM_copy(dm);
+ ret = CDDM_copy(dm, 0);
rel_ret = 1;
dvert = ret->getVertDataArray(ret, CD_MDEFORMVERT);
if (dvert == NULL) {
@@ -423,7 +423,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
}
static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
- struct EditMesh *UNUSED(editData),
+ struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData)
{
return applyModifier(md, ob, derivedData, 0, 1);
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 8effe4d7c1b..ad16cbe97a0 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -405,7 +405,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
else
ret = dm;
#else
- ret = CDDM_copy(dm);
+ ret = CDDM_copy(dm, 0);
rel_ret = 1;
dvert = ret->getVertDataArray(ret, CD_MDEFORMVERT);
if (dvert == NULL) {
@@ -471,8 +471,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
target_dm = CDDM_from_curve(obr);
else if (obr->type == OB_MESH) {
Mesh *me = (Mesh*)obr->data;
- if (me->edit_mesh)
- target_dm = CDDM_from_editmesh((EditMesh*)me->edit_mesh, me);
+ if (me->edit_btmesh)
+ target_dm = CDDM_from_BMEditMesh(me->edit_btmesh, me, 0);
else
target_dm = CDDM_from_mesh(me, obr);
}
@@ -532,7 +532,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
}
static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
- struct EditMesh *UNUSED(editData),
+ struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData)
{
return applyModifier(md, ob, derivedData, 0, 1);
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 34575a8d886..5f325e4b4cc 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: mathutils.c 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h
index eefaaaed122..9b8dbe06e3b 100644
--- a/source/blender/python/mathutils/mathutils.h
+++ b/source/blender/python/mathutils/mathutils.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: mathutils.h 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c
index f7cc1d4271a..d70a431d847 100644
--- a/source/blender/python/mathutils/mathutils_Color.c
+++ b/source/blender/python/mathutils/mathutils_Color.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: mathutils_Color.c 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/mathutils/mathutils_Color.h b/source/blender/python/mathutils/mathutils_Color.h
index 0fc880363f4..0afb0ee4dc1 100644
--- a/source/blender/python/mathutils/mathutils_Color.h
+++ b/source/blender/python/mathutils/mathutils_Color.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: mathutils_Color.h 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c
index c6be461a227..3da88bf8d48 100644
--- a/source/blender/python/mathutils/mathutils_Euler.c
+++ b/source/blender/python/mathutils/mathutils_Euler.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: mathutils_Euler.c 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/mathutils/mathutils_Euler.h b/source/blender/python/mathutils/mathutils_Euler.h
index 849e16c2bb7..2df3d6198b8 100644
--- a/source/blender/python/mathutils/mathutils_Euler.h
+++ b/source/blender/python/mathutils/mathutils_Euler.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: mathutils_Euler.h 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/mathutils/mathutils_Matrix.h b/source/blender/python/mathutils/mathutils_Matrix.h
index aa736d1e959..84a92bae2be 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.h
+++ b/source/blender/python/mathutils/mathutils_Matrix.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: mathutils_Matrix.h 38409 2011-07-15 04:01:47Z campbellbarton $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c
index eda6aa5c84e..44b3123c8e7 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: mathutils_Quaternion.c 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.h b/source/blender/python/mathutils/mathutils_Quaternion.h
index d606621390a..4ba70895680 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.h
+++ b/source/blender/python/mathutils/mathutils_Quaternion.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: mathutils_Quaternion.h 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index df8598cc3f1..e7d681042d0 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: mathutils_Vector.c 38409 2011-07-15 04:01:47Z campbellbarton $
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
diff --git a/source/blender/python/mathutils/mathutils_Vector.h b/source/blender/python/mathutils/mathutils_Vector.h
index 0ede836ce44..e430a100836 100644
--- a/source/blender/python/mathutils/mathutils_Vector.h
+++ b/source/blender/python/mathutils/mathutils_Vector.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: mathutils_Vector.h 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index dafd89757a9..e7fc06498a4 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: mathutils_geometry.c 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/python/mathutils/mathutils_geometry.h b/source/blender/python/mathutils/mathutils_geometry.h
index 4cc63054393..6510b6f55dc 100644
--- a/source/blender/python/mathutils/mathutils_geometry.h
+++ b/source/blender/python/mathutils/mathutils_geometry.h
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: mathutils_geometry.h 38409 2011-07-15 04:01:47Z campbellbarton $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript
index 9c724187c27..99ff10d19eb 100644
--- a/source/blender/render/SConscript
+++ b/source/blender/render/SConscript
@@ -6,7 +6,7 @@ raysources = env.Glob('intern/raytrace/*.cpp')
incs = 'intern/include #/intern/guardedalloc ../blenlib ../makesdna ../makesrna'
incs += ' extern/include ../blenkernel ../radiosity/extern/include ../imbuf'
-incs += ' ../include ../blenloader ../../../intern/smoke/extern ../../../intern/mikktspace'
+incs += ' ../include ../blenloader ../../../intern/smoke/extern ../../../intern/mikktspace ../bmesh'
cflags_raytrace = env['CCFLAGS']
cxxflags_raytrace = env['CXXFLAGS']
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 5968a6e64f8..057b768622d 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -1522,7 +1522,7 @@ static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int
if(sd->uvco && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
for(i=0; i<sd->totuv; i++) {
if(num != DMCACHE_NOTFOUND) {
- MFace *mface = dm->getFaceData(dm, num, CD_MFACE);
+ MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
MTFace *mtface = (MTFace*)CustomData_get_layer_n(&dm->faceData, CD_MTFACE, i);
mtface += num;
@@ -1539,7 +1539,7 @@ static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int
if(sd->mcol && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
for(i=0; i<sd->totcol; i++) {
if(num != DMCACHE_NOTFOUND) {
- MFace *mface = dm->getFaceData(dm, num, CD_MFACE);
+ MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
MCol *mc = (MCol*)CustomData_get_layer_n(&dm->faceData, CD_MCOL, i);
mc += num * 4;
@@ -1750,8 +1750,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if(ma->amb != 0.0f)
dosurfacecache= 1;
- totface= psmd->dm->getNumFaces(psmd->dm);
- origindex= psmd->dm->getFaceDataArray(psmd->dm, CD_ORIGINDEX);
+ totface= psmd->dm->getNumTessFaces(psmd->dm);
+ origindex= psmd->dm->getTessFaceDataArray(psmd->dm, CD_ORIGINDEX);
for(a=0; a<totface; a++)
strandbuf->totbound= MAX2(strandbuf->totbound, (origindex)? origindex[a]: a);
@@ -1795,7 +1795,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
num= pa->num_dmcache;
if(num == DMCACHE_NOTFOUND)
- if(pa->num < psmd->dm->getNumFaces(psmd->dm))
+ if(pa->num < psmd->dm->getNumTessFaces(psmd->dm))
num= pa->num;
get_particle_uvco_mcol(part->from, psmd->dm, pa->fuv, num, &sd);
@@ -1854,7 +1854,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
num = parent->num_dmcache;
if(num == DMCACHE_NOTFOUND)
- if(parent->num < psmd->dm->getNumFaces(psmd->dm))
+ if(parent->num < psmd->dm->getNumTessFaces(psmd->dm))
num = parent->num;
get_particle_uvco_mcol(part->from, psmd->dm, parent->fuv, num, &sd);
@@ -2720,8 +2720,8 @@ static void init_render_dm(DerivedMesh *dm, Render *re, ObjectRen *obr,
for(mat_iter= 0; (mat_iter < ob->totcol || (mat_iter==0 && ob->totcol==0)); mat_iter++) {
ma= give_render_material(re, ob, mat_iter+1);
- end= dm->getNumFaces(dm);
- mface= dm->getFaceArray(dm);
+ end= dm->getNumTessFaces(dm);
+ mface= dm->getTessFaceArray(dm);
for(a=0; a<end; a++, mface++) {
int v1, v2, v3, v4, flag;
@@ -3100,10 +3100,10 @@ static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort)
unsigned int *mcol=NULL;
int a, totedge=0, totface;
- mface= dm->getFaceArray(dm);
- totface= dm->getNumFaces(dm);
- tface= dm->getFaceDataArray(dm, CD_MTFACE);
- mcol= dm->getFaceDataArray(dm, CD_MCOL);
+ mface= dm->getTessFaceArray(dm);
+ totface= dm->getNumTessFaces(dm);
+ tface= dm->getTessFaceDataArray(dm, CD_MTFACE);
+ mcol= dm->getTessFaceDataArray(dm, CD_MCOL);
if(mcol==NULL && tface==NULL) return NULL;
@@ -3324,7 +3324,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
totvert= dm->getNumVerts(dm);
/* attempt to autsmooth on original mesh, only without subsurf */
- if(do_autosmooth && me->totvert==totvert && me->totface==dm->getNumFaces(dm))
+ if(do_autosmooth && me->totvert==totvert && me->totface==dm->getNumTessFaces(dm))
use_original_normals= 1;
ms = (totvert==me->totvert)?me->msticky:NULL;
@@ -3345,7 +3345,9 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
mul_m4_v3(mat, ver->co);
mul_transposed_m3_v3(imat, ver->n);
normalize_v3(ver->n);
- negate_v3(ver->n);
+
+ if(!negative_scale)
+ negate_v3(ver->n);
}
if(orco) {
@@ -3395,19 +3397,18 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
}
if(ok) {
- end= dm->getNumFaces(dm);
- mface= dm->getFaceArray(dm);
+ end= dm->getNumTessFaces(dm);
+ mface= dm->getTessFaceArray(dm);
for(a=0; a<end; a++, mface++) {
int v1, v2, v3, v4, flag;
if( mface->mat_nr==a1 ) {
float len;
- int reverse_verts = negative_scale!=0 && do_autosmooth==0;
- int rev_tab[] = {reverse_verts==0 ? 0 : 2, 1, reverse_verts==0 ? 2 : 0, 3};
- v1= reverse_verts==0 ? mface->v1 : mface->v3;
+
+ v1= mface->v1;
v2= mface->v2;
- v3= reverse_verts==0 ? mface->v3 : mface->v1;
+ v3= mface->v3;
v4= mface->v4;
flag= mface->flag & ME_SMOOTH;
@@ -3444,40 +3445,36 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
CustomDataLayer *layer;
MTFace *mtface, *mtf;
MCol *mcol, *mc;
- int index, mtfn= 0, mcn= 0, mtng=0, vindex;
+ int index, mtfn= 0, mcn= 0, mtng=0;
char *name;
- int nr_verts = v4!=0 ? 4 : 3;
for(index=0; index<dm->faceData.totlayer; index++) {
layer= &dm->faceData.layers[index];
name= layer->name;
if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) {
- int t;
mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1);
mtface= (MTFace*)layer->data;
- *mtf= mtface[a]; // copy face info
- for(vindex=0; vindex<nr_verts; vindex++)
- for(t=0; t<2; t++)
- mtf->uv[vindex][t]=mtface[a].uv[rev_tab[vindex]][t];
+ *mtf= mtface[a];
}
else if(layer->type == CD_MCOL && mcn < MAX_MCOL) {
mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1);
mcol= (MCol*)layer->data;
- for(vindex=0; vindex<nr_verts; vindex++)
- mc[vindex]=mcol[a*4+rev_tab[vindex]];
+ memcpy(mc, &mcol[a*4], sizeof(MCol)*4);
}
else if(layer->type == CD_TANGENT && mtng < 1)
{
if(need_nmap_tangent!=0)
{
const float * tangent = (const float *) layer->data;
+ int t;
+ int nr_verts = v4!=0 ? 4 : 3;
float * ftang = RE_vlakren_get_nmap_tangent(obr, vlr, 1);
- for(vindex=0; vindex<nr_verts; vindex++)
+ for(t=0; t<nr_verts; t++)
{
- QUATCOPY(ftang+vindex*4, tangent+a*16+rev_tab[vindex]*4);
- mul_mat3_m4_v3(mat, ftang+vindex*4);
- normalize_v3(ftang+vindex*4);
+ QUATCOPY(ftang+t*4, tangent+a*16+t*4);
+ mul_mat3_m4_v3(mat, ftang+t*4);
+ normalize_v3(ftang+t*4);
}
}
}
diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c
index ed12c08c193..644cb821e8c 100644
--- a/source/blender/render/intern/source/strand.c
+++ b/source/blender/render/intern/source/strand.c
@@ -978,7 +978,7 @@ StrandSurface *cache_strand_surface(Render *re, ObjectRen *obr, DerivedMesh *dm,
int a, totvert, totface;
totvert= dm->getNumVerts(dm);
- totface= dm->getNumFaces(dm);
+ totface= dm->getNumTessFaces(dm);
for(mesh=re->strandsurface.first; mesh; mesh=mesh->next)
if(mesh->obr.ob == obr->ob && mesh->obr.par == obr->par
@@ -1012,7 +1012,7 @@ StrandSurface *cache_strand_surface(Render *re, ObjectRen *obr, DerivedMesh *dm,
mul_m4_v3(mat, co[a]);
}
- mface= dm->getFaceArray(dm);
+ mface= dm->getTessFaceArray(dm);
for(a=0; a<mesh->totface; a++, mface++) {
mesh->face[a][0]= mface->v1;
mesh->face[a][1]= mface->v2;
diff --git a/source/blender/windowmanager/SConscript b/source/blender/windowmanager/SConscript
index ef6ddd18bb1..be037452284 100644
--- a/source/blender/windowmanager/SConscript
+++ b/source/blender/windowmanager/SConscript
@@ -10,7 +10,7 @@ sources = env.Glob('intern/*.c')
incs = '. ../editors/include ../python ../makesdna ../blenlib ../blenkernel'
incs += ' ../nodes ../imbuf ../blenloader ../render/extern/include'
incs += ' ../radiosity/extern/include'
-incs += ' ../makesrna ../gpu ../blenfont'
+incs += ' ../makesrna ../gpu ../blenfont ../bmesh'
incs += ' #/intern/guardedalloc #/intern/memutil #/intern/ghost'
incs += ' #/intern/elbeem #/extern/glew/include'
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index d2bc9cf8ba2..72af805a65b 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -235,6 +235,7 @@ static void draw_filled_lasso(wmGesture *gt)
short *lasso= (short *)gt->customdata;
int i;
+ BLI_begin_edgefill();
for (i=0; i<gt->points; i++, lasso+=2) {
float co[3];
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index b0be4bb9720..40da1024a56 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -62,6 +62,7 @@
#include "BKE_material.h" /* clear_matcopybuf */
#include "BLI_blenlib.h"
+#include "BLI_cellalloc.h"
#include "BLI_winstuff.h"
#include "RE_engine.h"
@@ -458,8 +459,10 @@ void WM_exit_ext(bContext *C, const short do_python)
GHOST_DisposeSystemPaths();
if(MEM_get_memory_blocks_in_use()!=0) {
- printf("Error: Not freed memory blocks: %d\n", MEM_get_memory_blocks_in_use());
+ printf("Error: Not freed memory blocks: %d\n", MEM_get_memory_blocks_in_use()+BLI_cellalloc_get_totblock());
MEM_printmemlist();
+ BLI_cellalloc_printleaks();
+ BLI_cellalloc_destroy();
}
wm_autosave_delete();
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index 701ad244fc1..8442045b91f 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -100,6 +100,7 @@ endif()
bf_intern_string
bf_intern_ghost
bf_rna
+ bf_bmesh
bf_blenkernel
bf_blenloader
bf_blenpluginapi
@@ -144,6 +145,7 @@ endif()
bf_blenfont
bf_intern_audaspace
blenkernel_blc
+ bf_bmesh
extern_binreloc
extern_minilzo
bf_intern_ghost # duplicate for linking
@@ -164,8 +166,6 @@ endif()
list(APPEND BLENDER_SORTED_LIBS extern_lzma)
endif()
- list(APPEND BLENDER_SORTED_LIBS extern_colamd)
-
if(WITH_MOD_DECIMATE)
list(APPEND BLENDER_SORTED_LIBS bf_intern_decimate)
endif()
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 1dbed479d40..94dc6a93cc4 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -103,8 +103,27 @@ struct bPythonConstraint;
struct bConstraintOb;
struct Context;
struct ChannelDriver;
+struct BMEditMesh;
+struct Heap;
+struct HeapNode;
+struct Scene;
/*new render funcs */
+void EDBM_selectmode_set(struct BMEditMesh *em) {}
+void EDBM_LoadEditBMesh(struct Scene *scene, struct Object *ob) {}
+void EDBM_MakeEditBMesh(struct ToolSettings *ts, struct Scene *scene, struct Object *ob) {}
+void *g_system;
+
+struct Heap* BLI_heap_new (void){return NULL;}
+void BLI_heap_free (struct Heap *heap, void *ptrfreefp) {}
+struct HeapNode* BLI_heap_insert (struct Heap *heap, float value, void *ptr){return NULL;}
+void BLI_heap_remove (struct Heap *heap, struct HeapNode *node) {}
+int BLI_heap_empty (struct Heap *heap) {return 0;}
+int BLI_heap_size (struct Heap *heap){return 0;}
+struct HeapNode* BLI_heap_top (struct Heap *heap){return NULL;}
+void* BLI_heap_popmin (struct Heap *heap){return NULL;}
+
+
float *RE_RenderLayerGetPass(struct RenderLayer *rl, int passtype) {return (float *) NULL;}
float RE_filter_value(int type, float x) {return 0.0f;}
struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name) {return (struct RenderLayer *)NULL;}
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 867ea37e0a1..217135360da 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -784,6 +784,7 @@ endif()
bf_python_ext
bf_python_mathutils
bf_ikplugin
+ bf_bmesh
bf_modifiers
bf_blenkernel
bf_nodes
@@ -814,7 +815,6 @@ endif()
bf_intern_smoke
extern_minilzo
extern_lzma
- extern_colamd
ge_logic_ketsji
extern_recastnavigation
ge_phys_common
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 1d083af7d07..a6a86a7793d 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -43,6 +43,8 @@
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
+#include <signal.h>
+
/* This little block needed for linking to Blender... */
@@ -120,6 +122,8 @@
#include "binreloc.h"
#endif
+static int no_handler = 0;
+
// from buildinfo.c
#ifdef BUILD_DATE
extern char build_date[];
@@ -315,6 +319,32 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
double PIL_check_seconds_timer(void);
+void segmentation_handler(int UNUSED(sig))
+{
+ char fname[256];
+
+ if (!G.main->name[0]) {
+ BLI_make_file_string("/", fname, BLI_temporary_dir(), "crash.blend");
+ }
+ else {
+ sprintf(fname, "%s.crash.blend", G.main->name);
+ }
+
+ BKE_undo_save(fname);
+
+ /*induce a real crash*/
+ signal(SIGSEGV, SIG_DFL);
+ *(int*)NULL = 0;
+}
+
+static int nocrashhandler(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
+{
+ no_handler = 1;
+
+ return 0;
+}
+
+
static int end_arguments(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
return -1;
@@ -1080,7 +1110,8 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
BLI_argsAdd(ba, 2, "-con", "--start-console", "\n\tStart with the console window open (ignored if -b is set)", start_with_console, NULL);
BLI_argsAdd(ba, 2, "-R", NULL, "\n\tRegister .blend extension, then exit (Windows only)", register_extension, NULL);
BLI_argsAdd(ba, 2, "-r", NULL, "\n\tSilently register .blend extension, then exit (Windows only)", register_extension, ba);
-
+ BLI_argsAdd(ba, 2, "--no_crash_handler", NULL, "disable crash handler", nocrashhandler, NULL);
+
/* third pass: disabling things and forcing settings */
BLI_argsAddCase(ba, 3, "-nojoystick", 1, NULL, 0, "\n\tDisable joystick support", no_joystick, syshandle);
BLI_argsAddCase(ba, 3, "-noglsl", 1, NULL, 0, "\n\tDisable GLSL shading", no_glsl, NULL);
@@ -1105,7 +1136,6 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
BLI_argsAdd(ba, 4, "-F", "--render-format", format_doc, set_image_type, C);
BLI_argsAdd(ba, 4, "-t", "--threads", "<threads>\n\tUse amount of <threads> for rendering in background\n\t[1-" STRINGIFY(BLENDER_MAX_THREADS) "], 0 for systems processor count.", set_threads, NULL);
BLI_argsAdd(ba, 4, "-x", "--use-extension", "<bool>\n\tSet option to add the file extension to the end of the file", set_extension, C);
-
}
#ifdef WITH_PYTHON_MODULE
@@ -1183,6 +1213,11 @@ int main(int argc, const char **argv)
BLI_argsParse(ba, 1, NULL, NULL);
+ if (!no_handler) {
+ signal(SIGSEGV, segmentation_handler);
+ //signal(SIGFPE, segmentation_handler);
+ }
+
#if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
G.background= 1; /* python module mode ALWAYS runs in background mode (for now) */
#else
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index 6f2ca28c135..505bbf9dee4 100644
--- a/source/gameengine/Converter/BL_ActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -158,8 +158,6 @@ void BL_ActionActuator::SetLocalTime(float curtime)
m_starttime = curtime;
- m_flag ^= ACT_FLAG_REVERSE;
-
break;
}
}
@@ -208,8 +206,9 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
if (m_flag & ACT_FLAG_REVERSE)
{
- start = m_endframe;
- end = m_startframe;
+ m_localtime = start;
+ start = end;
+ end = m_localtime;
}
break;
@@ -237,12 +236,6 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
RemoveAllEvents();
}
- if (bUseContinue && (m_flag & ACT_FLAG_ACTIVE))
- {
- m_localtime = obj->GetActionFrame(m_layer);
- ResetStartTime(curtime);
- }
-
if (m_flag & ACT_FLAG_ATTEMPT_PLAY)
SetLocalTime(curtime);
@@ -264,9 +257,6 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
{
m_flag &= ~ACT_FLAG_ACTIVE;
m_flag &= ~ACT_FLAG_ATTEMPT_PLAY;
-
- if (m_playtype == ACT_ACTION_PINGPONG)
- m_flag ^= ACT_FLAG_REVERSE;
return false;
}
@@ -276,7 +266,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
if (bPositiveEvent || (m_flag & ACT_FLAG_ATTEMPT_PLAY && !(m_flag & ACT_FLAG_ACTIVE)))
{
- if (bPositiveEvent && m_playtype == ACT_ACTION_PLAY)
+ if (bPositiveEvent)
{
if (obj->IsActionDone(m_layer))
m_localtime = start;
@@ -289,7 +279,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
if (bUseContinue)
obj->SetActionFrame(m_layer, m_localtime);
- if (m_playtype == ACT_ACTION_PLAY || m_playtype == ACT_ACTION_PINGPONG)
+ if (m_playtype == ACT_ACTION_PLAY)
m_flag |= ACT_FLAG_PLAY_END;
else
m_flag &= ~ACT_FLAG_PLAY_END;
@@ -317,6 +307,9 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
// We're done
m_flag &= ~ACT_FLAG_ACTIVE;
return false;
+ case ACT_ACTION_PINGPONG:
+ m_flag ^= ACT_FLAG_REVERSE;
+ // Now fallthrough to LOOP_END code
case ACT_ACTION_LOOP_END:
// Convert into a play and let it finish
obj->SetPlayMode(m_layer, BL_Action::ACT_MODE_PLAY);
@@ -334,6 +327,12 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
break;
}
}
+
+ if (bUseContinue && (m_flag & ACT_FLAG_ACTIVE))
+ {
+ m_localtime = obj->GetActionFrame(m_layer);
+ ResetStartTime(curtime);
+ }
return true;
}
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index cedebbb9d0d..cc1a6765269 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -737,16 +737,16 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
MVert *mvert = dm->getVertArray(dm);
int totvert = dm->getNumVerts(dm);
- MFace *mface = dm->getFaceArray(dm);
- MTFace *tface = static_cast<MTFace*>(dm->getFaceDataArray(dm, CD_MTFACE));
- MCol *mcol = static_cast<MCol*>(dm->getFaceDataArray(dm, CD_MCOL));
+ MFace *mface = dm->getTessFaceArray(dm);
+ MTFace *tface = static_cast<MTFace*>(dm->getTessFaceDataArray(dm, CD_MTFACE));
+ MCol *mcol = static_cast<MCol*>(dm->getTessFaceDataArray(dm, CD_MCOL));
float (*tangent)[4] = NULL;
- int totface = dm->getNumFaces(dm);
+ int totface = dm->getNumTessFaces(dm);
const char *tfaceName = "";
if(tface) {
DM_add_tangent_layer(dm);
- tangent = (float(*)[4])dm->getFaceDataArray(dm, CD_TANGENT);
+ tangent = (float(*)[4])dm->getTessFaceDataArray(dm, CD_TANGENT);
}
meshobj = new RAS_MeshObject(mesh);
diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp
index 81533205909..5ca3b8a93bd 100644
--- a/source/gameengine/Converter/BL_SkinDeformer.cpp
+++ b/source/gameengine/Converter/BL_SkinDeformer.cpp
@@ -34,7 +34,7 @@
#pragma warning (disable : 4786)
#endif //WIN32
-// Eigen3 stuff used for BGEDeformVerts
+// Eigen2 stuff used for BGEDeformVerts
#include <Eigen/Core>
#include <Eigen/LU>
@@ -287,7 +287,7 @@ void BL_SkinDeformer::BGEDeformVerts()
// Update Vertex Normal
- norm = norm_chan_mat.topLeftCorner<3, 3>()*norm;
+ norm = norm_chan_mat.corner<3, 3>(Eigen::TopLeft)*norm;
if (contrib > 0.0001f)
{
diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt
index b570489d6a2..e02b3d8f08a 100644
--- a/source/gameengine/Converter/CMakeLists.txt
+++ b/source/gameengine/Converter/CMakeLists.txt
@@ -50,7 +50,7 @@ set(INC
../../blender/makesrna
../../blender/windowmanager
../../../extern/bullet2/src
- ../../../extern/Eigen3
+ ../../../extern/Eigen2
../../../intern/container
../../../intern/guardedalloc
../../../intern/moto/include
diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript
index 5d8e2bc93b6..e155677e522 100644
--- a/source/gameengine/Converter/SConscript
+++ b/source/gameengine/Converter/SConscript
@@ -21,7 +21,7 @@ incs += ' #source/blender/windowmanager'
incs += ' #source/blender/makesrna'
incs += ' #source/blender/ikplugin'
incs += ' #extern/recastnavigation/Detour/Include'
-incs += ' #extern/Eigen3'
+incs += ' #extern/Eigen2'
incs += ' ' + env['BF_BULLET_INC']
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index b1781f1703e..fb07918ec5c 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -176,8 +176,8 @@ static BOOL scr_saver_init(int argc, char **argv)
void usage(const char* program, bool isBlenderPlayer)
{
const char * consoleoption;
- const char * example_filename = "";
- const char * example_pathname = "";
+ const char * filename = "";
+ const char * pathname = "";
#ifdef _WIN32
consoleoption = "-c ";
@@ -186,16 +186,16 @@ void usage(const char* program, bool isBlenderPlayer)
#endif
if (isBlenderPlayer) {
- example_filename = "filename.blend";
+ filename = "filename.blend";
#ifdef _WIN32
- example_pathname = "c:\\";
+ pathname = "c:\\";
#else
- example_pathname = "/home/user/";
+ pathname = "//home//user//";
#endif
}
printf("usage: %s [-w [w h l t]] [-f [fw fh fb ff]] %s[-g gamengineoptions] "
- "[-s stereomode] [-m aasamples] %s\n", program, consoleoption, example_filename);
+ "[-s stereomode] [-m aasamples] %s\n", program, consoleoption, filename);
printf(" -h: Prints this command summary\n\n");
printf(" -w: display in a window\n");
printf(" --Optional parameters--\n");
@@ -250,9 +250,9 @@ void usage(const char* program, bool isBlenderPlayer)
printf("\n");
printf(" - : all arguments after this are ignored, allowing python to access them from sys.argv\n");
printf("\n");
- printf("example: %s -w 320 200 10 10 -g noaudio%s%s\n", program, example_pathname, example_filename);
- printf("example: %s -g show_framerate = 0 %s%s\n", program, example_pathname, example_filename);
- printf("example: %s -i 232421 -m 16 %s%s\n\n", program, example_pathname, example_filename);
+ printf("example: %s -w 320 200 10 10 -g noaudio%s%s\n", program, pathname, filename);
+ printf("example: %s -g show_framerate = 0 %s%s\n", program, pathname, filename);
+ printf("example: %s -i 232421 -m 16 %s%s\n\n", program, pathname, filename);
}
static void get_filename(int argc, char **argv, char *filename)
@@ -365,7 +365,6 @@ int main(int argc, char** argv)
GHOST_TEmbedderWindowID parentWindow = 0;
bool isBlenderPlayer = false;
int validArguments=0;
- bool samplesParFound = false;
GHOST_TUns16 aasamples = 0;
#ifdef __linux__
@@ -407,8 +406,6 @@ int main(int argc, char** argv)
initglobals();
- // Blender's VBOs cause odd problems with modifiers (we have our own vbo code)
- U.gameflags |= USER_DISABLE_VBO;
// We load our own G.main, so free the one that initglobals() gives us
free_main(G.main);
G.main = NULL;
@@ -584,14 +581,8 @@ int main(int argc, char** argv)
break;
case 'm':
i++;
- samplesParFound = true;
if ((i+1) <= validArguments )
- aasamples = atoi(argv[i++]);
- else
- {
- error = true;
- printf("error: No argument supplied for -m");
- }
+ aasamples = atoi(argv[i++]);
break;
case 'c':
i++;
@@ -827,7 +818,7 @@ int main(int argc, char** argv)
if ((!fullScreenParFound) && (!windowParFound))
{
// Only use file settings when command line did not override
- if ((scene->gm.playerflag & GAME_PLAYER_FULLSCREEN)) {
+ if (scene->gm.fullscreen) {
//printf("fullscreen option found in Blender file\n");
fullScreen = true;
fullScreenWidth= scene->gm.xplay;
@@ -856,9 +847,6 @@ int main(int argc, char** argv)
else
scene->gm.stereoflag = STEREO_ENABLED;
- if (!samplesParFound)
- aasamples = scene->gm.aasamples;
-
if (stereoFlag == STEREO_DOME){
stereomode = RAS_IRasterizer::RAS_STEREO_DOME;
scene->gm.stereoflag = STEREO_DOME;
@@ -904,7 +892,7 @@ int main(int argc, char** argv)
#endif
{
app.startFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
- stereoWindow, stereomode, aasamples, (scene->gm.playerflag & GAME_PLAYER_DESKTOP_RESOLUTION));
+ stereoWindow, stereomode, aasamples);
}
}
else
diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp
index 931e5412338..2da3fdfd225 100644
--- a/source/gameengine/Ketsji/BL_Action.cpp
+++ b/source/gameengine/Ketsji/BL_Action.cpp
@@ -279,7 +279,7 @@ void BL_Action::SetLocalTime(float curtime)
void BL_Action::ResetStartTime(float curtime)
{
- float dt = (m_localtime > m_startframe) ? m_localtime - m_startframe : m_startframe - m_localtime;
+ float dt = m_localtime - m_startframe;
m_starttime = curtime - dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed);
SetLocalTime(curtime);
diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp
index 44cfd4bddbc..38795986c08 100644
--- a/source/gameengine/Ketsji/KX_Dome.cpp
+++ b/source/gameengine/Ketsji/KX_Dome.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/Ketsji/KX_Dome.cpp
+ * \ingroup ketsji
+ */
-----------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify it under
@@ -22,10 +24,6 @@ Developed as part of a Research and Development project for SAT - La Société d
-----------------------------------------------------------------------------
*/
-/** \file gameengine/Ketsji/KX_Dome.cpp
- * \ingroup ketsji
- */
-
#include "KX_Dome.h"
#ifdef WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_Dome.h b/source/gameengine/Ketsji/KX_Dome.h
index 0436e910469..3868a6a01d2 100644
--- a/source/gameengine/Ketsji/KX_Dome.h
+++ b/source/gameengine/Ketsji/KX_Dome.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify it under
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index 76bdd36a70f..cc2e59be02c 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -1424,11 +1424,11 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
}
MVert *mvert = dm->getVertArray(dm);
- MFace *mface = dm->getFaceArray(dm);
- numpolys = dm->getNumFaces(dm);
+ MFace *mface = dm->getTessFaceArray(dm);
+ numpolys = dm->getNumTessFaces(dm);
numverts = dm->getNumVerts(dm);
- int* index = (int*)dm->getFaceDataArray(dm, CD_ORIGINDEX);
- MTFace *tface = (MTFace *)dm->getFaceDataArray(dm, CD_MTFACE);
+ int* index = (int*)dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ MTFace *tface = (MTFace *)dm->getTessFaceDataArray(dm, CD_MTFACE);
m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH;
@@ -1724,10 +1724,10 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
* */
MVert *mvert = dm->getVertArray(dm);
- MFace *mface = dm->getFaceArray(dm);
- numpolys = dm->getNumFaces(dm);
+ MFace *mface = dm->getTessFaceArray(dm);
+ numpolys = dm->getNumTessFaces(dm);
numverts = dm->getNumVerts(dm);
- int* index = (int*)dm->getFaceDataArray(dm, CD_ORIGINDEX);
+ int* index = (int*)dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
MFace *mf;
MVert *mv;
@@ -1736,7 +1736,7 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
if(CustomData_has_layer(&dm->faceData, CD_MTFACE))
{
- MTFace *tface = (MTFace *)dm->getFaceDataArray(dm, CD_MTFACE);
+ MTFace *tface = (MTFace *)dm->getTessFaceDataArray(dm, CD_MTFACE);
MTFace *tf;
vector<bool> vert_tag_array(numverts, false);
diff --git a/source/gameengine/VideoTexture/BlendType.h b/source/gameengine/VideoTexture/BlendType.h
index 4d63031a363..e6d9f530923 100644
--- a/source/gameengine/VideoTexture/BlendType.h
+++ b/source/gameengine/VideoTexture/BlendType.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
diff --git a/source/gameengine/VideoTexture/Common.h b/source/gameengine/VideoTexture/Common.h
index fe9632b02bb..bc014c34e09 100644
--- a/source/gameengine/VideoTexture/Common.h
+++ b/source/gameengine/VideoTexture/Common.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
diff --git a/source/gameengine/VideoTexture/Exception.cpp b/source/gameengine/VideoTexture/Exception.cpp
index dc63a867e30..b792c597cf0 100644
--- a/source/gameengine/VideoTexture/Exception.cpp
+++ b/source/gameengine/VideoTexture/Exception.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/Exception.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,9 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/Exception.cpp
- * \ingroup bgevideotex
- */
#include <sstream>
#include <fstream>
diff --git a/source/gameengine/VideoTexture/Exception.h b/source/gameengine/VideoTexture/Exception.h
index af226fab75d..65b527d6d32 100644
--- a/source/gameengine/VideoTexture/Exception.h
+++ b/source/gameengine/VideoTexture/Exception.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
diff --git a/source/gameengine/VideoTexture/FilterBase.cpp b/source/gameengine/VideoTexture/FilterBase.cpp
index 28e36cf80e0..bd5794f95dd 100644
--- a/source/gameengine/VideoTexture/FilterBase.cpp
+++ b/source/gameengine/VideoTexture/FilterBase.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/FilterBase.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,11 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/FilterBase.cpp
- * \ingroup bgevideotex
- */
-
-
#include "FilterBase.h"
#include <PyObjectPlus.h>
diff --git a/source/gameengine/VideoTexture/FilterBase.h b/source/gameengine/VideoTexture/FilterBase.h
index bdb3106d58d..e83d980ebbf 100644
--- a/source/gameengine/VideoTexture/FilterBase.h
+++ b/source/gameengine/VideoTexture/FilterBase.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp
index fb5a83c7043..a6870772ab9 100644
--- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp
+++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/FilterBlueScreen.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,9 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/FilterBlueScreen.cpp
- * \ingroup bgevideotex
- */
#include <PyObjectPlus.h>
#include <structmember.h>
diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.h b/source/gameengine/VideoTexture/FilterBlueScreen.h
index 381941fdcca..2d69866cc56 100644
--- a/source/gameengine/VideoTexture/FilterBlueScreen.h
+++ b/source/gameengine/VideoTexture/FilterBlueScreen.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of blendTex library
diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp
index f3931c7e047..d51e13ea9c8 100644
--- a/source/gameengine/VideoTexture/FilterColor.cpp
+++ b/source/gameengine/VideoTexture/FilterColor.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/FilterColor.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,9 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/FilterColor.cpp
- * \ingroup bgevideotex
- */
#include <PyObjectPlus.h>
#include <structmember.h>
diff --git a/source/gameengine/VideoTexture/FilterColor.h b/source/gameengine/VideoTexture/FilterColor.h
index aeca4d326b4..b97c534b08e 100644
--- a/source/gameengine/VideoTexture/FilterColor.h
+++ b/source/gameengine/VideoTexture/FilterColor.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of blendTex library
diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp
index aacbc87a414..74de9c31da8 100644
--- a/source/gameengine/VideoTexture/FilterNormal.cpp
+++ b/source/gameengine/VideoTexture/FilterNormal.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/FilterNormal.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,9 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/FilterNormal.cpp
- * \ingroup bgevideotex
- */
#include <PyObjectPlus.h>
#include <structmember.h>
diff --git a/source/gameengine/VideoTexture/FilterNormal.h b/source/gameengine/VideoTexture/FilterNormal.h
index 0b4574d4d1f..11cea25101e 100644
--- a/source/gameengine/VideoTexture/FilterNormal.h
+++ b/source/gameengine/VideoTexture/FilterNormal.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of blendTex library
diff --git a/source/gameengine/VideoTexture/FilterSource.cpp b/source/gameengine/VideoTexture/FilterSource.cpp
index c5c164822a5..0955611b3e0 100644
--- a/source/gameengine/VideoTexture/FilterSource.cpp
+++ b/source/gameengine/VideoTexture/FilterSource.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/FilterSource.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,10 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/FilterSource.cpp
- * \ingroup bgevideotex
- */
-
// implementation
#include <PyObjectPlus.h>
diff --git a/source/gameengine/VideoTexture/FilterSource.h b/source/gameengine/VideoTexture/FilterSource.h
index 5b73fcda947..5b19afc12f4 100644
--- a/source/gameengine/VideoTexture/FilterSource.h
+++ b/source/gameengine/VideoTexture/FilterSource.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of blendTex library
diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp
index 0fe71dd8024..50190280337 100644
--- a/source/gameengine/VideoTexture/ImageBase.cpp
+++ b/source/gameengine/VideoTexture/ImageBase.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/ImageBase.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,10 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/ImageBase.cpp
- * \ingroup bgevideotex
- */
-
#include "ImageBase.h"
extern "C" {
#include "bgl.h"
diff --git a/source/gameengine/VideoTexture/ImageBase.h b/source/gameengine/VideoTexture/ImageBase.h
index e6469f4cb86..9f43cd9cf7d 100644
--- a/source/gameengine/VideoTexture/ImageBase.h
+++ b/source/gameengine/VideoTexture/ImageBase.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of blendTex library
diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp
index d9e3a592f6f..602ae3ddce9 100644
--- a/source/gameengine/VideoTexture/ImageBuff.cpp
+++ b/source/gameengine/VideoTexture/ImageBuff.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/ImageBuff.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,10 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/ImageBuff.cpp
- * \ingroup bgevideotex
- */
-
// implementation
#include <PyObjectPlus.h>
diff --git a/source/gameengine/VideoTexture/ImageBuff.h b/source/gameengine/VideoTexture/ImageBuff.h
index 1fd2d3f9ee6..4e89db220ea 100644
--- a/source/gameengine/VideoTexture/ImageBuff.h
+++ b/source/gameengine/VideoTexture/ImageBuff.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
diff --git a/source/gameengine/VideoTexture/ImageMix.cpp b/source/gameengine/VideoTexture/ImageMix.cpp
index d06ea485c8c..573daef88da 100644
--- a/source/gameengine/VideoTexture/ImageMix.cpp
+++ b/source/gameengine/VideoTexture/ImageMix.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/ImageMix.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,11 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/ImageMix.cpp
- * \ingroup bgevideotex
- */
-
-
// implementation
#include <PyObjectPlus.h>
diff --git a/source/gameengine/VideoTexture/ImageMix.h b/source/gameengine/VideoTexture/ImageMix.h
index d99f27576c1..2fdc0c894c8 100644
--- a/source/gameengine/VideoTexture/ImageMix.h
+++ b/source/gameengine/VideoTexture/ImageMix.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp
index 912d5864560..27668210811 100644
--- a/source/gameengine/VideoTexture/ImageRender.cpp
+++ b/source/gameengine/VideoTexture/ImageRender.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/ImageRender.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,10 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/ImageRender.cpp
- * \ingroup bgevideotex
- */
-
// implementation
#include <PyObjectPlus.h>
diff --git a/source/gameengine/VideoTexture/ImageRender.h b/source/gameengine/VideoTexture/ImageRender.h
index 61f441465c3..8480422fa24 100644
--- a/source/gameengine/VideoTexture/ImageRender.h
+++ b/source/gameengine/VideoTexture/ImageRender.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp
index 036dd893dcb..3b66be4bd9a 100644
--- a/source/gameengine/VideoTexture/ImageViewport.cpp
+++ b/source/gameengine/VideoTexture/ImageViewport.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/ImageViewport.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,10 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/ImageViewport.cpp
- * \ingroup bgevideotex
- */
-
// implementation
#include <PyObjectPlus.h>
diff --git a/source/gameengine/VideoTexture/ImageViewport.h b/source/gameengine/VideoTexture/ImageViewport.h
index 4195847c9d0..efd6a187212 100644
--- a/source/gameengine/VideoTexture/ImageViewport.h
+++ b/source/gameengine/VideoTexture/ImageViewport.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
diff --git a/source/gameengine/VideoTexture/PyTypeList.cpp b/source/gameengine/VideoTexture/PyTypeList.cpp
index 508ce233def..f9c2ad441b6 100644
--- a/source/gameengine/VideoTexture/PyTypeList.cpp
+++ b/source/gameengine/VideoTexture/PyTypeList.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/PyTypeList.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of blendTex library
@@ -20,9 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/PyTypeList.cpp
- * \ingroup bgevideotex
- */
#include "PyTypeList.h"
diff --git a/source/gameengine/VideoTexture/PyTypeList.h b/source/gameengine/VideoTexture/PyTypeList.h
index 3f1523294aa..020f3ebdde8 100644
--- a/source/gameengine/VideoTexture/PyTypeList.h
+++ b/source/gameengine/VideoTexture/PyTypeList.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of blendTex library
diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp
index 2066afbbf27..eaf6002663b 100644
--- a/source/gameengine/VideoTexture/Texture.cpp
+++ b/source/gameengine/VideoTexture/Texture.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/Texture.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,10 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/Texture.cpp
- * \ingroup bgevideotex
- */
-
// implementation
#include <PyObjectPlus.h>
diff --git a/source/gameengine/VideoTexture/Texture.h b/source/gameengine/VideoTexture/Texture.h
index 52e1dfeb148..15dc18481bc 100644
--- a/source/gameengine/VideoTexture/Texture.h
+++ b/source/gameengine/VideoTexture/Texture.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
diff --git a/source/gameengine/VideoTexture/VideoBase.cpp b/source/gameengine/VideoTexture/VideoBase.cpp
index 6662df8d7d1..38bd23788e1 100644
--- a/source/gameengine/VideoTexture/VideoBase.cpp
+++ b/source/gameengine/VideoTexture/VideoBase.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/VideoBase.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,10 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/VideoBase.cpp
- * \ingroup bgevideotex
- */
-
#if defined WIN32
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
diff --git a/source/gameengine/VideoTexture/VideoBase.h b/source/gameengine/VideoTexture/VideoBase.h
index a1eae96be57..b841fe8bc0f 100644
--- a/source/gameengine/VideoTexture/VideoBase.h
+++ b/source/gameengine/VideoTexture/VideoBase.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
index acc09931859..b48d1111fd2 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/VideoFFmpeg.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,11 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/VideoFFmpeg.cpp
- * \ingroup bgevideotex
- */
-
-
#ifdef WITH_FFMPEG
// INT64_C fix for some linux machines (C99ism)
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h
index 2be86b6c535..9cc10cb55db 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.h
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.h
@@ -1,4 +1,3 @@
-/*
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp
index c93fadada77..fbb74650e4c 100644
--- a/source/gameengine/VideoTexture/blendVideoTex.cpp
+++ b/source/gameengine/VideoTexture/blendVideoTex.cpp
@@ -1,4 +1,6 @@
-/*
+/** \file gameengine/VideoTexture/blendVideoTex.cpp
+ * \ingroup bgevideotex
+ */
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
@@ -20,10 +22,6 @@ http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
-/** \file gameengine/VideoTexture/blendVideoTex.cpp
- * \ingroup bgevideotex
- */
-
#include <PyObjectPlus.h>
#include <RAS_GLExtensionManager.h>
diff --git a/source/tests/check_deprecated.py b/source/tests/check_deprecated.py
index c5c7bdcdcb0..34b07518162 100644
--- a/source/tests/check_deprecated.py
+++ b/source/tests/check_deprecated.py
@@ -36,7 +36,7 @@ def is_c_header(filename):
def is_c(filename):
ext = splitext(filename)[1]
- return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"))
+ return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc"))
def is_c_any(filename):